From 50a9eab031f614bb714e4e074a07ff1dab677685 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Agneray?= <francois.agneray@lam.fr>
Date: Fri, 30 Jul 2021 16:13:57 +0200
Subject: [PATCH] Option opened for dataset, criteria, output family

---
 .../criteria-family-form.component.html       |  4 +++
 .../criteria-family-form.component.ts         |  3 ++-
 .../dataset-family-form.component.html        |  4 +++
 .../dataset-family-form.component.ts          |  3 ++-
 .../output-family-form.component.html         |  4 +++
 .../output-family-form.component.ts           |  3 ++-
 .../criteria/criteria-tabs.component.html     | 19 ++------------
 .../dataset/dataset-tabs.component.html       | 24 ++---------------
 .../output/output-tabs.component.html         | 21 ++-------------
 .../metamodel/models/criteria-family.model.ts |  1 +
 .../metamodel/models/dataset-family.model.ts  |  1 +
 .../metamodel/models/output-family.model.ts   |  1 +
 conf-dev/create-db.sh                         | 22 ++++++++--------
 .../__CG__AppEntityCriteriaFamily.php         | 26 +++++++++++++++++--
 .../__CG__AppEntityDatasetFamily.php          | 26 +++++++++++++++++--
 .../__CG__AppEntityOutputFamily.php           | 26 +++++++++++++++++--
 server/src/Action/CriteriaFamilyAction.php    |  3 ++-
 .../src/Action/CriteriaFamilyListAction.php   |  3 ++-
 server/src/Action/DatasetFamilyAction.php     |  3 ++-
 server/src/Action/DatasetFamilyListAction.php |  3 ++-
 server/src/Action/OutputFamilyAction.php      |  3 ++-
 server/src/Action/OutputFamilyListAction.php  |  3 ++-
 server/src/Entity/CriteriaFamily.php          | 20 +++++++++++++-
 server/src/Entity/DatasetFamily.php           | 20 +++++++++++++-
 server/src/Entity/OutputFamily.php            | 20 +++++++++++++-
 .../tests/Action/CriteriaFamilyActionTest.php |  3 ++-
 .../Action/CriteriaFamilyListActionTest.php   |  3 ++-
 .../tests/Action/DatasetFamilyActionTest.php  |  3 ++-
 .../Action/DatasetFamilyListActionTest.php    |  3 ++-
 .../tests/Action/OutputFamilyActionTest.php   |  3 ++-
 .../Action/OutputFamilyListActionTest.php     |  3 ++-
 31 files changed, 191 insertions(+), 93 deletions(-)

diff --git a/client/src/app/admin/components/criteria-family/criteria-family-form.component.html b/client/src/app/admin/components/criteria-family/criteria-family-form.component.html
index 9efb6a0c..d8b5a066 100644
--- a/client/src/app/admin/components/criteria-family/criteria-family-form.component.html
+++ b/client/src/app/admin/components/criteria-family/criteria-family-form.component.html
@@ -7,6 +7,10 @@
         <label for="display">Display</label>
         <input type="number" class="form-control" name="display" formControlName="display">
     </div>
+    <div class="custom-control custom-switch mb-3">
+        <input class="custom-control-input" type="checkbox" id="opened" name="opened" formControlName="opened">
+        <label class="custom-control-label" for="opened">Opened</label>
+    </div>
     <div class="form-group">
         <ng-content></ng-content>
     </div>
