From 7194a3c93744080e47e197d450cbcddfe82ed51e Mon Sep 17 00:00:00 2001 From: Brendan Le Ny <bleny@codelutin.com> Date: Tue, 1 Jun 2021 11:54:07 +0200 Subject: [PATCH 01/27] =?UTF-8?q?Change=20l'information=20retourn=C3=A9e?= =?UTF-8?q?=20au=20frontend=20pour=20d=C3=A9crire=20une=20application=20po?= =?UTF-8?q?ur=20quelque-chose=20de=20plus=20adapt=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../inra/oresing/rest/ApplicationResult.java | 23 +++++++++++++++++++ .../fr/inra/oresing/rest/OreSiResources.java | 10 ++++++-- .../inra/oresing/rest/OreSiResourcesTest.java | 12 ++++------ 3 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 src/main/java/fr/inra/oresing/rest/ApplicationResult.java diff --git a/src/main/java/fr/inra/oresing/rest/ApplicationResult.java b/src/main/java/fr/inra/oresing/rest/ApplicationResult.java new file mode 100644 index 000000000..3f3af5e07 --- /dev/null +++ b/src/main/java/fr/inra/oresing/rest/ApplicationResult.java @@ -0,0 +1,23 @@ +package fr.inra.oresing.rest; + +import lombok.Value; + +import java.util.Map; + +@Value +public class ApplicationResult { + String id; + String name; + String title; + Map<String, Reference> references; + + @Value + public static class Reference { + Map<String, Column> columns; + + @Value + public static class Column { + String title; + } + } +} diff --git a/src/main/java/fr/inra/oresing/rest/OreSiResources.java b/src/main/java/fr/inra/oresing/rest/OreSiResources.java index 6be34e4b2..82d5412be 100644 --- a/src/main/java/fr/inra/oresing/rest/OreSiResources.java +++ b/src/main/java/fr/inra/oresing/rest/OreSiResources.java @@ -1,6 +1,7 @@ package fr.inra.oresing.rest; import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; import fr.inra.oresing.checker.CheckerException; import fr.inra.oresing.model.Application; import fr.inra.oresing.model.BinaryFile; @@ -81,9 +82,14 @@ public class OreSiResources { } @GetMapping(value = "/applications/{nameOrId}", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity<Application> getApplication(@PathVariable("nameOrId") String nameOrId) { + public ResponseEntity<ApplicationResult> getApplication(@PathVariable("nameOrId") String nameOrId) { Application application = service.getApplication(nameOrId); - return ResponseEntity.ok(application); + Map<String, ApplicationResult.Reference> references = Maps.transformValues(application.getConfiguration().getReferences(), referenceDescription -> { + Map<String, ApplicationResult.Reference.Column> columns = Maps.transformEntries(referenceDescription.getColumns(), (column, columnDescription) -> new ApplicationResult.Reference.Column(column)); + return new ApplicationResult.Reference(columns); + }); + ApplicationResult applicationResult = new ApplicationResult(application.getId().toString(), application.getName(), application.getConfiguration().getApplication().getName(), references); + return ResponseEntity.ok(applicationResult); } @GetMapping(value = "/applications/{nameOrId}/configuration", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) diff --git a/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java b/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java index dbc430eda..a72b8524a 100644 --- a/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java +++ b/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java @@ -5,7 +5,6 @@ import com.google.common.base.Charsets; import com.google.common.io.Resources; import com.jayway.jsonpath.JsonPath; import fr.inra.oresing.OreSiNg; -import fr.inra.oresing.model.Application; import fr.inra.oresing.model.OreSiUser; import fr.inra.oresing.persistence.AuthenticationService; import lombok.extern.slf4j.Slf4j; @@ -37,9 +36,9 @@ import javax.servlet.http.Cookie; import java.io.InputStream; import java.net.URL; import java.nio.charset.StandardCharsets; -import java.util.Date; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -118,12 +117,11 @@ public class OreSiResourcesTest { .andExpect(jsonPath("$.id", Is.is(appId))) .andReturn().getResponse().getContentAsString(); - Application app2 = objectMapper.readValue(response, Application.class); + ApplicationResult applicationResult = objectMapper.readValue(response, ApplicationResult.class); - Date now = new Date(); - Assert.assertEquals("monsore", app2.getName()); - Assert.assertEquals(List.of("especes", "projet", "sites", "themes", "type de fichiers", "type_de_sites", "types_de_donnees_par_themes_de_sites_et_projet", "unites", "valeurs_qualitatives", "variables", "variables_et_unites_par_types_de_donnees"), app2.getReferenceType()); - Assert.assertEquals(List.of("pem"), app2.getDataType()); + Assert.assertEquals("monsore", applicationResult.getName()); + Assert.assertEquals(Set.of("especes", "projet", "sites", "themes", "type de fichiers", "type_de_sites", "types_de_donnees_par_themes_de_sites_et_projet", "unites", "valeurs_qualitatives", "variables", "variables_et_unites_par_types_de_donnees"), applicationResult.getReferences().keySet()); +// Assert.assertEquals(List.of("pem"), applicationResult.getDataType()); // Ajout de referentiel for (Map.Entry<String, String> e : fixtures.getMonsoreReferentielFiles().entrySet()) { -- GitLab From ec58e452fa808f002c35a36173b5345f76881851 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Tue, 1 Jun 2021 12:05:27 +0200 Subject: [PATCH 02/27] =?UTF-8?q?Cr=C3=A9e=20une=20ApplicationDetailsPage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui2/src/router/index.js | 11 +++++++++-- ui2/src/services/rest/ApplicationService.js | 4 ++++ ui2/src/style/_common.scss | 4 ++++ .../ApplicationCreationView.vue | 0 .../application/ApplicationDetailsView.vue | 13 +++++++++++++ .../{ => application}/ApplicationsView.vue | 17 ++++++++++++++--- 6 files changed, 44 insertions(+), 5 deletions(-) rename ui2/src/views/{ => application}/ApplicationCreationView.vue (100%) create mode 100644 ui2/src/views/application/ApplicationDetailsView.vue rename ui2/src/views/{ => application}/ApplicationsView.vue (74%) diff --git a/ui2/src/router/index.js b/ui2/src/router/index.js index e72efccf6..357e31fd9 100644 --- a/ui2/src/router/index.js +++ b/ui2/src/router/index.js @@ -1,8 +1,9 @@ import Vue from "vue"; import VueRouter from "vue-router"; import LoginView from "@/views/LoginView.vue"; -import ApplicationsView from "@/views/ApplicationsView.vue"; -import ApplicationCreationView from "@/views/ApplicationCreationView.vue"; +import ApplicationsView from "@/views/application/ApplicationsView.vue"; +import ApplicationCreationView from "@/views/application/ApplicationCreationView.vue"; +import ApplicationDetailsView from "@/views/application/ApplicationDetailsView.vue"; Vue.use(VueRouter); @@ -26,6 +27,12 @@ const routes = [ name: "Application creation", component: ApplicationCreationView, }, + { + path: "/application/:name", + name: "Application view", + component: ApplicationDetailsView, + props: true, + }, ]; const router = new VueRouter({ diff --git a/ui2/src/services/rest/ApplicationService.js b/ui2/src/services/rest/ApplicationService.js index 2a6737154..30b8561f7 100644 --- a/ui2/src/services/rest/ApplicationService.js +++ b/ui2/src/services/rest/ApplicationService.js @@ -16,4 +16,8 @@ export class ApplicationService extends Fetcher { async getApplications() { return this.get("applications/"); } + + async getApplication(id) { + return this.get("applications/" + id); + } } diff --git a/ui2/src/style/_common.scss b/ui2/src/style/_common.scss index 0237eb0c7..e9eaf9c75 100644 --- a/ui2/src/style/_common.scss +++ b/ui2/src/style/_common.scss @@ -19,6 +19,10 @@ a { color: $info; } +.clickable { + cursor: pointer; +} + // Input style .input-field { diff --git a/ui2/src/views/ApplicationCreationView.vue b/ui2/src/views/application/ApplicationCreationView.vue similarity index 100% rename from ui2/src/views/ApplicationCreationView.vue rename to ui2/src/views/application/ApplicationCreationView.vue diff --git a/ui2/src/views/application/ApplicationDetailsView.vue b/ui2/src/views/application/ApplicationDetailsView.vue new file mode 100644 index 000000000..39c79b372 --- /dev/null +++ b/ui2/src/views/application/ApplicationDetailsView.vue @@ -0,0 +1,13 @@ +<template> + <PageView> </PageView> +</template> + +<script> +import { Component, Vue } from "vue-property-decorator"; +import PageView from "@/views/common/PageView.vue"; + +@Component({ + components: { PageView }, +}) +export default class ApplicationDetailsView extends Vue {} +</script> diff --git a/ui2/src/views/ApplicationsView.vue b/ui2/src/views/application/ApplicationsView.vue similarity index 74% rename from ui2/src/views/ApplicationsView.vue rename to ui2/src/views/application/ApplicationsView.vue index e6845c3e6..ec72b6dce 100644 --- a/ui2/src/views/ApplicationsView.vue +++ b/ui2/src/views/application/ApplicationsView.vue @@ -18,10 +18,14 @@ height="100%" > <b-table-column field="name" label="Name" sortable width="50%" v-slot="props"> - {{ props.row.name }} + <div @click="displayApplication(props.row)" class="clickable"> + {{ props.row.name }} + </div> </b-table-column> <b-table-column field="creationDate" label="Creation Date" sortable v-slot="props"> - {{ new Date(props.row.creationDate) }} + <div @click="displayApplication(props.row)" class="clickable"> + {{ new Date(props.row.creationDate) }} + </div> </b-table-column> </b-table> </PageView> @@ -31,7 +35,7 @@ <script> import { ApplicationService } from "@/services/rest/ApplicationService"; import { Component, Vue } from "vue-property-decorator"; -import PageView from "./common/PageView.vue"; +import PageView from "@/views/common/PageView.vue"; @Component({ components: { PageView }, @@ -52,5 +56,12 @@ export default class ApplicationsView extends Vue { createApplication() { this.$router.push("/applicationCreation"); } + + displayApplication(application) { + if (!application) { + return; + } + this.$router.push("/application/" + application.name); + } } </script> -- GitLab From 6103ab7c1345f71bd65b63eb4f809cd45014d6d0 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Tue, 1 Jun 2021 18:00:46 +0200 Subject: [PATCH 03/27] =?UTF-8?q?Ajoute=20la=20s=C3=A9lection=20de=20r?= =?UTF-8?q?=C3=A9f=C3=A9rentiels=20et=20dataset?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/DatasetSelection.vue | 43 +++++++++++++ .../application/ReferenceSelection.vue | 42 +++++++++++++ ui2/src/locales/en.json | 12 +++- ui2/src/locales/fr.json | 12 +++- ui2/src/main.js | 8 ++- ui2/src/router/index.js | 2 +- ui2/src/services/rest/ApplicationService.js | 12 +++- .../application/ApplicationDetailsView.vue | 42 +++++++++++-- .../views/application/ApplicationsView.vue | 60 +++++++++---------- ui2/src/views/common/PageView.vue | 8 ++- 10 files changed, 199 insertions(+), 42 deletions(-) create mode 100644 ui2/src/components/application/DatasetSelection.vue create mode 100644 ui2/src/components/application/ReferenceSelection.vue diff --git a/ui2/src/components/application/DatasetSelection.vue b/ui2/src/components/application/DatasetSelection.vue new file mode 100644 index 000000000..0e2bae73f --- /dev/null +++ b/ui2/src/components/application/DatasetSelection.vue @@ -0,0 +1,43 @@ +<template> + <div> + <b-select + v-model="chosenDataType" + :placeholder="$t('datasetSelection.placeholder')" + @input="loadDataset" + expanded + v-if="application" + > + <option v-for="type in application.dataType" :key="type" :value="type"> + {{ type }} + </option> + </b-select> + </div> +</template> + +<script> +import { ApplicationService } from "@/services/rest/ApplicationService"; +import { Component, Prop, Vue } from "vue-property-decorator"; + +@Component({ + components: {}, +}) +export default class DatasetSelection extends Vue { + @Prop() application; + + applicationService = ApplicationService.INSTANCE; + + chosenDataType = null; + dataset = null; + + async loadDataset() { + try { + this.dataset = await this.applicationService.getDataset( + this.chosenDataType, + this.application.name + ); + } catch (error) { + this.alertService.toastServerError(); + } + } +} +</script> diff --git a/ui2/src/components/application/ReferenceSelection.vue b/ui2/src/components/application/ReferenceSelection.vue new file mode 100644 index 000000000..cd54b192e --- /dev/null +++ b/ui2/src/components/application/ReferenceSelection.vue @@ -0,0 +1,42 @@ +<template> + <div> + <b-select + v-model="chosenReferenceType" + :placeholder="$t('referenceSelection.placeholder')" + @input="getReference" + expanded + v-if="application" + > + <option v-for="type in application.referenceType" :key="type" :value="type"> + {{ type }} + </option> + </b-select> + </div> +</template> + +<script> +import { ApplicationService } from "@/services/rest/ApplicationService"; +import { Component, Prop, Vue } from "vue-property-decorator"; + +@Component({ + components: {}, +}) +export default class ReferenceSelection extends Vue { + @Prop() application; + applicationService = ApplicationService.INSTANCE; + + chosenReferenceType = null; + reference = null; + + async getReference() { + try { + this.reference = await this.applicationService.getReference( + this.chosenReferenceType, + this.application.name + ); + } catch (error) { + this.alertService.toastServerError(); + } + } +} +</script> diff --git a/ui2/src/locales/en.json b/ui2/src/locales/en.json index 7be687b97..b84ae454d 100644 --- a/ui2/src/locales/en.json +++ b/ui2/src/locales/en.json @@ -34,7 +34,6 @@ "menu": { "logout": "Log out", "applications": "Applications", - "references": "References", "french": "Français", "english": "English", "language": "Language" @@ -66,5 +65,16 @@ "unknownCheckerName": "For the validation rule : <code>{lineValidationRuleKey}</code>, '<code>{checkerName}</code>' is declared but is not a known checker", "csvBoundToUnknownVariable": "In the CSV format, header <code>{header}</code> is bound to unknown variable <code>{variable}</code>. Known variables: <code>{variables}</code>", "csvBoundToUnknownVariableComponent": "In the CSV format, header <code>{header}</code> is bound to <code>{variable}</code> but it has no <code>{component}</code> component. Known components: <code>{components}</code>" + }, + "applicationDetailsView": { + "application": "Application details", + "references": "References", + "dataset": "Datasets" + }, + "referenceSelection": { + "placeholder": "Chose the reference" + }, + "datasetSelection": { + "placeholder": "Chose the dataset" } } diff --git a/ui2/src/locales/fr.json b/ui2/src/locales/fr.json index 1cc85cb59..dfabff25b 100644 --- a/ui2/src/locales/fr.json +++ b/ui2/src/locales/fr.json @@ -34,7 +34,6 @@ "menu": { "logout": "Se déconnecter", "applications": "Applications", - "references": "Référentiels", "french": "Français", "english": "English", "language": "Langue" @@ -66,5 +65,16 @@ "unknownCheckerName": "Pour la règle de validation <code>{lineValidationRuleKey}</code>, '<code>{checkerName}</code>' est déclaré mais ce n’est pas un contrôle connu", "csvBoundToUnknownVariable": "Dans le format CSV, l’entête <code>{header}</code> est lié à la variable <code>{variable}</code> qui n'est pas connue. Variables connues <code>{variables}</code>", "csvBoundToUnknownVariableComponent": "Dans le format CSV, l’entête <code>{header}</code> est lié à la variable <code>{variable}</code> mais elle n'a pas de composant <code>{component}</code>. <br>Composants connus <code>{components}</code>" + }, + "applicationDetailsView": { + "application": "Détail de l'application", + "references": "Référentiels", + "dataset": "Données" + }, + "referenceSelection": { + "placeholder": "Choisir le référentiel" + }, + "datasetSelection": { + "placeholder": "Choisir les données" } } diff --git a/ui2/src/main.js b/ui2/src/main.js index 6ac7201b9..b04fe18ba 100644 --- a/ui2/src/main.js +++ b/ui2/src/main.js @@ -10,13 +10,16 @@ import { faArrowDown, faArrowUp, faCheck, + faDraftingCompass, faExclamationCircle, faEye, faEyeSlash, faGlobe, faPlus, + faPoll, faSignOutAlt, faUpload, + faWrench, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; library.add( @@ -31,7 +34,10 @@ library.add( faArrowUp, faArrowDown, faAngleLeft, - faAngleRight + faAngleRight, + faWrench, + faPoll, + faDraftingCompass ); Vue.component("vue-fontawesome", FontAwesomeIcon); diff --git a/ui2/src/router/index.js b/ui2/src/router/index.js index 357e31fd9..41b14e4e9 100644 --- a/ui2/src/router/index.js +++ b/ui2/src/router/index.js @@ -28,7 +28,7 @@ const routes = [ component: ApplicationCreationView, }, { - path: "/application/:name", + path: "/application/:applicationName", name: "Application view", component: ApplicationDetailsView, props: true, diff --git a/ui2/src/services/rest/ApplicationService.js b/ui2/src/services/rest/ApplicationService.js index 30b8561f7..15b15358f 100644 --- a/ui2/src/services/rest/ApplicationService.js +++ b/ui2/src/services/rest/ApplicationService.js @@ -17,7 +17,15 @@ export class ApplicationService extends Fetcher { return this.get("applications/"); } - async getApplication(id) { - return this.get("applications/" + id); + async getApplication(name) { + return this.get("applications/" + name); + } + + async getDataset(dataset, applicationName) { + return this.get(`applications/${applicationName}/data/${dataset}`); + } + + async getReference(reference, applicationName) { + return this.get(`applications/${applicationName}/references/${reference}`); } } diff --git a/ui2/src/views/application/ApplicationDetailsView.vue b/ui2/src/views/application/ApplicationDetailsView.vue index 39c79b372..9cb155a83 100644 --- a/ui2/src/views/application/ApplicationDetailsView.vue +++ b/ui2/src/views/application/ApplicationDetailsView.vue @@ -1,13 +1,47 @@ <template> - <PageView> </PageView> + <PageView> + <h1 class="title main-title">{{ applicationName }}</h1> + <b-tabs type="is-boxed" expanded class="mt-4"> + <b-tab-item :label="$t('applicationDetailsView.application')" icon="wrench"> </b-tab-item> + <b-tab-item :label="$t('applicationDetailsView.references')" icon="drafting-compass"> + <ReferenceSelection :key="application.id" :application="application" /> + </b-tab-item> + <b-tab-item :label="$t('applicationDetailsView.dataset')" icon="poll"> + <DatasetSelection :key="application.id" :application="application" /> + </b-tab-item> + </b-tabs> + </PageView> </template> <script> -import { Component, Vue } from "vue-property-decorator"; +import { Component, Prop, Vue } from "vue-property-decorator"; import PageView from "@/views/common/PageView.vue"; +import ReferenceSelection from "@/components/application/ReferenceSelection.vue"; +import { Application } from "@/model/Application"; +import { ApplicationService } from "@/services/rest/ApplicationService"; +import { AlertService } from "@/services/AlertService"; +import DatasetSelection from "@/components/application/DatasetSelection.vue"; @Component({ - components: { PageView }, + components: { PageView, ReferenceSelection, DatasetSelection }, }) -export default class ApplicationDetailsView extends Vue {} +export default class ApplicationDetailsView extends Vue { + @Prop() applicationName; + + applicationService = ApplicationService.INSTANCE; + alertService = AlertService.INSTANCE; + application = new Application(); + + created() { + this.init(); + } + + async init() { + try { + this.application = await this.applicationService.getApplication(this.applicationName); + } catch (error) { + this.alertService.toastServerError(); + } + } +} </script> diff --git a/ui2/src/views/application/ApplicationsView.vue b/ui2/src/views/application/ApplicationsView.vue index ec72b6dce..1f3358273 100644 --- a/ui2/src/views/application/ApplicationsView.vue +++ b/ui2/src/views/application/ApplicationsView.vue @@ -1,35 +1,33 @@ <template> - <div> - <PageView> - <h1 class="title main-title">{{ $t("titles.applications-page") }}</h1> - <div class="buttons"> - <b-button type="is-primary" @click="createApplication" icon-right="plus"> - {{ $t("applications.create") }} - </b-button> - </div> - <b-table - :data="applications" - :striped="true" - :isFocusable="true" - :isHoverable="true" - :sticky-header="true" - :paginated="true" - :per-page="15" - height="100%" - > - <b-table-column field="name" label="Name" sortable width="50%" v-slot="props"> - <div @click="displayApplication(props.row)" class="clickable"> - {{ props.row.name }} - </div> - </b-table-column> - <b-table-column field="creationDate" label="Creation Date" sortable v-slot="props"> - <div @click="displayApplication(props.row)" class="clickable"> - {{ new Date(props.row.creationDate) }} - </div> - </b-table-column> - </b-table> - </PageView> - </div> + <PageView> + <h1 class="title main-title">{{ $t("titles.applications-page") }}</h1> + <div class="buttons"> + <b-button type="is-primary" @click="createApplication" icon-right="plus"> + {{ $t("applications.create") }} + </b-button> + </div> + <b-table + :data="applications" + :striped="true" + :isFocusable="true" + :isHoverable="true" + :sticky-header="true" + :paginated="true" + :per-page="15" + height="100%" + > + <b-table-column field="name" label="Name" sortable width="50%" v-slot="props"> + <div @click="displayApplication(props.row)" class="clickable"> + {{ props.row.name }} + </div> + </b-table-column> + <b-table-column field="creationDate" label="Creation Date" sortable v-slot="props"> + <div @click="displayApplication(props.row)" class="clickable"> + {{ new Date(props.row.creationDate) }} + </div> + </b-table-column> + </b-table> + </PageView> </template> <script> diff --git a/ui2/src/views/common/PageView.vue b/ui2/src/views/common/PageView.vue index d2d33980d..9c0f0edfc 100644 --- a/ui2/src/views/common/PageView.vue +++ b/ui2/src/views/common/PageView.vue @@ -1,7 +1,7 @@ <template> <div class="PageView"> <MenuView v-if="hasMenu" /> - <div class="container PageView-container"> + <div :class="`container PageView-container ${hasMenu ? '' : 'noMenu'}`"> <slot></slot> </div> </div> @@ -36,5 +36,11 @@ export default class PageView extends Vue { .PageView-container { width: 100%; + height: calc(100% - #{$menu-height}); + padding-top: 1.5rem; + + &.noMenu { + height: 100%; + } } </style> -- GitLab From f23b70e1e98ea274e078d21df0bf7fecdb35134b Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Tue, 1 Jun 2021 18:04:22 +0200 Subject: [PATCH 04/27] Ajoute traduction des noms de colonnes --- ui2/src/locales/en.json | 3 ++- ui2/src/locales/fr.json | 3 ++- ui2/src/views/application/ApplicationsView.vue | 15 +++++++++++++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/ui2/src/locales/en.json b/ui2/src/locales/en.json index b84ae454d..9b6ecceec 100644 --- a/ui2/src/locales/en.json +++ b/ui2/src/locales/en.json @@ -42,7 +42,8 @@ "chose-config": "Chose a configuration", "create": "Create application", "name": "Application name", - "name-placeholder": "Write down the application name" + "name-placeholder": "Write down the application name", + "creation-date": "Creation date" }, "errors": { "emptyFile": "File is empty", diff --git a/ui2/src/locales/fr.json b/ui2/src/locales/fr.json index dfabff25b..1b07d95b6 100644 --- a/ui2/src/locales/fr.json +++ b/ui2/src/locales/fr.json @@ -42,7 +42,8 @@ "chose-config": "Choisir une configuration", "create": "Créer l'application", "name": "Nom de l'application", - "name-placeholder": "Entrer le nom de l'application" + "name-placeholder": "Entrer le nom de l'application", + "creation-date": "Date de création" }, "errors": { "emptyFile": "Le fichier est vide", diff --git a/ui2/src/views/application/ApplicationsView.vue b/ui2/src/views/application/ApplicationsView.vue index 1f3358273..cd7be17c3 100644 --- a/ui2/src/views/application/ApplicationsView.vue +++ b/ui2/src/views/application/ApplicationsView.vue @@ -16,12 +16,23 @@ :per-page="15" height="100%" > - <b-table-column field="name" label="Name" sortable width="50%" v-slot="props"> + <b-table-column + field="name" + :label="$t('applications.name')" + sortable + width="50%" + v-slot="props" + > <div @click="displayApplication(props.row)" class="clickable"> {{ props.row.name }} </div> </b-table-column> - <b-table-column field="creationDate" label="Creation Date" sortable v-slot="props"> + <b-table-column + field="creationDate" + :label="$t('applications.creation-date')" + sortable + v-slot="props" + > <div @click="displayApplication(props.row)" class="clickable"> {{ new Date(props.row.creationDate) }} </div> -- GitLab From c09474dbf61906387766f9d90b100d1db878ee40 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Tue, 8 Jun 2021 18:00:17 +0200 Subject: [PATCH 05/27] =?UTF-8?q?Supprime=20des=20composants=20obsol=C3=A8?= =?UTF-8?q?tes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/DatasetSelection.vue | 43 ------------------- .../application/ReferenceSelection.vue | 42 ------------------ ui2/src/locales/en.json | 6 --- ui2/src/locales/fr.json | 6 --- .../application/ApplicationDetailsView.vue | 9 +--- 5 files changed, 2 insertions(+), 104 deletions(-) delete mode 100644 ui2/src/components/application/DatasetSelection.vue delete mode 100644 ui2/src/components/application/ReferenceSelection.vue diff --git a/ui2/src/components/application/DatasetSelection.vue b/ui2/src/components/application/DatasetSelection.vue deleted file mode 100644 index 0e2bae73f..000000000 --- a/ui2/src/components/application/DatasetSelection.vue +++ /dev/null @@ -1,43 +0,0 @@ -<template> - <div> - <b-select - v-model="chosenDataType" - :placeholder="$t('datasetSelection.placeholder')" - @input="loadDataset" - expanded - v-if="application" - > - <option v-for="type in application.dataType" :key="type" :value="type"> - {{ type }} - </option> - </b-select> - </div> -</template> - -<script> -import { ApplicationService } from "@/services/rest/ApplicationService"; -import { Component, Prop, Vue } from "vue-property-decorator"; - -@Component({ - components: {}, -}) -export default class DatasetSelection extends Vue { - @Prop() application; - - applicationService = ApplicationService.INSTANCE; - - chosenDataType = null; - dataset = null; - - async loadDataset() { - try { - this.dataset = await this.applicationService.getDataset( - this.chosenDataType, - this.application.name - ); - } catch (error) { - this.alertService.toastServerError(); - } - } -} -</script> diff --git a/ui2/src/components/application/ReferenceSelection.vue b/ui2/src/components/application/ReferenceSelection.vue deleted file mode 100644 index cd54b192e..000000000 --- a/ui2/src/components/application/ReferenceSelection.vue +++ /dev/null @@ -1,42 +0,0 @@ -<template> - <div> - <b-select - v-model="chosenReferenceType" - :placeholder="$t('referenceSelection.placeholder')" - @input="getReference" - expanded - v-if="application" - > - <option v-for="type in application.referenceType" :key="type" :value="type"> - {{ type }} - </option> - </b-select> - </div> -</template> - -<script> -import { ApplicationService } from "@/services/rest/ApplicationService"; -import { Component, Prop, Vue } from "vue-property-decorator"; - -@Component({ - components: {}, -}) -export default class ReferenceSelection extends Vue { - @Prop() application; - applicationService = ApplicationService.INSTANCE; - - chosenReferenceType = null; - reference = null; - - async getReference() { - try { - this.reference = await this.applicationService.getReference( - this.chosenReferenceType, - this.application.name - ); - } catch (error) { - this.alertService.toastServerError(); - } - } -} -</script> diff --git a/ui2/src/locales/en.json b/ui2/src/locales/en.json index 9b6ecceec..a0571752e 100644 --- a/ui2/src/locales/en.json +++ b/ui2/src/locales/en.json @@ -71,11 +71,5 @@ "application": "Application details", "references": "References", "dataset": "Datasets" - }, - "referenceSelection": { - "placeholder": "Chose the reference" - }, - "datasetSelection": { - "placeholder": "Chose the dataset" } } diff --git a/ui2/src/locales/fr.json b/ui2/src/locales/fr.json index 1b07d95b6..627ba74bc 100644 --- a/ui2/src/locales/fr.json +++ b/ui2/src/locales/fr.json @@ -71,11 +71,5 @@ "application": "Détail de l'application", "references": "Référentiels", "dataset": "Données" - }, - "referenceSelection": { - "placeholder": "Choisir le référentiel" - }, - "datasetSelection": { - "placeholder": "Choisir les données" } } diff --git a/ui2/src/views/application/ApplicationDetailsView.vue b/ui2/src/views/application/ApplicationDetailsView.vue index 9cb155a83..fe2d0f43a 100644 --- a/ui2/src/views/application/ApplicationDetailsView.vue +++ b/ui2/src/views/application/ApplicationDetailsView.vue @@ -4,11 +4,8 @@ <b-tabs type="is-boxed" expanded class="mt-4"> <b-tab-item :label="$t('applicationDetailsView.application')" icon="wrench"> </b-tab-item> <b-tab-item :label="$t('applicationDetailsView.references')" icon="drafting-compass"> - <ReferenceSelection :key="application.id" :application="application" /> - </b-tab-item> - <b-tab-item :label="$t('applicationDetailsView.dataset')" icon="poll"> - <DatasetSelection :key="application.id" :application="application" /> </b-tab-item> + <b-tab-item :label="$t('applicationDetailsView.dataset')" icon="poll"> </b-tab-item> </b-tabs> </PageView> </template> @@ -16,14 +13,12 @@ <script> import { Component, Prop, Vue } from "vue-property-decorator"; import PageView from "@/views/common/PageView.vue"; -import ReferenceSelection from "@/components/application/ReferenceSelection.vue"; import { Application } from "@/model/Application"; import { ApplicationService } from "@/services/rest/ApplicationService"; import { AlertService } from "@/services/AlertService"; -import DatasetSelection from "@/components/application/DatasetSelection.vue"; @Component({ - components: { PageView, ReferenceSelection, DatasetSelection }, + components: { PageView }, }) export default class ApplicationDetailsView extends Vue { @Prop() applicationName; -- GitLab From 13b97170a26559b07b90be51f9ab2dbd6ead49c7 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Tue, 8 Jun 2021 18:37:31 +0200 Subject: [PATCH 06/27] Premier brouillon d'un ReferencesManagement --- .../application/ReferencesManagement.vue | 25 +++++++++++++++++++ ui2/src/main.js | 6 ++++- ui2/src/model/ApplicationResult.js | 18 +++++++++++++ .../application/ApplicationDetailsView.vue | 10 +++++--- 4 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 ui2/src/components/application/ReferencesManagement.vue create mode 100644 ui2/src/model/ApplicationResult.js diff --git a/ui2/src/components/application/ReferencesManagement.vue b/ui2/src/components/application/ReferencesManagement.vue new file mode 100644 index 000000000..8aca89c14 --- /dev/null +++ b/ui2/src/components/application/ReferencesManagement.vue @@ -0,0 +1,25 @@ +<template> + <div> + <div> + <b-button @click="setOpenSite" :icon-left="openSite ? 'caret-up' : 'caret-down'" /> Site + <div v-if="openSite">Parcelle</div> + </div> + <div>Unités</div> + </div> +</template> + +<script> +import { Component, Prop, Vue } from "vue-property-decorator"; +@Component({ + components: {}, +}) +export default class ReferencesManagement extends Vue { + @Prop() application; + + openSite = false; + + setOpenSite() { + this.openSite = !this.openSite; + } +} +</script> diff --git a/ui2/src/main.js b/ui2/src/main.js index b04fe18ba..185e8ed69 100644 --- a/ui2/src/main.js +++ b/ui2/src/main.js @@ -9,6 +9,8 @@ import { faAngleRight, faArrowDown, faArrowUp, + faCaretDown, + faCaretUp, faCheck, faDraftingCompass, faExclamationCircle, @@ -37,7 +39,9 @@ library.add( faAngleRight, faWrench, faPoll, - faDraftingCompass + faDraftingCompass, + faCaretUp, + faCaretDown ); Vue.component("vue-fontawesome", FontAwesomeIcon); diff --git a/ui2/src/model/ApplicationResult.js b/ui2/src/model/ApplicationResult.js new file mode 100644 index 000000000..c6631f3e8 --- /dev/null +++ b/ui2/src/model/ApplicationResult.js @@ -0,0 +1,18 @@ +export class ApplicationResult { + id; + name; + title; + references = { + idRef: { + id: "", + label: "", + children: [], + columns: { + id: "", + label: "", + key: false, + linkedTo: "", + }, + }, + }; +} diff --git a/ui2/src/views/application/ApplicationDetailsView.vue b/ui2/src/views/application/ApplicationDetailsView.vue index fe2d0f43a..ecad562f5 100644 --- a/ui2/src/views/application/ApplicationDetailsView.vue +++ b/ui2/src/views/application/ApplicationDetailsView.vue @@ -1,9 +1,10 @@ <template> <PageView> - <h1 class="title main-title">{{ applicationName }}</h1> + <h1 class="title main-title">{{ application.title }}</h1> <b-tabs type="is-boxed" expanded class="mt-4"> <b-tab-item :label="$t('applicationDetailsView.application')" icon="wrench"> </b-tab-item> <b-tab-item :label="$t('applicationDetailsView.references')" icon="drafting-compass"> + <ReferencesManagement :application="application" /> </b-tab-item> <b-tab-item :label="$t('applicationDetailsView.dataset')" icon="poll"> </b-tab-item> </b-tabs> @@ -13,19 +14,20 @@ <script> import { Component, Prop, Vue } from "vue-property-decorator"; import PageView from "@/views/common/PageView.vue"; -import { Application } from "@/model/Application"; +import { ApplicationResult } from "@/model/ApplicationResult"; import { ApplicationService } from "@/services/rest/ApplicationService"; import { AlertService } from "@/services/AlertService"; +import ReferencesManagement from "@/components/application/ReferencesManagement.vue"; @Component({ - components: { PageView }, + components: { PageView, ReferencesManagement }, }) export default class ApplicationDetailsView extends Vue { @Prop() applicationName; applicationService = ApplicationService.INSTANCE; alertService = AlertService.INSTANCE; - application = new Application(); + application = new ApplicationResult(); created() { this.init(); -- GitLab From 9e8f114112f93984d93cd1cc69d7633d4c333823 Mon Sep 17 00:00:00 2001 From: Brendan Le Ny <bleny@codelutin.com> Date: Tue, 8 Jun 2021 18:47:32 +0200 Subject: [PATCH 07/27] =?UTF-8?q?Compl=C3=A8te=20les=20informations=20reto?= =?UTF-8?q?urn=C3=A9es=20au=20front=20pour=20la=20description=20des=20r?= =?UTF-8?q?=C3=A9f=C3=A9rentiels=20d'une=20application?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../inra/oresing/rest/ApplicationResult.java | 7 +++++ .../fr/inra/oresing/rest/OreSiResources.java | 27 ++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/main/java/fr/inra/oresing/rest/ApplicationResult.java b/src/main/java/fr/inra/oresing/rest/ApplicationResult.java index 3f3af5e07..f3ee50860 100644 --- a/src/main/java/fr/inra/oresing/rest/ApplicationResult.java +++ b/src/main/java/fr/inra/oresing/rest/ApplicationResult.java @@ -3,6 +3,7 @@ package fr.inra.oresing.rest; import lombok.Value; import java.util.Map; +import java.util.Set; @Value public class ApplicationResult { @@ -13,11 +14,17 @@ public class ApplicationResult { @Value public static class Reference { + String id; + String label; + Set<String> children; Map<String, Column> columns; @Value public static class Column { + String id; String title; + boolean key; + String linkedTo; } } } diff --git a/src/main/java/fr/inra/oresing/rest/OreSiResources.java b/src/main/java/fr/inra/oresing/rest/OreSiResources.java index 82d5412be..34f625553 100644 --- a/src/main/java/fr/inra/oresing/rest/OreSiResources.java +++ b/src/main/java/fr/inra/oresing/rest/OreSiResources.java @@ -1,10 +1,15 @@ package fr.inra.oresing.rest; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Maps; +import com.google.common.collect.Ordering; +import com.google.common.collect.TreeMultimap; import fr.inra.oresing.checker.CheckerException; import fr.inra.oresing.model.Application; import fr.inra.oresing.model.BinaryFile; +import fr.inra.oresing.model.Configuration; import fr.inra.oresing.model.ReferenceValue; import fr.inra.oresing.persistence.OreSiRepository; import org.springframework.beans.factory.annotation.Autowired; @@ -84,9 +89,25 @@ public class OreSiResources { @GetMapping(value = "/applications/{nameOrId}", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<ApplicationResult> getApplication(@PathVariable("nameOrId") String nameOrId) { Application application = service.getApplication(nameOrId); - Map<String, ApplicationResult.Reference> references = Maps.transformValues(application.getConfiguration().getReferences(), referenceDescription -> { - Map<String, ApplicationResult.Reference.Column> columns = Maps.transformEntries(referenceDescription.getColumns(), (column, columnDescription) -> new ApplicationResult.Reference.Column(column)); - return new ApplicationResult.Reference(columns); + TreeMultimap<String, String> childrenPerReferences = TreeMultimap.create(); + application.getConfiguration().getCompositeReferences().values().forEach(compositeReferenceDescription -> { + ImmutableList<String> referenceTypes = compositeReferenceDescription.getComponents().stream() + .map(Configuration.CompositeReferenceComponentDescription::getReference) + .collect(ImmutableList.toImmutableList()); + ImmutableSortedSet<String> sortedReferenceTypes = ImmutableSortedSet.copyOf(Ordering.explicit(referenceTypes), referenceTypes); + sortedReferenceTypes.forEach(reference -> { + String child = sortedReferenceTypes.higher(reference); + if (child == null) { + // on est sur le dernier élément de la hiérarchie, pas de descendant + } else { + childrenPerReferences.put(reference, child); + } + }); + }); + Map<String, ApplicationResult.Reference> references = Maps.transformEntries(application.getConfiguration().getReferences(), (reference, referenceDescription) -> { + Map<String, ApplicationResult.Reference.Column> columns = Maps.transformEntries(referenceDescription.getColumns(), (column, columnDescription) -> new ApplicationResult.Reference.Column(column, column, referenceDescription.getKeyColumns().contains(column), null)); + Set<String> children = childrenPerReferences.get(reference); + return new ApplicationResult.Reference(reference, reference, children, columns); }); ApplicationResult applicationResult = new ApplicationResult(application.getId().toString(), application.getName(), application.getConfiguration().getApplication().getName(), references); return ResponseEntity.ok(applicationResult); -- GitLab From 95e7bae48921c3957750d41daa9581cfae8b5d74 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Thu, 10 Jun 2021 18:14:49 +0200 Subject: [PATCH 08/27] =?UTF-8?q?Premier=20jet=20de=20reconstitution=20de?= =?UTF-8?q?=20hi=C3=A9rarchie?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/ReferencesManagement.vue | 20 ++++++++--- ui2/src/components/common/CollapsibleTree.vue | 15 +++++++++ ui2/src/model/ApplicationResult.js | 2 +- ui2/src/utils/ConversionUtils.js | 33 +++++++++++++++++++ .../application/ApplicationDetailsView.vue | 5 ++- 5 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 ui2/src/components/common/CollapsibleTree.vue create mode 100644 ui2/src/utils/ConversionUtils.js diff --git a/ui2/src/components/application/ReferencesManagement.vue b/ui2/src/components/application/ReferencesManagement.vue index 8aca89c14..350a7252a 100644 --- a/ui2/src/components/application/ReferencesManagement.vue +++ b/ui2/src/components/application/ReferencesManagement.vue @@ -1,7 +1,12 @@ <template> <div> <div> - <b-button @click="setOpenSite" :icon-left="openSite ? 'caret-up' : 'caret-down'" /> Site + <FontAwesomeIcon + @click="openSite = !openSite" + :icon="openSite ? 'caret-up' : 'caret-down'" + class="clickable" + /> + Site <div v-if="openSite">Parcelle</div> </div> <div>Unités</div> @@ -10,16 +15,23 @@ <script> import { Component, Prop, Vue } from "vue-property-decorator"; +import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; +import { convertReferencesToTrees } from "@/utils/ConversionUtils"; + @Component({ - components: {}, + components: { FontAwesomeIcon }, }) export default class ReferencesManagement extends Vue { @Prop() application; openSite = false; + references = []; - setOpenSite() { - this.openSite = !this.openSite; + created() { + if (!this.application || !this.application.id) { + return; + } + this.references = convertReferencesToTrees(Object.values(this.application.references)); } } </script> diff --git a/ui2/src/components/common/CollapsibleTree.vue b/ui2/src/components/common/CollapsibleTree.vue new file mode 100644 index 000000000..21d82ecde --- /dev/null +++ b/ui2/src/components/common/CollapsibleTree.vue @@ -0,0 +1,15 @@ +<template> + <div></div> +</template> + +<script> +import { Component, Prop, Vue } from "vue-property-decorator"; +import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; + +@Component({ + components: { FontAwesomeIcon }, +}) +export default class CollapsibleTree extends Vue { + @Prop() application; +} +</script> diff --git a/ui2/src/model/ApplicationResult.js b/ui2/src/model/ApplicationResult.js index c6631f3e8..835c10792 100644 --- a/ui2/src/model/ApplicationResult.js +++ b/ui2/src/model/ApplicationResult.js @@ -9,7 +9,7 @@ export class ApplicationResult { children: [], columns: { id: "", - label: "", + title: "", key: false, linkedTo: "", }, diff --git a/ui2/src/utils/ConversionUtils.js b/ui2/src/utils/ConversionUtils.js new file mode 100644 index 000000000..b0ec6a540 --- /dev/null +++ b/ui2/src/utils/ConversionUtils.js @@ -0,0 +1,33 @@ +export function convertReferencesToTrees(references) { + const array = references.filter((ref) => { + return !references.some( + (r) => r.children && r.children.length !== 0 && r.children.some((c) => c === ref.id) + ); + }); + return convert(array, references); +} + +function convert(references, initialRef) { + references.forEach((ref) => { + if (ref.children && ref.children.length !== 0) { + const children = ref.children.map((c) => initialRef.find((r) => r.id === c)); + ref.children = convert(children, initialRef); + } else { + return ref; + // const parentIndex = initialRef.findIndex( + // (r) => r.children && r.children.length !== 0 && r.children.some((c) => c === ref.id) + // ); + // if (!parentIndex) { + // return ref; + // } else { + // return (initialRef[parentIndex].children = initialRef[parentIndex].children.map((c) => { + // if (c === ref.id) { + // return ref; + // } + // return c; + // })); + // } + } + }); + return references; +} diff --git a/ui2/src/views/application/ApplicationDetailsView.vue b/ui2/src/views/application/ApplicationDetailsView.vue index ecad562f5..f72a35ac6 100644 --- a/ui2/src/views/application/ApplicationDetailsView.vue +++ b/ui2/src/views/application/ApplicationDetailsView.vue @@ -2,11 +2,10 @@ <PageView> <h1 class="title main-title">{{ application.title }}</h1> <b-tabs type="is-boxed" expanded class="mt-4"> - <b-tab-item :label="$t('applicationDetailsView.application')" icon="wrench"> </b-tab-item> <b-tab-item :label="$t('applicationDetailsView.references')" icon="drafting-compass"> - <ReferencesManagement :application="application" /> + <ReferencesManagement :application="application" :key="application.id" /> </b-tab-item> - <b-tab-item :label="$t('applicationDetailsView.dataset')" icon="poll"> </b-tab-item> + <b-tab-item :label="$t('applicationDetailsView.dataset')" icon="poll">À venir</b-tab-item> </b-tabs> </PageView> </template> -- GitLab From 552603c4d8d894dcaa6c5ee1f81803e58b4d16fe Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Fri, 11 Jun 2021 10:23:42 +0200 Subject: [PATCH 09/27] =?UTF-8?q?Enl=C3=A8ve=20l'effet=20de=20bord=20modif?= =?UTF-8?q?iant=20les=20ref=20initiales?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui2/src/utils/ConversionUtils.js | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/ui2/src/utils/ConversionUtils.js b/ui2/src/utils/ConversionUtils.js index b0ec6a540..3e35a15cb 100644 --- a/ui2/src/utils/ConversionUtils.js +++ b/ui2/src/utils/ConversionUtils.js @@ -1,32 +1,24 @@ -export function convertReferencesToTrees(references) { - const array = references.filter((ref) => { +export function convertReferencesToTrees(initialReference) { + const references = JSON.parse(JSON.stringify(initialReference)); + const parents = references.filter((ref) => { return !references.some( (r) => r.children && r.children.length !== 0 && r.children.some((c) => c === ref.id) ); }); - return convert(array, references); + return replaceChildrenIdByObject(parents, references); } -function convert(references, initialRef) { +function replaceChildrenIdByObject(references, initialRef) { references.forEach((ref) => { if (ref.children && ref.children.length !== 0) { - const children = ref.children.map((c) => initialRef.find((r) => r.id === c)); - ref.children = convert(children, initialRef); + const children = ref.children.map((c) => { + const index = initialRef.findIndex((r) => r.id === c); + const [child] = initialRef.splice(index, 1); + return child; + }); + ref.children = replaceChildrenIdByObject(children, initialRef); } else { return ref; - // const parentIndex = initialRef.findIndex( - // (r) => r.children && r.children.length !== 0 && r.children.some((c) => c === ref.id) - // ); - // if (!parentIndex) { - // return ref; - // } else { - // return (initialRef[parentIndex].children = initialRef[parentIndex].children.map((c) => { - // if (c === ref.id) { - // return ref; - // } - // return c; - // })); - // } } }); return references; -- GitLab From 6214a857fa50d7df67e4d5adbcc59966de8f0ba2 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Fri, 11 Jun 2021 11:16:52 +0200 Subject: [PATCH 10/27] =?UTF-8?q?Ajoute=20un=20arbre=20pour=20afficher=20l?= =?UTF-8?q?es=20r=C3=A9f=C3=A9rentiels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/ReferencesManagement.vue | 22 +++++++-------- ui2/src/components/common/CollapsibleTree.vue | 27 +++++++++++++++++-- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/ui2/src/components/application/ReferencesManagement.vue b/ui2/src/components/application/ReferencesManagement.vue index 350a7252a..d7b8a0fe8 100644 --- a/ui2/src/components/application/ReferencesManagement.vue +++ b/ui2/src/components/application/ReferencesManagement.vue @@ -1,30 +1,26 @@ <template> <div> - <div> - <FontAwesomeIcon - @click="openSite = !openSite" - :icon="openSite ? 'caret-up' : 'caret-down'" - class="clickable" - /> - Site - <div v-if="openSite">Parcelle</div> - </div> - <div>Unités</div> + <CollapsibleTree + v-for="ref in references" + :key="ref.id" + :label="ref.label" + :children="ref.children" + :level="0" + /> </div> </template> <script> import { Component, Prop, Vue } from "vue-property-decorator"; -import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; import { convertReferencesToTrees } from "@/utils/ConversionUtils"; +import CollapsibleTree from "@/components/common/CollapsibleTree.vue"; @Component({ - components: { FontAwesomeIcon }, + components: { CollapsibleTree }, }) export default class ReferencesManagement extends Vue { @Prop() application; - openSite = false; references = []; created() { diff --git a/ui2/src/components/common/CollapsibleTree.vue b/ui2/src/components/common/CollapsibleTree.vue index 21d82ecde..1eee21da1 100644 --- a/ui2/src/components/common/CollapsibleTree.vue +++ b/ui2/src/components/common/CollapsibleTree.vue @@ -1,5 +1,24 @@ <template> - <div></div> + <div> + <div> + <FontAwesomeIcon + v-if="children && children.length !== 0" + @click="displayChildren = !displayChildren" + :icon="displayChildren ? 'caret-up' : 'caret-down'" + class="clickable" + /> + <div :style="`transform:translate(${level * 50}px);`">{{ label }}</div> + </div> + <div v-if="displayChildren"> + <CollapsibleTree + v-for="child in children" + :key="child.id" + :label="child.label" + :children="child.children" + :level="level + 1" + /> + </div> + </div> </template> <script> @@ -10,6 +29,10 @@ import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; components: { FontAwesomeIcon }, }) export default class CollapsibleTree extends Vue { - @Prop() application; + @Prop() label; + @Prop() children; + @Prop() level; + + displayChildren = false; } </script> -- GitLab From c02ae5c01bcbeac2c252b62ace2d1e198492db94 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Fri, 11 Jun 2021 11:54:14 +0200 Subject: [PATCH 11/27] =?UTF-8?q?Ajoute=20du=20style=20=C3=A0=20l'arbre?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui2/src/components/common/CollapsibleTree.vue | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/ui2/src/components/common/CollapsibleTree.vue b/ui2/src/components/common/CollapsibleTree.vue index 1eee21da1..daba82da4 100644 --- a/ui2/src/components/common/CollapsibleTree.vue +++ b/ui2/src/components/common/CollapsibleTree.vue @@ -1,11 +1,16 @@ <template> <div> - <div> + <div + :class="`CollapsibleTree-header ${ + children && children.length !== 0 && displayChildren ? '' : 'mb-1' + }`" + :style="`background-color:rgba(240, 245, 245, ${1 - level / 2})`" + > <FontAwesomeIcon v-if="children && children.length !== 0" @click="displayChildren = !displayChildren" :icon="displayChildren ? 'caret-up' : 'caret-down'" - class="clickable" + class="clickable mr-3" /> <div :style="`transform:translate(${level * 50}px);`">{{ label }}</div> </div> @@ -36,3 +41,12 @@ export default class CollapsibleTree extends Vue { displayChildren = false; } </script> + +<style lang="scss" scoped> +.CollapsibleTree-header { + display: flex; + align-items: center; + height: 40px; + padding: 0.75rem; +} +</style> -- GitLab From 723554f791e490482935ec0664654f97473a59d9 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Fri, 11 Jun 2021 12:25:27 +0200 Subject: [PATCH 12/27] =?UTF-8?q?Ajoute=20l'icone=20de=20t=C3=A9l=C3=A9cha?= =?UTF-8?q?rgement/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/ReferencesManagement.vue | 8 +++ ui2/src/components/common/CollapsibleTree.vue | 70 ++++++++++++++++--- 2 files changed, 70 insertions(+), 8 deletions(-) diff --git a/ui2/src/components/application/ReferencesManagement.vue b/ui2/src/components/application/ReferencesManagement.vue index d7b8a0fe8..adc38810b 100644 --- a/ui2/src/components/application/ReferencesManagement.vue +++ b/ui2/src/components/application/ReferencesManagement.vue @@ -6,6 +6,8 @@ :label="ref.label" :children="ref.children" :level="0" + :withDownload="true" + :onClickLabelCb="(event, label) => openRefDetails(event, label)" /> </div> </template> @@ -29,5 +31,11 @@ export default class ReferencesManagement extends Vue { } this.references = convertReferencesToTrees(Object.values(this.application.references)); } + + openRefDetails(event, label) { + event.stopPropagation(); + + console.log("OUVRIR DETAILS DE LA REF:", label); + } } </script> diff --git a/ui2/src/components/common/CollapsibleTree.vue b/ui2/src/components/common/CollapsibleTree.vue index daba82da4..a970dd44f 100644 --- a/ui2/src/components/common/CollapsibleTree.vue +++ b/ui2/src/components/common/CollapsibleTree.vue @@ -1,18 +1,36 @@ <template> <div> <div - :class="`CollapsibleTree-header ${ + :class="`CollapsibleTree-header ${children && children.length !== 0 ? 'clickable' : ''} ${ children && children.length !== 0 && displayChildren ? '' : 'mb-1' }`" :style="`background-color:rgba(240, 245, 245, ${1 - level / 2})`" + @click="displayChildren = !displayChildren" > - <FontAwesomeIcon - v-if="children && children.length !== 0" - @click="displayChildren = !displayChildren" - :icon="displayChildren ? 'caret-up' : 'caret-down'" - class="clickable mr-3" - /> - <div :style="`transform:translate(${level * 50}px);`">{{ label }}</div> + <div class="CollapsibleTree-header-infos"> + <FontAwesomeIcon + v-if="children && children.length !== 0" + :icon="displayChildren ? 'caret-up' : 'caret-down'" + class="clickable mr-3" + /> + <div + class="clickable CollapsibleTree-header-label" + :style="`transform:translate(${level * 50}px);`" + @click="(event) => onClickLabelCb(event, label)" + > + {{ label }} + </div> + </div> + <b-field class="file is-primary" v-if="withDownload"> + <b-upload v-model="refFile" class="file-label" accept=".csv"> + <span class="file-name" v-if="refFile"> + {{ refFile.name }} + </span> + <span class="file-cta"> + <b-icon class="file-icon" icon="upload"></b-icon> + </span> + </b-upload> + </b-field> </div> <div v-if="displayChildren"> <CollapsibleTree @@ -21,6 +39,8 @@ :label="child.label" :children="child.children" :level="level + 1" + :withDownload="withDownload" + :onClickLabelCb="onClickLabelCb" /> </div> </div> @@ -37,8 +57,11 @@ export default class CollapsibleTree extends Vue { @Prop() label; @Prop() children; @Prop() level; + @Prop() withDownload; + @Prop() onClickLabelCb; displayChildren = false; + refFile = null; } </script> @@ -48,5 +71,36 @@ export default class CollapsibleTree extends Vue { align-items: center; height: 40px; padding: 0.75rem; + justify-content: space-between; + + .file-icon { + margin-right: 0; + } + + .file-name { + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-width: 2px; + border-radius: 0px; + opacity: 0.8; + background-color: rgba(250, 250, 250, 1); + + &:hover { + opacity: 1; + } + } +} + +.CollapsibleTree-header-infos { + display: flex; + align-items: center; +} + +.CollapsibleTree-header-label { + &:hover { + color: $primary; + text-decoration: underline; + } } </style> -- GitLab From 454d75f82066cda99f4b4f862943ed65f71e25c5 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Mon, 14 Jun 2021 17:41:24 +0200 Subject: [PATCH 13/27] =?UTF-8?q?Cr=C3=A9e=20un=20panneau=20lat=C3=A9ral?= =?UTF-8?q?=20g=C3=A9n=C3=A9rique.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/ReferencesManagement.vue | 15 +++- ui2/src/components/common/SidePanel.vue | 72 +++++++++++++++++++ ui2/src/main.js | 4 +- ui2/src/style/_common.scss | 2 +- ui2/src/style/_variables.scss | 12 ++-- .../application/ApplicationDetailsView.vue | 10 ++- ui2/src/views/common/PageView.vue | 5 +- 7 files changed, 107 insertions(+), 13 deletions(-) create mode 100644 ui2/src/components/common/SidePanel.vue diff --git a/ui2/src/components/application/ReferencesManagement.vue b/ui2/src/components/application/ReferencesManagement.vue index adc38810b..d566eb6b2 100644 --- a/ui2/src/components/application/ReferencesManagement.vue +++ b/ui2/src/components/application/ReferencesManagement.vue @@ -9,6 +9,12 @@ :withDownload="true" :onClickLabelCb="(event, label) => openRefDetails(event, label)" /> + <SidePanel + :leftAlign="true" + :open="openPanel" + :title="chosenRef && chosenRef.label" + @openStateChanged="(newVal) => (openPanel = newVal)" + /> </div> </template> @@ -16,14 +22,17 @@ import { Component, Prop, Vue } from "vue-property-decorator"; import { convertReferencesToTrees } from "@/utils/ConversionUtils"; import CollapsibleTree from "@/components/common/CollapsibleTree.vue"; +import SidePanel from "../common/SidePanel.vue"; @Component({ - components: { CollapsibleTree }, + components: { CollapsibleTree, SidePanel }, }) export default class ReferencesManagement extends Vue { @Prop() application; references = []; + openPanel = false; + chosenRef = null; created() { if (!this.application || !this.application.id) { @@ -34,8 +43,8 @@ export default class ReferencesManagement extends Vue { openRefDetails(event, label) { event.stopPropagation(); - - console.log("OUVRIR DETAILS DE LA REF:", label); + this.openPanel = this.chosenRef && this.chosenRef.label === label ? !this.openPanel : true; + this.chosenRef = Object.values(this.application.references).find((ref) => ref.label === label); } } </script> diff --git a/ui2/src/components/common/SidePanel.vue b/ui2/src/components/common/SidePanel.vue new file mode 100644 index 000000000..af99ccbb7 --- /dev/null +++ b/ui2/src/components/common/SidePanel.vue @@ -0,0 +1,72 @@ +<template> + <div :class="`SidePanel ${leftAlign ? 'left-align' : 'right-align'} ${innerOpen ? 'open' : ''}`"> + <h1 class="title main-title">{{ title }}</h1> + <b-button class="SidePanel-close-button" icon-left="times" @click="innerOpen = false" /> + <slot></slot> + </div> +</template> + +<script> +import { Component, Prop, Vue, Watch } from "vue-property-decorator"; +import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; + +@Component({ + components: { FontAwesomeIcon }, +}) +export default class SidePanel extends Vue { + @Prop({ default: false }) leftAlign; + @Prop({ default: false }) open; + @Prop({ default: "" }) title; + + innerOpen = false; + + created() { + this.innerOpen = this.open; + } + + @Watch("open") + onExternalOpenStateChanged(newVal) { + this.innerOpen = newVal; + } + + @Watch("innerOpen") + onInnerOpenStateChanged(newVal) { + this.$emit("openStateChanged", newVal); + } +} +</script> + +<style lang="scss" scoped> +.SidePanel { + background-color: $light; + z-index: 1; + position: absolute; + height: 100%; + top: 0; + width: 33%; + padding: $container-padding-vert 2.5rem; + transition: transform 250ms; + + &.right-align { + right: 0; + transform: translateX(100%); + &.open { + transform: translateX(0); + } + } + + &.left-align { + left: 0; + transform: translateX(-100%); + &.open { + transform: translateX(0); + } + } +} + +.SidePanel-close-button { + position: absolute; + top: 0; + right: 0; +} +</style> diff --git a/ui2/src/main.js b/ui2/src/main.js index 185e8ed69..0e0737266 100644 --- a/ui2/src/main.js +++ b/ui2/src/main.js @@ -20,6 +20,7 @@ import { faPlus, faPoll, faSignOutAlt, + faTimes, faUpload, faWrench, } from "@fortawesome/free-solid-svg-icons"; @@ -41,7 +42,8 @@ library.add( faPoll, faDraftingCompass, faCaretUp, - faCaretDown + faCaretDown, + faTimes ); Vue.component("vue-fontawesome", FontAwesomeIcon); diff --git a/ui2/src/style/_common.scss b/ui2/src/style/_common.scss index e9eaf9c75..883a76358 100644 --- a/ui2/src/style/_common.scss +++ b/ui2/src/style/_common.scss @@ -6,7 +6,7 @@ body { .title { color: $primary; - margin-top: 1.5rem; + margin-top: $title-margin-top; &.main-title { display: flex; diff --git a/ui2/src/style/_variables.scss b/ui2/src/style/_variables.scss index 4b6281368..9004cb4bd 100644 --- a/ui2/src/style/_variables.scss +++ b/ui2/src/style/_variables.scss @@ -6,9 +6,11 @@ $font-family: "LiberationSans", Helvetica, Arial, sans-serif; $text-default-color: #2c3e50; $light-text: rgb(230, 230, 230); -// InputWithValidation -$input-field-margin-bot: 1rem; -$input-help-margin-top: 0.25rem; + +// PageView +$container-padding-hor: 3rem; +$container-padding-vert: $container-padding-hor / 2; +$title-margin-top: 1.5rem; // MenuView $menu-height: 80px; @@ -19,11 +21,11 @@ $menu-height: 80px; ***************************************************************************************************/ // General variables -$primary: rgb(0,163,166); +$primary: rgb(0, 163, 166); $info: #4ec6c2; $success: #bade81; $warning: #ffec60; $danger: #d13a18; $dark: #4b6464; -$light: #aab7b7; +$light: rgb(202, 216, 216); $family-primary: $font-family; diff --git a/ui2/src/views/application/ApplicationDetailsView.vue b/ui2/src/views/application/ApplicationDetailsView.vue index f72a35ac6..ecd584089 100644 --- a/ui2/src/views/application/ApplicationDetailsView.vue +++ b/ui2/src/views/application/ApplicationDetailsView.vue @@ -1,7 +1,7 @@ <template> <PageView> <h1 class="title main-title">{{ application.title }}</h1> - <b-tabs type="is-boxed" expanded class="mt-4"> + <b-tabs type="is-boxed" expanded class="mt-4 ApplicationDetailsView-tabs"> <b-tab-item :label="$t('applicationDetailsView.references')" icon="drafting-compass"> <ReferencesManagement :application="application" :key="application.id" /> </b-tab-item> @@ -41,3 +41,11 @@ export default class ApplicationDetailsView extends Vue { } } </script> + +<style lang="scss"> +.ApplicationDetailsView-tabs.b-tabs { + .tab-content { + position: initial; + } +} +</style> diff --git a/ui2/src/views/common/PageView.vue b/ui2/src/views/common/PageView.vue index 9c0f0edfc..57154602c 100644 --- a/ui2/src/views/common/PageView.vue +++ b/ui2/src/views/common/PageView.vue @@ -1,7 +1,7 @@ <template> <div class="PageView"> <MenuView v-if="hasMenu" /> - <div :class="`container PageView-container ${hasMenu ? '' : 'noMenu'}`"> + <div :class="`PageView-container ${hasMenu ? '' : 'noMenu'}`"> <slot></slot> </div> </div> @@ -37,7 +37,8 @@ export default class PageView extends Vue { .PageView-container { width: 100%; height: calc(100% - #{$menu-height}); - padding-top: 1.5rem; + padding: $container-padding-vert $container-padding-hor; + position: relative; &.noMenu { height: 100%; -- GitLab From 3c36b50c45bb567f8e4a4a6f489ede4a657d66bd Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Mon, 14 Jun 2021 18:49:50 +0200 Subject: [PATCH 14/27] =?UTF-8?q?Cr=C3=A9e=20un=20panneau=20sp=C3=A9cifiqu?= =?UTF-8?q?e=20pour=20les=20r=C3=A9f=C3=A9rentiels.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/ReferencesDetailsPanel.vue | 55 +++++++++++++++++++ .../application/ReferencesManagement.vue | 10 ++-- ui2/src/components/common/SidePanel.vue | 3 +- ui2/src/locales/en.json | 11 +++- ui2/src/locales/fr.json | 11 +++- ui2/src/main.js | 6 +- ui2/src/services/AlertService.js | 16 +++++- .../application/ApplicationDetailsView.vue | 2 +- 8 files changed, 102 insertions(+), 12 deletions(-) create mode 100644 ui2/src/components/application/ReferencesDetailsPanel.vue diff --git a/ui2/src/components/application/ReferencesDetailsPanel.vue b/ui2/src/components/application/ReferencesDetailsPanel.vue new file mode 100644 index 000000000..c9ac774d1 --- /dev/null +++ b/ui2/src/components/application/ReferencesDetailsPanel.vue @@ -0,0 +1,55 @@ +<template> + <SidePanel :open="open" :leftAlign="leftAlign" :title="reference && reference.label"> + <div class="Panel-buttons"> + <b-button type="is-primary" icon-left="eye">{{ + $t("referencesManagement.consult") + }}</b-button> + <b-button icon-left="download">{{ $t("referencesManagement.download") }}</b-button> + <b-button type="is-danger" icon-left="trash-alt" @click="askDeletionConfirmation">{{ + $t("referencesManagement.delete") + }}</b-button> + </div> + </SidePanel> +</template> + +<script> +import { AlertService } from "@/services/AlertService"; +import { Component, Prop, Vue } from "vue-property-decorator"; +import SidePanel from "../common/SidePanel.vue"; + +@Component({ + components: { SidePanel }, +}) +export default class ReferencesDetailsPanel extends Vue { + @Prop({ default: false }) leftAlign; + @Prop({ default: false }) open; + @Prop() reference; + + alertService = AlertService.INSTANCE; + + askDeletionConfirmation() { + this.alertService.dialog( + this.$t("alert.warning"), + this.$t("alert.reference-deletion-msg", { label: this.reference.label }), + this.$t("alert.delete"), + "is-danger", + () => this.deleteReference() + ); + } + + deleteReference() { + console.log("DELETE", this.reference); + } +} +</script> + +<style lang="scss" scoped> +.Panel-buttons { + display: flex; + flex-direction: column; + + .button { + margin-bottom: 0.5rem; + } +} +</style> diff --git a/ui2/src/components/application/ReferencesManagement.vue b/ui2/src/components/application/ReferencesManagement.vue index d566eb6b2..55408d6ea 100644 --- a/ui2/src/components/application/ReferencesManagement.vue +++ b/ui2/src/components/application/ReferencesManagement.vue @@ -9,10 +9,10 @@ :withDownload="true" :onClickLabelCb="(event, label) => openRefDetails(event, label)" /> - <SidePanel - :leftAlign="true" + <ReferencesDetailsPanel + :leftAlign="false" :open="openPanel" - :title="chosenRef && chosenRef.label" + :reference="chosenRef" @openStateChanged="(newVal) => (openPanel = newVal)" /> </div> @@ -22,10 +22,10 @@ import { Component, Prop, Vue } from "vue-property-decorator"; import { convertReferencesToTrees } from "@/utils/ConversionUtils"; import CollapsibleTree from "@/components/common/CollapsibleTree.vue"; -import SidePanel from "../common/SidePanel.vue"; +import ReferencesDetailsPanel from "./ReferencesDetailsPanel.vue"; @Component({ - components: { CollapsibleTree, SidePanel }, + components: { CollapsibleTree, ReferencesDetailsPanel }, }) export default class ReferencesManagement extends Vue { @Prop() application; diff --git a/ui2/src/components/common/SidePanel.vue b/ui2/src/components/common/SidePanel.vue index af99ccbb7..3acb689dd 100644 --- a/ui2/src/components/common/SidePanel.vue +++ b/ui2/src/components/common/SidePanel.vue @@ -8,10 +8,9 @@ <script> import { Component, Prop, Vue, Watch } from "vue-property-decorator"; -import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; @Component({ - components: { FontAwesomeIcon }, + components: {}, }) export default class SidePanel extends Vue { @Prop({ default: false }) leftAlign; diff --git a/ui2/src/locales/en.json b/ui2/src/locales/en.json index a0571752e..a479236f0 100644 --- a/ui2/src/locales/en.json +++ b/ui2/src/locales/en.json @@ -25,7 +25,10 @@ "cancel": "Cancel", "server-error": "A server error occured", "user-unknown": "Unknown user", - "application-creation-success": "L'application a été créée !" + "application-creation-success": "L'application a été créée !", + "warning": "Warning !", + "reference-deletion-msg": "You're about to delete the reference : {label}. Are you sure ?", + "delete": "Delete" }, "message": { "app-config-error": "Error in yaml file", @@ -71,5 +74,11 @@ "application": "Application details", "references": "References", "dataset": "Datasets" + }, + "referencesManagement": { + "actions": "Actions", + "consult": "Consult", + "download": "Download", + "delete": "Delete" } } diff --git a/ui2/src/locales/fr.json b/ui2/src/locales/fr.json index 627ba74bc..576fa9809 100644 --- a/ui2/src/locales/fr.json +++ b/ui2/src/locales/fr.json @@ -25,7 +25,10 @@ "cancel": "Annuler", "server-error": "Une erreur serveur est survenue", "user-unknown": "Identifiants inconnus", - "application-creation-success": "L'application a été créée !" + "application-creation-success": "L'application a été créée !", + "warning": "Attention !", + "reference-deletion-msg": "Vous allez supprimer le référentiel : {label}. Êtes-vous sûr ?", + "delete": "Supprimer" }, "message": { "app-config-error": "Erreur dans le fichier yaml", @@ -71,5 +74,11 @@ "application": "Détail de l'application", "references": "Référentiels", "dataset": "Données" + }, + "referencesManagement": { + "actions": "Actions", + "consult": "Consulter", + "download": "Télécharger", + "delete": "Supprimer" } } diff --git a/ui2/src/main.js b/ui2/src/main.js index 0e0737266..d96d4e015 100644 --- a/ui2/src/main.js +++ b/ui2/src/main.js @@ -12,6 +12,7 @@ import { faCaretDown, faCaretUp, faCheck, + faDownload, faDraftingCompass, faExclamationCircle, faEye, @@ -21,6 +22,7 @@ import { faPoll, faSignOutAlt, faTimes, + faTrashAlt, faUpload, faWrench, } from "@fortawesome/free-solid-svg-icons"; @@ -43,7 +45,9 @@ library.add( faDraftingCompass, faCaretUp, faCaretDown, - faTimes + faTimes, + faTrashAlt, + faDownload ); Vue.component("vue-fontawesome", FontAwesomeIcon); diff --git a/ui2/src/services/AlertService.js b/ui2/src/services/AlertService.js index be93def85..9064f6b9e 100644 --- a/ui2/src/services/AlertService.js +++ b/ui2/src/services/AlertService.js @@ -1,6 +1,6 @@ import { i18n } from "@/main"; import { BuefyTypes } from "@/utils/BuefyUtils"; -import { ToastProgrammatic } from "buefy"; +import { ToastProgrammatic, DialogProgrammatic } from "buefy"; const TOAST_INFO_DURATION = 3000; const TOAST_ERROR_DURATION = 8000; @@ -44,4 +44,18 @@ export class AlertService { toastServerError(error) { this.toastError(i18n.t("alert.server-error"), error); } + + dialog(title, message, confirmText, type, onConfirmCb) { + DialogProgrammatic.confirm({ + title: title, + message: message, + confirmText: confirmText, + type: type, + hasIcon: true, + cancelText: this.cancelMsg, + onConfirm: () => { + onConfirmCb(); + }, + }); + } } diff --git a/ui2/src/views/application/ApplicationDetailsView.vue b/ui2/src/views/application/ApplicationDetailsView.vue index ecd584089..1e94385cd 100644 --- a/ui2/src/views/application/ApplicationDetailsView.vue +++ b/ui2/src/views/application/ApplicationDetailsView.vue @@ -1,7 +1,7 @@ <template> <PageView> <h1 class="title main-title">{{ application.title }}</h1> - <b-tabs type="is-boxed" expanded class="mt-4 ApplicationDetailsView-tabs"> + <b-tabs type="is-boxed" expanded class="mt-4 ApplicationDetailsView-tabs" :animated="false"> <b-tab-item :label="$t('applicationDetailsView.references')" icon="drafting-compass"> <ReferencesManagement :application="application" :key="application.id" /> </b-tab-item> -- GitLab From e68cd601d5fb349425245a4c0fcb7508f151e6bd Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Tue, 15 Jun 2021 11:49:48 +0200 Subject: [PATCH 15/27] Donne un cb de fermeture au SidePanel --- ui2/src/components/application/ReferencesDetailsPanel.vue | 8 +++++++- ui2/src/components/application/ReferencesManagement.vue | 2 +- ui2/src/components/common/SidePanel.vue | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ui2/src/components/application/ReferencesDetailsPanel.vue b/ui2/src/components/application/ReferencesDetailsPanel.vue index c9ac774d1..7b017a863 100644 --- a/ui2/src/components/application/ReferencesDetailsPanel.vue +++ b/ui2/src/components/application/ReferencesDetailsPanel.vue @@ -1,5 +1,10 @@ <template> - <SidePanel :open="open" :leftAlign="leftAlign" :title="reference && reference.label"> + <SidePanel + :open="open" + :leftAlign="leftAlign" + :title="reference && reference.label" + :closeCb="closeCb" + > <div class="Panel-buttons"> <b-button type="is-primary" icon-left="eye">{{ $t("referencesManagement.consult") @@ -24,6 +29,7 @@ export default class ReferencesDetailsPanel extends Vue { @Prop({ default: false }) leftAlign; @Prop({ default: false }) open; @Prop() reference; + @Prop() closeCb; alertService = AlertService.INSTANCE; diff --git a/ui2/src/components/application/ReferencesManagement.vue b/ui2/src/components/application/ReferencesManagement.vue index 55408d6ea..9dd3cfe16 100644 --- a/ui2/src/components/application/ReferencesManagement.vue +++ b/ui2/src/components/application/ReferencesManagement.vue @@ -13,7 +13,7 @@ :leftAlign="false" :open="openPanel" :reference="chosenRef" - @openStateChanged="(newVal) => (openPanel = newVal)" + :closeCb="(newVal) => (openPanel = newVal)" /> </div> </template> diff --git a/ui2/src/components/common/SidePanel.vue b/ui2/src/components/common/SidePanel.vue index 3acb689dd..ff6565ff9 100644 --- a/ui2/src/components/common/SidePanel.vue +++ b/ui2/src/components/common/SidePanel.vue @@ -16,6 +16,7 @@ export default class SidePanel extends Vue { @Prop({ default: false }) leftAlign; @Prop({ default: false }) open; @Prop({ default: "" }) title; + @Prop() closeCb; innerOpen = false; @@ -30,7 +31,7 @@ export default class SidePanel extends Vue { @Watch("innerOpen") onInnerOpenStateChanged(newVal) { - this.$emit("openStateChanged", newVal); + this.closeCb(newVal); } } </script> -- GitLab From de5b83754be107bcf83a63f2f7aa4fe429d1fec3 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Tue, 15 Jun 2021 15:00:40 +0200 Subject: [PATCH 16/27] =?UTF-8?q?Met=20=C3=A0=20jour=20la=20route=20en=20f?= =?UTF-8?q?onction=20de=20l'index=20de=20tab?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui2/src/router/index.js | 2 +- .../application/ApplicationDetailsView.vue | 27 +++++++++++++++++-- .../views/application/ApplicationsView.vue | 2 +- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/ui2/src/router/index.js b/ui2/src/router/index.js index 41b14e4e9..d2e25baf8 100644 --- a/ui2/src/router/index.js +++ b/ui2/src/router/index.js @@ -28,7 +28,7 @@ const routes = [ component: ApplicationCreationView, }, { - path: "/application/:applicationName", + path: "/application/:applicationName/:tabIndex", name: "Application view", component: ApplicationDetailsView, props: true, diff --git a/ui2/src/views/application/ApplicationDetailsView.vue b/ui2/src/views/application/ApplicationDetailsView.vue index 1e94385cd..1783e4e29 100644 --- a/ui2/src/views/application/ApplicationDetailsView.vue +++ b/ui2/src/views/application/ApplicationDetailsView.vue @@ -1,7 +1,14 @@ <template> <PageView> <h1 class="title main-title">{{ application.title }}</h1> - <b-tabs type="is-boxed" expanded class="mt-4 ApplicationDetailsView-tabs" :animated="false"> + <b-tabs + v-model="currentTabIndex" + type="is-boxed" + expanded + class="mt-4 ApplicationDetailsView-tabs" + :animated="false" + @input="onTabSelection" + > <b-tab-item :label="$t('applicationDetailsView.references')" icon="drafting-compass"> <ReferencesManagement :application="application" :key="application.id" /> </b-tab-item> @@ -11,7 +18,7 @@ </template> <script> -import { Component, Prop, Vue } from "vue-property-decorator"; +import { Component, Prop, Vue, Watch } from "vue-property-decorator"; import PageView from "@/views/common/PageView.vue"; import { ApplicationResult } from "@/model/ApplicationResult"; import { ApplicationService } from "@/services/rest/ApplicationService"; @@ -23,12 +30,16 @@ import ReferencesManagement from "@/components/application/ReferencesManagement. }) export default class ApplicationDetailsView extends Vue { @Prop() applicationName; + @Prop() tabIndex; applicationService = ApplicationService.INSTANCE; alertService = AlertService.INSTANCE; application = new ApplicationResult(); + currentTabIndex = 0; + created() { + this.currentTabIndex = parseInt(this.tabIndex); this.init(); } @@ -39,6 +50,18 @@ export default class ApplicationDetailsView extends Vue { this.alertService.toastServerError(); } } + + @Watch("tabIndex") + onExternalTabIndexChanged(newVal) { + this.currentTabIndex = parseInt(newVal); + } + + onTabSelection() { + const params = this.$router.currentRoute.params; + if (this.currentTabIndex.toString() !== params["tabIndex"]) { + this.$router.push({ params: { tabIndex: this.currentTabIndex } }); + } + } } </script> diff --git a/ui2/src/views/application/ApplicationsView.vue b/ui2/src/views/application/ApplicationsView.vue index cd7be17c3..d0c318fda 100644 --- a/ui2/src/views/application/ApplicationsView.vue +++ b/ui2/src/views/application/ApplicationsView.vue @@ -70,7 +70,7 @@ export default class ApplicationsView extends Vue { if (!application) { return; } - this.$router.push("/application/" + application.name); + this.$router.push("/application/" + application.name + "/0"); } } </script> -- GitLab From f5866d61d040c337e0d6c00f2131dab44ec923ba Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Tue, 15 Jun 2021 16:11:52 +0200 Subject: [PATCH 17/27] Supprime les onglets pr affichage des applications --- .../application/ReferencesManagement.vue | 50 ------------- .../ReferencesDetailsPanel.vue | 0 ui2/src/locales/en.json | 9 +-- ui2/src/locales/fr.json | 9 +-- ui2/src/router/index.js | 8 +- .../application/ApplicationDetailsView.vue | 74 ------------------- .../views/application/ApplicationsView.vue | 25 +++---- .../references/ReferencesManagementView.vue | 69 +++++++++++++++++ 8 files changed, 89 insertions(+), 155 deletions(-) delete mode 100644 ui2/src/components/application/ReferencesManagement.vue rename ui2/src/components/{application => references}/ReferencesDetailsPanel.vue (100%) delete mode 100644 ui2/src/views/application/ApplicationDetailsView.vue create mode 100644 ui2/src/views/references/ReferencesManagementView.vue diff --git a/ui2/src/components/application/ReferencesManagement.vue b/ui2/src/components/application/ReferencesManagement.vue deleted file mode 100644 index 9dd3cfe16..000000000 --- a/ui2/src/components/application/ReferencesManagement.vue +++ /dev/null @@ -1,50 +0,0 @@ -<template> - <div> - <CollapsibleTree - v-for="ref in references" - :key="ref.id" - :label="ref.label" - :children="ref.children" - :level="0" - :withDownload="true" - :onClickLabelCb="(event, label) => openRefDetails(event, label)" - /> - <ReferencesDetailsPanel - :leftAlign="false" - :open="openPanel" - :reference="chosenRef" - :closeCb="(newVal) => (openPanel = newVal)" - /> - </div> -</template> - -<script> -import { Component, Prop, Vue } from "vue-property-decorator"; -import { convertReferencesToTrees } from "@/utils/ConversionUtils"; -import CollapsibleTree from "@/components/common/CollapsibleTree.vue"; -import ReferencesDetailsPanel from "./ReferencesDetailsPanel.vue"; - -@Component({ - components: { CollapsibleTree, ReferencesDetailsPanel }, -}) -export default class ReferencesManagement extends Vue { - @Prop() application; - - references = []; - openPanel = false; - chosenRef = null; - - created() { - if (!this.application || !this.application.id) { - return; - } - this.references = convertReferencesToTrees(Object.values(this.application.references)); - } - - openRefDetails(event, label) { - event.stopPropagation(); - this.openPanel = this.chosenRef && this.chosenRef.label === label ? !this.openPanel : true; - this.chosenRef = Object.values(this.application.references).find((ref) => ref.label === label); - } -} -</script> diff --git a/ui2/src/components/application/ReferencesDetailsPanel.vue b/ui2/src/components/references/ReferencesDetailsPanel.vue similarity index 100% rename from ui2/src/components/application/ReferencesDetailsPanel.vue rename to ui2/src/components/references/ReferencesDetailsPanel.vue diff --git a/ui2/src/locales/en.json b/ui2/src/locales/en.json index a479236f0..694ec9da0 100644 --- a/ui2/src/locales/en.json +++ b/ui2/src/locales/en.json @@ -46,7 +46,9 @@ "create": "Create application", "name": "Application name", "name-placeholder": "Write down the application name", - "creation-date": "Creation date" + "creation-date": "Creation date", + "actions": "Actions", + "references": "References" }, "errors": { "emptyFile": "File is empty", @@ -70,11 +72,6 @@ "csvBoundToUnknownVariable": "In the CSV format, header <code>{header}</code> is bound to unknown variable <code>{variable}</code>. Known variables: <code>{variables}</code>", "csvBoundToUnknownVariableComponent": "In the CSV format, header <code>{header}</code> is bound to <code>{variable}</code> but it has no <code>{component}</code> component. Known components: <code>{components}</code>" }, - "applicationDetailsView": { - "application": "Application details", - "references": "References", - "dataset": "Datasets" - }, "referencesManagement": { "actions": "Actions", "consult": "Consult", diff --git a/ui2/src/locales/fr.json b/ui2/src/locales/fr.json index 576fa9809..524122a40 100644 --- a/ui2/src/locales/fr.json +++ b/ui2/src/locales/fr.json @@ -46,7 +46,9 @@ "create": "Créer l'application", "name": "Nom de l'application", "name-placeholder": "Entrer le nom de l'application", - "creation-date": "Date de création" + "creation-date": "Date de création", + "actions": "Actions", + "references": "Référentiels" }, "errors": { "emptyFile": "Le fichier est vide", @@ -70,11 +72,6 @@ "csvBoundToUnknownVariable": "Dans le format CSV, l’entête <code>{header}</code> est lié à la variable <code>{variable}</code> qui n'est pas connue. Variables connues <code>{variables}</code>", "csvBoundToUnknownVariableComponent": "Dans le format CSV, l’entête <code>{header}</code> est lié à la variable <code>{variable}</code> mais elle n'a pas de composant <code>{component}</code>. <br>Composants connus <code>{components}</code>" }, - "applicationDetailsView": { - "application": "Détail de l'application", - "references": "Référentiels", - "dataset": "Données" - }, "referencesManagement": { "actions": "Actions", "consult": "Consulter", diff --git a/ui2/src/router/index.js b/ui2/src/router/index.js index d2e25baf8..e143fae3e 100644 --- a/ui2/src/router/index.js +++ b/ui2/src/router/index.js @@ -3,7 +3,7 @@ import VueRouter from "vue-router"; import LoginView from "@/views/LoginView.vue"; import ApplicationsView from "@/views/application/ApplicationsView.vue"; import ApplicationCreationView from "@/views/application/ApplicationCreationView.vue"; -import ApplicationDetailsView from "@/views/application/ApplicationDetailsView.vue"; +import ReferencesManagementView from "@/views/references/ReferencesManagementView.vue"; Vue.use(VueRouter); @@ -28,9 +28,9 @@ const routes = [ component: ApplicationCreationView, }, { - path: "/application/:applicationName/:tabIndex", - name: "Application view", - component: ApplicationDetailsView, + path: "/applications/:applicationName/references", + name: "References management view", + component: ReferencesManagementView, props: true, }, ]; diff --git a/ui2/src/views/application/ApplicationDetailsView.vue b/ui2/src/views/application/ApplicationDetailsView.vue deleted file mode 100644 index 1783e4e29..000000000 --- a/ui2/src/views/application/ApplicationDetailsView.vue +++ /dev/null @@ -1,74 +0,0 @@ -<template> - <PageView> - <h1 class="title main-title">{{ application.title }}</h1> - <b-tabs - v-model="currentTabIndex" - type="is-boxed" - expanded - class="mt-4 ApplicationDetailsView-tabs" - :animated="false" - @input="onTabSelection" - > - <b-tab-item :label="$t('applicationDetailsView.references')" icon="drafting-compass"> - <ReferencesManagement :application="application" :key="application.id" /> - </b-tab-item> - <b-tab-item :label="$t('applicationDetailsView.dataset')" icon="poll">À venir</b-tab-item> - </b-tabs> - </PageView> -</template> - -<script> -import { Component, Prop, Vue, Watch } from "vue-property-decorator"; -import PageView from "@/views/common/PageView.vue"; -import { ApplicationResult } from "@/model/ApplicationResult"; -import { ApplicationService } from "@/services/rest/ApplicationService"; -import { AlertService } from "@/services/AlertService"; -import ReferencesManagement from "@/components/application/ReferencesManagement.vue"; - -@Component({ - components: { PageView, ReferencesManagement }, -}) -export default class ApplicationDetailsView extends Vue { - @Prop() applicationName; - @Prop() tabIndex; - - applicationService = ApplicationService.INSTANCE; - alertService = AlertService.INSTANCE; - application = new ApplicationResult(); - - currentTabIndex = 0; - - created() { - this.currentTabIndex = parseInt(this.tabIndex); - this.init(); - } - - async init() { - try { - this.application = await this.applicationService.getApplication(this.applicationName); - } catch (error) { - this.alertService.toastServerError(); - } - } - - @Watch("tabIndex") - onExternalTabIndexChanged(newVal) { - this.currentTabIndex = parseInt(newVal); - } - - onTabSelection() { - const params = this.$router.currentRoute.params; - if (this.currentTabIndex.toString() !== params["tabIndex"]) { - this.$router.push({ params: { tabIndex: this.currentTabIndex } }); - } - } -} -</script> - -<style lang="scss"> -.ApplicationDetailsView-tabs.b-tabs { - .tab-content { - position: initial; - } -} -</style> diff --git a/ui2/src/views/application/ApplicationsView.vue b/ui2/src/views/application/ApplicationsView.vue index d0c318fda..bfc21d229 100644 --- a/ui2/src/views/application/ApplicationsView.vue +++ b/ui2/src/views/application/ApplicationsView.vue @@ -16,16 +16,8 @@ :per-page="15" height="100%" > - <b-table-column - field="name" - :label="$t('applications.name')" - sortable - width="50%" - v-slot="props" - > - <div @click="displayApplication(props.row)" class="clickable"> - {{ props.row.name }} - </div> + <b-table-column field="name" :label="$t('applications.name')" sortable v-slot="props"> + {{ props.row.name }} </b-table-column> <b-table-column field="creationDate" @@ -33,9 +25,12 @@ sortable v-slot="props" > - <div @click="displayApplication(props.row)" class="clickable"> - {{ new Date(props.row.creationDate) }} - </div> + {{ new Date(props.row.creationDate) }} + </b-table-column> + <b-table-column field="actions" :label="$t('applications.actions')" v-slot="props"> + <b-button icon-left="drafting-compass" @click="displayReferencesManagement(props.row)">{{ + $t("applications.references") + }}</b-button> </b-table-column> </b-table> </PageView> @@ -66,11 +61,11 @@ export default class ApplicationsView extends Vue { this.$router.push("/applicationCreation"); } - displayApplication(application) { + displayReferencesManagement(application) { if (!application) { return; } - this.$router.push("/application/" + application.name + "/0"); + this.$router.push("/applications/" + application.name + "/references"); } } </script> diff --git a/ui2/src/views/references/ReferencesManagementView.vue b/ui2/src/views/references/ReferencesManagementView.vue new file mode 100644 index 000000000..2c32ec239 --- /dev/null +++ b/ui2/src/views/references/ReferencesManagementView.vue @@ -0,0 +1,69 @@ +<template> + <PageView> + <h1 class="title main-title">{{ application.title }}</h1> + <div> + <CollapsibleTree + v-for="ref in references" + :key="ref.id" + :label="ref.label" + :children="ref.children" + :level="0" + :withDownload="true" + :onClickLabelCb="(event, label) => openRefDetails(event, label)" + /> + <ReferencesDetailsPanel + :leftAlign="false" + :open="openPanel" + :reference="chosenRef" + :closeCb="(newVal) => (openPanel = newVal)" + /> + </div> + </PageView> +</template> + +<script> +import { Component, Prop, Vue } from "vue-property-decorator"; +import { convertReferencesToTrees } from "@/utils/ConversionUtils"; +import CollapsibleTree from "@/components/common/CollapsibleTree.vue"; +import ReferencesDetailsPanel from "@/components/references/ReferencesDetailsPanel.vue"; +import { ApplicationService } from "@/services/rest/ApplicationService"; +import PageView from "../common/PageView.vue"; +import { ApplicationResult } from "@/model/ApplicationResult"; + +@Component({ + components: { CollapsibleTree, ReferencesDetailsPanel, PageView }, +}) +export default class ReferencesManagementView extends Vue { + @Prop() applicationName; + + applicationService = ApplicationService.INSTANCE; + + references = []; + openPanel = false; + chosenRef = null; + application = new ApplicationResult(); + + created() { + console.log(this.applicationName); + this.init(); + } + + async init() { + try { + this.application = await this.applicationService.getApplication(this.applicationName); + if (!this.application || !this.application.id) { + return; + } + this.references = convertReferencesToTrees(Object.values(this.application.references)); + } catch (error) { + this.alertService.toastServerError(); + } + } + + openRefDetails(event, label) { + event.stopPropagation(); + this.openPanel = this.chosenRef && this.chosenRef.label === label ? !this.openPanel : true; + this.chosenRef = Object.values(this.application.references).find((ref) => ref.label === label); + } +} +</script> -- GitLab From 2b61c39fe669780d887cdae3e9982ed37c2592e2 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Tue, 15 Jun 2021 16:31:12 +0200 Subject: [PATCH 18/27] Rend le menu collapsible. --- ui2/src/style/_variables.scss | 1 + ui2/src/views/common/MenuView.vue | 100 +++++++++++++++++++----------- 2 files changed, 65 insertions(+), 36 deletions(-) diff --git a/ui2/src/style/_variables.scss b/ui2/src/style/_variables.scss index 9004cb4bd..c276b43bd 100644 --- a/ui2/src/style/_variables.scss +++ b/ui2/src/style/_variables.scss @@ -6,6 +6,7 @@ $font-family: "LiberationSans", Helvetica, Arial, sans-serif; $text-default-color: #2c3e50; $light-text: rgb(230, 230, 230); +$primary-slightly-transparent: rgba(0, 163, 166, 0.8); // PageView $container-padding-hor: 3rem; diff --git a/ui2/src/views/common/MenuView.vue b/ui2/src/views/common/MenuView.vue index 5880b3ddd..7fe563a62 100644 --- a/ui2/src/views/common/MenuView.vue +++ b/ui2/src/views/common/MenuView.vue @@ -1,39 +1,46 @@ <template> - <b-navbar class="menu-view"> - <template #start> - <b-navbar-item tag="router-link" :to="{ path: '/applications' }"> - {{ $t("menu.applications") }} - </b-navbar-item> - </template> - - <template #end> - <b-navbar-item tag="div"> - <div class="buttons"> - <b-button type="is-info" @click="logout" icon-right="sign-out-alt">{{ - $t("menu.logout") - }}</b-button> - </div> - </b-navbar-item> - <b-navbar-item tag="div"> - <b-field> - <b-select - v-model="chosenLocale" - :placeholder="$t('menu.language')" - icon="globe" - @input="setUserPrefLocale" - > - <option :value="locales.FRENCH">{{ $t("menu.french") }}</option> - <option :value="locales.ENGLISH">{{ $t("menu.english") }}</option> - </b-select> - </b-field> - </b-navbar-item> - <b-navbar-item href="https://www.inrae.fr/"> - <img class="logo_blanc" src="@/assets/logo-inrae_blanc.svg" /> - <img class="logo_vert" src="@/assets/Logo-INRAE.svg" /> - </b-navbar-item> - <img class="logo_rep" src="@/assets/Rep-FR-logo.svg" /> - </template> - </b-navbar> + <div class="menu-view-container"> + <b-navbar class="menu-view" v-if="open"> + <template #start> + <b-navbar-item tag="router-link" :to="{ path: '/applications' }"> + {{ $t("menu.applications") }} + </b-navbar-item> + </template> + + <template #end> + <b-navbar-item tag="div"> + <div class="buttons"> + <b-button type="is-info" @click="logout" icon-right="sign-out-alt">{{ + $t("menu.logout") + }}</b-button> + </div> + </b-navbar-item> + <b-navbar-item tag="div"> + <b-field> + <b-select + v-model="chosenLocale" + :placeholder="$t('menu.language')" + icon="globe" + @input="setUserPrefLocale" + > + <option :value="locales.FRENCH">{{ $t("menu.french") }}</option> + <option :value="locales.ENGLISH">{{ $t("menu.english") }}</option> + </b-select> + </b-field> + </b-navbar-item> + <b-navbar-item href="https://www.inrae.fr/"> + <img class="logo_blanc" src="@/assets/logo-inrae_blanc.svg" /> + <img class="logo_vert" src="@/assets/Logo-INRAE.svg" /> + </b-navbar-item> + <img class="logo_rep" src="@/assets/Rep-FR-logo.svg" /> + </template> + </b-navbar> + <FontAwesomeIcon + @click="open = !open" + :icon="open ? 'caret-up' : 'caret-down'" + class="clickable mr-3 menu-view-collapsible-icon" + /> + </div> </template> <script> @@ -43,9 +50,10 @@ import { LoginService } from "@/services/rest/LoginService"; import { UserPreferencesService } from "@/services/UserPreferencesService"; import { Locales } from "@/utils/LocaleUtils.js"; +import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; @Component({ - components: {}, + components: { FontAwesomeIcon }, }) export default class MenuView extends Vue { loginService = LoginService.INSTANCE; @@ -53,6 +61,7 @@ export default class MenuView extends Vue { locales = Locales; chosenLocale = ""; + open = true; created() { this.chosenLocale = this.userPreferencesService.getUserPrefLocale(); @@ -119,4 +128,23 @@ export default class MenuView extends Vue { } } } + +.menu-view-container { + line-height: 0; +} + +.menu-view-collapsible-icon { + width: 100%; + background-color: $primary-slightly-transparent; + height: 30px; + opacity: 0.8; + + &:hover { + opacity: 1; + } + + path { + fill: white; + } +} </style> -- GitLab From f98c527ce7d308d2b5b4f55cc169cba8593086e4 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Tue, 15 Jun 2021 16:35:23 +0200 Subject: [PATCH 19/27] Ajoute des exemples dans les placeholders --- ui2/src/locales/en.json | 6 +++--- ui2/src/locales/fr.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ui2/src/locales/en.json b/ui2/src/locales/en.json index 694ec9da0..da3c20d9a 100644 --- a/ui2/src/locales/en.json +++ b/ui2/src/locales/en.json @@ -9,9 +9,9 @@ "signin": "Sign in", "signup": "Sign up", "login": "Login", - "login-placeholder": "Write down the login", + "login-placeholder": "Ex: michel", "pwd": "Password", - "pwd-placeholder": "Write down the password", + "pwd-placeholder": "Ex: xxxx", "pwd-forgotten": "Forgotten password ? " }, "validation": { @@ -45,7 +45,7 @@ "chose-config": "Chose a configuration", "create": "Create application", "name": "Application name", - "name-placeholder": "Write down the application name", + "name-placeholder": "Ex : olac", "creation-date": "Creation date", "actions": "Actions", "references": "References" diff --git a/ui2/src/locales/fr.json b/ui2/src/locales/fr.json index 524122a40..10d16fce8 100644 --- a/ui2/src/locales/fr.json +++ b/ui2/src/locales/fr.json @@ -9,9 +9,9 @@ "signin": "Se connecter", "signup": "Créer un compte", "login": "Identifiant", - "login-placeholder": "Entrer l'identifiant", + "login-placeholder": "Ex: michel", "pwd": "Mot de passe", - "pwd-placeholder": "Entrer le mot de passe", + "pwd-placeholder": "Ex: xxxx", "pwd-forgotten": "Mot de passe oublié ?" }, "validation": { @@ -45,7 +45,7 @@ "chose-config": "Choisir une configuration", "create": "Créer l'application", "name": "Nom de l'application", - "name-placeholder": "Entrer le nom de l'application", + "name-placeholder": "Ex : olac", "creation-date": "Date de création", "actions": "Actions", "references": "Référentiels" -- GitLab From 77ff988854b1ff9706d4dd7eabdb992374e61840 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Tue, 15 Jun 2021 17:06:34 +0200 Subject: [PATCH 20/27] :construction: Ajoute un sous menu --- ui2/src/components/common/CollapsibleTree.vue | 9 +-- ui2/src/components/common/SubMenu.vue | 49 ++++++++++++++ ui2/src/style/_common.scss | 8 +++ ui2/src/style/_variables.scss | 65 ++++++++++--------- .../references/ReferencesManagementView.vue | 10 ++- 5 files changed, 99 insertions(+), 42 deletions(-) create mode 100644 ui2/src/components/common/SubMenu.vue diff --git a/ui2/src/components/common/CollapsibleTree.vue b/ui2/src/components/common/CollapsibleTree.vue index a970dd44f..488ecd4c0 100644 --- a/ui2/src/components/common/CollapsibleTree.vue +++ b/ui2/src/components/common/CollapsibleTree.vue @@ -14,7 +14,7 @@ class="clickable mr-3" /> <div - class="clickable CollapsibleTree-header-label" + class="link" :style="`transform:translate(${level * 50}px);`" @click="(event) => onClickLabelCb(event, label)" > @@ -96,11 +96,4 @@ export default class CollapsibleTree extends Vue { display: flex; align-items: center; } - -.CollapsibleTree-header-label { - &:hover { - color: $primary; - text-decoration: underline; - } -} </style> diff --git a/ui2/src/components/common/SubMenu.vue b/ui2/src/components/common/SubMenu.vue new file mode 100644 index 000000000..4643085fe --- /dev/null +++ b/ui2/src/components/common/SubMenu.vue @@ -0,0 +1,49 @@ +<template> + <div class="SubMenu"> + <span class="SubMenu-root">{{ root }}</span> + <div v-for="path in paths" :key="path.label"> + <span class="SubMenu-path-separator mr-1 ml-1">/</span> + <span @click="path.clickCb" class="link"> {{ path.label }}</span> + </div> + </div> +</template> + +<script> +import { Component, Prop, Vue } from "vue-property-decorator"; + +export class SubMenuPath { + label; + clickCb; + + constructor(label, clickCb) { + this.label = label; + this.clickCb = clickCb; + } +} + +@Component({ + components: {}, +}) +export default class SubMenu extends Vue { + @Prop() root; + @Prop() paths; + + created() { + console.log(this.paths); + } +} +</script> + +<style lang="scss" scoped> +.SubMenu { + display: flex; + height: 40px; + background-color: $info-transparent; +} + +.SubMenu-root { + color: $dark; + font-weight: 600; + font-size: 1.2em; +} +</style> diff --git a/ui2/src/style/_common.scss b/ui2/src/style/_common.scss index 883a76358..04baf8edb 100644 --- a/ui2/src/style/_common.scss +++ b/ui2/src/style/_common.scss @@ -23,6 +23,14 @@ a { cursor: pointer; } +.link { + cursor: pointer; + &:hover { + color: $primary; + text-decoration: underline; + } +} + // Input style .input-field { diff --git a/ui2/src/style/_variables.scss b/ui2/src/style/_variables.scss index c276b43bd..4abde752e 100644 --- a/ui2/src/style/_variables.scss +++ b/ui2/src/style/_variables.scss @@ -1,32 +1,33 @@ -/************************************************************************************************** -* Global app variables (defined in the app) * -***************************************************************************************************/ - -$font-family: "LiberationSans", Helvetica, Arial, sans-serif; - -$text-default-color: #2c3e50; -$light-text: rgb(230, 230, 230); -$primary-slightly-transparent: rgba(0, 163, 166, 0.8); - -// PageView -$container-padding-hor: 3rem; -$container-padding-vert: $container-padding-hor / 2; -$title-margin-top: 1.5rem; - -// MenuView -$menu-height: 80px; - -/************************************************************************************************** -* Buefy/Bulma customizations * -* see all customizable variables here https://buefy.org/documentation/customization/ * -***************************************************************************************************/ - -// General variables -$primary: rgb(0, 163, 166); -$info: #4ec6c2; -$success: #bade81; -$warning: #ffec60; -$danger: #d13a18; -$dark: #4b6464; -$light: rgb(202, 216, 216); -$family-primary: $font-family; +/************************************************************************************************** +* Global app variables (defined in the app) * +***************************************************************************************************/ + +$font-family: "LiberationSans", Helvetica, Arial, sans-serif; + +$text-default-color: #2c3e50; +$light-text: rgb(230, 230, 230); +$primary-slightly-transparent: rgba(0, 163, 166, 0.8); +$info-transparent: rgba(78, 198, 194, 0.3); + +// PageView +$container-padding-hor: 3rem; +$container-padding-vert: $container-padding-hor / 2; +$title-margin-top: 1.5rem; + +// MenuView +$menu-height: 80px; + +/************************************************************************************************** +* Buefy/Bulma customizations * +* see all customizable variables here https://buefy.org/documentation/customization/ * +***************************************************************************************************/ + +// General variables +$primary: rgb(0, 163, 166); +$info: rgb(78, 198, 194); +$success: #bade81; +$warning: #ffec60; +$danger: #d13a18; +$dark: #4b6464; +$light: rgb(202, 216, 216); +$family-primary: $font-family; diff --git a/ui2/src/views/references/ReferencesManagementView.vue b/ui2/src/views/references/ReferencesManagementView.vue index 2c32ec239..95c8bf8be 100644 --- a/ui2/src/views/references/ReferencesManagementView.vue +++ b/ui2/src/views/references/ReferencesManagementView.vue @@ -1,5 +1,6 @@ <template> <PageView> + <SubMenu :root="application.title" :paths="subMenuPaths" /> <h1 class="title main-title">{{ application.title }}</h1> <div> <CollapsibleTree @@ -29,9 +30,10 @@ import ReferencesDetailsPanel from "@/components/references/ReferencesDetailsPan import { ApplicationService } from "@/services/rest/ApplicationService"; import PageView from "../common/PageView.vue"; import { ApplicationResult } from "@/model/ApplicationResult"; +import SubMenu, { SubMenuPath } from "@/components/common/SubMenu.vue"; @Component({ - components: { CollapsibleTree, ReferencesDetailsPanel, PageView }, + components: { CollapsibleTree, ReferencesDetailsPanel, PageView, SubMenu }, }) export default class ReferencesManagementView extends Vue { @Prop() applicationName; @@ -42,9 +44,13 @@ export default class ReferencesManagementView extends Vue { openPanel = false; chosenRef = null; application = new ApplicationResult(); + subMenuPaths = [ + new SubMenuPath("references", () => + this.$router.push(`/applications/${this.applicationName}/references`) + ), + ]; created() { - console.log(this.applicationName); this.init(); } -- GitLab From 5983d30c1ebacfe7c87a6117fcd00ade1767e55a Mon Sep 17 00:00:00 2001 From: Brendan Le Ny <bleny@codelutin.com> Date: Tue, 15 Jun 2021 17:42:53 +0200 Subject: [PATCH 21/27] =?UTF-8?q?Corrige=20les=20donn=C3=A9es=20renvoy?= =?UTF-8?q?=C3=A9es=20au=20front=20au=20chargement=20du=20contenu=20d'un?= =?UTF-8?q?=20r=C3=A9f=C3=A9rentiel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../inra/oresing/rest/GetReferenceResult.java | 18 ++++++++++++++++++ .../fr/inra/oresing/rest/OreSiResources.java | 15 +++++++++++++-- .../inra/oresing/rest/OreSiResourcesTest.java | 13 ++++++------- 3 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 src/main/java/fr/inra/oresing/rest/GetReferenceResult.java diff --git a/src/main/java/fr/inra/oresing/rest/GetReferenceResult.java b/src/main/java/fr/inra/oresing/rest/GetReferenceResult.java new file mode 100644 index 000000000..d1488cc30 --- /dev/null +++ b/src/main/java/fr/inra/oresing/rest/GetReferenceResult.java @@ -0,0 +1,18 @@ +package fr.inra.oresing.rest; + +import lombok.Value; + +import java.util.Map; +import java.util.Set; + +@Value +public class GetReferenceResult { + Set<ReferenceValue> referenceValues; + + @Value + public static class ReferenceValue { + String hierarchicalKey; + String naturalKey; + Map<String, String> values; + } +} diff --git a/src/main/java/fr/inra/oresing/rest/OreSiResources.java b/src/main/java/fr/inra/oresing/rest/OreSiResources.java index 34f625553..c21f7d125 100644 --- a/src/main/java/fr/inra/oresing/rest/OreSiResources.java +++ b/src/main/java/fr/inra/oresing/rest/OreSiResources.java @@ -2,6 +2,7 @@ package fr.inra.oresing.rest; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Maps; import com.google.common.collect.Ordering; @@ -30,6 +31,7 @@ import org.springframework.web.util.UriUtils; import java.io.IOException; import java.net.URI; import java.nio.charset.Charset; +import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Optional; @@ -164,12 +166,21 @@ public class OreSiResources { * @return un tableau de chaine */ @GetMapping(value = "/applications/{nameOrId}/references/{refType}", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity<List<ReferenceValue>> listReferences( + public ResponseEntity<GetReferenceResult> listReferences( @PathVariable("nameOrId") String nameOrId, @PathVariable("refType") String refType, @RequestParam MultiValueMap<String, String> params) { List<ReferenceValue> list = service.findReference(nameOrId, refType, params); - return ResponseEntity.ok(list); + ImmutableSet<GetReferenceResult.ReferenceValue> referenceValues = list.stream() + .map(referenceValue -> + new GetReferenceResult.ReferenceValue( + referenceValue.getHierarchicalKey(), + referenceValue.getNaturalKey(), + referenceValue.getRefValues() + ) + ) + .collect(ImmutableSortedSet.toImmutableSortedSet(Comparator.comparing(GetReferenceResult.ReferenceValue::getHierarchicalKey))); + return ResponseEntity.ok(new GetReferenceResult(referenceValues)); } @GetMapping(value = "/applications/{nameOrId}/references/{refType}/{column}", produces = MediaType.APPLICATION_JSON_VALUE) diff --git a/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java b/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java index 06c356d0e..ed6123d07 100644 --- a/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java +++ b/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java @@ -36,7 +36,6 @@ import javax.servlet.http.Cookie; import java.io.InputStream; import java.net.URL; import java.nio.charset.StandardCharsets; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -146,8 +145,8 @@ public class OreSiResourcesTest { .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) .andReturn().getResponse().getContentAsString(); - List refs = objectMapper.readValue(getReferencesResponse, List.class); - Assert.assertEquals(9, refs.size()); + GetReferenceResult GetReferenceResult = objectMapper.readValue(getReferencesResponse, GetReferenceResult.class); + Assert.assertEquals(9, GetReferenceResult.getReferenceValues().size()); // ajout de data resource = getClass().getResource(fixtures.getPemDataResourceName()); @@ -371,8 +370,8 @@ public class OreSiResourcesTest { .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) .andReturn().getResponse().getContentAsString(); - List refs = objectMapper.readValue(getReferenceResponse, List.class); - Assert.assertEquals(103, refs.size()); + GetReferenceResult refs = objectMapper.readValue(getReferenceResponse, GetReferenceResult.class); + Assert.assertEquals(103, refs.getReferenceValues().size()); // Ajout de referentiel for (Map.Entry<String, String> e : fixtures.getAcbbReferentielFiles().entrySet()) { @@ -397,8 +396,8 @@ public class OreSiResourcesTest { .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) .andReturn().getResponse().getContentAsString(); - refs = objectMapper.readValue(getReferenceResponse, List.class); - Assert.assertEquals(103, refs.size()); + refs = objectMapper.readValue(getReferenceResponse, GetReferenceResult.class); + Assert.assertEquals(103, refs.getReferenceValues().size()); // ajout de data try (InputStream in = getClass().getResourceAsStream(fixtures.getFluxToursDataResourceName())) { -- GitLab From efbd6812b6179f56b507b989d0c366d0f9f7a965 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Wed, 16 Jun 2021 17:59:31 +0200 Subject: [PATCH 22/27] =?UTF-8?q?Am=C3=A9liore=20le=20style=20du=20sous-me?= =?UTF-8?q?nu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui2/src/components/common/CollapsibleTree.vue | 2 +- ui2/src/components/common/SubMenu.vue | 14 ++++++----- ui2/src/locales/en.json | 6 +++-- ui2/src/locales/fr.json | 6 +++-- ui2/src/main.js | 4 ++- .../references/ReferencesManagementView.vue | 25 +++++++++++++------ 6 files changed, 38 insertions(+), 19 deletions(-) diff --git a/ui2/src/components/common/CollapsibleTree.vue b/ui2/src/components/common/CollapsibleTree.vue index 488ecd4c0..e08213784 100644 --- a/ui2/src/components/common/CollapsibleTree.vue +++ b/ui2/src/components/common/CollapsibleTree.vue @@ -10,7 +10,7 @@ <div class="CollapsibleTree-header-infos"> <FontAwesomeIcon v-if="children && children.length !== 0" - :icon="displayChildren ? 'caret-up' : 'caret-down'" + :icon="displayChildren ? 'caret-down' : 'caret-right'" class="clickable mr-3" /> <div diff --git a/ui2/src/components/common/SubMenu.vue b/ui2/src/components/common/SubMenu.vue index 4643085fe..1c796bd60 100644 --- a/ui2/src/components/common/SubMenu.vue +++ b/ui2/src/components/common/SubMenu.vue @@ -1,9 +1,13 @@ <template> <div class="SubMenu"> <span class="SubMenu-root">{{ root }}</span> - <div v-for="path in paths" :key="path.label"> + <div v-for="(path, index) in paths" :key="path.label"> <span class="SubMenu-path-separator mr-1 ml-1">/</span> - <span @click="path.clickCb" class="link"> {{ path.label }}</span> + <span + @click="index !== paths.length - 1 ? path.clickCb : ''" + :class="index !== paths.length - 1 ? 'link' : ''" + >{{ path.label }}</span + > </div> </div> </template> @@ -27,10 +31,6 @@ export class SubMenuPath { export default class SubMenu extends Vue { @Prop() root; @Prop() paths; - - created() { - console.log(this.paths); - } } </script> @@ -39,6 +39,8 @@ export default class SubMenu extends Vue { display: flex; height: 40px; background-color: $info-transparent; + align-items: center; + padding: 0.5rem; } .SubMenu-root { diff --git a/ui2/src/locales/en.json b/ui2/src/locales/en.json index 17c1f7053..62facb478 100644 --- a/ui2/src/locales/en.json +++ b/ui2/src/locales/en.json @@ -2,7 +2,7 @@ "titles": { "login-page": "Welcome to SI-ORE", "applications-page": "My applications", - "references-page": "My references", + "references-page": "{applicationName} references", "application-creation": "Application creation" }, "login": { @@ -80,6 +80,8 @@ "actions": "Actions", "consult": "Consult", "download": "Download", - "delete": "Delete" + "delete": "Delete", + "references": "References", + "data": "Data" } } diff --git a/ui2/src/locales/fr.json b/ui2/src/locales/fr.json index 8cda2930c..ef3c339d6 100644 --- a/ui2/src/locales/fr.json +++ b/ui2/src/locales/fr.json @@ -2,7 +2,7 @@ "titles": { "login-page": "Bienvenue sur SI-ORE", "applications-page": "Mes applications", - "references-page": "Mes référentiels", + "references-page": "Référentiels de {applicationName}", "application-creation": "Créer une application" }, "login": { @@ -80,6 +80,8 @@ "actions": "Actions", "consult": "Consulter", "download": "Télécharger", - "delete": "Supprimer" + "delete": "Supprimer", + "references": "Référentiels", + "data": "Données" } } diff --git a/ui2/src/main.js b/ui2/src/main.js index 7665747a1..4b248832a 100644 --- a/ui2/src/main.js +++ b/ui2/src/main.js @@ -26,6 +26,7 @@ import { faUpload, faWrench, faVial, + faCaretRight, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; library.add( @@ -49,7 +50,8 @@ library.add( faTimes, faTrashAlt, faDownload, - faVial + faVial, + faCaretRight ); Vue.component("vue-fontawesome", FontAwesomeIcon); diff --git a/ui2/src/views/references/ReferencesManagementView.vue b/ui2/src/views/references/ReferencesManagementView.vue index 95c8bf8be..c71dba800 100644 --- a/ui2/src/views/references/ReferencesManagementView.vue +++ b/ui2/src/views/references/ReferencesManagementView.vue @@ -1,7 +1,9 @@ <template> - <PageView> + <PageView class="ReferencesManagementView"> <SubMenu :root="application.title" :paths="subMenuPaths" /> - <h1 class="title main-title">{{ application.title }}</h1> + <h1 class="title main-title"> + {{ $t("titles.references-page", { applicationName: application.title }) }} + </h1> <div> <CollapsibleTree v-for="ref in references" @@ -44,13 +46,14 @@ export default class ReferencesManagementView extends Vue { openPanel = false; chosenRef = null; application = new ApplicationResult(); - subMenuPaths = [ - new SubMenuPath("references", () => - this.$router.push(`/applications/${this.applicationName}/references`) - ), - ]; + subMenuPaths = []; created() { + this.subMenuPaths = [ + new SubMenuPath(this.$t("referencesManagement.references").toLowerCase(), () => + this.$router.push(`/applications/${this.applicationName}/references`) + ), + ]; this.init(); } @@ -73,3 +76,11 @@ export default class ReferencesManagementView extends Vue { } } </script> + +<style lang="scss"> +.ReferencesManagementView { + .PageView-container { + padding-top: 0.5rem; + } +} +</style> -- GitLab From 8d25b9fc47d07b3c324a02b8e11e108f22197fb1 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Wed, 16 Jun 2021 19:31:05 +0200 Subject: [PATCH 23/27] =?UTF-8?q?Ajoute=20la=20page=20affichant=20les=20do?= =?UTF-8?q?nn=C3=A9es=20de=20r=C3=A9f=C3=A9rences?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui2/src/components/common/SubMenu.vue | 6 +- .../references/ReferencesDetailsPanel.vue | 6 +- ui2/src/locales/en.json | 1 + ui2/src/locales/fr.json | 1 + ui2/src/router/index.js | 6 ++ ui2/src/views/common/MenuView.vue | 2 +- ui2/src/views/common/PageView.vue | 5 + .../views/references/ReferenceTableView.vue | 101 ++++++++++++++++++ .../references/ReferencesManagementView.vue | 13 +-- 9 files changed, 129 insertions(+), 12 deletions(-) create mode 100644 ui2/src/views/references/ReferenceTableView.vue diff --git a/ui2/src/components/common/SubMenu.vue b/ui2/src/components/common/SubMenu.vue index 1c796bd60..2b5d444c6 100644 --- a/ui2/src/components/common/SubMenu.vue +++ b/ui2/src/components/common/SubMenu.vue @@ -4,7 +4,7 @@ <div v-for="(path, index) in paths" :key="path.label"> <span class="SubMenu-path-separator mr-1 ml-1">/</span> <span - @click="index !== paths.length - 1 ? path.clickCb : ''" + @click="index !== paths.length - 1 ? path.clickCb() : ''" :class="index !== paths.length - 1 ? 'link' : ''" >{{ path.label }}</span > @@ -40,7 +40,9 @@ export default class SubMenu extends Vue { height: 40px; background-color: $info-transparent; align-items: center; - padding: 0.5rem; + padding: 0.5rem $container-padding-hor; + width: calc(100% + 2 * #{$container-padding-hor}); + transform: translateX(-$container-padding-hor); } .SubMenu-root { diff --git a/ui2/src/components/references/ReferencesDetailsPanel.vue b/ui2/src/components/references/ReferencesDetailsPanel.vue index 7b017a863..10c56d924 100644 --- a/ui2/src/components/references/ReferencesDetailsPanel.vue +++ b/ui2/src/components/references/ReferencesDetailsPanel.vue @@ -6,7 +6,7 @@ :closeCb="closeCb" > <div class="Panel-buttons"> - <b-button type="is-primary" icon-left="eye">{{ + <b-button type="is-primary" icon-left="eye" @click="emitConsult">{{ $t("referencesManagement.consult") }}</b-button> <b-button icon-left="download">{{ $t("referencesManagement.download") }}</b-button> @@ -46,6 +46,10 @@ export default class ReferencesDetailsPanel extends Vue { deleteReference() { console.log("DELETE", this.reference); } + + emitConsult() { + this.$emit("consultReference", this.reference.id); + } } </script> diff --git a/ui2/src/locales/en.json b/ui2/src/locales/en.json index 62facb478..847b772b6 100644 --- a/ui2/src/locales/en.json +++ b/ui2/src/locales/en.json @@ -3,6 +3,7 @@ "login-page": "Welcome to SI-ORE", "applications-page": "My applications", "references-page": "{applicationName} references", + "references-data": "{refName} data", "application-creation": "Application creation" }, "login": { diff --git a/ui2/src/locales/fr.json b/ui2/src/locales/fr.json index ef3c339d6..8d5802fc0 100644 --- a/ui2/src/locales/fr.json +++ b/ui2/src/locales/fr.json @@ -3,6 +3,7 @@ "login-page": "Bienvenue sur SI-ORE", "applications-page": "Mes applications", "references-page": "Référentiels de {applicationName}", + "references-data": "Données de {refName}", "application-creation": "Créer une application" }, "login": { diff --git a/ui2/src/router/index.js b/ui2/src/router/index.js index e143fae3e..0001e72b4 100644 --- a/ui2/src/router/index.js +++ b/ui2/src/router/index.js @@ -4,6 +4,7 @@ import LoginView from "@/views/LoginView.vue"; import ApplicationsView from "@/views/application/ApplicationsView.vue"; import ApplicationCreationView from "@/views/application/ApplicationCreationView.vue"; import ReferencesManagementView from "@/views/references/ReferencesManagementView.vue"; +import ReferenceTable from "@/views/references/ReferenceTableView.vue"; Vue.use(VueRouter); @@ -33,6 +34,11 @@ const routes = [ component: ReferencesManagementView, props: true, }, + { + path: "/applications/:applicationName/references/:refId", + component: ReferenceTable, + props: true, + }, ]; const router = new VueRouter({ diff --git a/ui2/src/views/common/MenuView.vue b/ui2/src/views/common/MenuView.vue index 7fe563a62..b98c505e9 100644 --- a/ui2/src/views/common/MenuView.vue +++ b/ui2/src/views/common/MenuView.vue @@ -61,7 +61,7 @@ export default class MenuView extends Vue { locales = Locales; chosenLocale = ""; - open = true; + open = false; created() { this.chosenLocale = this.userPreferencesService.getUserPrefLocale(); diff --git a/ui2/src/views/common/PageView.vue b/ui2/src/views/common/PageView.vue index 57154602c..0da059501 100644 --- a/ui2/src/views/common/PageView.vue +++ b/ui2/src/views/common/PageView.vue @@ -32,6 +32,11 @@ export default class PageView extends Vue { <style lang="scss" scoped> .PageView { height: 100%; + &.with-submenu { + .PageView-container { + padding-top: 0rem; + } + } } .PageView-container { diff --git a/ui2/src/views/references/ReferenceTableView.vue b/ui2/src/views/references/ReferenceTableView.vue new file mode 100644 index 000000000..4fc66f428 --- /dev/null +++ b/ui2/src/views/references/ReferenceTableView.vue @@ -0,0 +1,101 @@ +<template> + <PageView class="with-submenu"> + <SubMenu :root="application.title" :paths="subMenuPaths" /> + <h1 class="title main-title"> + {{ $t("titles.references-data", { refName: reference.label }) }} + </h1> + + <div v-if="reference && columns"> + <b-table + :data="[]" + :striped="true" + :isFocusable="true" + :isHoverable="true" + :sticky-header="true" + :paginated="true" + :per-page="15" + height="100%" + > + <b-table-column + v-for="column in columns" + :key="column.id" + :field="column.title" + :label="column.title" + sortable + :sticky="column.key" + > + </b-table-column> + </b-table> + </div> + </PageView> +</template> + +<script> +import SubMenu, { SubMenuPath } from "@/components/common/SubMenu.vue"; +import { ApplicationResult } from "@/model/ApplicationResult"; +import { AlertService } from "@/services/AlertService"; +import { ApplicationService } from "@/services/rest/ApplicationService"; +import { Prop, Vue, Component } from "vue-property-decorator"; +import PageView from "../common/PageView.vue"; + +@Component({ + components: { PageView, SubMenu }, +}) +export default class ReferenceTableView extends Vue { + @Prop() applicationName; + @Prop() refId; + + alertService = AlertService.INSTANCE; + applicationService = ApplicationService.INSTANCE; + + application = new ApplicationResult(); + subMenuPaths = []; + reference = {}; + columns = []; + + created() { + this.init(); + } + + async init() { + try { + this.application = await this.applicationService.getApplication(this.applicationName); + this.setInitialVariables(); + } catch (error) { + this.alertService.toastServerError(); + } + } + + setInitialVariables() { + if (!this.application || !this.application.references) { + return; + } + + this.reference = Object.values(this.application.references).find( + (ref) => ref.id === this.refId + ); + + this.subMenuPaths = [ + new SubMenuPath(this.$t("referencesManagement.references").toLowerCase(), () => + this.$router.push(`/applications/${this.applicationName}/references`) + ), + new SubMenuPath(this.reference.label, () => + this.$router.push(`/applications/${this.applicationName}/references/${this.refId}`) + ), + ]; + + if (this.reference && this.reference.columns) { + this.columns = Object.values(this.reference.columns).sort((c1, c2) => { + if (c1.title < c2.title) { + return -1; + } + + if (c1.title > c2.title) { + return 1; + } + return 0; + }); + } + } +} +</script> diff --git a/ui2/src/views/references/ReferencesManagementView.vue b/ui2/src/views/references/ReferencesManagementView.vue index c71dba800..0ad0d53aa 100644 --- a/ui2/src/views/references/ReferencesManagementView.vue +++ b/ui2/src/views/references/ReferencesManagementView.vue @@ -1,5 +1,5 @@ <template> - <PageView class="ReferencesManagementView"> + <PageView class="with-submenu"> <SubMenu :root="application.title" :paths="subMenuPaths" /> <h1 class="title main-title"> {{ $t("titles.references-page", { applicationName: application.title }) }} @@ -19,6 +19,7 @@ :open="openPanel" :reference="chosenRef" :closeCb="(newVal) => (openPanel = newVal)" + @consultReference="consultReference" /> </div> </PageView> @@ -74,13 +75,9 @@ export default class ReferencesManagementView extends Vue { this.openPanel = this.chosenRef && this.chosenRef.label === label ? !this.openPanel : true; this.chosenRef = Object.values(this.application.references).find((ref) => ref.label === label); } -} -</script> -<style lang="scss"> -.ReferencesManagementView { - .PageView-container { - padding-top: 0.5rem; + consultReference(id) { + this.$router.push(`/applications/${this.applicationName}/references/${id}`); } } -</style> +</script> -- GitLab From 312cb017fb55a05c6a3fe60b5d03e79ffe13d093 Mon Sep 17 00:00:00 2001 From: Brendan Le Ny <bleny@codelutin.com> Date: Thu, 17 Jun 2021 14:57:14 +0200 Subject: [PATCH 24/27] =?UTF-8?q?Exposer=20au=20front=20les=20types=20de?= =?UTF-8?q?=20donn=C3=A9es,=20les=20variables=20et=20les=20composants?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../inra/oresing/rest/ApplicationResult.java | 21 +++++++++++++++++++ .../fr/inra/oresing/rest/OreSiResources.java | 11 +++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/main/java/fr/inra/oresing/rest/ApplicationResult.java b/src/main/java/fr/inra/oresing/rest/ApplicationResult.java index f3ee50860..70da2822b 100644 --- a/src/main/java/fr/inra/oresing/rest/ApplicationResult.java +++ b/src/main/java/fr/inra/oresing/rest/ApplicationResult.java @@ -11,6 +11,7 @@ public class ApplicationResult { String name; String title; Map<String, Reference> references; + Map<String, DataType> dataTypes; @Value public static class Reference { @@ -27,4 +28,24 @@ public class ApplicationResult { String linkedTo; } } + + @Value + public static class DataType { + String id; + String label; + Map<String, Variable> variables; + + @Value + public static class Variable { + String id; + String label; + Map<String, Component> components; + + @Value + public static class Component { + String id; + String label; + } + } + } } diff --git a/src/main/java/fr/inra/oresing/rest/OreSiResources.java b/src/main/java/fr/inra/oresing/rest/OreSiResources.java index c21f7d125..b94fbf109 100644 --- a/src/main/java/fr/inra/oresing/rest/OreSiResources.java +++ b/src/main/java/fr/inra/oresing/rest/OreSiResources.java @@ -111,7 +111,16 @@ public class OreSiResources { Set<String> children = childrenPerReferences.get(reference); return new ApplicationResult.Reference(reference, reference, children, columns); }); - ApplicationResult applicationResult = new ApplicationResult(application.getId().toString(), application.getName(), application.getConfiguration().getApplication().getName(), references); + Map<String, ApplicationResult.DataType> dataTypes = Maps.transformEntries(application.getConfiguration().getDataTypes(), (dataType, dataTypeDescription) -> { + Map<String, ApplicationResult.DataType.Variable> variables = Maps.transformEntries(dataTypeDescription.getData(), (variable, variableDescription) -> { + Map<String, ApplicationResult.DataType.Variable.Component> components = Maps.transformEntries(variableDescription.getComponents(), (component, componentDescription) -> { + return new ApplicationResult.DataType.Variable.Component(component, component); + }); + return new ApplicationResult.DataType.Variable(variable, variable, components); + }); + return new ApplicationResult.DataType(dataType, dataType, variables); + }); + ApplicationResult applicationResult = new ApplicationResult(application.getId().toString(), application.getName(), application.getConfiguration().getApplication().getName(), references, dataTypes); return ResponseEntity.ok(applicationResult); } -- GitLab From f7e07847c476a5a95845af6d4b4bdb69ba87d7ec Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Thu, 17 Jun 2021 16:59:53 +0200 Subject: [PATCH 25/27] =?UTF-8?q?Branche=20le=20t=C3=A9l=C3=A9versement=20?= =?UTF-8?q?au=20backend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui2/src/components/common/CollapsibleTree.vue | 13 +++++++++---- ui2/src/locales/en.json | 4 +++- ui2/src/locales/fr.json | 4 +++- ui2/src/services/rest/ApplicationService.js | 4 ---- ui2/src/services/rest/ReferenceService.js | 19 +++++++++++++++++++ .../references/ReferencesManagementView.vue | 17 ++++++++++++++++- 6 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 ui2/src/services/rest/ReferenceService.js diff --git a/ui2/src/components/common/CollapsibleTree.vue b/ui2/src/components/common/CollapsibleTree.vue index e08213784..652fb7790 100644 --- a/ui2/src/components/common/CollapsibleTree.vue +++ b/ui2/src/components/common/CollapsibleTree.vue @@ -21,8 +21,13 @@ {{ label }} </div> </div> - <b-field class="file is-primary" v-if="withDownload"> - <b-upload v-model="refFile" class="file-label" accept=".csv"> + <b-field class="file is-primary" v-if="onUploadCb"> + <b-upload + v-model="refFile" + class="file-label" + accept=".csv" + @input="() => onUploadCb(label, refFile)" + > <span class="file-name" v-if="refFile"> {{ refFile.name }} </span> @@ -39,8 +44,8 @@ :label="child.label" :children="child.children" :level="level + 1" - :withDownload="withDownload" :onClickLabelCb="onClickLabelCb" + :onUploadCb="onUploadCb" /> </div> </div> @@ -57,8 +62,8 @@ export default class CollapsibleTree extends Vue { @Prop() label; @Prop() children; @Prop() level; - @Prop() withDownload; @Prop() onClickLabelCb; + @Prop() onUploadCb; displayChildren = false; refFile = null; diff --git a/ui2/src/locales/en.json b/ui2/src/locales/en.json index 847b772b6..7a13a47c2 100644 --- a/ui2/src/locales/en.json +++ b/ui2/src/locales/en.json @@ -30,7 +30,9 @@ "application-validate-success": "The YAML file is valid!", "warning": "Warning !", "reference-deletion-msg": "You're about to delete the reference : {label}. Are you sure ?", - "delete": "Delete" + "delete": "Delete", + "reference-csv-upload-error": "An error occured while uploading the csv file", + "reference-updated": "Reference updated" }, "message": { "app-config-error": "Error in yaml file", diff --git a/ui2/src/locales/fr.json b/ui2/src/locales/fr.json index 8d5802fc0..2a24d21b6 100644 --- a/ui2/src/locales/fr.json +++ b/ui2/src/locales/fr.json @@ -30,7 +30,9 @@ "application-validate-success": "Le fichier YAML est valide !", "warning": "Attention !", "reference-deletion-msg": "Vous allez supprimer le référentiel : {label}. Êtes-vous sûr ?", - "delete": "Supprimer" + "delete": "Supprimer", + "reference-csv-upload-error": "Une erreur s'est produite au téléversement du fichier csv", + "reference-updated": "Référentiel mis à jour" }, "message": { "app-config-error": "Erreur dans le fichier yaml", diff --git a/ui2/src/services/rest/ApplicationService.js b/ui2/src/services/rest/ApplicationService.js index 914600308..54869e111 100644 --- a/ui2/src/services/rest/ApplicationService.js +++ b/ui2/src/services/rest/ApplicationService.js @@ -25,10 +25,6 @@ export class ApplicationService extends Fetcher { return this.get(`applications/${applicationName}/data/${dataset}`); } - async getReference(reference, applicationName) { - return this.get(`applications/${applicationName}/references/${reference}`); - } - async validateConfiguration(applicationConfig) { return this.post("validate-configuration", { file: applicationConfig.file, diff --git a/ui2/src/services/rest/ReferenceService.js b/ui2/src/services/rest/ReferenceService.js new file mode 100644 index 000000000..49c4d596b --- /dev/null +++ b/ui2/src/services/rest/ReferenceService.js @@ -0,0 +1,19 @@ +import { Fetcher } from "../Fetcher"; + +export class ReferenceService extends Fetcher { + static INSTANCE = new ReferenceService(); + + constructor() { + super(); + } + + async getReference(applicationName, referenceId) { + return this.get(`applications/${applicationName}/references/${referenceId}`); + } + + async createReference(applicationName, referenceId, refFile) { + return this.post(`applications/${applicationName}/references/${referenceId}`, { + file: refFile, + }); + } +} diff --git a/ui2/src/views/references/ReferencesManagementView.vue b/ui2/src/views/references/ReferencesManagementView.vue index 0ad0d53aa..f5151530f 100644 --- a/ui2/src/views/references/ReferencesManagementView.vue +++ b/ui2/src/views/references/ReferencesManagementView.vue @@ -11,8 +11,8 @@ :label="ref.label" :children="ref.children" :level="0" - :withDownload="true" :onClickLabelCb="(event, label) => openRefDetails(event, label)" + :onUploadCb="(label, refFile) => uploadReferenceCsv(label, refFile)" /> <ReferencesDetailsPanel :leftAlign="false" @@ -31,9 +31,12 @@ import { convertReferencesToTrees } from "@/utils/ConversionUtils"; import CollapsibleTree from "@/components/common/CollapsibleTree.vue"; import ReferencesDetailsPanel from "@/components/references/ReferencesDetailsPanel.vue"; import { ApplicationService } from "@/services/rest/ApplicationService"; +import { ReferenceService } from "@/services/rest/ReferenceService"; + import PageView from "../common/PageView.vue"; import { ApplicationResult } from "@/model/ApplicationResult"; import SubMenu, { SubMenuPath } from "@/components/common/SubMenu.vue"; +import { AlertService } from "@/services/AlertService"; @Component({ components: { CollapsibleTree, ReferencesDetailsPanel, PageView, SubMenu }, @@ -42,6 +45,8 @@ export default class ReferencesManagementView extends Vue { @Prop() applicationName; applicationService = ApplicationService.INSTANCE; + referenceService = ReferenceService.INSTANCE; + alertService = AlertService.INSTANCE; references = []; openPanel = false; @@ -79,5 +84,15 @@ export default class ReferencesManagementView extends Vue { consultReference(id) { this.$router.push(`/applications/${this.applicationName}/references/${id}`); } + + async uploadReferenceCsv(label, refFile) { + const reference = Object.values(this.application.references).find((ref) => ref.label === label); + try { + await this.referenceService.createReference(this.applicationName, reference.id, refFile); + this.alertService.toastSuccess(this.$t("alert.reference-updated")); + } catch (error) { + this.alertService.toastError(this.$t("alert.reference-csv-upload-error"), error); + } + } } </script> -- GitLab From 6cbdcae934a856c37307b5ea3071548b1c434e82 Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Thu, 17 Jun 2021 17:23:32 +0200 Subject: [PATCH 26/27] =?UTF-8?q?Branche=20les=20donn=C3=A9es=20de=20r?= =?UTF-8?q?=C3=A9f=C3=A9rentiels=20au=20back?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui2/src/services/rest/ReferenceService.js | 2 +- .../views/references/ReferenceTableView.vue | 30 +++++++++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/ui2/src/services/rest/ReferenceService.js b/ui2/src/services/rest/ReferenceService.js index 49c4d596b..36c03c446 100644 --- a/ui2/src/services/rest/ReferenceService.js +++ b/ui2/src/services/rest/ReferenceService.js @@ -7,7 +7,7 @@ export class ReferenceService extends Fetcher { super(); } - async getReference(applicationName, referenceId) { + async getReferenceValues(applicationName, referenceId) { return this.get(`applications/${applicationName}/references/${referenceId}`); } diff --git a/ui2/src/views/references/ReferenceTableView.vue b/ui2/src/views/references/ReferenceTableView.vue index 4fc66f428..ac4054039 100644 --- a/ui2/src/views/references/ReferenceTableView.vue +++ b/ui2/src/views/references/ReferenceTableView.vue @@ -7,7 +7,7 @@ <div v-if="reference && columns"> <b-table - :data="[]" + :data="tableValues" :striped="true" :isFocusable="true" :isHoverable="true" @@ -19,11 +19,13 @@ <b-table-column v-for="column in columns" :key="column.id" - :field="column.title" + :field="column.id" :label="column.title" sortable :sticky="column.key" + v-slot="props" > + {{ props.row[column.id] }} </b-table-column> </b-table> </div> @@ -35,6 +37,7 @@ import SubMenu, { SubMenuPath } from "@/components/common/SubMenu.vue"; import { ApplicationResult } from "@/model/ApplicationResult"; import { AlertService } from "@/services/AlertService"; import { ApplicationService } from "@/services/rest/ApplicationService"; +import { ReferenceService } from "@/services/rest/ReferenceService"; import { Prop, Vue, Component } from "vue-property-decorator"; import PageView from "../common/PageView.vue"; @@ -47,20 +50,30 @@ export default class ReferenceTableView extends Vue { alertService = AlertService.INSTANCE; applicationService = ApplicationService.INSTANCE; + referenceService = ReferenceService.INSTANCE; application = new ApplicationResult(); subMenuPaths = []; reference = {}; columns = []; + referenceValues = []; + tableValues = []; - created() { - this.init(); + async created() { + await this.init(); + this.setInitialVariables(); } async init() { try { this.application = await this.applicationService.getApplication(this.applicationName); - this.setInitialVariables(); + const references = await this.referenceService.getReferenceValues( + this.applicationName, + this.refId + ); + if (references) { + this.referenceValues = references.referenceValues; + } } catch (error) { this.alertService.toastServerError(); } @@ -96,6 +109,13 @@ export default class ReferenceTableView extends Vue { return 0; }); } + + console.log(this.columns); + + if (this.referenceValues) { + this.tableValues = Object.values(this.referenceValues).map((refValue) => refValue.values); + console.log(this.tableValues); + } } } </script> -- GitLab From c6a7493e3571a87d00c63add053619b9d8a0d1eb Mon Sep 17 00:00:00 2001 From: Aurore Lecointe <lecointe@codelutin.com> Date: Thu, 17 Jun 2021 17:55:29 +0200 Subject: [PATCH 27/27] =?UTF-8?q?Met=20les=20actions=20sur=20les=20r=C3=A9?= =?UTF-8?q?f=C3=A9rentiels=20sur=20la=20ligne?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui2/src/components/common/CollapsibleTree.vue | 65 ++++++++++++++----- .../references/ReferencesDetailsPanel.vue | 8 --- ui2/src/model/Button.js | 15 +++++ .../references/ReferencesManagementView.vue | 19 +++++- 4 files changed, 80 insertions(+), 27 deletions(-) create mode 100644 ui2/src/model/Button.js diff --git a/ui2/src/components/common/CollapsibleTree.vue b/ui2/src/components/common/CollapsibleTree.vue index 652fb7790..d12ccdda5 100644 --- a/ui2/src/components/common/CollapsibleTree.vue +++ b/ui2/src/components/common/CollapsibleTree.vue @@ -21,21 +21,34 @@ {{ label }} </div> </div> - <b-field class="file is-primary" v-if="onUploadCb"> - <b-upload - v-model="refFile" - class="file-label" - accept=".csv" - @input="() => onUploadCb(label, refFile)" - > - <span class="file-name" v-if="refFile"> - {{ refFile.name }} - </span> - <span class="file-cta"> - <b-icon class="file-icon" icon="upload"></b-icon> - </span> - </b-upload> - </b-field> + <div class="CollapsibleTree-buttons"> + <b-field class="file button is-small is-info" v-if="onUploadCb"> + <b-upload + v-model="refFile" + class="file-label" + accept=".csv" + @input="() => onUploadCb(label, refFile)" + > + <span class="file-name" v-if="refFile"> + {{ refFile.name }} + </span> + <span class="file-cta"> + <b-icon class="file-icon" icon="upload"></b-icon> + </span> + </b-upload> + </b-field> + <div v-for="button in buttons" :key="button.id"> + <b-button + :icon-left="button.iconName" + size="is-small" + @click="button.clickCb(label)" + class="ml-1" + :type="button.type" + > + {{ button.label }}</b-button + > + </div> + </div> </div> <div v-if="displayChildren"> <CollapsibleTree @@ -46,6 +59,7 @@ :level="level + 1" :onClickLabelCb="onClickLabelCb" :onUploadCb="onUploadCb" + :buttons="buttons" /> </div> </div> @@ -64,6 +78,7 @@ export default class CollapsibleTree extends Vue { @Prop() level; @Prop() onClickLabelCb; @Prop() onUploadCb; + @Prop() buttons; displayChildren = false; refFile = null; @@ -71,10 +86,12 @@ export default class CollapsibleTree extends Vue { </script> <style lang="scss" scoped> +$row-height: 40px; + .CollapsibleTree-header { display: flex; align-items: center; - height: 40px; + height: $row-height; padding: 0.75rem; justify-content: space-between; @@ -101,4 +118,20 @@ export default class CollapsibleTree extends Vue { display: flex; align-items: center; } + +.CollapsibleTree-buttons { + display: flex; + height: $row-height; + align-items: center; + + .file { + margin-bottom: 0; + + .file-cta { + height: 100%; + background-color: transparent; + border-color: transparent; + } + } +} </style> diff --git a/ui2/src/components/references/ReferencesDetailsPanel.vue b/ui2/src/components/references/ReferencesDetailsPanel.vue index 10c56d924..1fdae4b09 100644 --- a/ui2/src/components/references/ReferencesDetailsPanel.vue +++ b/ui2/src/components/references/ReferencesDetailsPanel.vue @@ -6,10 +6,6 @@ :closeCb="closeCb" > <div class="Panel-buttons"> - <b-button type="is-primary" icon-left="eye" @click="emitConsult">{{ - $t("referencesManagement.consult") - }}</b-button> - <b-button icon-left="download">{{ $t("referencesManagement.download") }}</b-button> <b-button type="is-danger" icon-left="trash-alt" @click="askDeletionConfirmation">{{ $t("referencesManagement.delete") }}</b-button> @@ -46,10 +42,6 @@ export default class ReferencesDetailsPanel extends Vue { deleteReference() { console.log("DELETE", this.reference); } - - emitConsult() { - this.$emit("consultReference", this.reference.id); - } } </script> diff --git a/ui2/src/model/Button.js b/ui2/src/model/Button.js new file mode 100644 index 000000000..5d3d08c39 --- /dev/null +++ b/ui2/src/model/Button.js @@ -0,0 +1,15 @@ +export class Button { + id; + label; + iconName; + clickCb; + type; + + constructor(label, iconName, clickCb, type, id) { + this.label = label; + this.iconName = iconName; + this.clickCb = clickCb; + this.id = id ? id : label ? label : iconName; + this.type = type; + } +} diff --git a/ui2/src/views/references/ReferencesManagementView.vue b/ui2/src/views/references/ReferencesManagementView.vue index f5151530f..370caf82f 100644 --- a/ui2/src/views/references/ReferencesManagementView.vue +++ b/ui2/src/views/references/ReferencesManagementView.vue @@ -13,13 +13,13 @@ :level="0" :onClickLabelCb="(event, label) => openRefDetails(event, label)" :onUploadCb="(label, refFile) => uploadReferenceCsv(label, refFile)" + :buttons="buttons" /> <ReferencesDetailsPanel :leftAlign="false" :open="openPanel" :reference="chosenRef" :closeCb="(newVal) => (openPanel = newVal)" - @consultReference="consultReference" /> </div> </PageView> @@ -37,6 +37,7 @@ import PageView from "../common/PageView.vue"; import { ApplicationResult } from "@/model/ApplicationResult"; import SubMenu, { SubMenuPath } from "@/components/common/SubMenu.vue"; import { AlertService } from "@/services/AlertService"; +import { Button } from "@/model/Button"; @Component({ components: { CollapsibleTree, ReferencesDetailsPanel, PageView, SubMenu }, @@ -53,6 +54,15 @@ export default class ReferencesManagementView extends Vue { chosenRef = null; application = new ApplicationResult(); subMenuPaths = []; + buttons = [ + new Button( + this.$t("referencesManagement.consult"), + "eye", + (label) => this.consultReference(label), + "is-primary" + ), + new Button(this.$t("referencesManagement.download"), "download"), + ]; created() { this.subMenuPaths = [ @@ -81,8 +91,11 @@ export default class ReferencesManagementView extends Vue { this.chosenRef = Object.values(this.application.references).find((ref) => ref.label === label); } - consultReference(id) { - this.$router.push(`/applications/${this.applicationName}/references/${id}`); + consultReference(label) { + const ref = Object.values(this.application.references).find((ref) => ref.label === label); + if (ref) { + this.$router.push(`/applications/${this.applicationName}/references/${ref.id}`); + } } async uploadReferenceCsv(label, refFile) { -- GitLab