From 60234b644d10a3450c77ecfdf590e89c25c8155c Mon Sep 17 00:00:00 2001 From: Pierre-Jean CHANCELLIER <paidge_cs@hotmail.com> Date: Fri, 21 Jan 2022 15:49:17 +0100 Subject: [PATCH] prettier configuration --- .editorconfig | 13 - .prettierrc | 16 + README.md | 28 +- assets/css/_bootstrap.scss | 52 ++- assets/css/_font.scss | 82 ++--- assets/css/style.scss | 10 +- components/Graph.vue | 150 ++++----- components/badge/CertifStatus.vue | 58 ++-- components/badge/Dispo.vue | 45 +-- components/badge/Quality.vue | 33 +- components/badge/Status.vue | 70 ++-- components/btn/Clipboard.vue | 70 ++-- components/btn/Loading.vue | 30 +- components/btn/Theme.vue | 116 ++++--- components/certif/List.vue | 357 ++++++++++++-------- components/member/Card.vue | 222 +++++++----- components/member/List.vue | 92 ++--- components/navigation/Bar.vue | 402 +++++++++++----------- components/navigation/Breadcrumb.vue | 39 ++- components/navigation/Language.vue | 31 +- components/navigation/Loader.vue | 30 +- components/navigation/menu/Group.vue | 30 +- components/navigation/menu/Sidebar.vue | 86 +++-- graphql/cache.js | 14 +- graphql/clients/coindufeu.js | 4 +- graphql/clients/endpoints.js | 4 +- graphql/clients/otherclient.js | 4 +- graphql/fragmentTypes.json | 25 +- graphql/schemaQuery.js | 10 +- i18n/index.js | 2 +- i18n/locales/en.json | 194 +++++------ i18n/locales/es.json | 192 +++++------ i18n/locales/fr.json | 194 +++++------ jsconfig.json | 20 +- layouts/default.vue | 110 +++--- layouts/error.vue | 48 +-- nuxt.config.js | 2 +- package.json | 64 ++-- pages/chartjs.vue | 191 ++++++----- pages/index.vue | 183 +++++----- pages/membres/_hash.vue | 247 ++++++++------ pages/membres/index.vue | 151 +++++---- pages/parametres.vue | 145 ++++---- pages/previsions/futurs_membres.vue | 448 +++++++++++++++---------- pages/previsions/index.vue | 114 +++---- pages/template.vue | 143 ++++---- plugins/filters.js | 8 +- 47 files changed, 2543 insertions(+), 2036 deletions(-) delete mode 100644 .editorconfig create mode 100644 .prettierrc diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 5d12634..0000000 --- a/.editorconfig +++ /dev/null @@ -1,13 +0,0 @@ -# editorconfig.org -root = true - -[*] -indent_style = space -indent_size = 2 -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[*.md] -trim_trailing_whitespace = false diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..dfbed09 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,16 @@ +{ + "arrowParens": "always", + "bracketSpacing": true, + "bracketSameLine": true, + "embeddedLanguageFormatting": "auto", + "endOfLine": "lf", + "htmlWhitespaceSensitivity": "css", + "printWidth": 80, + "quoteProps": "as-needed", + "semi": false, + "singleQuote": false, + "tabWidth": 2, + "trailingComma": "none", + "useTabs": true, + "vueIndentScriptAndStyle": false +} diff --git a/README.md b/README.md index 1997f67..cca8eb7 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,28 @@ # wotwizard-ui +## Prerequisite + +This project needs NodeJS v16 + ## Contribute + ```bash $ git clone https://git.duniter.org/paidge/wotwizard-ui.git $ cd wotwizard-ui +$ nvm use 16 $ git checkout -b my-branch $ npm install $ npm run dev +... Development... $ npm run analyze $ git commit $ git push ``` + Then create a merge request. ### Add a new page + Copy/paste the file `./pages/template.vue` and rename it to create a new page. This template is extremly commented for beginners so you can create an apollo query and display the response very easily even using i18n ! @@ -21,11 +30,11 @@ This template is extremly commented for beginners so you can create an apollo qu If you want to add your page in the menu, edit the `menus` variable in the `./layouts/default.vue` file. ### ChartJS + There is an example to use component graph lazyly in `./pages/chartjs.vue`. ### GraphQL - All files concerning Apollo Graphql are stored in `./graphql`. The schema documentation is stored in the `./graphql/doc/graphQLschema.txt` file. @@ -35,6 +44,7 @@ In `queries.js` you'll find all queries. If you want to add a 2nd graphQL server, edit `./graphql/clients/endpoints.js` to put your URL and uncomment the line concerning the `apollo.clientConfigs.myotherclient` option in `nuxt.config.js`. I have not tested this functionnality. ### Special Directories + For detailed explanation on how things work, check out the [documentation](https://nuxtjs.org). You can create the following extra directories, some of which have special behaviors. Only `pages` is required; you can delete them if you don't want to use their functionality. @@ -57,7 +67,6 @@ Layouts are a great help when you want to change the look and feel of your Nuxt More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/layouts). - #### `pages` This directory contains your application views and routes. Nuxt will read all the `*.vue` files inside this directory and setup Vue Router automatically. @@ -93,19 +102,10 @@ $ nvm use 16 # install dependencies $ npm install -# serve with hot reload at localhost:3000 -$ npm run dev - -# Analyze assets to check bundle's size -$ npm run analyze - # build for production and launch server for Server Side Rendering (SSR) $ npm run build $ npm run start -# generate static project -$ npm run generate - -# update introspection schema for graphql server -$ npm run build-fragment -``` \ No newline at end of file +# Or generate static project +$ npm run generates +``` diff --git a/assets/css/_bootstrap.scss b/assets/css/_bootstrap.scss index 19a1e15..8b120fc 100644 --- a/assets/css/_bootstrap.scss +++ b/assets/css/_bootstrap.scss @@ -1,39 +1,37 @@ - - @import "~bootstrap/scss/functions"; - @import "~bootstrap/scss/variables"; - @import "~bootstrap/scss/mixins"; - @import "~bootstrap/scss/root"; - @import "~bootstrap/scss/reboot"; - @import "~bootstrap/scss/type"; - @import "~bootstrap/scss/images"; - @import "~bootstrap/scss/code"; - @import "~bootstrap/scss/grid"; - @import "~bootstrap/scss/tables"; - @import "~bootstrap/scss/forms"; - @import "~bootstrap/scss/buttons"; - @import "~bootstrap/scss/transitions"; +@import "~bootstrap/scss/functions"; +@import "~bootstrap/scss/variables"; +@import "~bootstrap/scss/mixins"; +@import "~bootstrap/scss/root"; +@import "~bootstrap/scss/reboot"; +@import "~bootstrap/scss/type"; +@import "~bootstrap/scss/images"; +@import "~bootstrap/scss/code"; +@import "~bootstrap/scss/grid"; +@import "~bootstrap/scss/tables"; +@import "~bootstrap/scss/forms"; +@import "~bootstrap/scss/buttons"; +@import "~bootstrap/scss/transitions"; // @import "~bootstrap/scss/dropdown"; // @import "~bootstrap/scss/button-group"; - @import "~bootstrap/scss/input-group"; +@import "~bootstrap/scss/input-group"; // @import "~bootstrap/scss/custom-forms"; - @import "~bootstrap/scss/nav"; - @import "~bootstrap/scss/navbar"; - @import "~bootstrap/scss/card"; - @import "~bootstrap/scss/breadcrumb"; +@import "~bootstrap/scss/nav"; +@import "~bootstrap/scss/navbar"; +@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/alert"; // @import "~bootstrap/scss/progress"; // @import "~bootstrap/scss/media"; - @import "~bootstrap/scss/list-group"; - @import "~bootstrap/scss/close"; +@import "~bootstrap/scss/list-group"; +@import "~bootstrap/scss/close"; // @import "~bootstrap/scss/toasts"; // @import "~bootstrap/scss/modal"; - @import "~bootstrap/scss/tooltip"; +@import "~bootstrap/scss/tooltip"; // @import "~bootstrap/scss/popover"; // @import "~bootstrap/scss/carousel"; // @import "~bootstrap/scss/spinners"; - @import "~bootstrap/scss/utilities"; - @import "~bootstrap/scss/print"; - \ No newline at end of file +@import "~bootstrap/scss/utilities"; +@import "~bootstrap/scss/print"; diff --git a/assets/css/_font.scss b/assets/css/_font.scss index 373e3c1..be9b73a 100644 --- a/assets/css/_font.scss +++ b/assets/css/_font.scss @@ -1,69 +1,69 @@ @font-face { - font-family: "Montserrat"; - src: url("~assets/fonts/Montserrat-Light.otf") format("truetype"); - font-weight: 300; - font-style: normal; + font-family: "Montserrat"; + src: url("~assets/fonts/Montserrat-Light.otf") format("truetype"); + font-weight: 300; + font-style: normal; } @font-face { - font-family: "Montserrat"; - src: url("~assets/fonts/Montserrat-LightItalic.otf") format("truetype"); - font-weight: 300; - font-style: italic; + font-family: "Montserrat"; + src: url("~assets/fonts/Montserrat-LightItalic.otf") format("truetype"); + font-weight: 300; + font-style: italic; } @font-face { - font-family: "Montserrat"; - src: url("~assets/fonts/Montserrat-Regular.otf") format("truetype"); - font-weight: normal; - font-style: normal; + font-family: "Montserrat"; + src: url("~assets/fonts/Montserrat-Regular.otf") format("truetype"); + font-weight: normal; + font-style: normal; } @font-face { - font-family: "Montserrat"; - src: url("~assets/fonts/Montserrat-Italic.otf") format("truetype"); - font-weight: normal; - font-style: italic; + font-family: "Montserrat"; + src: url("~assets/fonts/Montserrat-Italic.otf") format("truetype"); + font-weight: normal; + font-style: italic; } @font-face { - font-family: "Montserrat"; - src: url("~assets/fonts/Montserrat-SemiBold.otf") format("truetype"); - font-weight: 500; - font-style: normal; + font-family: "Montserrat"; + src: url("~assets/fonts/Montserrat-SemiBold.otf") format("truetype"); + font-weight: 500; + font-style: normal; } @font-face { - font-family: "Montserrat"; - src: url("~assets/fonts/Montserrat-SemiBoldItalic.otf") format("truetype"); - font-weight: 500; - font-style: italic; + font-family: "Montserrat"; + src: url("~assets/fonts/Montserrat-SemiBoldItalic.otf") format("truetype"); + font-weight: 500; + font-style: italic; } @font-face { - font-family: "Montserrat"; - src: url("~assets/fonts/Montserrat-Bold.otf") format("truetype"); - font-weight: bold; - font-style: normal; + font-family: "Montserrat"; + src: url("~assets/fonts/Montserrat-Bold.otf") format("truetype"); + font-weight: bold; + font-style: normal; } @font-face { - font-family: "Montserrat"; - src: url("~assets/fonts/Montserrat-BoldItalic.otf") format("truetype"); - font-weight: bold; - font-style: italic; + font-family: "Montserrat"; + src: url("~assets/fonts/Montserrat-BoldItalic.otf") format("truetype"); + font-weight: bold; + font-style: italic; } @font-face { - font-family: "Montserrat"; - src: url("~assets/fonts/Montserrat-ExtraBold.otf") format("truetype"); - font-weight: 800; - font-style: normal; + font-family: "Montserrat"; + src: url("~assets/fonts/Montserrat-ExtraBold.otf") format("truetype"); + font-weight: 800; + font-style: normal; } @font-face { - font-family: "Montserrat"; - src: url("~assets/fonts/Montserrat-ExtraBoldItalic.otf") format("truetype"); - font-weight: 800; - font-style: italic; -} \ No newline at end of file + font-family: "Montserrat"; + src: url("~assets/fonts/Montserrat-ExtraBoldItalic.otf") format("truetype"); + font-weight: 800; + font-style: italic; +} diff --git a/assets/css/style.scss b/assets/css/style.scss index 41df294..b36e7b5 100644 --- a/assets/css/style.scss +++ b/assets/css/style.scss @@ -36,9 +36,9 @@ $card-bg: var(--background-color-secondary); $close-color: var(--text-primary-color); $close-font-weight: 500; -@import 'font'; -@import 'bootstrap'; +@import "font"; +@import "bootstrap"; -.table-hover tbody tr{ - cursor: pointer; -} \ No newline at end of file +.table-hover tbody tr { + cursor: pointer; +} diff --git a/components/Graph.vue b/components/Graph.vue index aa2f218..fac93ad 100644 --- a/components/Graph.vue +++ b/components/Graph.vue @@ -1,85 +1,85 @@ <template> - <div> - <canvas :id="id" @click="test($event)"></canvas> - </div> + <div> + <canvas :id="id" @click="test($event)"></canvas> + </div> </template> <script> -import Chart from 'chart.js/auto' +import Chart from "chart.js/auto" export const chartTypes = [ - 'line', - 'bar', - 'doughnut', - 'bubble', - 'scatter', - // 'radar', - // 'polarArea' + "line", + "bar", + "doughnut", + "bubble", + "scatter" + // 'radar', + // 'polarArea' ] export default { - props: { - id: { - type: String, - default : 'my-chart', - required: true - }, - type: { - type: String, - default: 'line', - required: true, - validator: function (value) { - return chartTypes.indexOf(value) !== -1 - } - }, - data: { - type: Object, - default: undefined, - required: true - }, - options: { - type: Object, - default: undefined - } - }, - data() { - return { - chart: undefined, - chartData: { - type: this.type, - data: this.data, - options: this.options - } - } - }, - methods: { - createChart() { - this.chart?.destroy() - this.chart = new Chart(document.getElementById(this.id), this.chartData) - } - }, - mounted() { - this.createChart() - }, - watch: { - type: { - handler(n,o) { - this.chartData.type = n - this.createChart() - } - }, - data: { - handler(n,o){ - this.chartData.data = n - this.createChart() - } - }, - options: { - handler(n,o) { - this.chartData.options = n - this.createChart() - } - } - } + props: { + id: { + type: String, + default: "my-chart", + required: true + }, + type: { + type: String, + default: "line", + required: true, + validator: function (value) { + return chartTypes.indexOf(value) !== -1 + } + }, + data: { + type: Object, + default: undefined, + required: true + }, + options: { + type: Object, + default: undefined + } + }, + data() { + return { + chart: undefined, + chartData: { + type: this.type, + data: this.data, + options: this.options + } + } + }, + methods: { + createChart() { + this.chart?.destroy() + this.chart = new Chart(document.getElementById(this.id), this.chartData) + } + }, + mounted() { + this.createChart() + }, + watch: { + type: { + handler(n, o) { + this.chartData.type = n + this.createChart() + } + }, + data: { + handler(n, o) { + this.chartData.data = n + this.createChart() + } + }, + options: { + handler(n, o) { + this.chartData.options = n + this.createChart() + } + } + } } -</script> \ No newline at end of file +</script> diff --git a/components/badge/CertifStatus.vue b/components/badge/CertifStatus.vue index 3dcfa43..c24c671 100644 --- a/components/badge/CertifStatus.vue +++ b/components/badge/CertifStatus.vue @@ -1,34 +1,46 @@ <template> - <span class="danger font-weight-normal" :class="classWarning" :title="textWarning" v-if="($options.filters.dateStatus(limitDate) != 'success') && (['MEMBER', 'MISSING'].includes(memberStatus))">âš - <span class="sr-only">{{ textWarning }}</span> - </span> + <span + class="danger font-weight-normal" + :class="classWarning" + :title="textWarning" + v-if=" + $options.filters.dateStatus(limitDate) != 'success' && + ['MEMBER', 'MISSING'].includes(memberStatus) + " + >âš + <span class="sr-only">{{ textWarning }}</span> + </span> </template> <script> export default { - props: { - limitDate : { - type: Number, - default: 0 - }, - memberStatus : String - }, - computed: { - classWarning() { - return { - 'text-danger' : this.$options.filters.dateStatus(this.limitDate) == 'danger', - 'text-warning' : this.$options.filters.dateStatus(this.limitDate) == 'warning' - } - }, - textWarning() { - return (this.$options.filters.dateStatus(this.limitDate) == 'danger') ? this.$i18n.t('statut.manquecertif') : this.$i18n.t('statut.bientotmanquecertif') - } - } + props: { + limitDate: { + type: Number, + default: 0 + }, + memberStatus: String + }, + computed: { + classWarning() { + return { + "text-danger": + this.$options.filters.dateStatus(this.limitDate) == "danger", + "text-warning": + this.$options.filters.dateStatus(this.limitDate) == "warning" + } + }, + textWarning() { + return this.$options.filters.dateStatus(this.limitDate) == "danger" + ? this.$i18n.t("statut.manquecertif") + : this.$i18n.t("statut.bientotmanquecertif") + } + } } </script> <style lang="scss" scoped> .danger { - cursor: default; + cursor: default; } -</style> \ No newline at end of file +</style> diff --git a/components/badge/Dispo.vue b/components/badge/Dispo.vue index ad18eb3..82581a6 100644 --- a/components/badge/Dispo.vue +++ b/components/badge/Dispo.vue @@ -1,25 +1,32 @@ <template> - <small> - <span class="badge" - :class="{ - 'badge-success': isDispo, - 'badge-danger': !isDispo, - }"> - {{ isDispo ? $t('membre.dispo') : $t('membre.nodispo') + ' > ' + $d(new Date(dateDispo*1000), 'short') }} - </span> - </small> + <small> + <span + class="badge" + :class="{ + 'badge-success': isDispo, + 'badge-danger': !isDispo + }"> + {{ + isDispo + ? $t("membre.dispo") + : $t("membre.nodispo") + + " > " + + $d(new Date(dateDispo * 1000), "short") + }} + </span> + </small> </template> <script> export default { - props: { - isDispo: { - type: Boolean, - required: true - }, - dateDispo: { - type: Number - } - } + props: { + isDispo: { + type: Boolean, + required: true + }, + dateDispo: { + type: Number + } + } } -</script> \ No newline at end of file +</script> diff --git a/components/badge/Quality.vue b/components/badge/Quality.vue index 261bb74..0f9c000 100644 --- a/components/badge/Quality.vue +++ b/components/badge/Quality.vue @@ -1,22 +1,23 @@ <template> - <small> - <span class="badge" - :class="{ - 'badge-success': quality>=80, - 'badge-warning': quality<80, - }"> - {{ Math.round(quality*100)/100 }} - </span> - </small> + <small> + <span + class="badge" + :class="{ + 'badge-success': quality >= 80, + 'badge-warning': quality < 80 + }"> + {{ Math.round(quality * 100) / 100 }} + </span> + </small> </template> <script> export default { - props: { - quality: { - type: Number, - required: true - } - } + props: { + quality: { + type: Number, + required: true + } + } } -</script> \ No newline at end of file +</script> diff --git a/components/badge/Status.vue b/components/badge/Status.vue index ed5e794..086493d 100644 --- a/components/badge/Status.vue +++ b/components/badge/Status.vue @@ -1,38 +1,44 @@ <template> - <small> - <span class="badge" :class="this.displayStatus(membre).class"> - {{ this.displayStatus(membre).str }} - </span> - </small> + <small> + <span class="badge" :class="this.displayStatus(membre).class"> + {{ this.displayStatus(membre).str }} + </span> + </small> </template> <script> export default { - props: { - membre: { - type: Object, - required: true - } - }, - methods: { - displayStatus: function(member){ - switch (member.status) { - case 'NEWCOMER': - return {str: this.$i18n.t('statut.newcomer'),class: 'badge-info'} - case 'MISSING': - return {str: this.$i18n.t('statut.missing'),class: 'badge-danger'} - case 'MEMBER': - if (this.$options.filters.dateStatus(member.limitDate) == 'warning') { - return {str: this.$i18n.t('statut.renew'),class: 'badge-warning'} - } else { - return {str: this.$i18n.t('statut.member'),class: 'badge-success'} - } - case 'REVOKED': - return {str: this.$i18n.t('statut.revoked'),class: 'badge-secondary'} - default: - return 'N/A' - } - } - } + props: { + membre: { + type: Object, + required: true + } + }, + methods: { + displayStatus: function (member) { + switch (member.status) { + case "NEWCOMER": + return { str: this.$i18n.t("statut.newcomer"), class: "badge-info" } + case "MISSING": + return { str: this.$i18n.t("statut.missing"), class: "badge-danger" } + case "MEMBER": + if (this.$options.filters.dateStatus(member.limitDate) == "warning") { + return { str: this.$i18n.t("statut.renew"), class: "badge-warning" } + } else { + return { + str: this.$i18n.t("statut.member"), + class: "badge-success" + } + } + case "REVOKED": + return { + str: this.$i18n.t("statut.revoked"), + class: "badge-secondary" + } + default: + return "N/A" + } + } + } } -</script> \ No newline at end of file +</script> diff --git a/components/btn/Clipboard.vue b/components/btn/Clipboard.vue index 212b311..eb8c5f0 100644 --- a/components/btn/Clipboard.vue +++ b/components/btn/Clipboard.vue @@ -1,43 +1,51 @@ <template> -<div class="clipboard input-group input-group-sm mb-3 mx-auto"> - <div class="input-group-prepend"> - <button id="btncopy" class="btn btn-outline-secondary px-4 py-1" type="button" @click="copyText"></button> - </div> - <input type="text" class="form-control text-truncate" :value="textContent" disabled> -</div> + <div class="clipboard input-group input-group-sm mb-3 mx-auto"> + <div class="input-group-prepend"> + <button + id="btncopy" + class="btn btn-outline-secondary px-4 py-1" + type="button" + @click="copyText"></button> + </div> + <input + type="text" + class="form-control text-truncate" + :value="textContent" + disabled /> + </div> </template> <script> export default { - props: { - textContent: { - type: String, - required: true - } - }, - methods: { - copyText() { - navigator.clipboard.writeText(this.textContent) - $('#btncopy').tooltip({ - title: this.$t('copie') + ' !', - trigger: 'manual' - }) - $('#btncopy').tooltip('show') - setTimeout(() => { - $('#btncopy').tooltip('hide') - },500) - } - } + props: { + textContent: { + type: String, + required: true + } + }, + methods: { + copyText() { + navigator.clipboard.writeText(this.textContent) + $("#btncopy").tooltip({ + title: this.$t("copie") + " !", + trigger: "manual" + }) + $("#btncopy").tooltip("show") + setTimeout(() => { + $("#btncopy").tooltip("hide") + }, 500) + } + } } </script> <style lang="scss"> .clipboard { - max-width:500px; + max-width: 500px; - button { - background: url("~assets/img/clipboard.svg") no-repeat 50% 50% #fff; - background-size: 40%; - } + button { + background: url("~assets/img/clipboard.svg") no-repeat 50% 50% #fff; + background-size: 40%; + } } -</style> \ No newline at end of file +</style> diff --git a/components/btn/Loading.vue b/components/btn/Loading.vue index 1a54f44..2937b4c 100644 --- a/components/btn/Loading.vue +++ b/components/btn/Loading.vue @@ -1,18 +1,24 @@ <template> - <button type="submit" class="btn btn-primary" :disabled="isWaiting || disabled"> - <span v-if="isWaiting"> - <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> - Chargement... - </span> - <span v-else>Go !</span> - </button> + <button + type="submit" + class="btn btn-primary" + :disabled="isWaiting || disabled"> + <span v-if="isWaiting"> + <span + class="spinner-border spinner-border-sm" + role="status" + aria-hidden="true"></span> + {{ $t("chargement") }}... + </span> + <span v-else>Go !</span> + </button> </template> <script> export default { - props: { - isWaiting: Boolean, - disabled: Boolean - } + props: { + isWaiting: Boolean, + disabled: Boolean + } } -</script> \ No newline at end of file +</script> diff --git a/components/btn/Theme.vue b/components/btn/Theme.vue index 9282fd7..0c46a7c 100644 --- a/components/btn/Theme.vue +++ b/components/btn/Theme.vue @@ -1,76 +1,88 @@ <template> - <div> - <input @change="toggleTheme" id="checkbox" type="checkbox" class="switch-checkbox" /> - <label for="checkbox" class="switch-label d-flex align-items-center justify-content-between position-relative mb-0 "> - <span>🌙</span> - <span>☀ï¸</span> - <div class="switch-toggle position-absolute rounded-circle" :class="{ 'switch-toggle-checked': userTheme === 'dark-theme' }"></div> - </label> - </div> + <div> + <input + @change="toggleTheme" + id="checkbox" + type="checkbox" + class="switch-checkbox" /> + <label + for="checkbox" + class="switch-label d-flex align-items-center justify-content-between position-relative mb-0"> + <span>🌙</span> + <span>☀ï¸</span> + <div + class="switch-toggle position-absolute rounded-circle" + :class="{ 'switch-toggle-checked': userTheme === 'dark-theme' }"></div> + </label> + </div> </template> <script> export default { - mounted() { - this.setTheme(localStorage.getItem("user-theme")) - }, + mounted() { + this.setTheme(localStorage.getItem("user-theme")) + }, - data() { - return { - userTheme: "light-theme", - }; - }, + data() { + return { + userTheme: "light-theme" + } + }, - methods: { - toggleTheme() { - if (this.userTheme === "light-theme") { - this.setTheme("dark-theme") - } else { - this.setTheme("light-theme") - } - }, + methods: { + toggleTheme() { + if (this.userTheme === "light-theme") { + this.setTheme("dark-theme") + } else { + this.setTheme("light-theme") + } + }, - setTheme(theme) { - if (theme == null) {theme="light-theme"} - localStorage.setItem("user-theme", theme) - this.userTheme = theme - document.documentElement.className = theme - } - }, -}; + setTheme(theme) { + if (theme == null) { + theme = "light-theme" + } + localStorage.setItem("user-theme", theme) + this.userTheme = theme + document.documentElement.className = theme + } + } +} </script> <style scoped> -*, ::before, ::after { - box-sizing: initial; +*, +::before, +::after { + box-sizing: initial; } .switch-checkbox { - display: none; + display: none; } .switch-label { - background: var(--text-primary-color); - border-radius: var(--element-size); - cursor: pointer; - font-size: calc(var(--element-size) * 0.3); - height: calc(var(--element-size) * 0.35); - padding: calc(var(--element-size) * 0.1); - transition: background 0.5s ease; - width: var(--element-size); - z-index: 1; + background: var(--text-primary-color); + border-radius: var(--element-size); + cursor: pointer; + font-size: calc(var(--element-size) * 0.3); + height: calc(var(--element-size) * 0.35); + padding: calc(var(--element-size) * 0.1); + transition: background 0.5s ease; + width: var(--element-size); + z-index: 1; } .switch-toggle { - background-color: var(--background-color-primary); - top: calc(var(--element-size) * 0.07); - left: calc(var(--element-size) * 0.07); - height: calc(var(--element-size) * 0.4); - width: calc(var(--element-size) * 0.4); - transform: translateX(0); - transition: transform 0.3s ease, background-color 0.5s ease; + background-color: var(--background-color-primary); + top: calc(var(--element-size) * 0.07); + left: calc(var(--element-size) * 0.07); + height: calc(var(--element-size) * 0.4); + width: calc(var(--element-size) * 0.4); + transform: translateX(0); + transition: transform 0.3s ease, background-color 0.5s ease; } .switch-toggle-checked { - transform: translateX(calc(var(--element-size) * 0.6)) !important; + transform: translateX(calc(var(--element-size) * 0.6)) !important; } </style> diff --git a/components/certif/List.vue b/components/certif/List.vue index f409b6e..b072885 100644 --- a/components/certif/List.vue +++ b/components/certif/List.vue @@ -1,154 +1,241 @@ <template> - <div class="table-responsive"> - <table class="table table-striped table-hover" v-if="certifsPending.length > 0"> - <tbody> - <tr v-for="certif in certifsPending" :key="getNeighbor(certif).uid + certif.expires_on" - @click="$router.push(localePath({name:'membres-hash', params: {hash: getNeighbor(certif).hash}}))"> - <th scope="row" class="py-1"> - <div> - {{ getNeighbor(certif).uid }} - <BadgeCertifStatus :limitDate="getNeighbor(certif).received_certifications.limit" :memberStatus="getNeighbor(certif).status" /> - <BadgeQuality :quality="getNeighbor(certif).quality.ratio" v-if="getNeighbor(certif).status != 'REVOKED'" /> - </div> - <div> - <BadgeStatus :membre="getNeighbor(certif)" /> - <BadgeDispo :isDispo="getNeighbor(certif).minDatePassed" :dateDispo="getNeighbor(certif).minDate" v-if="getNeighbor(certif).status == 'MEMBER'" /> - </div> - </th> - <td class="text-right py-1"> - <small><span class="badge" :class="'badge-'+ $options.filters.dateStatus(certif.expires_on)">{{ $d(new Date(certif.expires_on*1000), 'short') }}</span></small> - <small class="d-block"><span class="badge badge-secondary">{{ $t('traitement') }}</span></small> - </td> - </tr> - </tbody> - </table> - <hr v-if="(certifsPending.length > 0) && (certifsTriees.length > 0)" /> - <table class="table table-striped table-hover" v-if="certifsTriees.length > 0"> - <thead> - <th @click="sort('uid')"> - {{ $t('membres') }} - <div class="d-inline-block position-absolute ml-2"> - <div class="up" :class="{ - 'sorted' : currentSortDir == 'desc' && currentSort == 'uid', - 'invisible' : currentSortDir == 'asc' && currentSort == 'uid' - }">â–²</div> - <div class="down" :class="{ - 'sorted' : currentSortDir == 'asc' && currentSort == 'uid', - 'invisible' : currentSortDir == 'desc' && currentSort == 'uid' - }">â–¼</div> - </div> - </th> - <th @click="sort('expires_on')"> - {{ $t('expire') }} - <div class="d-inline-block position-absolute ml-2"> - <div class="up" :class="{ - 'sorted' : currentSortDir == 'desc' && currentSort == 'expires_on', - 'invisible' : currentSortDir == 'asc' && currentSort == 'expires_on' - }">â–²</div> - <div class="down" :class="{ - 'sorted' : currentSortDir == 'asc' && currentSort == 'expires_on', - 'invisible' : currentSortDir == 'desc' && currentSort == 'expires_on' - }">â–¼</div> - </div> - </th> - </thead> - <tbody> - <tr v-for="certif in certifsTriees" :key="getNeighbor(certif).uid + certif.expires_on" - @click="$router.push(localePath({name:'membres-hash', params: {hash: getNeighbor(certif).hash}}))"> - <th scope="row" class="py-1"> - <div> - {{ getNeighbor(certif).uid }} - <BadgeCertifStatus :limitDate="getNeighbor(certif).received_certifications.limit" :memberStatus="getNeighbor(certif).status" /> - <BadgeQuality :quality="getNeighbor(certif).quality.ratio" v-if="getNeighbor(certif).status != 'REVOKED'" /> - </div> - <div> - <BadgeStatus :membre="getNeighbor(certif)" /> - <BadgeDispo :isDispo="getNeighbor(certif).minDatePassed" :dateDispo="getNeighbor(certif).minDate" v-if="getNeighbor(certif).status == 'MEMBER'" /> - </div> - </th> - <td class="text-right py-1"> - <small><span class="badge" :class="'badge-'+ $options.filters.dateStatus(certif.expires_on)">{{ $d(new Date(certif.expires_on*1000), 'long') }}</span></small> - </td> - </tr> - </tbody> - </table> - </div> + <div class="table-responsive"> + <table + class="table table-striped table-hover" + v-if="certifsPending.length > 0"> + <tbody> + <tr + v-for="certif in certifsPending" + :key="getNeighbor(certif).uid + certif.expires_on" + @click=" + $router.push( + localePath({ + name: 'membres-hash', + params: { hash: getNeighbor(certif).hash } + }) + ) + "> + <th scope="row" class="py-1"> + <div> + {{ getNeighbor(certif).uid }} + <BadgeCertifStatus + :limitDate="getNeighbor(certif).received_certifications.limit" + :memberStatus="getNeighbor(certif).status" /> + <BadgeQuality + :quality="getNeighbor(certif).quality.ratio" + v-if="getNeighbor(certif).status != 'REVOKED'" /> + </div> + <div> + <BadgeStatus :membre="getNeighbor(certif)" /> + <BadgeDispo + :isDispo="getNeighbor(certif).minDatePassed" + :dateDispo="getNeighbor(certif).minDate" + v-if="getNeighbor(certif).status == 'MEMBER'" /> + </div> + </th> + <td class="text-right py-1"> + <small + ><span + class="badge" + :class=" + 'badge-' + $options.filters.dateStatus(certif.expires_on) + " + >{{ $d(new Date(certif.expires_on * 1000), "short") }}</span + ></small + > + <small class="d-block" + ><span class="badge badge-secondary">{{ + $t("traitement") + }}</span></small + > + </td> + </tr> + </tbody> + </table> + <hr v-if="certifsPending.length > 0 && certifsTriees.length > 0" /> + <table + class="table table-striped table-hover" + v-if="certifsTriees.length > 0"> + <thead> + <th @click="sort('uid')"> + {{ $t("membres") }} + <div class="d-inline-block position-absolute ml-2"> + <div + class="up" + :class="{ + sorted: currentSortDir == 'desc' && currentSort == 'uid', + invisible: currentSortDir == 'asc' && currentSort == 'uid' + }"> + â–² + </div> + <div + class="down" + :class="{ + sorted: currentSortDir == 'asc' && currentSort == 'uid', + invisible: currentSortDir == 'desc' && currentSort == 'uid' + }"> + â–¼ + </div> + </div> + </th> + <th @click="sort('expires_on')"> + {{ $t("expire") }} + <div class="d-inline-block position-absolute ml-2"> + <div + class="up" + :class="{ + sorted: currentSortDir == 'desc' && currentSort == 'expires_on', + invisible: + currentSortDir == 'asc' && currentSort == 'expires_on' + }"> + â–² + </div> + <div + class="down" + :class="{ + sorted: currentSortDir == 'asc' && currentSort == 'expires_on', + invisible: + currentSortDir == 'desc' && currentSort == 'expires_on' + }"> + â–¼ + </div> + </div> + </th> + </thead> + <tbody> + <tr + v-for="certif in certifsTriees" + :key="getNeighbor(certif).uid + certif.expires_on" + @click=" + $router.push( + localePath({ + name: 'membres-hash', + params: { hash: getNeighbor(certif).hash } + }) + ) + "> + <th scope="row" class="py-1"> + <div> + {{ getNeighbor(certif).uid }} + <BadgeCertifStatus + :limitDate="getNeighbor(certif).received_certifications.limit" + :memberStatus="getNeighbor(certif).status" /> + <BadgeQuality + :quality="getNeighbor(certif).quality.ratio" + v-if="getNeighbor(certif).status != 'REVOKED'" /> + </div> + <div> + <BadgeStatus :membre="getNeighbor(certif)" /> + <BadgeDispo + :isDispo="getNeighbor(certif).minDatePassed" + :dateDispo="getNeighbor(certif).minDate" + v-if="getNeighbor(certif).status == 'MEMBER'" /> + </div> + </th> + <td class="text-right py-1"> + <small + ><span + class="badge" + :class=" + 'badge-' + $options.filters.dateStatus(certif.expires_on) + " + >{{ $d(new Date(certif.expires_on * 1000), "long") }}</span + ></small + > + </td> + </tr> + </tbody> + </table> + </div> </template> <script> export default { - data() { - return { - currentSort:'expires_on', - currentSortDir:'asc' - } - }, - props : { - certifs : Array, - type : { - type: String, - required: true, - validator: function (value) { - const types = ['received','sent'] - return types.indexOf(value) !== -1 - } - } - }, - methods : { - getNeighbor(certif) { - return this.type == "received" ? certif.from : certif.to - }, - sort(s) { - if(s === this.currentSort) { - this.currentSortDir = this.currentSortDir==='asc'?'desc':'asc'; - } - this.currentSort = s; - } - }, - computed : { - certifsTriees() { - return this.certifs.slice().sort((a, b) => { - let modifier = this.currentSortDir === 'desc' ? -1 : 1 - let sens = this.type == 'received' ? "from" : "to" + data() { + return { + currentSort: "expires_on", + currentSortDir: "asc" + } + }, + props: { + certifs: Array, + type: { + type: String, + required: true, + validator: function (value) { + const types = ["received", "sent"] + return types.indexOf(value) !== -1 + } + } + }, + methods: { + getNeighbor(certif) { + return this.type == "received" ? certif.from : certif.to + }, + sort(s) { + if (s === this.currentSort) { + this.currentSortDir = this.currentSortDir === "asc" ? "desc" : "asc" + } + this.currentSort = s + } + }, + computed: { + certifsTriees() { + return this.certifs + .slice() + .sort((a, b) => { + let modifier = this.currentSortDir === "desc" ? -1 : 1 + let sens = this.type == "received" ? "from" : "to" - if (this.currentSort == 'expires_on') { - if(a['expires_on'] < b['expires_on']) return -1 * modifier - if(a['expires_on'] > b['expires_on']) return 1 * modifier - } else { - if(a[sens]['uid'].toLowerCase() < b[sens]['uid'].toLowerCase()) return -1 * modifier - if(a[sens]['uid'].toLowerCase() > b[sens]['uid'].toLowerCase()) return 1 * modifier - } + if (this.currentSort == "expires_on") { + if (a["expires_on"] < b["expires_on"]) return -1 * modifier + if (a["expires_on"] > b["expires_on"]) return 1 * modifier + } else { + if (a[sens]["uid"].toLowerCase() < b[sens]["uid"].toLowerCase()) + return -1 * modifier + if (a[sens]["uid"].toLowerCase() > b[sens]["uid"].toLowerCase()) + return 1 * modifier + } - return 0 - }).filter((el) => {return el.pending == false}) - }, - certifsPending() { - return this.certifs.slice().sort((a, b) => a.expires_on - b.expires_on).filter((el) => {return el.pending == true}) - } - } + return 0 + }) + .filter((el) => { + return el.pending == false + }) + }, + certifsPending() { + return this.certifs + .slice() + .sort((a, b) => a.expires_on - b.expires_on) + .filter((el) => { + return el.pending == true + }) + } + } } </script> <style lang="scss" scoped> thead th { - position: relative; - cursor:pointer; - background: var(--background-color-secondary); + position: relative; + cursor: pointer; + background: var(--background-color-secondary); - &:last-child { - padding-right: 1.5rem; - text-align: right; - } + &:last-child { + padding-right: 1.5rem; + text-align: right; + } } -.up, .down { - line-height: 10px; - font-size: 1.1rem; - transform: scale(1.5,1); - opacity: .3; +.up, +.down { + line-height: 10px; + font-size: 1.1rem; + transform: scale(1.5, 1); + opacity: 0.3; } .sorted { - opacity: 1; + opacity: 1; } -</style> \ No newline at end of file +</style> diff --git a/components/member/Card.vue b/components/member/Card.vue index 973b6bf..df50275 100644 --- a/components/member/Card.vue +++ b/components/member/Card.vue @@ -1,91 +1,159 @@ <template> -<div class="card member"> - <div class="card-body"> - <h2 class="card-title text-center"> - {{ hash.uid }} - <BadgeStatus :membre="hash" /> - </h2> - <BtnClipboard :textContent="this.hash.pubkey" /> - <div class="table-responsive"> - <table class="table table-sm table-borderless" v-if="hash.status != 'REVOKED'"> - <tbody> - <tr v-if="hash.status == 'MEMBER'"> - <th scope="row">{{ $t('membre.referent') }} :</th> - <td :class="{'list-group-item-success': hash.sentry, 'list-group-item-warning': !hash.sentry}">{{ hash.sentry ? $t('oui') : $t('non') }}</td> - </tr> - <tr v-if="hash.status != 'NEWCOMER'"> - <th scope="row">{{ $t('membre.qualite') }} :</th> - <td :class="{ - 'list-group-item-success': hash.quality.ratio >= 80, - 'list-group-item-warning': hash.quality.ratio < 80, - }">{{ Math.round(hash.quality.ratio*100)/100 }}</td> - </tr> - <tr> - <th scope="row">{{ $t('membre.distance') }} :</th> - <td :class="{ - 'list-group-item-success': hash.status != 'NEWCOMER' ? hash.distance.dist_ok : hash.distanceE.dist_ok, - 'list-group-item-danger': hash.status != 'NEWCOMER' ? !hash.distance.dist_ok : !hash.distanceE.dist_ok, - }">{{ hash.status != 'NEWCOMER' ? Math.round(hash.distance.value.ratio*100)/100 : Math.round(hash.distanceE.value.ratio*100)/100 }}</td> - </tr> - <tr> - <th scope="row">{{ hash.status != 'MISSING' ? $t('membre.datelimadhesion') : $t('membre.datelimrevoc')}} :</th> - <td :class="hash.status != 'MISSING' ? 'list-group-item-'+ $options.filters.dateStatus(hash.limitDate) : 'list-group-item-danger'">{{ $d(new Date(hash.limitDate*1000), 'long') }}</td> - </tr> - <tr v-if="hash.status == 'MEMBER'"> - <th scope="row">{{ $t('membre.datemanquecertifs') }} :</th> - <td :class="'list-group-item-'+ $options.filters.dateStatus(hash.received_certifications.limit)">{{ $d(new Date(hash.received_certifications.limit*1000), 'long') }}</td> - </tr> - <tr v-if="hash.status == 'MEMBER'"> - <th scope="row">{{ $t('membre.dispocertif') }} :</th> - <td :class="{ - 'list-group-item-success': hash.minDatePassed, - 'list-group-item-danger': !hash.minDatePassed, - }">{{ hash.minDatePassed ? $t('oui') : $t('non') }} <small v-if="!hash.minDatePassed">( > {{ $d(new Date(hash.minDate*1000), 'long') }} )</small></td> - </tr> - <tr v-if="hash.status == 'MEMBER'"> - <th scope="row">{{ $t('membre.nb_certifs') }} :</th> - <td :class="{ - 'list-group-item-success': hash.sent_certifications.length<=80, - 'list-group-item-warning': hash.sent_certifications.length>80, - 'list-group-item-danger': hash.sent_certifications.length>90, - }">{{ 100-hash.sent_certifications.length }}</td> - </tr> - </tbody> - </table> - </div> - </div> -</div> + <div class="card member"> + <div class="card-body"> + <h2 class="card-title text-center"> + {{ hash.uid }} + <BadgeStatus :membre="hash" /> + </h2> + <BtnClipboard :textContent="this.hash.pubkey" /> + <div class="table-responsive"> + <table + class="table table-sm table-borderless" + v-if="hash.status != 'REVOKED'"> + <tbody> + <tr v-if="hash.status == 'MEMBER'"> + <th scope="row">{{ $t("membre.referent") }} :</th> + <td + :class="{ + 'list-group-item-success': hash.sentry, + 'list-group-item-warning': !hash.sentry + }"> + {{ hash.sentry ? $t("oui") : $t("non") }} + </td> + </tr> + <tr v-if="hash.status != 'NEWCOMER'"> + <th scope="row">{{ $t("membre.qualite") }} :</th> + <td + :class="{ + 'list-group-item-success': hash.quality.ratio >= 80, + 'list-group-item-warning': hash.quality.ratio < 80 + }"> + {{ Math.round(hash.quality.ratio * 100) / 100 }} + </td> + </tr> + <tr> + <th scope="row">{{ $t("membre.distance") }} :</th> + <td + :class="{ + 'list-group-item-success': + hash.status != 'NEWCOMER' + ? hash.distance.dist_ok + : hash.distanceE.dist_ok, + 'list-group-item-danger': + hash.status != 'NEWCOMER' + ? !hash.distance.dist_ok + : !hash.distanceE.dist_ok + }"> + {{ + hash.status != "NEWCOMER" + ? Math.round(hash.distance.value.ratio * 100) / 100 + : Math.round(hash.distanceE.value.ratio * 100) / 100 + }} + </td> + </tr> + <tr> + <th scope="row"> + {{ + hash.status != "MISSING" + ? $t("membre.datelimadhesion") + : $t("membre.datelimrevoc") + }} : + </th> + <td + :class=" + hash.status != 'MISSING' + ? 'list-group-item-' + + $options.filters.dateStatus(hash.limitDate) + : 'list-group-item-danger' + "> + {{ $d(new Date(hash.limitDate * 1000), "long") }} + </td> + </tr> + <tr v-if="hash.status == 'MEMBER'"> + <th scope="row">{{ $t("membre.datemanquecertifs") }} :</th> + <td + :class=" + 'list-group-item-' + + $options.filters.dateStatus( + hash.received_certifications.limit + ) + "> + {{ + $d( + new Date(hash.received_certifications.limit * 1000), + "long" + ) + }} + </td> + </tr> + <tr v-if="hash.status == 'MEMBER'"> + <th scope="row">{{ $t("membre.dispocertif") }} :</th> + <td + :class="{ + 'list-group-item-success': hash.minDatePassed, + 'list-group-item-danger': !hash.minDatePassed + }"> + {{ hash.minDatePassed ? $t("oui") : $t("non") }} + <small v-if="!hash.minDatePassed" + >( > {{ $d(new Date(hash.minDate * 1000), "long") }} )</small + > + </td> + </tr> + <tr v-if="hash.status == 'MEMBER'"> + <th scope="row">{{ $t("membre.nb_certifs") }} :</th> + <td + :class="{ + 'list-group-item-success': + hash.sent_certifications.length <= 80, + 'list-group-item-warning': + hash.sent_certifications.length > 80, + 'list-group-item-danger': hash.sent_certifications.length > 90 + }"> + {{ 100 - hash.sent_certifications.length }} + </td> + </tr> + </tbody> + </table> + </div> + </div> + </div> </template> <script> export default { - props: { - hash: Object - } + props: { + hash: Object + } } </script> <style lang="scss"> .member { - .table { - text-align: center; - width: auto; - margin: auto; + .table { + text-align: center; + width: auto; + margin: auto; - tr { - display: flex; - flex-direction: column; - } - } + tr { + display: flex; + flex-direction: column; + } + } } -@media (min-width:576px) { - .member { - .table { - tr {display: table-row;} - th {text-align: right;} - td {text-align: left;} - } - } +@media (min-width: 576px) { + .member { + .table { + tr { + display: table-row; + } + th { + text-align: right; + } + td { + text-align: left; + } + } + } } -</style> \ No newline at end of file +</style> diff --git a/components/member/List.vue b/components/member/List.vue index 5541d3d..3e6814d 100644 --- a/components/member/List.vue +++ b/components/member/List.vue @@ -1,47 +1,57 @@ <template> - <div class="table-responsive"> - <table class="table table-striped table-hover"> - <thead v-if="displayHead"> - <tr> - <th scope="col">UID</th> - <th scope="col" class="d-none d-xl-table-cell" v-if="displayPubkey">PUBKEY</th> - </tr> - </thead> - <tbody> - <tr v-for="member in members" :key="member.uid" - @click="redirect(member.hash)"> - <th scope="row"> - {{ member.uid }} - <BadgeCertifStatus :limitDate="member.received_certifications.limit" :memberStatus="member.status" /> - <BadgeStatus :membre="member" /> - </th> - <td class="d-none d-xl-table-cell" v-if="displayPubkey">{{ member.pubkey }}</td> - </tr> - </tbody> - </table> - </div> + <div class="table-responsive"> + <table class="table table-striped table-hover"> + <thead v-if="displayHead"> + <tr> + <th scope="col">UID</th> + <th scope="col" class="d-none d-xl-table-cell" v-if="displayPubkey"> + PUBKEY + </th> + </tr> + </thead> + <tbody> + <tr + v-for="member in members" + :key="member.uid" + @click="redirect(member.hash)"> + <th scope="row"> + {{ member.uid }} + <BadgeCertifStatus + :limitDate="member.received_certifications.limit" + :memberStatus="member.status" /> + <BadgeStatus :membre="member" /> + </th> + <td class="d-none d-xl-table-cell" v-if="displayPubkey"> + {{ member.pubkey }} + </td> + </tr> + </tbody> + </table> + </div> </template> <script> export default { - props: { - members: { - type: Array, - required: true - }, - displayPubkey: { - type: Boolean, - default: true - }, - displayHead: { - type: Boolean, - default: true - } - }, - methods: { - redirect(hash) { - this.$router.push(this.localePath({name:'membres-hash', params: {hash}})) - } - }, + props: { + members: { + type: Array, + required: true + }, + displayPubkey: { + type: Boolean, + default: true + }, + displayHead: { + type: Boolean, + default: true + } + }, + methods: { + redirect(hash) { + this.$router.push( + this.localePath({ name: "membres-hash", params: { hash } }) + ) + } + } } -</script> \ No newline at end of file +</script> diff --git a/components/navigation/Bar.vue b/components/navigation/Bar.vue index d83bd37..8a22db9 100644 --- a/components/navigation/Bar.vue +++ b/components/navigation/Bar.vue @@ -1,231 +1,239 @@ <template> - <header class="header position-fixed"> - <div class="position-relative"> - <button class="toggle btn border-secondary position-absolute p-1 m-1 ml-3" @click="toggleMenu"><span></span></button> - <NavigationBreadcrumb :breadcrumb="breadcrumb" /> - </div> - <NavigationMenuSidebar @toggleMenu="toggleMenu" :menus="menus" /> - <div class="bg_overlay position-fixed" @click="toggleMenu"></div> - </header> + <header class="header position-fixed"> + <div class="position-relative"> + <button + class="toggle btn border-secondary position-absolute p-1 m-1 ml-3" + @click="toggleMenu"> + <span></span> + </button> + <NavigationBreadcrumb :breadcrumb="breadcrumb" /> + </div> + <NavigationMenuSidebar @toggleMenu="toggleMenu" :menus="menus" /> + <div class="bg_overlay position-fixed" @click="toggleMenu"></div> + </header> </template> <script> export default { - data() { - return { - isOpen: false - } - }, - props: { - breadcrumb: Array, - menus: Array - }, - methods: { - toggleMenu() { - document.querySelector('.app').classList.toggle('open') - console.log(this.isOpen) - - this.isOpen = !this.isOpen - console.log(this.isOpen) - - localStorage.setItem("menu-open", this.isOpen) - } - }, - mounted() { - this.isOpen = (localStorage.getItem("menu-open") == "true") - if (this.isOpen) { - document.querySelector('.app').classList.add('open') - } - } + data() { + return { + isOpen: false + } + }, + props: { + breadcrumb: Array, + menus: Array + }, + methods: { + toggleMenu() { + document.querySelector(".app").classList.toggle("open") + console.log(this.isOpen) + + this.isOpen = !this.isOpen + console.log(this.isOpen) + + localStorage.setItem("menu-open", this.isOpen) + } + }, + mounted() { + this.isOpen = localStorage.getItem("menu-open") == "true" + if (this.isOpen) { + document.querySelector(".app").classList.add("open") + } + } } - </script> <style lang="scss"> $btn-width: 50px; .header { - --menu-width: 0px; - width: 100%; - z-index: 100; - background: var(--background-color-primary); - transition: width .5s ease-in-out; - - .open & { - --menu-width: 320px; - } - - @media (min-width:1200px) { - width: calc(99vw - var(--menu-width)); - } + --menu-width: 0px; + width: 100%; + z-index: 100; + background: var(--background-color-primary); + transition: width 0.5s ease-in-out; + + .open & { + --menu-width: 320px; + } + + @media (min-width: 1200px) { + width: calc(99vw - var(--menu-width)); + } } nav.breadcrumb-wrapper { - margin: 8px 15px 8px 80px; - display: flex; - flex-direction: column; - gap: 1rem; - background: var(--background-color-secondary); - - a {color: var(--text-primary-color)} - - .breadcrumb-item.active { - opacity: .7; - } - - @media (min-width:768px) { - flex-direction: row; - justify-content: space-between; - align-items: center; - } + margin: 8px 15px 8px 80px; + display: flex; + flex-direction: column; + gap: 1rem; + background: var(--background-color-secondary); + + a { + color: var(--text-primary-color); + } + + .breadcrumb-item.active { + opacity: 0.7; + } + + @media (min-width: 768px) { + flex-direction: row; + justify-content: space-between; + align-items: center; + } } %hamburger-line { - display: block; - height: 4px; - width: .8 * $btn-width; - background: var(--text-primary-color); - content: ""; - position: absolute; - transition-property: transform; - border-radius: 4px; + display: block; + height: 4px; + width: 0.8 * $btn-width; + background: var(--text-primary-color); + content: ""; + position: absolute; + transition-property: transform; + border-radius: 4px; } .toggle { - height: $btn-width; - width: $btn-width; - line-height: $btn-width; - - span { - @extend %hamburger-line; - top: 50%; - transform: translateY(-50%); - transition-timing-function: cubic-bezier(.55,.055,.675,.19); - transition-duration: 75ms; - - .open & { - transform: rotate(45deg); - display: block; - margin-top: -2px; - } - - &::before { - transition: top 75ms ease .12s,opacity 75ms ease; - @extend %hamburger-line; - top: -10px; - - .open & { - opacity: 0; - } - } - - &::after { - transition: bottom 75ms ease .12s,transform 75ms cubic-bezier(.55,.055,.675,.19); - @extend %hamburger-line; - bottom: -10px; - - .open & { - top: 0; - transform: rotate(-90deg); - } - } - } + height: $btn-width; + width: $btn-width; + line-height: $btn-width; + + span { + @extend %hamburger-line; + top: 50%; + transform: translateY(-50%); + transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + transition-duration: 75ms; + + .open & { + transform: rotate(45deg); + display: block; + margin-top: -2px; + } + + &::before { + transition: top 75ms ease 0.12s, opacity 75ms ease; + @extend %hamburger-line; + top: -10px; + + .open & { + opacity: 0; + } + } + + &::after { + transition: bottom 75ms ease 0.12s, + transform 75ms cubic-bezier(0.55, 0.055, 0.675, 0.19); + @extend %hamburger-line; + bottom: -10px; + + .open & { + top: 0; + transform: rotate(-90deg); + } + } + } } .menu { - background: var(--background-color-primary); - width: var(--menu-size); - top: 0; - z-index: 1200; - height: 100vh; - padding: 1.1rem 0.5rem; - overflow-y: scroll; - scrollbar-color: #6969dd #e0e0e0; - scrollbar-width: thin; - transition: left .5s ease-in-out; - left: -400px; - - h1 {color: var(--text-primary-color);} - - .list-group-item { - &-action:not(.active) { - background: transparent; - - &:hover { - background: rgba(0, 0, 255, 0.075); - color: var(--text-primary-color); - } - } - - div { - transition: left .3s ease-in-out; - left: 0; - - &::before { - content: "›"; - position: relative; - left: -.5em; - } - - &:hover { - left: .5em; - } - } - } - - .open & { - left: 0; - } - - .close { - --size: 50px; - width: var(--size); - height: var(--size); - top: .8rem; - right: 0; - font-size: 2rem; - } - - h2 { - cursor: default; - } + background: var(--background-color-primary); + width: var(--menu-size); + top: 0; + z-index: 1200; + height: 100vh; + padding: 1.1rem 0.5rem; + overflow-y: scroll; + scrollbar-color: #6969dd #e0e0e0; + scrollbar-width: thin; + transition: left 0.5s ease-in-out; + left: -400px; + + h1 { + color: var(--text-primary-color); + } + + .list-group-item { + &-action:not(.active) { + background: transparent; + + &:hover { + background: rgba(0, 0, 255, 0.075); + color: var(--text-primary-color); + } + } + + div { + transition: left 0.3s ease-in-out; + left: 0; + + &::before { + content: "›"; + position: relative; + left: -0.5em; + } + + &:hover { + left: 0.5em; + } + } + } + + .open & { + left: 0; + } + + .close { + --size: 50px; + width: var(--size); + height: var(--size); + top: 0.8rem; + right: 0; + font-size: 2rem; + } + + h2 { + cursor: default; + } } .bg_overlay { - top: 0; - left: 0; - right: 0; - height: 120vh; - z-index: 1100; - visibility: hidden; - opacity: 0; - transition: all .5s ease; - background-color: rgba(34,41,47,.5); - - .open & { - opacity: 1; - visibility: visible; - } + top: 0; + left: 0; + right: 0; + height: 120vh; + z-index: 1100; + visibility: hidden; + opacity: 0; + transition: all 0.5s ease; + background-color: rgba(34, 41, 47, 0.5); + + .open & { + opacity: 1; + visibility: visible; + } } .logo { - max-width: 75px; + max-width: 75px; } -@media (min-width:1200px) { - .open { - &.app { - margin-left: var(--menu-size); - } - - .menu { - left: 0; - } - - .bg_overlay { - visibility: hidden; - opacity: 0; - } - } +@media (min-width: 1200px) { + .open { + &.app { + margin-left: var(--menu-size); + } + + .menu { + left: 0; + } + + .bg_overlay { + visibility: hidden; + opacity: 0; + } + } } </style> diff --git a/components/navigation/Breadcrumb.vue b/components/navigation/Breadcrumb.vue index 30f678a..db0b14d 100644 --- a/components/navigation/Breadcrumb.vue +++ b/components/navigation/Breadcrumb.vue @@ -1,22 +1,29 @@ <template> - <nav aria-label="Fil d'Ariane" class="breadcrumb-wrapper rounded p-3"> - <ol class="breadcrumb m-0 p-0"> - <li class="breadcrumb-item" :class="{ 'active': item.active }" :aria-current="item.active ? 'page' : null" v-for="item in breadcrumb" :key="item.text"> - <NuxtLink :to="localePath(item.to)" v-if="item.to">{{ item.text }}</NuxtLink> - <span v-else>{{ item.text }}</span> - </li> - </ol> - <div class="d-flex justify-content-between align-items-center"> - <NavigationLanguage class="mr-3" /> - <BtnTheme /> - </div> - </nav> + <nav aria-label="Fil d'Ariane" class="breadcrumb-wrapper rounded p-3"> + <ol class="breadcrumb m-0 p-0"> + <li + class="breadcrumb-item" + :class="{ active: item.active }" + :aria-current="item.active ? 'page' : null" + v-for="item in breadcrumb" + :key="item.text"> + <NuxtLink :to="localePath(item.to)" v-if="item.to">{{ + item.text + }}</NuxtLink> + <span v-else>{{ item.text }}</span> + </li> + </ol> + <div class="d-flex justify-content-between align-items-center"> + <NavigationLanguage class="mr-3" /> + <BtnTheme /> + </div> + </nav> </template> <script> export default { - props: { - breadcrumb: Array - } + props: { + breadcrumb: Array + } } -</script> \ No newline at end of file +</script> diff --git a/components/navigation/Language.vue b/components/navigation/Language.vue index 2e968ba..ab88bb4 100644 --- a/components/navigation/Language.vue +++ b/components/navigation/Language.vue @@ -1,19 +1,24 @@ <template> -<div> - <select class="form-control" @change="saveLocale($event)" v-model="$i18n.locale"> - <option v-for="lang in $i18n.locales" :key="lang.code" :value="lang.code">{{ lang.name }}</option> - </select> -</div> + <div> + <select + class="form-control" + @change="saveLocale($event)" + v-model="$i18n.locale"> + <option v-for="lang in $i18n.locales" :key="lang.code" :value="lang.code"> + {{ lang.name }} + </option> + </select> + </div> </template> <script> export default { - methods: { - saveLocale(e) { - this.$i18n.locale = e.target.value - this.$i18n.setLocaleCookie(e.target.value) - this.$router.push(this.switchLocalePath(e.target.value)) - } - } + methods: { + saveLocale(e) { + this.$i18n.locale = e.target.value + this.$i18n.setLocaleCookie(e.target.value) + this.$router.push(this.switchLocalePath(e.target.value)) + } + } } -</script> \ No newline at end of file +</script> diff --git a/components/navigation/Loader.vue b/components/navigation/Loader.vue index 1e99a26..50314b6 100644 --- a/components/navigation/Loader.vue +++ b/components/navigation/Loader.vue @@ -1,24 +1,28 @@ <template> -<transition name="fade"> - <div class="loader overflow-hidden text-center position-absolute" v-if="isLoading"> - <img src="~@/assets/img/loader.gif"> - <div class="text-center font-weight-bold my-3">{{ $t('chargement') }}...</div> - </div> -</transition> + <transition name="fade"> + <div + class="loader overflow-hidden text-center position-absolute" + v-if="isLoading"> + <img src="~@/assets/img/loader.gif" /> + <div class="text-center font-weight-bold my-3"> + {{ $t("chargement") }}... + </div> + </div> + </transition> </template> <script> export default { - props: {isLoading: Boolean} + props: { isLoading: Boolean } } </script> <style lang="scss"> .loader { - z-index: 50; - left: 50%; - transform: translateX(-50%); - --color: #391855; - color: var(--text-primary-color); + z-index: 50; + left: 50%; + transform: translateX(-50%); + --color: #391855; + color: var(--text-primary-color); } -</style> \ No newline at end of file +</style> diff --git a/components/navigation/menu/Group.vue b/components/navigation/menu/Group.vue index 59b285b..e6fe0a7 100644 --- a/components/navigation/menu/Group.vue +++ b/components/navigation/menu/Group.vue @@ -1,18 +1,24 @@ <template> - <div class="mb-4"> - <h2 class="small text-muted text-uppercase ml-4 mb-2 pb-3 border-bottom">{{ $t(menu.title) }}</h2> - <div class="nav navbar-nav list-group list-group-flush"> - <NuxtLink class="list-group-item list-group-item-action p-0 pl-3" :to="localePath(item.path)" v-for="item in menu.items" :key="item.path"> - <div class="position-relative py-3">{{ $t(item.title) }}</div> - </NuxtLink> - </div> - </div> + <div class="mb-4"> + <h2 class="small text-muted text-uppercase ml-4 mb-2 pb-3 border-bottom"> + {{ $t(menu.title) }} + </h2> + <div class="nav navbar-nav list-group list-group-flush"> + <NuxtLink + class="list-group-item list-group-item-action p-0 pl-3" + :to="localePath(item.path)" + v-for="item in menu.items" + :key="item.path"> + <div class="position-relative py-3">{{ $t(item.title) }}</div> + </NuxtLink> + </div> + </div> </template> <script> export default { - props: { - menu: Object - } + props: { + menu: Object + } } -</script> \ No newline at end of file +</script> diff --git a/components/navigation/menu/Sidebar.vue b/components/navigation/menu/Sidebar.vue index 2b837b1..0a3974f 100644 --- a/components/navigation/menu/Sidebar.vue +++ b/components/navigation/menu/Sidebar.vue @@ -1,41 +1,59 @@ <template> - <aside class="menu shadow position-fixed"> - <div class="nav_header pb-3 mb-4"> - <nuxt-link :to="localePath('/')" class="d-flex"> - <img src="@/assets/img/logo.png" alt="Accueil" class="logo"> - <div><h1 class="h2">Wotwizard</h1><small class="text-muted">{{ $t('slogan') }}</small></div> - </nuxt-link> - <div class="d-flex text-info justify-content-between align-items-baseline mt-3 mx-2"> - <div class="">v0.02</div> - <div class="small" v-if="countMax">Bloc n°<span class="font-weight-bold">{{ countMax.number }}</span> ({{ $d(new Date(countMax.utc0*1000), 'short') }} {{ $t('time.a') }} {{ $d(new Date(countMax.utc0*1000), 'time') }})</div> - </div> - <button type="button" class="close position-absolute d-xl-none" aria-label="Close" @click="toggleMenu"> - <span aria-hidden="true">×</span> - </button> - </div> - <nav> - <NavigationMenuGroup v-for="menu in menus" :key="menu.title" :menu="menu"/> - </nav> - </aside> + <aside class="menu shadow position-fixed"> + <div class="nav_header pb-3 mb-4"> + <nuxt-link :to="localePath('/')" class="d-flex"> + <img src="@/assets/img/logo.png" alt="Accueil" class="logo" /> + <div> + <h1 class="h2">Wotwizard</h1> + <small class="text-muted">{{ $t("slogan") }}</small> + </div> + </nuxt-link> + <div + class="d-flex text-info justify-content-between align-items-baseline mt-3 mx-2"> + <div class="">v0.02</div> + <div class="small" v-if="countMax"> + Bloc n°<span class="font-weight-bold">{{ countMax.number }}</span> ({{ + $d(new Date(countMax.utc0 * 1000), "short") + }} + {{ $t("time.a") }} {{ $d(new Date(countMax.utc0 * 1000), "time") }}) + </div> + </div> + <button + type="button" + class="close position-absolute d-xl-none" + aria-label="Close" + @click="toggleMenu"> + <span aria-hidden="true">×</span> + </button> + </div> + <nav> + <NavigationMenuGroup + v-for="menu in menus" + :key="menu.title" + :menu="menu" /> + </nav> + </aside> </template> <script> -import {LAST_BLOCK} from '@/graphql/queries.js' +import { LAST_BLOCK } from "@/graphql/queries.js" export default { - props: { - menus: Array - }, - methods: { - toggleMenu() { - this.$emit('toggleMenu') - } - }, - apollo: { - countMax : { - query: LAST_BLOCK, - error (err) {this.error = err.message} - } - }, + props: { + menus: Array + }, + methods: { + toggleMenu() { + this.$emit("toggleMenu") + } + }, + apollo: { + countMax: { + query: LAST_BLOCK, + error(err) { + this.error = err.message + } + } + } } -</script> \ No newline at end of file +</script> diff --git a/graphql/cache.js b/graphql/cache.js index a8035d3..21055e0 100644 --- a/graphql/cache.js +++ b/graphql/cache.js @@ -3,19 +3,19 @@ import introspectionQueryResultData from './fragmentTypes.json'; const fragmentMatcher = new IntrospectionFragmentMatcher({ introspectionQueryResultData - }) +}) - // Apparemment il faut utiliser la syntaxe Apollo v2 +// Apparemment il faut utiliser la syntaxe Apollo v2 export const cache = new InMemoryCache({ addTypename: false, fragmentMatcher, dataIdFromObject: object => { switch (object.__typename) { - case 'Identity': return object.hash - case 'Event': return object.block.number - case 'EventId': return `${object.member.hash}:${object.inOut}` - case 'Forecast': return `${object.member.hash}:${object.date}:${object.after}:${object.proba}` - default: return defaultDataIdFromObject(object); // fall back to default handling + case 'Identity': return object.hash + case 'Event': return object.block.number + case 'EventId': return `${object.member.hash}:${object.inOut}` + case 'Forecast': return `${object.member.hash}:${object.date}:${object.after}:${object.proba}` + default: return defaultDataIdFromObject(object); // fall back to default handling } } }) \ No newline at end of file diff --git a/graphql/clients/coindufeu.js b/graphql/clients/coindufeu.js index f0db19e..defa902 100644 --- a/graphql/clients/coindufeu.js +++ b/graphql/clients/coindufeu.js @@ -2,8 +2,8 @@ import { HttpLink } from 'apollo-link-http' import { setContext } from 'apollo-link-context' import { from } from 'apollo-link' -import {ENDPOINT1} from './endpoints' -import {cache} from '../cache' +import { ENDPOINT1 } from './endpoints' +import { cache } from '../cache' export default ctx => { const ssrMiddleware = setContext((_, { headers }) => { diff --git a/graphql/clients/endpoints.js b/graphql/clients/endpoints.js index 5108540..c3fb96a 100644 --- a/graphql/clients/endpoints.js +++ b/graphql/clients/endpoints.js @@ -1,4 +1,4 @@ module.exports = { - ENDPOINT1 : 'https://wwgql.coinduf.eu', - ENDPOINT2 : 'https://myserver.com' + ENDPOINT1: 'https://wwgql.coinduf.eu', + ENDPOINT2: 'https://myserver.com' } \ No newline at end of file diff --git a/graphql/clients/otherclient.js b/graphql/clients/otherclient.js index 1a6b095..a2b2016 100644 --- a/graphql/clients/otherclient.js +++ b/graphql/clients/otherclient.js @@ -2,8 +2,8 @@ import { HttpLink } from 'apollo-link-http' import { setContext } from 'apollo-link-context' import { from } from 'apollo-link' -import {ENDPOINT2} from './endpoints' -import {cache} from '../cache' +import { ENDPOINT2 } from './endpoints' +import { cache } from '../cache' export default ctx => { const ssrMiddleware = setContext((_, { headers }) => { diff --git a/graphql/fragmentTypes.json b/graphql/fragmentTypes.json index 1ee79b1..551fbb1 100644 --- a/graphql/fragmentTypes.json +++ b/graphql/fragmentTypes.json @@ -1 +1,24 @@ -{"__schema":{"types":[{"kind":"UNION","name":"CertifOrDossier","possibleTypes":[{"name":"MarkedDatedCertification"},{"name":"MarkedDossier"}]},{"kind":"INTERFACE","name":"File","possibleTypes":[{"name":"FileS"}]},{"kind":"INTERFACE","name":"WWResult","possibleTypes":[{"name":"WWResultS"}]}]}} \ No newline at end of file +{ + "__schema": { + "types": [ + { + "kind": "UNION", + "name": "CertifOrDossier", + "possibleTypes": [ + { "name": "MarkedDatedCertification" }, + { "name": "MarkedDossier" } + ] + }, + { + "kind": "INTERFACE", + "name": "File", + "possibleTypes": [{ "name": "FileS" }] + }, + { + "kind": "INTERFACE", + "name": "WWResult", + "possibleTypes": [{ "name": "WWResultS" }] + } + ] + } +} diff --git a/graphql/schemaQuery.js b/graphql/schemaQuery.js index 736bec3..da45416 100644 --- a/graphql/schemaQuery.js +++ b/graphql/schemaQuery.js @@ -1,4 +1,4 @@ -const {ENDPOINT1} = require('./clients/endpoints'); +const { ENDPOINT1 } = require('./clients/endpoints'); const fetch = require('node-fetch'); const fs = require('fs'); @@ -22,13 +22,13 @@ fetch(ENDPOINT1, { `, }), }) -.then(result => result.json()) -.then(result => { + .then(result => result.json()) + .then(result => { const filteredData = result.data.__schema.types.filter( type => type.possibleTypes !== null ) result.data.__schema.types = filteredData; - + fs.writeFile('./graphql/fragmentTypes.json', JSON.stringify(result.data), err => { if (err) { console.error('Error writing fragmentTypes file', err); @@ -36,4 +36,4 @@ fetch(ENDPOINT1, { console.log('Fragment types successfully extracted!'); } }); -}); \ No newline at end of file + }); \ No newline at end of file diff --git a/i18n/index.js b/i18n/index.js index e72ec82..d89d139 100644 --- a/i18n/index.js +++ b/i18n/index.js @@ -1,7 +1,7 @@ import en from './locales/en.json' import fr from './locales/fr.json' import es from './locales/es.json' -import {dateTimeFormats} from './locales/dateTimeFormats' +import { dateTimeFormats } from './locales/dateTimeFormats' export default { fallbackLocale: 'en', diff --git a/i18n/locales/en.json b/i18n/locales/en.json index 79765fe..1658d61 100644 --- a/i18n/locales/en.json +++ b/i18n/locales/en.json @@ -1,98 +1,98 @@ { - "accueil": "Home", - "aurevoir": "Goodbye to", - "bienvenue": "Welcome to", - "bloc": "Block", - "certifications": { - "envoyees" : "Certificates sent", - "recues" : "Certificates received " - }, - "chargement" : "Loading", - "copie" : "Copied", - "description": "Description", - "dev": "In development", - "expire": "Expires", - "futuremembers": "Future members", - "infos": "Informations", - "inout": "Entries and exits of the web of trust for the last 2 days", - "inpreparation": "In preparation", - "membre": { - "datelimadhesion": "Membership deadline", - "datelimrevoc" : "Deadline before revocation ", - "datemanquecertifs": "Date before running out of certs", - "dispo": "Available", - "dispocertif": "Available to certify", - "distance": "Distance", - "nb_certifs": "Nb of available certs", - "nodispo": "Unavailable", - "qualite": "Quality", - "referent": "Referent" - }, - "membres": "Members", - "nom": "Name", - "non": "No", - "oui": "Yes", - "params": { - "breadcrumb": "Parameters", - "name": { - "avgGenTime": "The average time for writing 1 block (wished time)", - "c": "The relative growth of the UD every <code>dtReeval</code> period", - "dt": "Time period between two UD", - "dtDiffEval": "The number of blocks required to evaluate again PoWMin value", - "dtReeval": "Time period between two re-evaluation of the UD", - "idtyWindow": "Maximum delay an identity can wait before being expired for non-writing", - "medianTimeBlocks": "Number of blocks used for calculating median time", - "msPeriod": "Minimum delay between 2 memberships of a same issuer", - "msValidity": "Maximum age of an active membership", - "msWindow": "Maximum delay a membership can wait before being expired for non-writing", - "percentRot": "The proportion of calculating members not excluded from the proof of work", - "sigPeriod": "Minimum delay between two certifications of a same issuer", - "sigQty": "Minimum quantity of signatures to be part of the WoT", - "sigReplay": "Minimum delay before replaying a certification", - "sigStock": "Maximum quantity of active certifications made by member", - "sigValidity": "Maximum age of an active certification", - "sigWindow": "Maximum delay a certification can wait before being expired for non-writing", - "stepMax": "Maximum distance between a WOT member and <code>xpercent</code> of sentries", - "txWindow": "Maximum delay a transaction can wait before being expired for non-writing", - "ud0": "UD(0), i.e. initial Universal Dividend", - "udReevalTime0": "Time of first reevaluation of the UD", - "udTime0": "Time of first UD", - "xpercent": "Minimum percent of sentries to reach to match the distance rule" - }, - "title": "Blockchain parameters" - }, - "previsions" : { - "certificationsinternes": "No internal certification | 1 internal certification | {n} internal certifications", - "dossiersattente": "No pending files | 1 pending file | {n} pending files", - "pardate": "Forecasts by dates", - "parmembre": "Forecasts by members", - "permutations": "No permutation | 1 permutation | {n} permutations", - "title": "Forecasts" - }, - "recherche": { - "desc" : "Enter the start of a nickname or public key", - "title": "Your search" - }, - "revoila": "Here they are again", - "slogan": "The Web of Trust’s wizard", - "statut" : { - "bientotmanquecertif": "Needs certifications soon", - "manquecertif": "Needs certifications", - "member": "Member", - "missing": "Membership lost", - "newcomer": "Future member", - "renew": "Membership to renew", - "revoked": "Revoked member" - }, - "time": { - "a": "at" - }, - "traitement": "Ongoing treatment", - "tri": { - "pardate": "Sort by date", - "parmembres": "Sort by members" - }, - "type": "Type", - "valeur": "Value", - "wot": "Web of trust" -} \ No newline at end of file + "accueil": "Home", + "aurevoir": "Goodbye to", + "bienvenue": "Welcome to", + "bloc": "Block", + "certifications": { + "envoyees": "Certificates sent", + "recues": "Certificates received " + }, + "chargement": "Loading", + "copie": "Copied", + "description": "Description", + "dev": "In development", + "expire": "Expires", + "futuremembers": "Future members", + "infos": "Informations", + "inout": "Entries and exits of the web of trust for the last 2 days", + "inpreparation": "In preparation", + "membre": { + "datelimadhesion": "Membership deadline", + "datelimrevoc": "Deadline before revocation ", + "datemanquecertifs": "Date before running out of certs", + "dispo": "Available", + "dispocertif": "Available to certify", + "distance": "Distance", + "nb_certifs": "Nb of available certs", + "nodispo": "Unavailable", + "qualite": "Quality", + "referent": "Referent" + }, + "membres": "Members", + "nom": "Name", + "non": "No", + "oui": "Yes", + "params": { + "breadcrumb": "Parameters", + "name": { + "avgGenTime": "The average time for writing 1 block (wished time)", + "c": "The relative growth of the UD every <code>dtReeval</code> period", + "dt": "Time period between two UD", + "dtDiffEval": "The number of blocks required to evaluate again PoWMin value", + "dtReeval": "Time period between two re-evaluation of the UD", + "idtyWindow": "Maximum delay an identity can wait before being expired for non-writing", + "medianTimeBlocks": "Number of blocks used for calculating median time", + "msPeriod": "Minimum delay between 2 memberships of a same issuer", + "msValidity": "Maximum age of an active membership", + "msWindow": "Maximum delay a membership can wait before being expired for non-writing", + "percentRot": "The proportion of calculating members not excluded from the proof of work", + "sigPeriod": "Minimum delay between two certifications of a same issuer", + "sigQty": "Minimum quantity of signatures to be part of the WoT", + "sigReplay": "Minimum delay before replaying a certification", + "sigStock": "Maximum quantity of active certifications made by member", + "sigValidity": "Maximum age of an active certification", + "sigWindow": "Maximum delay a certification can wait before being expired for non-writing", + "stepMax": "Maximum distance between a WOT member and <code>xpercent</code> of sentries", + "txWindow": "Maximum delay a transaction can wait before being expired for non-writing", + "ud0": "UD(0), i.e. initial Universal Dividend", + "udReevalTime0": "Time of first reevaluation of the UD", + "udTime0": "Time of first UD", + "xpercent": "Minimum percent of sentries to reach to match the distance rule" + }, + "title": "Blockchain parameters" + }, + "previsions": { + "certificationsinternes": "No internal certification | 1 internal certification | {n} internal certifications", + "dossiersattente": "No pending files | 1 pending file | {n} pending files", + "pardate": "Forecasts by dates", + "parmembre": "Forecasts by members", + "permutations": "No permutation | 1 permutation | {n} permutations", + "title": "Forecasts" + }, + "recherche": { + "desc": "Enter the start of a nickname or public key", + "title": "Your search" + }, + "revoila": "Here they are again", + "slogan": "The Web of Trust’s wizard", + "statut": { + "bientotmanquecertif": "Needs certifications soon", + "manquecertif": "Needs certifications", + "member": "Member", + "missing": "Membership lost", + "newcomer": "Future member", + "renew": "Membership to renew", + "revoked": "Revoked member" + }, + "time": { + "a": "at" + }, + "traitement": "Ongoing treatment", + "tri": { + "pardate": "Sort by date", + "parmembres": "Sort by members" + }, + "type": "Type", + "valeur": "Value", + "wot": "Web of trust" +} diff --git a/i18n/locales/es.json b/i18n/locales/es.json index ca3fa96..295186d 100644 --- a/i18n/locales/es.json +++ b/i18n/locales/es.json @@ -1,98 +1,98 @@ { - "accueil": "Página principal", - "aurevoir": "Salen", - "bienvenue": "Entran", - "bloc": "Bloque", - "certifications": { - "envoyees" : "Certificaciones enviadas", - "recues" : "Certificaciones recibidas " - }, - "chargement" : "Cargando", - "copie" : "Copiada", - "description": "Descripción", - "dev": "En desarrollo", - "expire": "Expira el", - "futuremembers": "Futuros miembros", - "infos": "Informaciones", - "inout": "Entradas y salidas de la red de confianza en los últimos 2 dÃas", - "inpreparation": "En preparación", - "membre": { - "datelimadhesion": "Fecha lÃmite de membresÃa", - "datelimrevoc" : "Fecha lÃmite de la autorevocación", - "datemanquecertifs": "Fecha antes de quedarse sin certificaciones", - "dispo": "Disponible", - "dispocertif": "Disponible para certificar", - "distance": "Distancia", - "nb_certifs": "Núm. de certificaciones disponibles", - "nodispo": "Indisponible", - "qualite": "Calidad de enlace", - "referent": "Referente o de control" - }, - "membres": "Miembros", - "nom": "Nombre", - "non": "No", - "oui": "SÃ", - "params": { - "breadcrumb": "Parámetros", - "name": { - "avgGenTime": "The average time for writing 1 block (wished time)", - "c": "The relative growth of the UD every <code>dtReeval</code> period", - "dt": "Time period between two UD", - "dtDiffEval": "The number of blocks required to evaluate again PoWMin value", - "dtReeval": "Time period between two re-evaluation of the UD", - "idtyWindow": "Maximum delay an identity can wait before being expired for non-writing", - "medianTimeBlocks": "Number of blocks used for calculating median time", - "msPeriod": "Minimum delay between 2 memberships of a same issuer", - "msValidity": "Maximum age of an active membership", - "msWindow": "Maximum delay a membership can wait before being expired for non-writing", - "percentRot": "The proportion of calculating members not excluded from the proof of work", - "sigPeriod": "Minimum delay between two certifications of a same issuer", - "sigQty": "Minimum quantity of signatures to be part of the WoT", - "sigReplay": "Minimum delay before replaying a certification", - "sigStock": "Maximum quantity of active certifications made by member", - "sigValidity": "Maximum age of an active certification", - "sigWindow": "Maximum delay a certification can wait before being expired for non-writing", - "stepMax": "Maximum distance between a WOT member and <code>xpercent</code> of sentries", - "txWindow": "Maximum delay a transaction can wait before being expired for non-writing", - "ud0": "UD(0), i.e. initial Universal Dividend", - "udReevalTime0": "Time of first reevaluation of the UD", - "udTime0": "Time of first UD", - "xpercent": "Minimum percent of sentries to reach to match the distance rule" - }, - "title": "Parámetros de la blockchain" - }, - "previsions" : { - "certificationsinternes": "Sin certificación interna | 1 certificación interna | {n} certificaciones internas", - "dossiersattente": "No hay candidaturas pendientes | 1 candidatura pendiente | {n} candidaturas pendientes", - "pardate": "Previsiones por fecha", - "parmembre": "Previsiones por miembros", - "permutations": "Sin permutación | 1 permutación | {n} permutaciones", - "title": "Pronósticos" - }, - "recherche": { - "desc" : "Introduce el comienzo de un pseudónimo o llave pública", - "title": "Buscar" - }, - "revoila": "Regresan", - "slogan": "El mago de la Red de Confianza", - "statut" : { - "bientotmanquecertif": "Pronto necesitará certificaciones", - "manquecertif": "Faltan certificaciones", - "member": "Miembro", - "missing": "MembresÃa perdida", - "newcomer": "Futur@ miembro", - "renew": "MembresÃa por renovar", - "revoked": "MembresÃa revocada" - }, - "time": { - "a": "a" - }, - "traitement": "Tratamiento en curso", - "tri": { - "pardate": "Ordenar por fecha", - "parmembres": "Clasificar por miembros" - }, - "type": "Tipo", - "valeur": "Valor", - "wot": "Red de confianza" + "accueil": "Página principal", + "aurevoir": "Salen", + "bienvenue": "Entran", + "bloc": "Bloque", + "certifications": { + "envoyees": "Certificaciones enviadas", + "recues": "Certificaciones recibidas " + }, + "chargement": "Cargando", + "copie": "Copiada", + "description": "Descripción", + "dev": "En desarrollo", + "expire": "Expira el", + "futuremembers": "Futuros miembros", + "infos": "Informaciones", + "inout": "Entradas y salidas de la red de confianza en los últimos 2 dÃas", + "inpreparation": "En preparación", + "membre": { + "datelimadhesion": "Fecha lÃmite de membresÃa", + "datelimrevoc": "Fecha lÃmite de la autorevocación", + "datemanquecertifs": "Fecha antes de quedarse sin certificaciones", + "dispo": "Disponible", + "dispocertif": "Disponible para certificar", + "distance": "Distancia", + "nb_certifs": "Núm. de certificaciones disponibles", + "nodispo": "Indisponible", + "qualite": "Calidad de enlace", + "referent": "Referente o de control" + }, + "membres": "Miembros", + "nom": "Nombre", + "non": "No", + "oui": "SÃ", + "params": { + "breadcrumb": "Parámetros", + "name": { + "avgGenTime": "The average time for writing 1 block (wished time)", + "c": "The relative growth of the UD every <code>dtReeval</code> period", + "dt": "Time period between two UD", + "dtDiffEval": "The number of blocks required to evaluate again PoWMin value", + "dtReeval": "Time period between two re-evaluation of the UD", + "idtyWindow": "Maximum delay an identity can wait before being expired for non-writing", + "medianTimeBlocks": "Number of blocks used for calculating median time", + "msPeriod": "Minimum delay between 2 memberships of a same issuer", + "msValidity": "Maximum age of an active membership", + "msWindow": "Maximum delay a membership can wait before being expired for non-writing", + "percentRot": "The proportion of calculating members not excluded from the proof of work", + "sigPeriod": "Minimum delay between two certifications of a same issuer", + "sigQty": "Minimum quantity of signatures to be part of the WoT", + "sigReplay": "Minimum delay before replaying a certification", + "sigStock": "Maximum quantity of active certifications made by member", + "sigValidity": "Maximum age of an active certification", + "sigWindow": "Maximum delay a certification can wait before being expired for non-writing", + "stepMax": "Maximum distance between a WOT member and <code>xpercent</code> of sentries", + "txWindow": "Maximum delay a transaction can wait before being expired for non-writing", + "ud0": "UD(0), i.e. initial Universal Dividend", + "udReevalTime0": "Time of first reevaluation of the UD", + "udTime0": "Time of first UD", + "xpercent": "Minimum percent of sentries to reach to match the distance rule" + }, + "title": "Parámetros de la blockchain" + }, + "previsions": { + "certificationsinternes": "Sin certificación interna | 1 certificación interna | {n} certificaciones internas", + "dossiersattente": "No hay candidaturas pendientes | 1 candidatura pendiente | {n} candidaturas pendientes", + "pardate": "Previsiones por fecha", + "parmembre": "Previsiones por miembros", + "permutations": "Sin permutación | 1 permutación | {n} permutaciones", + "title": "Pronósticos" + }, + "recherche": { + "desc": "Introduce el comienzo de un pseudónimo o llave pública", + "title": "Buscar" + }, + "revoila": "Regresan", + "slogan": "El mago de la Red de Confianza", + "statut": { + "bientotmanquecertif": "Pronto necesitará certificaciones", + "manquecertif": "Faltan certificaciones", + "member": "Miembro", + "missing": "MembresÃa perdida", + "newcomer": "Futur@ miembro", + "renew": "MembresÃa por renovar", + "revoked": "MembresÃa revocada" + }, + "time": { + "a": "a" + }, + "traitement": "Tratamiento en curso", + "tri": { + "pardate": "Ordenar por fecha", + "parmembres": "Clasificar por miembros" + }, + "type": "Tipo", + "valeur": "Valor", + "wot": "Red de confianza" } diff --git a/i18n/locales/fr.json b/i18n/locales/fr.json index 1aac9fc..eb3969c 100644 --- a/i18n/locales/fr.json +++ b/i18n/locales/fr.json @@ -1,98 +1,98 @@ { - "accueil": "Accueil", - "aurevoir": "Au revoir à ", - "bienvenue": "Bienvenue à ", - "bloc": "Bloc", - "certifications": { - "envoyees" : "Certifications envoyées", - "recues" : "Certifications reçues " - }, - "chargement" : "Chargement", - "copie" : "Copiée", - "description": "Description", - "dev": "En Développement", - "expire": "Expire le", - "futuremembers": "Futurs membres", - "infos": "Informations", - "inout": "Entrées et sorties de la toile de confiance des 2 derniers jours", - "inpreparation": "En préparation", - "membre": { - "datelimadhesion": "Date limite d'adhésion", - "datelimrevoc" : "Date limite avant révocation ", - "datemanquecertifs": "Date avant de manquer de certifs", - "dispo": "Disponible", - "dispocertif": "Disponible pour certifier", - "distance": "Distance", - "nb_certifs": "Nbre de certifs disponibles", - "nodispo": "Indisponible", - "qualite": "Qualité", - "referent": "Référent" - }, - "membres": "Membres", - "nom": "Nom", - "non": "Non", - "oui": "Oui", - "params": { - "breadcrumb": "Paramètres", - "name": { - "avgGenTime": "Temps moyen d’écriture d’un bloc (temps espéré)", - "c": "Croissance relative du DU pour chaque période <code>dtReeval</code>", - "dt": "Délai entre deux DU", - "dtDiffEval": "Nombre de blocs requis avant de réévaluer à nouveau la difficulté minimale de la Preuve de Travail", - "dtReeval": "Délai entre deux réévaluations du DU", - "idtyWindow": "Délai maximum qu'une identité peut attendre en piscine avant d'être rejetée pour non-écriture dans un bloc", - "medianTimeBlocks": "Nombre de blocs utilisés pour le calcul du temps moyen", - "msPeriod": "Délai minimum entre 2 demandes d'adhésion pour une même personne", - "msValidity": "Durée maximale d'une adhésion", - "msWindow": "Délai maximum qu'une adhésion peut attendre en piscine avant d'être rejetée pour non-écriture dans un bloc", - "percentRot": "Proportion des membres calculants non exclus de la preuve de travail", - "sigPeriod": "Délai minimum entre deux certifications d'un même émetteur", - "sigQty": "Nombre minimal de certifications reçues pour faire partie de la Toile de Confiance", - "sigReplay": "Délai minimum avant le renouvellement possible d'une certification", - "sigStock": "Nombre de certifications actives maximum envoyées par membre", - "sigValidity": "Durée de vie d'une certification active", - "sigWindow": "Délai maximal qu'une certification peut attendre en piscine avant d'être rejetée pour non-écriture dans un bloc", - "stepMax": "Distance maximale entre un membre et <code>xpercent</code> des membres référents", - "txWindow": "Délai maximum qu'une transaction peut attendre en piscine avant d'être rejetée pour non-écriture dans un bloc", - "ud0": "Montant du DU initial", - "udReevalTime0": "Date de la première réévaluation du DU", - "udTime0": "Date du premier DU", - "xpercent": "Pourcentage minimal de membres référents à atteindre pour respecter la règle de distance" - }, - "title": "Paramètres de la blockchain" - }, - "previsions" : { - "certificationsinternes": "Aucune certification interne | 1 certification interne | {n} certifications internes", - "dossiersattente": "Aucun dossier en attente | 1 dossier en attente | {n} dossiers en attente", - "pardate": "Prévisions par date", - "parmembre": "Prévisions par membres", - "permutations": "Aucune permutation | 1 permutation | {n} permutations", - "title": "Prévisions" - }, - "recherche": { - "desc" : "Saisissez le début d'un pseudo ou d'une clé publique", - "title": "Votre recherche" - }, - "revoila": "Les revoilà ", - "slogan": "Le magicien de la Toile de Confiance", - "statut" : { - "bientotmanquecertif": "Bientôt en manque de certifications", - "manquecertif": "En manque de certifications", - "member": "Membre", - "missing": "Adhésion perdue", - "newcomer": "Futur membre", - "renew": "Adhésion à renouveler", - "revoked": "Membre révoqué" - }, - "time": { - "a": "à " - }, - "traitement": "En cours de traitement", - "tri": { - "pardate": "Tri par date", - "parmembres": "Tri par membres" - }, - "type": "Type", - "valeur": "Valeur", - "wot": "Toile de confiance" -} \ No newline at end of file + "accueil": "Accueil", + "aurevoir": "Au revoir à ", + "bienvenue": "Bienvenue à ", + "bloc": "Bloc", + "certifications": { + "envoyees": "Certifications envoyées", + "recues": "Certifications reçues " + }, + "chargement": "Chargement", + "copie": "Copiée", + "description": "Description", + "dev": "En Développement", + "expire": "Expire le", + "futuremembers": "Futurs membres", + "infos": "Informations", + "inout": "Entrées et sorties de la toile de confiance des 2 derniers jours", + "inpreparation": "En préparation", + "membre": { + "datelimadhesion": "Date limite d'adhésion", + "datelimrevoc": "Date limite avant révocation ", + "datemanquecertifs": "Date avant de manquer de certifs", + "dispo": "Disponible", + "dispocertif": "Disponible pour certifier", + "distance": "Distance", + "nb_certifs": "Nbre de certifs disponibles", + "nodispo": "Indisponible", + "qualite": "Qualité", + "referent": "Référent" + }, + "membres": "Membres", + "nom": "Nom", + "non": "Non", + "oui": "Oui", + "params": { + "breadcrumb": "Paramètres", + "name": { + "avgGenTime": "Temps moyen d’écriture d’un bloc (temps espéré)", + "c": "Croissance relative du DU pour chaque période <code>dtReeval</code>", + "dt": "Délai entre deux DU", + "dtDiffEval": "Nombre de blocs requis avant de réévaluer à nouveau la difficulté minimale de la Preuve de Travail", + "dtReeval": "Délai entre deux réévaluations du DU", + "idtyWindow": "Délai maximum qu'une identité peut attendre en piscine avant d'être rejetée pour non-écriture dans un bloc", + "medianTimeBlocks": "Nombre de blocs utilisés pour le calcul du temps moyen", + "msPeriod": "Délai minimum entre 2 demandes d'adhésion pour une même personne", + "msValidity": "Durée maximale d'une adhésion", + "msWindow": "Délai maximum qu'une adhésion peut attendre en piscine avant d'être rejetée pour non-écriture dans un bloc", + "percentRot": "Proportion des membres calculants non exclus de la preuve de travail", + "sigPeriod": "Délai minimum entre deux certifications d'un même émetteur", + "sigQty": "Nombre minimal de certifications reçues pour faire partie de la Toile de Confiance", + "sigReplay": "Délai minimum avant le renouvellement possible d'une certification", + "sigStock": "Nombre de certifications actives maximum envoyées par membre", + "sigValidity": "Durée de vie d'une certification active", + "sigWindow": "Délai maximal qu'une certification peut attendre en piscine avant d'être rejetée pour non-écriture dans un bloc", + "stepMax": "Distance maximale entre un membre et <code>xpercent</code> des membres référents", + "txWindow": "Délai maximum qu'une transaction peut attendre en piscine avant d'être rejetée pour non-écriture dans un bloc", + "ud0": "Montant du DU initial", + "udReevalTime0": "Date de la première réévaluation du DU", + "udTime0": "Date du premier DU", + "xpercent": "Pourcentage minimal de membres référents à atteindre pour respecter la règle de distance" + }, + "title": "Paramètres de la blockchain" + }, + "previsions": { + "certificationsinternes": "Aucune certification interne | 1 certification interne | {n} certifications internes", + "dossiersattente": "Aucun dossier en attente | 1 dossier en attente | {n} dossiers en attente", + "pardate": "Prévisions par date", + "parmembre": "Prévisions par membres", + "permutations": "Aucune permutation | 1 permutation | {n} permutations", + "title": "Prévisions" + }, + "recherche": { + "desc": "Saisissez le début d'un pseudo ou d'une clé publique", + "title": "Votre recherche" + }, + "revoila": "Les revoilà ", + "slogan": "Le magicien de la Toile de Confiance", + "statut": { + "bientotmanquecertif": "Bientôt en manque de certifications", + "manquecertif": "En manque de certifications", + "member": "Membre", + "missing": "Adhésion perdue", + "newcomer": "Futur membre", + "renew": "Adhésion à renouveler", + "revoked": "Membre révoqué" + }, + "time": { + "a": "à " + }, + "traitement": "En cours de traitement", + "tri": { + "pardate": "Tri par date", + "parmembres": "Tri par membres" + }, + "type": "Type", + "valeur": "Valeur", + "wot": "Toile de confiance" +} diff --git a/jsconfig.json b/jsconfig.json index 29037a6..ea02ae4 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,12 +1,12 @@ { - "compilerOptions": { - "baseUrl": ".", - "paths": { - "~/*": ["./*"], - "@/*": ["./*"], - "~~/*": ["./*"], - "@@/*": ["./*"] - } - }, - "exclude": ["node_modules", ".nuxt", "dist"] + "compilerOptions": { + "baseUrl": ".", + "paths": { + "~/*": ["./*"], + "@/*": ["./*"], + "~~/*": ["./*"], + "@@/*": ["./*"] + } + }, + "exclude": ["node_modules", ".nuxt", "dist"] } diff --git a/layouts/default.vue b/layouts/default.vue index 728447b..cc59e35 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -1,82 +1,80 @@ <template> - <div class="app"> - <NavigationBar :breadcrumb="breadcrumb" :menus="menus" /> - <Nuxt /> - </div> + <div class="app"> + <NavigationBar :breadcrumb="breadcrumb" :menus="menus" /> + <Nuxt /> + </div> </template> <script> export default { - data() { - return { - breadcrumb: [], - // Les title correspondent aux chaînes de traduction dans /i18n/locales - menus : [ - { - title: 'wot', - items : [ - {path: '/membres',title: 'membres'} - ] - }, - { - title: 'previsions.title', - items : [ - {path: '/previsions/futurs_membres',title: 'futuremembers'} - ] - }, - { - title: 'infos', - items : [ - {path: '/parametres',title: 'params.title'} - ] - } - ] - } - }, - created() { - this.$nuxt.$on('changeRoute', (breadcrumb) => { - this.breadcrumb = breadcrumb - }) - } + data() { + return { + breadcrumb: [], + // Les title correspondent aux chaînes de traduction dans /i18n/locales + menus: [ + { + title: "wot", + items: [{ path: "/membres", title: "membres" }] + }, + { + title: "previsions.title", + items: [ + { path: "/previsions/futurs_membres", title: "futuremembers" } + ] + }, + { + title: "infos", + items: [{ path: "/parametres", title: "params.title" }] + } + ] + } + }, + created() { + this.$nuxt.$on("changeRoute", (breadcrumb) => { + this.breadcrumb = breadcrumb + }) + } } </script> <style lang="scss"> /* Define styles for the default root window element */ :root { - --text-primary-color: var(--dark); - --text-secondary-color: #8a8a8a; - --background-color-primary: var(--white); - --background-color-secondary: #e9ecef; - --element-size: 4rem; - --menu-size: 320px; + --text-primary-color: var(--dark); + --text-secondary-color: #8a8a8a; + --background-color-primary: var(--white); + --background-color-secondary: #e9ecef; + --element-size: 4rem; + --menu-size: 320px; } /* Define styles for the root window with dark - mode preference */ :root.dark-theme { - --text-primary-color: var(--white); - --text-secondary-color: #c9c9c9; - --background-color-primary: var(--dark); - --background-color-secondary: hsl(210, 16%, 60%); + --text-primary-color: var(--white); + --text-secondary-color: #c9c9c9; + --background-color-primary: var(--dark); + --background-color-secondary: hsl(210, 16%, 60%); } .app { - transition: margin .5s ease-in-out; + transition: margin 0.5s ease-in-out; } main { - padding-top: 10rem; - position: relative; + padding-top: 10rem; + position: relative; - @media (min-width:768px) { - padding-top: 8rem; - } + @media (min-width: 768px) { + padding-top: 8rem; + } } -.fade-enter-active, .fade-leave-active { - transition: opacity .5s; +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.5s; } -.fade-enter, .fade-leave-to { - opacity: 0; +.fade-enter, +.fade-leave-to { + opacity: 0; } -</style> \ No newline at end of file +</style> diff --git a/layouts/error.vue b/layouts/error.vue index 96bb5c7..ca51e9c 100644 --- a/layouts/error.vue +++ b/layouts/error.vue @@ -1,33 +1,37 @@ <template> -<main class="content"> - <h2 v-if="error.statusCode === 404" class="display-2 text-center mb-5">Page not found</h2> - <h2 v-else class="display-2 text-center mb-5">An error occurred - {{ error.statusCode }} </h2> - <NuxtLink to="/" class="d-block text-center">Retour à l'accueil</NuxtLink> -</main> + <main class="content"> + <h2 v-if="error.statusCode === 404" class="display-2 text-center mb-5"> + Page not found + </h2> + <h2 v-else class="display-2 text-center mb-5"> + An error occurred - {{ error.statusCode }} + </h2> + <NuxtLink to="/" class="d-block text-center">Retour à l'accueil</NuxtLink> + </main> </template> <script> export default { - data() { - return { - breadcrumb: [ - { - text: 'Erreur ', - active: true - } - ] - } - }, - mounted () { - $nuxt.$emit('changeRoute',this.breadcrumb) - }, - props: ['error'], - layout: 'error' + data() { + return { + breadcrumb: [ + { + text: "Erreur ", + active: true + } + ] + } + }, + mounted() { + $nuxt.$emit("changeRoute", this.breadcrumb) + }, + props: ["error"], + layout: "error" } </script> <style lang="scss"> .app { - transition: margin .5s ease-in-out; + transition: margin 0.5s ease-in-out; } -</style> \ No newline at end of file +</style> diff --git a/nuxt.config.js b/nuxt.config.js index 439bef4..1f08452 100644 --- a/nuxt.config.js +++ b/nuxt.config.js @@ -50,7 +50,7 @@ export default { '@nuxtjs/i18n' ], - i18n : { + i18n: { defaultLocale: 'fr', locales: [ { diff --git a/package.json b/package.json index 9c1faee..67082a7 100644 --- a/package.json +++ b/package.json @@ -1,34 +1,34 @@ { - "name": "wotwizard-ui", - "version": "1.0.0", - "private": true, - "scripts": { - "dev": "nuxt", - "build": "npm-run-all -p build-fragment nuxt-build", - "start": "npm-run-all -p build-fragment nuxt-start", - "generate": "npm-run-all -p build-fragment nuxt-generate", - "analyze": "nuxt build --analyze", - "build-fragment": "node graphql/schemaQuery.js", - "nuxt-build": "nuxt build", - "nuxt-start": "nuxt start", - "nuxt-generate": "nuxt generate" - }, - "dependencies": { - "@nuxtjs/apollo": "^4.0.1-rc.5", - "@nuxtjs/i18n": "^7.2.0", - "@nuxtjs/pwa": "^3.3.5", - "apollo-link-context": "^1.0.20", - "apollo-link-http": "^1.5.17", - "bootstrap": "^4.6.1", - "chart.js": "^3.6.2", - "core-js": "^3.15.1", - "graphql-tag": "^2.12.6", - "nuxt": "^2.15.8", - "vue": "^2.6.14" - }, - "devDependencies": { - "npm-run-all": "^4.1.5", - "sass": "^1.45.0", - "sass-loader": "^10.2.0" - } + "name": "wotwizard-ui", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "nuxt", + "build": "npm-run-all -p build-fragment nuxt-build", + "start": "npm-run-all -p build-fragment nuxt-start", + "generate": "npm-run-all -p build-fragment nuxt-generate", + "analyze": "nuxt build --analyze", + "build-fragment": "node graphql/schemaQuery.js", + "nuxt-build": "nuxt build", + "nuxt-start": "nuxt start", + "nuxt-generate": "nuxt generate" + }, + "dependencies": { + "@nuxtjs/apollo": "^4.0.1-rc.5", + "@nuxtjs/i18n": "^7.2.0", + "@nuxtjs/pwa": "^3.3.5", + "apollo-link-context": "^1.0.20", + "apollo-link-http": "^1.5.17", + "bootstrap": "^4.6.1", + "chart.js": "^3.6.2", + "core-js": "^3.15.1", + "graphql-tag": "^2.12.6", + "nuxt": "^2.15.8", + "vue": "^2.6.14" + }, + "devDependencies": { + "npm-run-all": "^4.1.5", + "sass": "^1.45.0", + "sass-loader": "^10.2.0" + } } diff --git a/pages/chartjs.vue b/pages/chartjs.vue index a8483d5..8101966 100644 --- a/pages/chartjs.vue +++ b/pages/chartjs.vue @@ -1,93 +1,116 @@ <template> - <main class="container-fluid"> - <h2 class="display-2 text-center mb-5">Test ChartJS</h2> - <div class="row"> - <div class="col-md-6 mx-auto"> - <div class="alert alert-danger">En développement</div> - </div> - </div> - <div class="demo p-5 m-auto"> - <select class="form-control my-4" v-model="chartType"> - <option v-for="type in allTypes" :key="type">{{ type }}</option> - </select> - <button @click="fillData" class="btn btn-primary mb-5">Randomize</button> - <LazyGraph id="monGraph" :type="chartType" :data="data" :options="options" /> - </div> - </main> + <main class="container-fluid"> + <h2 class="display-2 text-center mb-5">Test ChartJS</h2> + <div class="row"> + <div class="col-md-6 mx-auto"> + <div class="alert alert-danger">En développement</div> + </div> + </div> + <div class="demo p-5 m-auto"> + <select class="form-control my-4" v-model="chartType"> + <option v-for="type in allTypes" :key="type">{{ type }}</option> + </select> + <button @click="fillData" class="btn btn-primary mb-5">Randomize</button> + <LazyGraph + id="monGraph" + :type="chartType" + :data="data" + :options="options" /> + </div> + </main> </template> <script> -import {chartTypes} from "~/components/Graph.vue" +import { chartTypes } from "~/components/Graph.vue" export default { - data () { - return { - allTypes: chartTypes, - chartType: "line", - options: { - responsive: true, - lineTension: 1 - }, - data: {}, - breadcrumb: [ - { - text: this.$t('accueil'), - to: "/" - }, - { - text: 'ChartJS', - active: true - } - ] - } - }, - methods: { - fillData () { - this.data = { - labels: ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"], - datasets: [{ - label: "Number of Moons", - data: this.generateArray(8), - backgroundColor: this.generateColor(), - borderColor: this.generateColor(), - borderWidth: 2 - }, - { - label: "Planetary Mass (relative to the Sun x 10^-6)", - data: this.generateArray(8), - backgroundColor: this.generateColor(), - borderColor: this.generateColor(), - borderWidth: 2 - }] - } - }, - generateColor() { - return "rgba(" + this.getRandomInt(255) + "," + this.getRandomInt(255) + "," + this.getRandomInt(255) + ",.5)" - }, - generateArray (nb_items) { - let ret = [] - for (let i=0;i<nb_items;i++) { - ret[i] = this.getRandomInt(50) - } - return ret - }, - getRandomInt (max) { - return Math.floor(Math.random() * (max - 5 + 1)) + 5 - } - }, - nuxtI18n: { - paths: { - fr: '/graphiques', - en: '/graphics', - es: '/graficos' - } - }, - mounted () { - $nuxt.$emit('changeRoute',this.breadcrumb) - // On remplit les données dans le graph - this.fillData() - } - } + data() { + return { + allTypes: chartTypes, + chartType: "line", + options: { + responsive: true, + lineTension: 1 + }, + data: {}, + breadcrumb: [ + { + text: this.$t("accueil"), + to: "/" + }, + { + text: "ChartJS", + active: true + } + ] + } + }, + methods: { + fillData() { + this.data = { + labels: [ + "Mercury", + "Venus", + "Earth", + "Mars", + "Jupiter", + "Saturn", + "Uranus", + "Neptune" + ], + datasets: [ + { + label: "Number of Moons", + data: this.generateArray(8), + backgroundColor: this.generateColor(), + borderColor: this.generateColor(), + borderWidth: 2 + }, + { + label: "Planetary Mass (relative to the Sun x 10^-6)", + data: this.generateArray(8), + backgroundColor: this.generateColor(), + borderColor: this.generateColor(), + borderWidth: 2 + } + ] + } + }, + generateColor() { + return ( + "rgba(" + + this.getRandomInt(255) + + "," + + this.getRandomInt(255) + + "," + + this.getRandomInt(255) + + ",.5)" + ) + }, + generateArray(nb_items) { + let ret = [] + for (let i = 0; i < nb_items; i++) { + ret[i] = this.getRandomInt(50) + } + return ret + }, + getRandomInt(max) { + return Math.floor(Math.random() * (max - 5 + 1)) + 5 + } + }, + nuxtI18n: { + paths: { + fr: "/graphiques", + en: "/graphics", + es: "/graficos" + } + }, + mounted() { + $nuxt.$emit("changeRoute", this.breadcrumb) + // On remplit les données dans le graph + this.fillData() + } +} </script> <style lang="sass" scoped> diff --git a/pages/index.vue b/pages/index.vue index 85a0b27..ef21b7c 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -1,94 +1,113 @@ <template> -<main class="container"> - <h2 class="text-center mb-5 font-weight-light">{{ $t('inout') }}</h2> - <NavigationLoader :isLoading="$apollo.queries.newMembers.loading" /> - <transition name="fade"> - <div class="alert alert-danger" v-if="error">{{ error }}</div> - </transition> - <transition name="fade"> - <div class="result" v-if="newMembers"> - <div class="row text-center"> - <div class="col-md-6 col-lg-4"> - <h2 class="h4 text-success">{{ $t('bienvenue') }}</h2> - <MemberList :members="newMembers['entrees']" :displayPubkey="false" :displayHead="false" /> - </div> - <div class="col-md-6 col-lg-4"> - <h2 class="h4 text-danger">{{ $t('aurevoir') }}</h2> - <MemberList :members="newMembers['sorties']" :displayPubkey="false" :displayHead="false" /> - </div> - <div class="col-lg-4"> - <h2 class="h4 text-info">{{ $t('revoila') }}</h2> - <MemberList :members="newMembers['renew']" :displayPubkey="false" :displayHead="false" /> - </div> - </div> - </div> - </transition> -</main> + <main class="container"> + <h2 class="text-center mb-5 font-weight-light">{{ $t("inout") }}</h2> + <NavigationLoader :isLoading="$apollo.queries.newMembers.loading" /> + <transition name="fade"> + <div class="alert alert-danger" v-if="error">{{ error }}</div> + </transition> + <transition name="fade"> + <div class="result" v-if="newMembers"> + <div class="row text-center"> + <div class="col-md-6 col-lg-4"> + <h2 class="h4 text-success">{{ $t("bienvenue") }}</h2> + <MemberList + :members="newMembers['entrees']" + :displayPubkey="false" + :displayHead="false" /> + </div> + <div class="col-md-6 col-lg-4"> + <h2 class="h4 text-danger">{{ $t("aurevoir") }}</h2> + <MemberList + :members="newMembers['sorties']" + :displayPubkey="false" + :displayHead="false" /> + </div> + <div class="col-lg-4"> + <h2 class="h4 text-info">{{ $t("revoila") }}</h2> + <MemberList + :members="newMembers['renew']" + :displayPubkey="false" + :displayHead="false" /> + </div> + </div> + </div> + </transition> + </main> </template> <script> -import {LAST_EVENTS} from '@/graphql/queries.js' +import { LAST_EVENTS } from "@/graphql/queries.js" -const today = Math.round(Date.now() /1000) +const today = Math.round(Date.now() / 1000) export default { - data() { - return { - breadcrumb: [ - { - text: this.$t('accueil'), - to: '/' - } - ], - error: null - } - }, - methods: { - addValue(arr,val) { - if (arr.filter(function(e) { return e.uid === val.uid }).length == 0) { - arr.push(val) - } - return arr - } - }, - apollo: { - newMembers : { - query: LAST_EVENTS, - variables() {return {start:today-86400*2,end:today}}, - update (data) { - let result = {'entrees':[],'sorties':[],'renew':[]} - let users = [] + data() { + return { + breadcrumb: [ + { + text: this.$t("accueil"), + to: "/" + } + ], + error: null + } + }, + methods: { + addValue(arr, val) { + if ( + arr.filter(function (e) { + return e.uid === val.uid + }).length == 0 + ) { + arr.push(val) + } + return arr + } + }, + apollo: { + newMembers: { + query: LAST_EVENTS, + variables() { + return { start: today - 86400 * 2, end: today } + }, + update(data) { + let result = { entrees: [], sorties: [], renew: [] } + let users = [] - for (let i = 0; i < data.membersCount.length; i++) { - for (let j =0; j < data.membersCount[i].idList.length; j++) { - let member = data.membersCount[i].idList[j] - member.member.inOut = member.inOut + for (let i = 0; i < data.membersCount.length; i++) { + for (let j = 0; j < data.membersCount[i].idList.length; j++) { + let member = data.membersCount[i].idList[j] + member.member.inOut = member.inOut - if (!users.includes(member.member.uid)) { - if (member.member.history.length==1) { - this.addValue(result['entrees'],member.member) - } else if (member.inOut) { - this.addValue(result['renew'],member.member) - } else { - this.addValue(result['sorties'],member.member) - } - } + if (!users.includes(member.member.uid)) { + if (member.member.history.length == 1) { + this.addValue(result["entrees"], member.member) + } else if (member.inOut) { + this.addValue(result["renew"], member.member) + } else { + this.addValue(result["sorties"], member.member) + } + } - users.push(member.member.uid) - } - } + users.push(member.member.uid) + } + } - for (let list in result) { - result[list].sort((a, b) => (a.uid.toLowerCase() > b.uid.toLowerCase()) ? 1 : -1) - } - - return result - }, - error (err) {this.error = err.message} - } - }, - mounted () { - $nuxt.$emit('changeRoute',this.breadcrumb) - } + for (let list in result) { + result[list].sort((a, b) => + a.uid.toLowerCase() > b.uid.toLowerCase() ? 1 : -1 + ) + } + + return result + }, + error(err) { + this.error = err.message + } + } + }, + mounted() { + $nuxt.$emit("changeRoute", this.breadcrumb) + } } -</script> \ No newline at end of file +</script> diff --git a/pages/membres/_hash.vue b/pages/membres/_hash.vue index 035bc02..d9402bc 100644 --- a/pages/membres/_hash.vue +++ b/pages/membres/_hash.vue @@ -1,105 +1,154 @@ <template> - <main> - <NavigationLoader :isLoading="$apollo.queries.idFromHash.loading" /> - <transition name="fade"> - <div class="alert alert-danger" v-if="error">{{ error }}</div> - </transition> - <transition name="fade"> - <div v-if="idFromHash"> - <div class="container-md"> - <div class="row"> - <div class="col-lg-9 col-xl-8 mx-auto my-3"> - <MemberCard :hash="idFromHash" /> - </div> - </div> - </div> - <div class="container"> - <div class="row mt-3" v-if="idFromHash.status != 'REVOKED'"> - <div class="col-sm-10 col-md-7 col-lg-5 mb-3 mx-auto"> - <h3 class="h4 text-center" :class="{ - 'text-success' : ['NEWCOMER','MISSING'].includes(idFromHash.status) && idFromHash.received_certifications.certifications.length>=5, - 'text-danger' : ['NEWCOMER','MISSING'].includes(idFromHash.status) && idFromHash.received_certifications.certifications.length<5, - }">{{ $t('certifications.recues') }} ({{ nbCertifs('received') }}<span v-if="nbCertifsPending('received') != 0">{{ ' + ' + nbCertifsPending('received') }}</span>) - <BadgeCertifStatus :limitDate="idFromHash.received_certifications.limit" :memberStatus="idFromHash.status" /> - </h3> - <CertifList :certifs="idFromHash.received_certifications.certifications" type="received" /> - </div> - <div class="col-sm-10 col-md-7 col-lg-5 mx-auto" v-if="['MISSING','MEMBER'].includes(idFromHash.status)"> - <h3 class="h4 text-center">{{ $t('certifications.envoyees') }} ({{nbCertifs('sent') }}<span v-if="nbCertifsPending('sent') != 0">{{ ' + ' + nbCertifsPending('sent') }}</span>)</h3> - <CertifList :certifs="idFromHash.sent_certifications" type="sent" /> - </div> - </div> - </div> - </div> - </transition> - </main> + <main> + <NavigationLoader :isLoading="$apollo.queries.idFromHash.loading" /> + <transition name="fade"> + <div class="alert alert-danger" v-if="error">{{ error }}</div> + </transition> + <transition name="fade"> + <div v-if="idFromHash"> + <div class="container-md"> + <div class="row"> + <div class="col-lg-9 col-xl-8 mx-auto my-3"> + <MemberCard :hash="idFromHash" /> + </div> + </div> + </div> + <div class="container"> + <div class="row mt-3" v-if="idFromHash.status != 'REVOKED'"> + <div class="col-sm-10 col-md-7 col-lg-5 mb-3 mx-auto"> + <h3 + class="h4 text-center" + :class="{ + 'text-success': + ['NEWCOMER', 'MISSING'].includes(idFromHash.status) && + idFromHash.received_certifications.certifications.length >= + 5, + 'text-danger': + ['NEWCOMER', 'MISSING'].includes(idFromHash.status) && + idFromHash.received_certifications.certifications.length < 5 + }"> + {{ $t("certifications.recues") }} ({{ nbCertifs("received") + }}<span v-if="nbCertifsPending('received') != 0">{{ + " + " + nbCertifsPending("received") + }}</span + >) + <BadgeCertifStatus + :limitDate="idFromHash.received_certifications.limit" + :memberStatus="idFromHash.status" /> + </h3> + <CertifList + :certifs="idFromHash.received_certifications.certifications" + type="received" /> + </div> + <div + class="col-sm-10 col-md-7 col-lg-5 mx-auto" + v-if="['MISSING', 'MEMBER'].includes(idFromHash.status)"> + <h3 class="h4 text-center"> + {{ $t("certifications.envoyees") }} ({{ nbCertifs("sent") + }}<span v-if="nbCertifsPending('sent') != 0">{{ + " + " + nbCertifsPending("sent") + }}</span + >) + </h3> + <CertifList + :certifs="idFromHash.sent_certifications" + type="sent" /> + </div> + </div> + </div> + </div> + </transition> + </main> </template> <script> -import {SEARCH_MEMBER} from "@/graphql/queries" -import CertifStatus from '~/components/badge/CertifStatus.vue'; +import { SEARCH_MEMBER } from "@/graphql/queries" +import CertifStatus from "~/components/badge/CertifStatus.vue" export default { - components: { CertifStatus }, - data() { - return { - breadcrumb: [ - { - text: this.$t('accueil'), - to: '/' - }, - { - text: this.$t('membres'), - to: '/membres' - }, - { - text: '', - active: true - } - ], - error: null - }; - }, - methods: { - nbCertifs(sens) { - return sens == "received" ? this.idFromHash.received_certifications.certifications.filter((el) => {return el.pending == false}).length : this.idFromHash.sent_certifications.filter((el) => {return el.pending == false}).length - }, - nbCertifsPending(sens) { - return sens == "received" ? this.idFromHash.received_certifications.certifications.filter((el) => {return el.pending == true}).length : this.idFromHash.sent_certifications.filter((el) => {return el.pending == true}).length - } - }, - apollo: { - idFromHash: { - query: SEARCH_MEMBER, - variables() {return { hash: this.$route.params.hash }}, - error (err) {this.error = err.message} - } - }, - nuxtI18n: { - paths: { - fr: '/membres/:hash', - en: '/members/:hash', - es: '/miembros/:hash' - } - }, - computed: { - classWarning() { - return { - 'text-danger' : !this.idFromHash.received_certifications.limit, - 'text-warning' : this.$options.filters.dateStatus(this.idFromHash.received_certifications.limit) == 'warning' - } - } - }, - mounted() { - $nuxt.$emit("changeRoute", this.breadcrumb) - }, - watch: { - idFromHash: { - handler(n,o) { - this.breadcrumb[2].text = this.idFromHash.uid - $nuxt.$emit("changeRoute", this.breadcrumb) - } - } - } -}; -</script> \ No newline at end of file + components: { CertifStatus }, + data() { + return { + breadcrumb: [ + { + text: this.$t("accueil"), + to: "/" + }, + { + text: this.$t("membres"), + to: "/membres" + }, + { + text: "", + active: true + } + ], + error: null + } + }, + methods: { + nbCertifs(sens) { + return sens == "received" + ? this.idFromHash.received_certifications.certifications.filter( + (el) => { + return el.pending == false + } + ).length + : this.idFromHash.sent_certifications.filter((el) => { + return el.pending == false + }).length + }, + nbCertifsPending(sens) { + return sens == "received" + ? this.idFromHash.received_certifications.certifications.filter( + (el) => { + return el.pending == true + } + ).length + : this.idFromHash.sent_certifications.filter((el) => { + return el.pending == true + }).length + } + }, + apollo: { + idFromHash: { + query: SEARCH_MEMBER, + variables() { + return { hash: this.$route.params.hash } + }, + error(err) { + this.error = err.message + } + } + }, + nuxtI18n: { + paths: { + fr: "/membres/:hash", + en: "/members/:hash", + es: "/miembros/:hash" + } + }, + computed: { + classWarning() { + return { + "text-danger": !this.idFromHash.received_certifications.limit, + "text-warning": + this.$options.filters.dateStatus( + this.idFromHash.received_certifications.limit + ) == "warning" + } + } + }, + mounted() { + $nuxt.$emit("changeRoute", this.breadcrumb) + }, + watch: { + idFromHash: { + handler(n, o) { + this.breadcrumb[2].text = this.idFromHash.uid + $nuxt.$emit("changeRoute", this.breadcrumb) + } + } + } +} +</script> diff --git a/pages/membres/index.vue b/pages/membres/index.vue index d367653..6dfd4c9 100644 --- a/pages/membres/index.vue +++ b/pages/membres/index.vue @@ -1,73 +1,92 @@ <template> -<main class="container"> - <h2 class="text-center mb-5 font-weight-light">{{ $t('membres') }}</h2> - <div class="row mb-4"> - <div class="col-6 m-auto text-center"> - <label for="rech" class="form-label">{{ $t('recherche.title') }}</label> - <input type="text" class="form-control" id="rech" aria-describedby="rechHelp" v-model="param" autocomplete="off" @keyup="save"> - <small id="rechHelp" class="form-text text-muted">{{ $t('recherche.desc') }}</small> - </div> - </div> - <NavigationLoader :isLoading="$apollo.queries.idSearch.loading" /> - <transition name="fade"> - <div class="alert alert-danger" v-if="error">{{ error }}</div> - </transition> - <transition name="fade"> - <div class="row" v-if="idSearch && param.length>2 && !$apollo.queries.idSearch.loading"> - <div class="col-8 m-auto"> - <MemberList :members="idSearch.ids"/> - </div> - </div> - </transition> -</main> + <main class="container"> + <h2 class="text-center mb-5 font-weight-light">{{ $t("membres") }}</h2> + <div class="row mb-4"> + <div class="col-6 m-auto text-center"> + <label for="rech" class="form-label">{{ $t("recherche.title") }}</label> + <input + type="text" + class="form-control" + id="rech" + aria-describedby="rechHelp" + v-model="param" + autocomplete="off" + @keyup="save" /> + <small id="rechHelp" class="form-text text-muted">{{ + $t("recherche.desc") + }}</small> + </div> + </div> + <NavigationLoader :isLoading="$apollo.queries.idSearch.loading" /> + <transition name="fade"> + <div class="alert alert-danger" v-if="error">{{ error }}</div> + </transition> + <transition name="fade"> + <div + class="row" + v-if=" + idSearch && param.length > 2 && !$apollo.queries.idSearch.loading + "> + <div class="col-8 m-auto"> + <MemberList :members="idSearch.ids" /> + </div> + </div> + </transition> + </main> </template> <script> -import {SEARCH_MEMBERS} from '@/graphql/queries' +import { SEARCH_MEMBERS } from "@/graphql/queries" export default { - data() { - return { - breadcrumb: [ - { - text: this.$t('accueil'), - to: '/' - }, - { - text: this.$t('membres'), - active: true - } - ], - param: '', - error: null - } - }, - methods: { - save() { - localStorage.setItem('search', this.param) - } - }, - apollo: { - idSearch : { - query: SEARCH_MEMBERS, - variables() {return {hint:this.param}}, - skip() {return this.param.length < 3}, - error (err) {this.error = err.message} - } - }, - nuxtI18n: { - paths: { - fr: '/membres', - en: '/members', - es: '/miembros' - } - }, - mounted () { - $nuxt.$emit('changeRoute',this.breadcrumb) - // Rechargement du input - if (localStorage.search) { - this.param = localStorage.getItem('search') - } - } + data() { + return { + breadcrumb: [ + { + text: this.$t("accueil"), + to: "/" + }, + { + text: this.$t("membres"), + active: true + } + ], + param: "", + error: null + } + }, + methods: { + save() { + localStorage.setItem("search", this.param) + } + }, + apollo: { + idSearch: { + query: SEARCH_MEMBERS, + variables() { + return { hint: this.param } + }, + skip() { + return this.param.length < 3 + }, + error(err) { + this.error = err.message + } + } + }, + nuxtI18n: { + paths: { + fr: "/membres", + en: "/members", + es: "/miembros" + } + }, + mounted() { + $nuxt.$emit("changeRoute", this.breadcrumb) + // Rechargement du input + if (localStorage.search) { + this.param = localStorage.getItem("search") + } + } } -</script> \ No newline at end of file +</script> diff --git a/pages/parametres.vue b/pages/parametres.vue index 444f71d..a7b0ddf 100644 --- a/pages/parametres.vue +++ b/pages/parametres.vue @@ -1,74 +1,85 @@ <template> -<main class="container"> - <h2 class="text-center mb-5 font-weight-light">{{ $t('params.title') }}</h2> - <NavigationLoader :isLoading="$apollo.queries.allParameters.loading" /> - <transition name="fade"> - <div class="alert alert-danger" v-if="error">{{ error }}</div> - </transition> - <transition name="fade"> - <div class="table-responsive" v-if="allParameters"> - <table class="table table-striped"> - <thead> - <th>{{ $t('nom') }}</th> - <th class="d-none d-sm-table-cell">{{ $t('type') }}</th> - <th>{{ $t('valeur') }}</th> - <th class="d-none d-md-table-cell">{{ $t('description') }}</th> - </thead> - <tbody> - <tr v-for="param in allParameters" :key="param.name"> - <th scope="row">{{ param.name }}</th> - <td scope="row" class="d-none d-sm-table-cell">{{ param.par_type }}</td> - <td scope="row">{{ param.value }}</td> - <td scope="row" class="d-none d-md-table-cell" v-html="$t('params.name.' + param.name)"></td> - </tr> - </tbody> - </table> - </div> - </transition> -</main> + <main class="container"> + <h2 class="text-center mb-5 font-weight-light">{{ $t("params.title") }}</h2> + <NavigationLoader :isLoading="$apollo.queries.allParameters.loading" /> + <transition name="fade"> + <div class="alert alert-danger" v-if="error">{{ error }}</div> + </transition> + <transition name="fade"> + <div class="table-responsive" v-if="allParameters"> + <table class="table table-striped"> + <thead> + <th>{{ $t("nom") }}</th> + <th class="d-none d-sm-table-cell">{{ $t("type") }}</th> + <th>{{ $t("valeur") }}</th> + <th class="d-none d-md-table-cell">{{ $t("description") }}</th> + </thead> + <tbody> + <tr v-for="param in allParameters" :key="param.name"> + <th scope="row">{{ param.name }}</th> + <td scope="row" class="d-none d-sm-table-cell"> + {{ param.par_type }} + </td> + <td scope="row">{{ param.value }}</td> + <td + scope="row" + class="d-none d-md-table-cell" + v-html="$t('params.name.' + param.name)"></td> + </tr> + </tbody> + </table> + </div> + </transition> + </main> </template> <script> -import {PARAMS} from '@/graphql/queries.js' +import { PARAMS } from "@/graphql/queries.js" export default { - data() { - return { - breadcrumb: [ - { - text: this.$t('accueil'), - to: '/' - }, - { - text: this.$t('params.breadcrumb'), - active: true - } - ], - error: null - } - }, - apollo: { - allParameters : { - query: PARAMS, - update (data) { - return data.allParameters.sort((a,b) => { - if (a.name < b.name) {return -1;} - if (a.name > b.name) {return 1;} - return 0; - }) - }, - error (err) {this.error = err.message} - } - }, - nuxtI18n: { - paths: { - fr: '/parametres', - en: '/parameters', - es: '/parametros' - } - }, - mounted () { - $nuxt.$emit('changeRoute',this.breadcrumb) - } + data() { + return { + breadcrumb: [ + { + text: this.$t("accueil"), + to: "/" + }, + { + text: this.$t("params.breadcrumb"), + active: true + } + ], + error: null + } + }, + apollo: { + allParameters: { + query: PARAMS, + update(data) { + return data.allParameters.sort((a, b) => { + if (a.name < b.name) { + return -1 + } + if (a.name > b.name) { + return 1 + } + return 0 + }) + }, + error(err) { + this.error = err.message + } + } + }, + nuxtI18n: { + paths: { + fr: "/parametres", + en: "/parameters", + es: "/parametros" + } + }, + mounted() { + $nuxt.$emit("changeRoute", this.breadcrumb) + } } -</script> \ No newline at end of file +</script> diff --git a/pages/previsions/futurs_membres.vue b/pages/previsions/futurs_membres.vue index cc98a8b..c40b31e 100644 --- a/pages/previsions/futurs_membres.vue +++ b/pages/previsions/futurs_membres.vue @@ -1,199 +1,289 @@ <template> -<main class="container"> - <NavigationLoader :isLoading="$apollo.queries.wwResult.loading" /> - <transition name="fade"> - <div class="alert alert-danger" v-if="error">{{ error }}</div> - </transition> - <transition name="fade"> - <div v-if="wwResult"> - <h2 class="text-center mb-5 font-weight-light">{{ $t('previsions.title') }} <small><span class="badge badge-secondary">{{ $tc('previsions.dossiersattente', wwResult.dossiers_nb) }}</span></small></h2> - <div class="alert alert-info" role="alert"> - <ul class="list-unstyled m-0"> - <li>{{ $tc('previsions.certificationsinternes', wwResult.certifs_nb) }}</li> - <li>{{ $tc('previsions.permutations', wwResult.permutations_nb) }}</li> - </ul> - </div> - <div class="row"> - <div class="col-12 text-center mb-4"> - <div class="form-check form-check-inline"> - <input class="form-check-input" type="radio" id="forecastsByNames" value="forecastsByNames" checked v-model="display" @change="save"> - <label class="form-check-label" for="forecastsByNames"> - {{ $t('tri.parmembres') }} - </label> - </div> - <div class="form-check form-check-inline"> - <input class="form-check-input" type="radio" id="forecastsByDates" value="forecastsByDates" v-model="display" @change="save"> - <label class="form-check-label" for="forecastsByDates"> - {{ $t('tri.pardate') }} - </label> - </div> - </div> - <div class="col-lg-8 m-auto"> - <div v-if="display=='forecastsByNames'"> - <h3>{{ $t('previsions.parmembre') }}</h3> - <div class="table-responsive"> - <table class="table table-striped table-hover"> - <tbody> - <tr v-for="forecast in wwResult.forecastsByNames" :key="forecast.member.uid" @click="$router.push(localePath({name:'membres-hash', params:{hash:forecast.member.hash}}))"> - <th scope="row"> - {{ forecast.member.uid }} - <BadgeStatus :membre="forecast.member" /> - </th> - <td class="p-0"> - <div class="d-flex justify-content-between p-3" v-for="date in forecast.forecasts" :key="date.date"> - <div class="forecast_date mr-3" v-if="date.date<9999999999">{{ $d(new Date(date.date*1000), 'short') }} {{ $t('time.a') }} {{ $d(new Date(date.date*1000), 'hour').replace(" ", " ") }}</div> - <div class="forecast_date mr-3" v-else>N/A</div> - <div>{{ Math.round(date.proba * 100) }} %</div> - </div> - </td> - </tr> - </tbody> - </table> - </div> - </div> - <div v-if="display=='forecastsByDates'"> - <h3>{{ $t('previsions.pardate') }}</h3> - <div class="table-responsive"> - <table class="table table-striped"> - <tbody> - <tr v-for="forecast in wwResult.forecastsByDates" :key="forecast.date"> - <th scope="row" class="forecast_date" v-if="forecast.date<9999999999">{{ $d(new Date(forecast.date*1000), 'short') }} {{ $t('time.a') }} {{ $d(new Date(forecast.date*1000), 'hour') }}</th> - <th scope="row" class="forecast_date" v-else>N/A</th> - <td class="p-0"> - <div class="list-group rounded-0"> - <nuxt-link class="list-group-item list-group-item-action border-0 d-flex justify-content-between" :to="localePath('/membres/' + member.member.hash)" v-for="member in forecast.forecasts" :key="member.member.uid"> - <div class="mr-3">{{ member.member.uid }} <BadgeStatus :membre="member.member" /></div> - <div>{{ Math.round(member.proba * 100) }} %</div> - </nuxt-link> - </div> - </td> - </tr> - </tbody> - </table> - </div> - </div> - </div> - </div> - </div> - </transition> -</main> + <main class="container"> + <NavigationLoader :isLoading="$apollo.queries.wwResult.loading" /> + <transition name="fade"> + <div class="alert alert-danger" v-if="error">{{ error }}</div> + </transition> + <transition name="fade"> + <div v-if="wwResult"> + <h2 class="text-center mb-5 font-weight-light"> + {{ $t("previsions.title") }} + <small + ><span class="badge badge-secondary">{{ + $tc("previsions.dossiersattente", wwResult.dossiers_nb) + }}</span></small + > + </h2> + <div class="alert alert-info" role="alert"> + <ul class="list-unstyled m-0"> + <li> + {{ + $tc("previsions.certificationsinternes", wwResult.certifs_nb) + }} + </li> + <li> + {{ $tc("previsions.permutations", wwResult.permutations_nb) }} + </li> + </ul> + </div> + <div class="row"> + <div class="col-12 text-center mb-4"> + <div class="form-check form-check-inline"> + <input + class="form-check-input" + type="radio" + id="forecastsByNames" + value="forecastsByNames" + checked + v-model="display" + @change="save" /> + <label class="form-check-label" for="forecastsByNames"> + {{ $t("tri.parmembres") }} + </label> + </div> + <div class="form-check form-check-inline"> + <input + class="form-check-input" + type="radio" + id="forecastsByDates" + value="forecastsByDates" + v-model="display" + @change="save" /> + <label class="form-check-label" for="forecastsByDates"> + {{ $t("tri.pardate") }} + </label> + </div> + </div> + <div class="col-lg-8 m-auto"> + <div v-if="display == 'forecastsByNames'"> + <h3>{{ $t("previsions.parmembre") }}</h3> + <div class="table-responsive"> + <table class="table table-striped table-hover"> + <tbody> + <tr + v-for="forecast in wwResult.forecastsByNames" + :key="forecast.member.uid" + @click=" + $router.push( + localePath({ + name: 'membres-hash', + params: { hash: forecast.member.hash } + }) + ) + "> + <th scope="row"> + {{ forecast.member.uid }} + <BadgeStatus :membre="forecast.member" /> + </th> + <td class="p-0"> + <div + class="d-flex justify-content-between p-3" + v-for="date in forecast.forecasts" + :key="date.date"> + <div + class="forecast_date mr-3" + v-if="date.date < 9999999999"> + {{ $d(new Date(date.date * 1000), "short") }} + {{ $t("time.a") }} + {{ + $d(new Date(date.date * 1000), "hour").replace( + " ", + " " + ) + }} + </div> + <div class="forecast_date mr-3" v-else>N/A</div> + <div>{{ Math.round(date.proba * 100) }} %</div> + </div> + </td> + </tr> + </tbody> + </table> + </div> + </div> + <div v-if="display == 'forecastsByDates'"> + <h3>{{ $t("previsions.pardate") }}</h3> + <div class="table-responsive"> + <table class="table table-striped"> + <tbody> + <tr + v-for="forecast in wwResult.forecastsByDates" + :key="forecast.date"> + <th + scope="row" + class="forecast_date" + v-if="forecast.date < 9999999999"> + {{ $d(new Date(forecast.date * 1000), "short") }} + {{ $t("time.a") }} + {{ $d(new Date(forecast.date * 1000), "hour") }} + </th> + <th scope="row" class="forecast_date" v-else>N/A</th> + <td class="p-0"> + <div class="list-group rounded-0"> + <nuxt-link + class="list-group-item list-group-item-action border-0 d-flex justify-content-between" + :to="localePath('/membres/' + member.member.hash)" + v-for="member in forecast.forecasts" + :key="member.member.uid"> + <div class="mr-3"> + {{ member.member.uid }} + <BadgeStatus :membre="member.member" /> + </div> + <div> + {{ Math.round(member.proba * 100) }} % + </div> + </nuxt-link> + </div> + </td> + </tr> + </tbody> + </table> + </div> + </div> + </div> + </div> + </div> + </transition> + </main> </template> <script> -import {NEWCOMERS} from '@/graphql/queries' +import { NEWCOMERS } from "@/graphql/queries" export default { - data() { - return { - breadcrumb: [ - { - text: this.$t('accueil'), - to: '/' - }, - { - text: this.$t('previsions.title'), - to: '/previsions' - }, - { - text: this.$t('futuremembers'), - active: true - } - ], - error: null, - display: 'forecastsByNames' - } - }, - methods: { - save() { - localStorage.setItem('previsions', this.display) - } - }, - apollo: { - wwResult : { - query: NEWCOMERS, - update (data) { - let result = {'byName':[],'byDate':[]} - let forecasts = data.wwResult.forecastsByNames + data() { + return { + breadcrumb: [ + { + text: this.$t("accueil"), + to: "/" + }, + { + text: this.$t("previsions.title"), + to: "/previsions" + }, + { + text: this.$t("futuremembers"), + active: true + } + ], + error: null, + display: "forecastsByNames" + } + }, + methods: { + save() { + localStorage.setItem("previsions", this.display) + } + }, + apollo: { + wwResult: { + query: NEWCOMERS, + update(data) { + let result = { byName: [], byDate: [] } + let forecasts = data.wwResult.forecastsByNames - for (let i = 0; i < forecasts.length; i++) { - let member = forecasts[i].member + for (let i = 0; i < forecasts.length; i++) { + let member = forecasts[i].member - // On traite les forecasts par nom - if (result['byName'].filter(function(e) { return e.member && e.member.uid === member.uid; }).length == 0) { - result['byName'].push({ - member: member, - forecasts: [{ - date: forecasts[i].date, - after: forecasts[i].after, - proba: forecasts[i].proba - }] - }) - } else { - result['byName'].filter(function(e) { return e.member && e.member.uid === member.uid; })[0].forecasts.push({ - date: forecasts[i].date, - after: forecasts[i].after, - proba: forecasts[i].proba - }) - } + // On traite les forecasts par nom + if ( + result["byName"].filter(function (e) { + return e.member && e.member.uid === member.uid + }).length == 0 + ) { + result["byName"].push({ + member: member, + forecasts: [ + { + date: forecasts[i].date, + after: forecasts[i].after, + proba: forecasts[i].proba + } + ] + }) + } else { + result["byName"] + .filter(function (e) { + return e.member && e.member.uid === member.uid + })[0] + .forecasts.push({ + date: forecasts[i].date, + after: forecasts[i].after, + proba: forecasts[i].proba + }) + } - // On traite les forecasts par date - if (result['byDate'].filter(function(e) { return e.date === forecasts[i].date }).length == 0) { - result['byDate'].push({ - date: forecasts[i].date, - forecasts: [{ - member: member, - after: forecasts[i].after, - proba: forecasts[i].proba - }] - }) - } else { - result['byDate'].filter(function(e) { return e.date === forecasts[i].date })[0].forecasts.push({ - member: member, - after: forecasts[i].after, - proba: forecasts[i].proba - }) - } - } + // On traite les forecasts par date + if ( + result["byDate"].filter(function (e) { + return e.date === forecasts[i].date + }).length == 0 + ) { + result["byDate"].push({ + date: forecasts[i].date, + forecasts: [ + { + member: member, + after: forecasts[i].after, + proba: forecasts[i].proba + } + ] + }) + } else { + result["byDate"] + .filter(function (e) { + return e.date === forecasts[i].date + })[0] + .forecasts.push({ + member: member, + after: forecasts[i].after, + proba: forecasts[i].proba + }) + } + } - result['byDate'].sort((a, b) => (a.date > b.date) ? 1 : -1) + result["byDate"].sort((a, b) => (a.date > b.date ? 1 : -1)) - return { - permutations_nb: data.wwResult.permutations_nb, - dossiers_nb: data.wwResult.dossiers_nb, - certifs_nb: data.wwResult.certifs_nb, - forecastsByNames: result['byName'], - forecastsByDates: result['byDate'] - } - }, - error (err) {this.error = err.message} - } - }, - nuxtI18n: { - paths: { - fr: '/previsions/futurs_membres', - en: '/forecasts/future_members', - es: '/pronosticos/futuros_miembros' - } - }, - mounted () { - $nuxt.$emit('changeRoute',this.breadcrumb) - if (localStorage.previsions) { - this.display = localStorage.getItem('previsions') - } - } + return { + permutations_nb: data.wwResult.permutations_nb, + dossiers_nb: data.wwResult.dossiers_nb, + certifs_nb: data.wwResult.certifs_nb, + forecastsByNames: result["byName"], + forecastsByDates: result["byDate"] + } + }, + error(err) { + this.error = err.message + } + } + }, + nuxtI18n: { + paths: { + fr: "/previsions/futurs_membres", + en: "/forecasts/future_members", + es: "/pronosticos/futuros_miembros" + } + }, + mounted() { + $nuxt.$emit("changeRoute", this.breadcrumb) + if (localStorage.previsions) { + this.display = localStorage.getItem("previsions") + } + } } </script> <style lang="scss" scoped> .list-group-item { - background: transparent; - &:hover { - background: rgba(0, 0, 255, 0.075); - color: var(--text-primary-color); - } + background: transparent; + &:hover { + background: rgba(0, 0, 255, 0.075); + color: var(--text-primary-color); + } } .forecast_date { - min-width: 150px; + min-width: 150px; } -</style> \ No newline at end of file +</style> diff --git a/pages/previsions/index.vue b/pages/previsions/index.vue index ba77d5d..bee732c 100644 --- a/pages/previsions/index.vue +++ b/pages/previsions/index.vue @@ -1,63 +1,65 @@ <template> -<main class="container"> - <h2 class="text-center mb-5 font-weight-light">En préparation</h2> - <div class="alert alert-danger">En développement</div> - <NavigationLoader :isLoading="$apollo.queries.previsions.loading" /> - <transition name="fade"> - <div class="alert alert-danger" v-if="error">{{ error }}</div> - </transition> - <transition name="fade"> - <div v-if="previsions"> - {{ previsions }} - </div> - </transition> -</main> + <main class="container"> + <h2 class="text-center mb-5 font-weight-light">En préparation</h2> + <div class="alert alert-danger">En développement</div> + <NavigationLoader :isLoading="$apollo.queries.previsions.loading" /> + <transition name="fade"> + <div class="alert alert-danger" v-if="error">{{ error }}</div> + </transition> + <transition name="fade"> + <div v-if="previsions"> + {{ previsions }} + </div> + </transition> + </main> </template> <script> -import {PREVISIONS} from '@/graphql/queries' +import { PREVISIONS } from "@/graphql/queries" export default { - data() { - return { - breadcrumb: [ - { - text: this.$t('accueil'), - to: '/' - }, - { - text: this.$t('previsions.title'), - active: true - } - ], - display: 'forecastsByNames', - error: null - } - }, - apollo: { - previsions : { - query: PREVISIONS, - update (data) { - return { - // now: data.now, - // sigQty: data.parameter.sigQty, - // certifs_dossiers: data.wwFile.certifs_dossiers - data - } - }, - error (err) {this.error = err.message} - } - }, - nuxtI18n: { - paths: { - fr: '/previsions', - en: '/forecasts', - es: '/pronosticos' - } - }, - mounted () { - // Mise à jour du fil d'ariane au chargement - $nuxt.$emit('changeRoute',this.breadcrumb) - } + data() { + return { + breadcrumb: [ + { + text: this.$t("accueil"), + to: "/" + }, + { + text: this.$t("previsions.title"), + active: true + } + ], + display: "forecastsByNames", + error: null + } + }, + apollo: { + previsions: { + query: PREVISIONS, + update(data) { + return { + // now: data.now, + // sigQty: data.parameter.sigQty, + // certifs_dossiers: data.wwFile.certifs_dossiers + data + } + }, + error(err) { + this.error = err.message + } + } + }, + nuxtI18n: { + paths: { + fr: "/previsions", + en: "/forecasts", + es: "/pronosticos" + } + }, + mounted() { + // Mise à jour du fil d'ariane au chargement + $nuxt.$emit("changeRoute", this.breadcrumb) + } } -</script> \ No newline at end of file +</script> diff --git a/pages/template.vue b/pages/template.vue index 38d0caf..33c3972 100644 --- a/pages/template.vue +++ b/pages/template.vue @@ -1,13 +1,18 @@ <template> -<main class="container"> - <h2 class="text-center mb-5 font-weight-light">{{ myvar }}</h2> - <code>For internal links, use <NuxtLink :to="localePath('path/page')">My link</NuxtLink></code> - <p>Use <code>$t() and $d()</code> functions to translate strings and dates</p> - <!-- <NavigationLoader :isLoading="$apollo.queries.myresponse.loading" /> --> - <!-- <transition name="fade"> + <main class="container"> + <h2 class="text-center mb-5 font-weight-light">{{ myvar }}</h2> + <code + >For internal links, use + <NuxtLink :to="localePath('path/page')">My link</NuxtLink></code + > + <p> + Use <code>$t() and $d()</code> functions to translate strings and dates + </p> + <!-- <NavigationLoader :isLoading="$apollo.queries.myresponse.loading" /> --> + <!-- <transition name="fade"> <div class="alert alert-danger" v-if="error">{{ error }}</div> </transition> --> - <!-- <transition name="fade"> + <!-- <transition name="fade"> <div class="result" v-if="myresponse"> <div class="row text-center"> <div class="col-lg-6"> @@ -16,7 +21,7 @@ </div> </div> </transition> --> -</main> + </main> </template> <script> @@ -24,69 +29,67 @@ // import {MY_QUERY} from '@/graphql/queries.js' export default { - data() { - // local variables - return { - breadcrumb: [ - { - text: this.$t('accueil'), - to: '/' - }, - { - // Translations are stored in ./i18n/locales folder - text: this.$t('mypage.mytitle'), - active: true - } - ], - error: null, - myvar : "Hello World !" - } - }, - // local functions. You can use : - // {{ myFunction() }} in template if a value is returned - // - this.myFunction everywhere in the page but not in arrows functions - // - @event="myFunction" on Vue eventHandlers - // methods: { - // myFunction() { - - // } - // }, - // For computed values. Use {{ myComputedValue }} in the template - // computed: { - // myComputedValue : function() { - // return this.var * 3 - // } - // }, - // apollo: { - // // Use {{ myresponse }} in the template. If update is omitted, this name should correspond to the Query Type ! - // myresponse : { - // query: MY_QUERY, - // // Optional : this is for parametered queries - // // variables() {return {param1:value1,param2:value2}}, - // // Optional : treat the response before display. If omitted, the query name must correspond to the Query Type ! - // // update (data) { - - // // return data - // // }, - // error (err) {this.error = err.message} - // } - // }, - // Route's i18n (Need to rebuild App) - nuxtI18n: { - paths: { - fr: '/mapage', - en: '/mypage', - es: '/mipagina' - } - }, - mounted () { - // Update breadcrumb when the page is displayed - $nuxt.$emit('changeRoute',this.breadcrumb) - } + data() { + // local variables + return { + breadcrumb: [ + { + text: this.$t("accueil"), + to: "/" + }, + { + // Translations are stored in ./i18n/locales folder + text: this.$t("mypage.mytitle"), + active: true + } + ], + error: null, + myvar: "Hello World !" + } + }, + // local functions. You can use : + // {{ myFunction() }} in template if a value is returned + // - this.myFunction everywhere in the page but not in arrows functions + // - @event="myFunction" on Vue eventHandlers + // methods: { + // myFunction() { + + // } + // }, + // For computed values. Use {{ myComputedValue }} in the template + // computed: { + // myComputedValue : function() { + // return this.var * 3 + // } + // }, + // apollo: { + // // Use {{ myresponse }} in the template. If update is omitted, this name should correspond to the Query Type ! + // myresponse : { + // query: MY_QUERY, + // // Optional : this is for parametered queries + // // variables() {return {param1:value1,param2:value2}}, + // // Optional : treat the response before display. If omitted, the query name must correspond to the Query Type ! + // // update (data) { + + // // return data + // // }, + // error (err) {this.error = err.message} + // } + // }, + // Route's i18n (Need to rebuild App) + nuxtI18n: { + paths: { + fr: "/mapage", + en: "/mypage", + es: "/mipagina" + } + }, + mounted() { + // Update breadcrumb when the page is displayed + $nuxt.$emit("changeRoute", this.breadcrumb) + } } </script> <!-- Add "scoped" attribute to limit CSS to this page only --> -<style lang="scss" scoped> - -</style> \ No newline at end of file +<style lang="scss" scoped></style> diff --git a/plugins/filters.js b/plugins/filters.js index d66a273..1654212 100644 --- a/plugins/filters.js +++ b/plugins/filters.js @@ -1,13 +1,13 @@ import Vue from 'vue' Vue.filter('dateStatus', (val) => { - const diff = val - (Date.now()/1000) + const diff = val - (Date.now() / 1000) switch (true) { - case diff<0: + case diff < 0: return 'danger' - case diff<2635200: + case diff < 2635200: return 'warning' - case diff>=2635200: + case diff >= 2635200: return 'success' } }) \ No newline at end of file -- GitLab