diff --git a/client/src/app/admin/components/criteria-family/criteria-family-form.component.ts b/client/src/app/admin/components/criteria-family/criteria-family-form.component.ts
index ee12b1ee..9013e5e8 100644
--- a/client/src/app/admin/components/criteria-family/criteria-family-form.component.ts
+++ b/client/src/app/admin/components/criteria-family/criteria-family-form.component.ts
@@ -22,7 +22,8 @@ export class CriteriaFamilyFormComponent {
 
     public form = new FormGroup({
         label: new FormControl('', [Validators.required]),
-        display: new FormControl('', [Validators.required])
+        display: new FormControl('', [Validators.required]),
+        opened: new FormControl(true)
     });
 
     ngOnInit() {
diff --git a/client/src/app/admin/components/dataset-family/dataset-family-form.component.html b/client/src/app/admin/components/dataset-family/dataset-family-form.component.html
index f55dbbd1..0da5da14 100644
--- a/client/src/app/admin/components/dataset-family/dataset-family-form.component.html
+++ b/client/src/app/admin/components/dataset-family/dataset-family-form.component.html
@@ -7,6 +7,10 @@
         <label for="display">Display</label>
         <input type="number" class="form-control" id="display" name="display" formControlName="display">
     </div>
+    <div class="custom-control custom-switch mb-3">
+        <input class="custom-control-input" type="checkbox" id="opened" name="opened" formControlName="opened">
+        <label class="custom-control-label" for="opened">Opened</label>
+    </div>
     <div class="form-group">
         <ng-content></ng-content>
     </div>
diff --git a/client/src/app/admin/components/dataset-family/dataset-family-form.component.ts b/client/src/app/admin/components/dataset-family/dataset-family-form.component.ts
index 2d1e8a1d..c79513ee 100644
--- a/client/src/app/admin/components/dataset-family/dataset-family-form.component.ts
+++ b/client/src/app/admin/components/dataset-family/dataset-family-form.component.ts
@@ -22,7 +22,8 @@ export class DatasetFamilyFormComponent implements OnInit {
 
     public form = new FormGroup({
         label: new FormControl('', [Validators.required]),
-        display: new FormControl('', [Validators.required])
+        display: new FormControl('', [Validators.required]),
+        opened: new FormControl(true)
     });
 
     ngOnInit() {
diff --git a/client/src/app/admin/components/output-family/output-family-form.component.html b/client/src/app/admin/components/output-family/output-family-form.component.html
index 9efb6a0c..d8b5a066 100644
--- a/client/src/app/admin/components/output-family/output-family-form.component.html
+++ b/client/src/app/admin/components/output-family/output-family-form.component.html
@@ -7,6 +7,10 @@
         <label for="display">Display</label>
         <input type="number" class="form-control" name="display" formControlName="display">
     </div>
+    <div class="custom-control custom-switch mb-3">
+        <input class="custom-control-input" type="checkbox" id="opened" name="opened" formControlName="opened">
+        <label class="custom-control-label" for="opened">Opened</label>
+    </div>
     <div class="form-group">
         <ng-content></ng-content>
     </div>
diff --git a/client/src/app/admin/components/output-family/output-family-form.component.ts b/client/src/app/admin/components/output-family/output-family-form.component.ts
index 1193be90..c3688107 100644
--- a/client/src/app/admin/components/output-family/output-family-form.component.ts
+++ b/client/src/app/admin/components/output-family/output-family-form.component.ts
@@ -22,7 +22,8 @@ export class OutputFamilyFormComponent {
 
     public form = new FormGroup({
         label: new FormControl('', [Validators.required]),
-        display: new FormControl('', [Validators.required])
+        display: new FormControl('', [Validators.required]),
+        opened: new FormControl(true)
     });
 
     ngOnInit() {
diff --git a/client/src/app/instance/search/components/criteria/criteria-tabs.component.html b/client/src/app/instance/search/components/criteria/criteria-tabs.component.html
index 45c654c3..fa9d3aef 100644
--- a/client/src/app/instance/search/components/criteria/criteria-tabs.component.html
+++ b/client/src/app/instance/search/components/criteria/criteria-tabs.component.html
@@ -1,21 +1,6 @@
-<div *ngIf="criteriaFamilyList.length == 1 && (attributeList | attributeListByFamily:criteriaFamilyList[0].id).length > 0">
-    <div class="border rounded my-2">
-        <p class="border-bottom bg-light text-primary py-4 pl-4">{{ criteriaFamilyList[0].label }}</p>
-        <div class="px-3">
-            <app-criteria-by-family 
-                [attributeList]="attributeList | attributeListByFamily:criteriaFamilyList[0].id"
-                [criteriaList]="criteriaList" 
-                (addCriterion)="emitAdd($event)" 
-                (deleteCriterion)="emitDelete($event)">
-            </app-criteria-by-family>
-        </div>
-    </div>
-</div>
-
-<accordion *ngIf="criteriaFamilyList.length > 1" [isAnimated]="true">
+<accordion [isAnimated]="true">
     <ng-container *ngFor="let family of criteriaFamilyList">
-        <accordion-group #ag *ngIf="(attributeList | attributeListByFamily:family.id).length > 0" [panelClass]="'custom-accordion'"
-            [isOpen]="true" class="my-2">
+        <accordion-group #ag *ngIf="(attributeList | attributeListByFamily:family.id).length > 0" [panelClass]="'custom-accordion'" [isOpen]="family.opened" class="my-2">
             <button class="btn btn-link btn-block clearfix" accordion-heading>
                 <span class="pull-left float-left">
                     {{ family.label }}
diff --git a/client/src/app/instance/search/components/dataset/dataset-tabs.component.html b/client/src/app/instance/search/components/dataset/dataset-tabs.component.html
index 08d61aae..0407fe89 100644
--- a/client/src/app/instance/search/components/dataset/dataset-tabs.component.html
+++ b/client/src/app/instance/search/components/dataset/dataset-tabs.component.html
@@ -1,26 +1,6 @@
-<div *ngIf="datasetFamilyList.length === 1">
-    <div class="border rounded my-2">
-        <p *ngIf="(datasetList | datasetListByFamily:datasetFamilyList[0].id).length === 1" class="border-bottom bg-light text-primary py-4 pl-4">Dataset</p>
-        <p *ngIf="(datasetList | datasetListByFamily:datasetFamilyList[0].id).length > 1" class="border-bottom bg-light text-primary py-4 pl-4">List of datasets</p>
-        <ul class="p-0">
-            <li *ngFor="let dataset of (datasetList | datasetListByFamily:datasetFamilyList[0].id); last as isLast"
-                class="list-unstyled px-3 pt-3 pb-0">
-                <app-dataset-card
-                    [dataset]="dataset"
-                    [survey]="surveyList | surveyByName:dataset.survey_name"
-                    [instanceSelected]="instanceSelected"
-                    [datasetSelected]="datasetSelected">
-                </app-dataset-card>
-                <hr *ngIf="!isLast">
-            </li>
-        </ul>
-    </div>
-</div>
-
-<accordion *ngIf="datasetFamilyList.length > 1" [isAnimated]="true">
+<accordion [isAnimated]="true">
     <ng-container *ngFor="let family of datasetFamilyList">
-        <accordion-group #ag *ngIf="(datasetList | datasetListByFamily:family.id).length > 0" [panelClass]="'custom-accordion'"
-            [isOpen]="true" class="my-2">
+        <accordion-group #ag *ngIf="(datasetList | datasetListByFamily:family.id).length > 0" [panelClass]="'custom-accordion'" [isOpen]="family.opened" class="my-2">
             <button class="btn btn-link btn-block clearfix" accordion-heading>
                 <span class="pull-left float-left">
                     {{ family.label }}
diff --git a/client/src/app/instance/search/components/output/output-tabs.component.html b/client/src/app/instance/search/components/output/output-tabs.component.html
index f8bc426a..b90fc7bf 100644
--- a/client/src/app/instance/search/components/output/output-tabs.component.html
+++ b/client/src/app/instance/search/components/output/output-tabs.component.html
@@ -1,22 +1,5 @@
-<div *ngIf="outputFamilyList.length == 1">
-    <div class="border rounded my-2">
-        <p class="border-bottom bg-light text-primary py-4 pl-4 mb-0">{{ outputFamilyList[0].label }}</p>
-        <div class="px-3 pb-3 pt-0">
-            <app-output-by-family
-                [outputFamily]="outputFamilyList[0]" 
-                [attributeList]="attributeList"
-                [outputCategoryList]="outputCategoryList" 
-                [outputList]="outputList"
-                [designColor]="designColor"
-                (change)="change.emit($event)">
-            </app-output-by-family>
-        </div>
-    </div>
-</div>
-
-<accordion *ngIf="outputFamilyList.length > 1" [isAnimated]="true">
-    <accordion-group #ag *ngFor="let family of outputFamilyList"
-        [panelClass]="'custom-accordion-output'" class="my-2" [isOpen]="true">
+<accordion [isAnimated]="true">
+    <accordion-group #ag *ngFor="let family of outputFamilyList" [panelClass]="'custom-accordion-output'" class="my-2" [isOpen]="family.opened">
         <button class="btn btn-link btn-block clearfix" accordion-heading>
             <span class="pull-left float-left">
                 {{ family.label }}
diff --git a/client/src/app/metamodel/models/criteria-family.model.ts b/client/src/app/metamodel/models/criteria-family.model.ts
index 568bb380..aeb7f90a 100644
--- a/client/src/app/metamodel/models/criteria-family.model.ts
+++ b/client/src/app/metamodel/models/criteria-family.model.ts
@@ -11,4 +11,5 @@ export interface CriteriaFamily {
     id: number;
     label: string;
     display: number;
+    opened: boolean;
 }
diff --git a/client/src/app/metamodel/models/dataset-family.model.ts b/client/src/app/metamodel/models/dataset-family.model.ts
index f9e0f25a..391f9039 100644
--- a/client/src/app/metamodel/models/dataset-family.model.ts
+++ b/client/src/app/metamodel/models/dataset-family.model.ts
@@ -11,4 +11,5 @@ export interface DatasetFamily {
     id: number;
     label: string;
     display: number;
+    opened: boolean;
 }
diff --git a/client/src/app/metamodel/models/output-family.model.ts b/client/src/app/metamodel/models/output-family.model.ts
index a673a0a5..d1d1e076 100644
--- a/client/src/app/metamodel/models/output-family.model.ts
+++ b/client/src/app/metamodel/models/output-family.model.ts
@@ -11,4 +11,5 @@ export interface OutputFamily {
     id: number;
     label: string;
     display: number;
+    opened: boolean;
 }
diff --git a/conf-dev/create-db.sh b/conf-dev/create-db.sh
index 3f1568ea..464504e5 100644
--- a/conf-dev/create-db.sh
+++ b/conf-dev/create-db.sh
@@ -67,9 +67,9 @@ curl -d '{"name":"svom","label":"SVOM","description":"Survey used for testing","
 curl -d '{"name":"iris","label":"IRiS","description":"Survey used for testing","link":"http://iris.lam.fr","manager":"S. Basa","id_database":1}' --header 'Content-Type: application/json' -X POST http://localhost/survey
 
 # Add dataset families
-curl -d '{"label":"Default dataset family","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/instance/default/dataset-family
-curl -d '{"label":"SVOM dataset family","display":20}' --header 'Content-Type: application/json' -X POST http://localhost/instance/default/dataset-family
-curl -d '{"label":"IRiS dataset family","display":30}' --header 'Content-Type: application/json' -X POST http://localhost/instance/default/dataset-family
+curl -d '{"label":"Default dataset family","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/instance/default/dataset-family
+curl -d '{"label":"SVOM dataset family","display":20,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/instance/default/dataset-family
+curl -d '{"label":"IRiS dataset family","display":30,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/instance/default/dataset-family
 
 # Add datasets
 curl -d '{"name":"vipers_dr2_w1","table_ref":"aspic_vipers_dr2_w1","label":"VIPERS-W1 (DR2)","description":"VIPERS W1 dataset","display":10,"data_path":"\/ASPIC\/VIPERS_DR2","config":{"images":[],"cone_search":{"cone_search_enabled":false,"cone_search_opened":true,"cone_search_column_ra":null,"cone_search_column_dec":null,"cone_search_plot_enabled":false,"cone_search_sdss_enabled":true,"cone_search_sdss_display":10,"cone_search_background":[]},"download":{"download_enabled":true,"download_opened":false,"download_csv":true,"download_ascii":true,"download_vo":false,"download_archive":true},"summary":{"summary_enabled":true,"summary_opened":false},"server_link":{"server_link_enabled":false,"server_link_opened":false},"samp":{"samp_enabled":false,"samp_opened":false},"datatable":{"datatable_enabled":true,"datatable_opened":false,"datatable_selectable_rows":false}},"public":true,"survey_name":"anis_survey"}' --header 'Content-Type: application/json' -X POST http://localhost/dataset-family/1/dataset
@@ -78,8 +78,8 @@ curl -d '{"name":"observations","table_ref":"v_observation","label":"IRiS obs","
 curl -d '{"name":"vvds_f02_udeep","table_ref":"aspic_vvds_f02_udeep","label":"VVDS2h Ultra Deep","description":"VVDS2h Ultra Deep","display":20,"data_path":"","config":{"images":[],"cone_search":{"cone_search_enabled":false,"cone_search_opened":true,"cone_search_column_ra":null,"cone_search_column_dec":null,"cone_search_plot_enabled":false,"cone_search_sdss_enabled":true,"cone_search_sdss_display":10,"cone_search_background":[]},"download":{"download_enabled":true,"download_opened":false,"download_csv":true,"download_ascii":true,"download_vo":false,"download_archive":true},"summary":{"summary_enabled":true,"summary_opened":false},"server_link":{"server_link_enabled":false,"server_link_opened":false},"samp":{"samp_enabled":false,"samp_opened":false},"datatable":{"datatable_enabled":true,"datatable_opened":false,"datatable_selectable_rows":false}},"public":true,"survey_name":"anis_survey"}' --header 'Content-Type: application/json' -X POST http://localhost/dataset-family/1/dataset
 
 # Add vipers_dr2_w1 attributes
-curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/criteria-family
-curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/output-family
+curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/criteria-family
+curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/output-family
 curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/output-family/1/output-category
 
 curl -d '{"id":1,"name":"num","label":"num","form_label":"num","description":null,"output_display":10,"criteria_display":10,"search_flag":"ID","search_type":"field","type":"decimal","operator":"eq","min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"detail","renderer_config":{"display":"text","blank":true},"display_detail":10,"selected":true,"order_by":false,"order_display":10,"detail":true,"renderer_detail":null,"renderer_detail_config":null,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":1,"id_output_category":1}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute
@@ -99,8 +99,8 @@ curl -d '{"id":57,"name":"spec1dnoise","label":"spec1dnoise","form_label":"spec1
 curl -d '{"id":58,"name":"spec1dsky","label":"spec1dsky","form_label":"spec1dsky","description":null,"output_display":580,"criteria_display":580,"search_flag":null,"search_type":null,"type":"text","operator":null,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"download","renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"display_detail":580,"selected":true,"order_by":false,"order_display":580,"detail":true,"renderer_detail":null,"renderer_detail_config":null,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute
 
 # Add sp_cards attributes
-curl -d '{"label":"Card","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/criteria-family
-curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/output-family
+curl -d '{"label":"Card","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/criteria-family
+curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/output-family
 curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/output-family/2/output-category
 
 curl -d '{"id":1,"name":"acronym","label":"acronym","form_label":"Product Acronym","description":null,"output_display":10,"criteria_display":10,"search_flag":"ID","search_type":"select","type":"string","operator":"eq","min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":[],"display_detail":10,"selected":true,"order_by":false,"order_display":10,"detail":false,"renderer_detail":null,"renderer_detail_config":null,"options":[{"label":"LAMTEST","value":"LAMTEST","display":10},{"label":"LAMTEST_DC1","value":"LAMTEST_DC1","display":20},{"label":"MXT-EVT-CAL","value":"MXT-EVT-CAL","display":30}],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":2,"id_output_category":2}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute
@@ -114,8 +114,8 @@ curl -d '{"id":8,"name":"search_kw","label":"search_kw","form_label":"KWs search
 curl -d '{"id":9,"name":"json_schema_uploaded","label":"json_schema_uploaded","form_label":"json_schema_uploaded","description":null,"output_display":90,"criteria_display":90,"search_flag":null,"search_type":null,"type":"json","operator":null,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"display_detail":90,"selected":true,"order_by":false,"order_display":90,"detail":false,"renderer_detail":null,"renderer_detail_config":null,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute
 
 # Add observations attributes
-curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/criteria-family
-curl -d '{"label":"Default parameters","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/output-family
+curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/criteria-family
+curl -d '{"label":"Default parameters","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/output-family
 curl -d '{"label":"Astrometry","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/output-family/3/output-category
 curl -d '{"label":"Observation","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/output-family/3/output-category
 
@@ -130,8 +130,8 @@ curl -d '{"id":8,"name":"fits_file","label":"fits_file","form_label":"fits_file"
 curl -d '{"id":9,"name":"fits_png","label":"fits_png","form_label":"fits_png","description":null,"output_display":90,"criteria_display":90,"search_flag":null,"search_type":null,"type":"string","operator":null,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"image","renderer_config":{"type":"fits","display":"modal","width":"50","height":"50"},"display_detail":90,"selected":true,"order_by":false,"order_display":90,"detail":false,"renderer_detail":null,"renderer_detail_config":null,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":4}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute
 
 # Add vvds_f02_udeep attributes
-curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/criteria-family
-curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/output-family
+curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/criteria-family
+curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/output-family
 curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/output-family/4/output-category
 
 curl -d '{"id":1,"name":"vvds_ident","label":"vvds_ident","form_label":"vvds_ident","description":null,"output_display":10,"criteria_display":10,"search_flag":"ID","search_type":null,"type":"decimal","operator":null,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"display_detail":10,"selected":true,"order_by":false,"order_display":10,"detail":false,"renderer_detail":null,"renderer_detail_config":null,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":5}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute
diff --git a/server/doctrine-proxy/__CG__AppEntityCriteriaFamily.php b/server/doctrine-proxy/__CG__AppEntityCriteriaFamily.php
index 5b8e0972..91114f9e 100644
--- a/server/doctrine-proxy/__CG__AppEntityCriteriaFamily.php
+++ b/server/doctrine-proxy/__CG__AppEntityCriteriaFamily.php
@@ -66,10 +66,10 @@ class CriteriaFamily extends \App\Entity\CriteriaFamily implements \Doctrine\ORM
     public function __sleep()
     {
         if ($this->__isInitialized__) {
-            return ['__isInitialized__', 'id', 'label', 'display', 'dataset'];
+            return ['__isInitialized__', 'id', 'label', 'display', 'opened', 'dataset'];
         }
 
-        return ['__isInitialized__', 'id', 'label', 'display', 'dataset'];
+        return ['__isInitialized__', 'id', 'label', 'display', 'opened', 'dataset'];
     }
 
     /**
@@ -235,6 +235,28 @@ class CriteriaFamily extends \App\Entity\CriteriaFamily implements \Doctrine\ORM
         return parent::setDisplay($display);
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    public function getOpened()
+    {
+
+        $this->__initializer__ && $this->__initializer__->__invoke($this, 'getOpened', []);
+
+        return parent::getOpened();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function setOpened($opened)
+    {
+
+        $this->__initializer__ && $this->__initializer__->__invoke($this, 'setOpened', [$opened]);
+
+        return parent::setOpened($opened);
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git a/server/doctrine-proxy/__CG__AppEntityDatasetFamily.php b/server/doctrine-proxy/__CG__AppEntityDatasetFamily.php
index 0adf9739..f86a2a91 100644
--- a/server/doctrine-proxy/__CG__AppEntityDatasetFamily.php
+++ b/server/doctrine-proxy/__CG__AppEntityDatasetFamily.php
@@ -66,10 +66,10 @@ class DatasetFamily extends \App\Entity\DatasetFamily implements \Doctrine\ORM\P
     public function __sleep()
     {
         if ($this->__isInitialized__) {
-            return ['__isInitialized__', 'id', 'label', 'display', 'instance', 'datasets'];
+            return ['__isInitialized__', 'id', 'label', 'display', 'opened', 'instance', 'datasets'];
         }
 
-        return ['__isInitialized__', 'id', 'label', 'display', 'instance', 'datasets'];
+        return ['__isInitialized__', 'id', 'label', 'display', 'opened', 'instance', 'datasets'];
     }
 
     /**
@@ -235,6 +235,28 @@ class DatasetFamily extends \App\Entity\DatasetFamily implements \Doctrine\ORM\P
         return parent::setDisplay($display);
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    public function getOpened()
+    {
+
+        $this->__initializer__ && $this->__initializer__->__invoke($this, 'getOpened', []);
+
+        return parent::getOpened();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function setOpened($opened)
+    {
+
+        $this->__initializer__ && $this->__initializer__->__invoke($this, 'setOpened', [$opened]);
+
+        return parent::setOpened($opened);
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git a/server/doctrine-proxy/__CG__AppEntityOutputFamily.php b/server/doctrine-proxy/__CG__AppEntityOutputFamily.php
index 2b372a63..6f3aedeb 100644
--- a/server/doctrine-proxy/__CG__AppEntityOutputFamily.php
+++ b/server/doctrine-proxy/__CG__AppEntityOutputFamily.php
@@ -66,10 +66,10 @@ class OutputFamily extends \App\Entity\OutputFamily implements \Doctrine\ORM\Pro
     public function __sleep()
     {
         if ($this->__isInitialized__) {
-            return ['__isInitialized__', 'id', 'label', 'display', 'dataset'];
+            return ['__isInitialized__', 'id', 'label', 'display', 'opened', 'dataset'];
         }
 
-        return ['__isInitialized__', 'id', 'label', 'display', 'dataset'];
+        return ['__isInitialized__', 'id', 'label', 'display', 'opened', 'dataset'];
     }
 
     /**
@@ -235,6 +235,28 @@ class OutputFamily extends \App\Entity\OutputFamily implements \Doctrine\ORM\Pro
         return parent::getDisplay();
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    public function getOpened()
+    {
+
+        $this->__initializer__ && $this->__initializer__->__invoke($this, 'getOpened', []);
+
+        return parent::getOpened();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function setOpened($opened)
+    {
+
+        $this->__initializer__ && $this->__initializer__->__invoke($this, 'setOpened', [$opened]);
+
+        return parent::setOpened($opened);
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git a/server/src/Action/CriteriaFamilyAction.php b/server/src/Action/CriteriaFamilyAction.php
index 74489ad8..2f4a4bbd 100644
--- a/server/src/Action/CriteriaFamilyAction.php
+++ b/server/src/Action/CriteriaFamilyAction.php
@@ -59,7 +59,7 @@ final class CriteriaFamilyAction extends AbstractAction
         if ($request->getMethod() === PUT) {
             $parsedBody = $request->getParsedBody();
 
-            $fields = array('label', 'display');
+            $fields = array('label', 'display', 'opened');
             foreach ($fields as $a) {
                 if ($this->isEmptyField($a, $parsedBody)) {
                     throw new HttpBadRequestException(
@@ -96,6 +96,7 @@ final class CriteriaFamilyAction extends AbstractAction
     {
         $family->setLabel($parsedBody['label']);
         $family->setDisplay($parsedBody['display']);
+        $family->setOpened($parsedBody['opened']);
         $this->em->flush();
     }
 }
diff --git a/server/src/Action/CriteriaFamilyListAction.php b/server/src/Action/CriteriaFamilyListAction.php
index cd4a2afa..cb057226 100644
--- a/server/src/Action/CriteriaFamilyListAction.php
+++ b/server/src/Action/CriteriaFamilyListAction.php
@@ -63,7 +63,7 @@ final class CriteriaFamilyListAction extends AbstractAction
             $parsedBody = $request->getParsedBody();
 
             // To work this action needs information
-            foreach (array('label', 'display') as $a) {
+            foreach (array('label', 'display', 'opened') as $a) {
                 if ($this->isEmptyField($a, $parsedBody)) {
                     throw new HttpBadRequestException(
                         $request,
@@ -94,6 +94,7 @@ final class CriteriaFamilyListAction extends AbstractAction
         $family = new CriteriaFamily($dataset);
         $family->setLabel($parsedBody['label']);
         $family->setDisplay($parsedBody['display']);
+        $family->setOpened($parsedBody['opened']);
 
         $this->em->persist($family);
         $this->em->flush();
diff --git a/server/src/Action/DatasetFamilyAction.php b/server/src/Action/DatasetFamilyAction.php
index 5d78b77b..774ba164 100644
--- a/server/src/Action/DatasetFamilyAction.php
+++ b/server/src/Action/DatasetFamilyAction.php
@@ -59,7 +59,7 @@ final class DatasetFamilyAction extends AbstractAction
         if ($request->getMethod() === PUT) {
             $parsedBody = $request->getParsedBody();
 
-            $fields = array('label', 'display');
+            $fields = array('label', 'display', 'opened');
             foreach ($fields as $a) {
                 if ($this->isEmptyField($a, $parsedBody)) {
                     throw new HttpBadRequestException(
@@ -96,6 +96,7 @@ final class DatasetFamilyAction extends AbstractAction
     {
         $family->setLabel($parsedBody['label']);
         $family->setDisplay($parsedBody['display']);
+        $family->setOpened($parsedBody['opened']);
         $this->em->flush();
     }
 }
diff --git a/server/src/Action/DatasetFamilyListAction.php b/server/src/Action/DatasetFamilyListAction.php
index 408c1efd..628d5626 100644
--- a/server/src/Action/DatasetFamilyListAction.php
+++ b/server/src/Action/DatasetFamilyListAction.php
@@ -60,7 +60,7 @@ final class DatasetFamilyListAction extends AbstractAction
             $parsedBody = $request->getParsedBody();
 
             // To work this action needs information
-            foreach (array('label', 'display') as $a) {
+            foreach (array('label', 'display', 'opened') as $a) {
                 if ($this->isEmptyField($a, $parsedBody)) {
                     throw new HttpBadRequestException(
                         $request,
@@ -91,6 +91,7 @@ final class DatasetFamilyListAction extends AbstractAction
         $family = new DatasetFamily($instance);
         $family->setLabel($parsedBody['label']);
         $family->setDisplay($parsedBody['display']);
+        $family->setOpened($parsedBody['opened']);
 
         $this->em->persist($family);
         $this->em->flush();
diff --git a/server/src/Action/OutputFamilyAction.php b/server/src/Action/OutputFamilyAction.php
index a13c399d..fc0b92b4 100644
--- a/server/src/Action/OutputFamilyAction.php
+++ b/server/src/Action/OutputFamilyAction.php
@@ -59,7 +59,7 @@ final class OutputFamilyAction extends AbstractAction
         if ($request->getMethod() === PUT) {
             $parsedBody = $request->getParsedBody();
 
-            $fields = array('label', 'display');
+            $fields = array('label', 'display', 'opened');
             foreach ($fields as $a) {
                 if ($this->isEmptyField($a, $parsedBody)) {
                     throw new HttpBadRequestException(
@@ -96,6 +96,7 @@ final class OutputFamilyAction extends AbstractAction
     {
         $family->setLabel($parsedBody['label']);
         $family->setDisplay($parsedBody['display']);
+        $family->setOpened($parsedBody['opened']);
         $this->em->flush();
     }
 }
diff --git a/server/src/Action/OutputFamilyListAction.php b/server/src/Action/OutputFamilyListAction.php
index ce4b6426..6e112af0 100644
--- a/server/src/Action/OutputFamilyListAction.php
+++ b/server/src/Action/OutputFamilyListAction.php
@@ -63,7 +63,7 @@ final class OutputFamilyListAction extends AbstractAction
             $parsedBody = $request->getParsedBody();
 
             // To work this action needs information
-            foreach (array('label', 'display') as $a) {
+            foreach (array('label', 'display', 'opened') as $a) {
                 if ($this->isEmptyField($a, $parsedBody)) {
                     throw new HttpBadRequestException(
                         $request,
@@ -92,6 +92,7 @@ final class OutputFamilyListAction extends AbstractAction
         $family = new OutputFamily($dataset);
         $family->setLabel($parsedBody['label']);
         $family->setDisplay($parsedBody['display']);
+        $family->setOpened($parsedBody['opened']);
 
         $this->em->persist($family);
         $this->em->flush();
diff --git a/server/src/Entity/CriteriaFamily.php b/server/src/Entity/CriteriaFamily.php
index 91e66122..b238afd0 100644
--- a/server/src/Entity/CriteriaFamily.php
+++ b/server/src/Entity/CriteriaFamily.php
@@ -44,6 +44,13 @@ class CriteriaFamily implements \JsonSerializable
      */
     protected $display;
 
+    /**
+     * @var bool
+     *
+     * @Column(type="boolean", nullable=false)
+     */
+    protected $opened;
+
     /**
      * @var Dataset
      *
@@ -82,12 +89,23 @@ class CriteriaFamily implements \JsonSerializable
         $this->display = $display;
     }
 
+    public function getOpened()
+    {
+        return $this->opened;
+    }
+
+    public function setOpened($opened)
+    {
+        $this->opened = $opened;
+    }
+
     public function jsonSerialize()
     {
         return [
             'id' => $this->getId(),
             'label' => $this->getLabel(),
-            'display' => $this->getDisplay()
+            'display' => $this->getDisplay(),
+            'opened' => $this->getOpened()
         ];
     }
 }
diff --git a/server/src/Entity/DatasetFamily.php b/server/src/Entity/DatasetFamily.php
index df0b25ae..4a53a132 100644
--- a/server/src/Entity/DatasetFamily.php
+++ b/server/src/Entity/DatasetFamily.php
@@ -44,6 +44,13 @@ class DatasetFamily implements \JsonSerializable
      */
     protected $display;
 
+    /**
+     * @var bool
+     *
+     * @Column(type="boolean", nullable=false)
+     */
+    protected $opened;
+
     /**
      * @var Instance
      *
@@ -89,6 +96,16 @@ class DatasetFamily implements \JsonSerializable
         $this->display = $display;
     }
 
+    public function getOpened()
+    {
+        return $this->opened;
+    }
+
+    public function setOpened($opened)
+    {
+        $this->opened = $opened;
+    }
+
     public function getInstance()
     {
         return $this->instance;
@@ -104,7 +121,8 @@ class DatasetFamily implements \JsonSerializable
         return [
             'id' => $this->getId(),
             'label' => $this->getLabel(),
-            'display' => $this->getDisplay()
+            'display' => $this->getDisplay(),
+            'opened' => $this->getOpened()
         ];
     }
 }
diff --git a/server/src/Entity/OutputFamily.php b/server/src/Entity/OutputFamily.php
index 278954ea..1e10fd6b 100644
--- a/server/src/Entity/OutputFamily.php
+++ b/server/src/Entity/OutputFamily.php
@@ -44,6 +44,13 @@ class OutputFamily implements \JsonSerializable
      */
     protected $display;
 
+    /**
+     * @var bool
+     *
+     * @Column(type="boolean", nullable=false)
+     */
+    protected $opened;
+
     /**
      * @var Dataset
      *
@@ -82,12 +89,23 @@ class OutputFamily implements \JsonSerializable
         return $this->display;
     }
 
+    public function getOpened()
+    {
+        return $this->opened;
+    }
+
+    public function setOpened($opened)
+    {
+        $this->opened = $opened;
+    }
+
     public function jsonSerialize()
     {
         return [
             'id' => $this->getId(),
             'label' => $this->getLabel(),
-            'display' => $this->getDisplay()
+            'display' => $this->getDisplay(),
+            'opened' => $this->getOpened()
         ];
     }
 }
diff --git a/server/tests/Action/CriteriaFamilyActionTest.php b/server/tests/Action/CriteriaFamilyActionTest.php
index 5b9e3fd1..51e6fd73 100644
--- a/server/tests/Action/CriteriaFamilyActionTest.php
+++ b/server/tests/Action/CriteriaFamilyActionTest.php
@@ -77,7 +77,8 @@ final class CriteriaFamilyActionTest extends TestCase
 
         $fields = array(
             'label' => 'Modfied family',
-            'display' => 20
+            'display' => 20,
+            'opened' => true
         );
 
         $request = $this->getRequest('PUT')->withParsedBody($fields);
diff --git a/server/tests/Action/CriteriaFamilyListActionTest.php b/server/tests/Action/CriteriaFamilyListActionTest.php
index 9eab6362..b0cd8314 100644
--- a/server/tests/Action/CriteriaFamilyListActionTest.php
+++ b/server/tests/Action/CriteriaFamilyListActionTest.php
@@ -85,7 +85,8 @@ final class CriteriaFamilyListActionTest extends TestCase
 
         $fields = array(
             'label' => 'Default criteria family',
-            'display' => 10
+            'display' => 10,
+            'opened' => true
         );
         $request = $this->getRequest('POST')->withParsedBody($fields);
         $response = ($this->action)($request, new Response(), array('name' => 'obs_cat'));
diff --git a/server/tests/Action/DatasetFamilyActionTest.php b/server/tests/Action/DatasetFamilyActionTest.php
index f2b162c0..429e4345 100644
--- a/server/tests/Action/DatasetFamilyActionTest.php
+++ b/server/tests/Action/DatasetFamilyActionTest.php
@@ -77,7 +77,8 @@ final class DatasetFamilyActionTest extends TestCase
 
         $fields = array(
             'label' => 'Modfied family',
-            'display' => 20
+            'display' => 20,
+            'opened' => true
         );
         $request = $this->getRequest('PUT')->withParsedBody($fields);
         ($this->action)($request, new Response(), array('id' => 1));
diff --git a/server/tests/Action/DatasetFamilyListActionTest.php b/server/tests/Action/DatasetFamilyListActionTest.php
index f184e3b2..cfbcb25a 100644
--- a/server/tests/Action/DatasetFamilyListActionTest.php
+++ b/server/tests/Action/DatasetFamilyListActionTest.php
@@ -84,7 +84,8 @@ final class DatasetFamilyListActionTest extends TestCase
 
         $fields = array(
             'label' => 'Default family',
-            'display' => 10
+            'display' => 10,
+            'opened' => true
         );
 
         $request = $this->getRequest('POST')->withParsedBody($fields);
diff --git a/server/tests/Action/OutputFamilyActionTest.php b/server/tests/Action/OutputFamilyActionTest.php
index 73c391b1..948c359c 100644
--- a/server/tests/Action/OutputFamilyActionTest.php
+++ b/server/tests/Action/OutputFamilyActionTest.php
@@ -77,7 +77,8 @@ final class OutputFamilyActionTest extends TestCase
 
         $fields = array(
             'label' => 'Modfied family',
-            'display' => 20
+            'display' => 20,
+            'opened' => true
         );
 
         $request = $this->getRequest('PUT')->withParsedBody($fields);
diff --git a/server/tests/Action/OutputFamilyListActionTest.php b/server/tests/Action/OutputFamilyListActionTest.php
index 9f5953d7..f094c9c2 100644
--- a/server/tests/Action/OutputFamilyListActionTest.php
+++ b/server/tests/Action/OutputFamilyListActionTest.php
@@ -85,7 +85,8 @@ final class OutputFamilyListActionTest extends TestCase
 
         $fields = array(
             'label' => 'Default output family',
-            'display' => 10
+            'display' => 10,
+            'opened' => true
         );
 
         $request = $this->getRequest('POST')->withParsedBody($fields);
-- 
GitLab