From 0bddc54306efd8750e204979b2077656462b4a07 Mon Sep 17 00:00:00 2001
From: pkupczyk <piotr.kupczyk@id.ethz.ch>
Date: Thu, 16 Mar 2023 16:50:15 +0100
Subject: [PATCH] SSDM-13133 : Add info to Admin UI : registrator,
 registrationDate, modificationDate for types, vocabularies, terms, property
 types

---
 .../types/common/EntityTypesGrid.jsx          |  7 ++++
 .../types/common/PropertyTypesGrid.jsx        | 15 +++++++
 .../types/common/VocabularyTypesGrid.jsx      | 20 ++++++++++
 .../vocabularytype/VocabularyTypeForm.jsx     | 15 +++++++
 .../VocabularyTypeFormControllerAdd.js        |  4 ++
 .../VocabularyTypeFormControllerLoad.js       |  5 +++
 .../js/components/types/search/TypeSearch.jsx | 27 +++++++++----
 ...VocabularyTypeFormComponentAddTerm.test.js |  8 +++-
 .../VocabularyTypeFormComponentLoad.test.js   | 12 ++++++
 .../VocabularyTypeFormComponentSort.test.js   |  8 +++-
 .../search/TypeSearchComponentLoad.test.js    | 40 +++++++++++++++++++
 11 files changed, 150 insertions(+), 11 deletions(-)

diff --git a/ui-admin/src/js/components/types/common/EntityTypesGrid.jsx b/ui-admin/src/js/components/types/common/EntityTypesGrid.jsx
index 0e4e388db2c..fd08a125448 100644
--- a/ui-admin/src/js/components/types/common/EntityTypesGrid.jsx
+++ b/ui-admin/src/js/components/types/common/EntityTypesGrid.jsx
@@ -2,6 +2,7 @@ import React from 'react'
 import GridWithOpenbis from '@src/js/components/common/grid/GridWithOpenbis.jsx'
 import EntityTypeLink from '@src/js/components/common/link/EntityTypeLink.jsx'
 import PluginLink from '@src/js/components/common/link/PluginLink.jsx'
+import date from '@src/js/common/date.js'
 import openbis from '@src/js/services/openbis.js'
 import messages from '@src/js/common/messages.js'
 import logger from '@src/js/common/logger.js'
@@ -123,6 +124,12 @@ class EntityTypesGrid extends React.PureComponent {
       })
     }
 
+    columns.push({
+      name: 'modificationDate',
+      label: messages.get(messages.MODIFICATION_DATE),
+      getValue: ({ row }) => date.format(row.modificationDate)
+    })
+
     return columns
   }
 }
diff --git a/ui-admin/src/js/components/types/common/PropertyTypesGrid.jsx b/ui-admin/src/js/components/types/common/PropertyTypesGrid.jsx
index 9275a57b15e..c5f8ea8c58c 100644
--- a/ui-admin/src/js/components/types/common/PropertyTypesGrid.jsx
+++ b/ui-admin/src/js/components/types/common/PropertyTypesGrid.jsx
@@ -5,6 +5,8 @@ import EntityTypeLink from '@src/js/components/common/link/EntityTypeLink.jsx'
 import VocabularyTypeLink from '@src/js/components/common/link/VocabularyTypeLink.jsx'
 import PropertyTypesGridUsagesCell from '@src/js/components/types/common/PropertyTypesGridUsagesCell.jsx'
 import PropertyTypesGridXMLCell from '@src/js/components/types/common/PropertyTypesGridXMLCell.jsx'
+import UserLink from '@src/js/components/common/link/UserLink.jsx'
+import date from '@src/js/common/date.js'
 import openbis from '@src/js/services/openbis.js'
 import messages from '@src/js/common/messages.js'
 import logger from '@src/js/common/logger.js'
@@ -102,6 +104,19 @@ class PropertyTypesGrid extends React.PureComponent {
             renderValue: ({ row }) => {
               return <PropertyTypesGridUsagesCell value={row.usages} />
             }
+          },
+          {
+            name: 'registrator',
+            label: messages.get(messages.REGISTRATOR),
+            getValue: ({ row }) => row.registrator,
+            renderValue: ({ value }) => {
+              return <UserLink userId={value} />
+            }
+          },
+          {
+            name: 'registrationDate',
+            label: messages.get(messages.REGISTRATION_DATE),
+            getValue: ({ row }) => date.format(row.registrationDate)
           }
         ]}
         rows={rows}
diff --git a/ui-admin/src/js/components/types/common/VocabularyTypesGrid.jsx b/ui-admin/src/js/components/types/common/VocabularyTypesGrid.jsx
index 62019e7c089..e66e3202303 100644
--- a/ui-admin/src/js/components/types/common/VocabularyTypesGrid.jsx
+++ b/ui-admin/src/js/components/types/common/VocabularyTypesGrid.jsx
@@ -2,6 +2,8 @@ import React from 'react'
 import GridWithOpenbis from '@src/js/components/common/grid/GridWithOpenbis.jsx'
 import GridExportOptions from '@src/js/components/common/grid/GridExportOptions.js'
 import VocabularyTypeLink from '@src/js/components/common/link/VocabularyTypeLink.jsx'
+import UserLink from '@src/js/components/common/link/UserLink.jsx'
+import date from '@src/js/common/date.js'
 import messages from '@src/js/common/messages.js'
 import logger from '@src/js/common/logger.js'
 
@@ -36,6 +38,24 @@ class VocabularyTypesGrid extends React.PureComponent {
             name: 'urlTemplate',
             label: messages.get(messages.URL_TEMPLATE),
             getValue: ({ row }) => row.urlTemplate
+          },
+          {
+            name: 'registrator',
+            label: messages.get(messages.REGISTRATOR),
+            getValue: ({ row }) => row.registrator,
+            renderValue: ({ value }) => {
+              return <UserLink userId={value} />
+            }
+          },
+          {
+            name: 'registrationDate',
+            label: messages.get(messages.REGISTRATION_DATE),
+            getValue: ({ row }) => date.format(row.registrationDate)
+          },
+          {
+            name: 'modificationDate',
+            label: messages.get(messages.MODIFICATION_DATE),
+            getValue: ({ row }) => date.format(row.modificationDate)
           }
         ]}
         rows={rows}
diff --git a/ui-admin/src/js/components/types/form/vocabularytype/VocabularyTypeForm.jsx b/ui-admin/src/js/components/types/form/vocabularytype/VocabularyTypeForm.jsx
index d68bdd5a6df..71e0cff3c44 100644
--- a/ui-admin/src/js/components/types/form/vocabularytype/VocabularyTypeForm.jsx
+++ b/ui-admin/src/js/components/types/form/vocabularytype/VocabularyTypeForm.jsx
@@ -10,6 +10,8 @@ import VocabularyTypeFormController from '@src/js/components/types/form/vocabula
 import VocabularyTypeFormFacade from '@src/js/components/types/form/vocabularytype/VocabularyTypeFormFacade.js'
 import VocabularyTypeFormParameters from '@src/js/components/types/form/vocabularytype/VocabularyTypeFormParameters.jsx'
 import VocabularyTypeFormButtons from '@src/js/components/types/form/vocabularytype/VocabularyTypeFormButtons.jsx'
+import UserLink from '@src/js/components/common/link/UserLink.jsx'
+import date from '@src/js/common/date.js'
 import ids from '@src/js/common/consts/ids.js'
 import messages from '@src/js/common/messages.js'
 import logger from '@src/js/common/logger.js'
@@ -34,6 +36,19 @@ const columns = [
     name: 'official',
     label: messages.get(messages.OFFICIAL),
     getValue: ({ row }) => row.official.value
+  },
+  {
+    name: 'registrator',
+    label: messages.get(messages.REGISTRATOR),
+    getValue: ({ row }) => row.registrator.value,
+    renderValue: ({ value }) => {
+      return <UserLink userId={value} />
+    }
+  },
+  {
+    name: 'registrationDate',
+    label: messages.get(messages.REGISTRATION_DATE),
+    getValue: ({ row }) => date.format(row.registrationDate.value)
   }
 ]
 
diff --git a/ui-admin/src/js/components/types/form/vocabularytype/VocabularyTypeFormControllerAdd.js b/ui-admin/src/js/components/types/form/vocabularytype/VocabularyTypeFormControllerAdd.js
index 187c7fa574a..511588bb7da 100644
--- a/ui-admin/src/js/components/types/form/vocabularytype/VocabularyTypeFormControllerAdd.js
+++ b/ui-admin/src/js/components/types/form/vocabularytype/VocabularyTypeFormControllerAdd.js
@@ -25,6 +25,10 @@ export default class VocabularyTypeFormControllerAdd {
         visible: false,
         enabled: false
       }),
+      registrationDate: FormUtil.createField({
+        visible: false,
+        enabled: false
+      }),
       original: null
     }
 
diff --git a/ui-admin/src/js/components/types/form/vocabularytype/VocabularyTypeFormControllerLoad.js b/ui-admin/src/js/components/types/form/vocabularytype/VocabularyTypeFormControllerLoad.js
index da8af9ad50c..11d10e69285 100644
--- a/ui-admin/src/js/components/types/form/vocabularytype/VocabularyTypeFormControllerLoad.js
+++ b/ui-admin/src/js/components/types/form/vocabularytype/VocabularyTypeFormControllerLoad.js
@@ -112,6 +112,11 @@ export default class VocabularyTypeFormControllerLoad extends PageControllerLoad
         value: registrator,
         visible: false,
         enabled: false
+      }),
+      registrationDate: FormUtil.createField({
+        value: _.get(loadedTerm, 'registrationDate', null),
+        visible: false,
+        enabled: false
       })
     }
     term.original = _.cloneDeep(term)
diff --git a/ui-admin/src/js/components/types/search/TypeSearch.jsx b/ui-admin/src/js/components/types/search/TypeSearch.jsx
index 72987798c34..7d70ec17d17 100644
--- a/ui-admin/src/js/components/types/search/TypeSearch.jsx
+++ b/ui-admin/src/js/components/types/search/TypeSearch.jsx
@@ -83,7 +83,8 @@ class TypeSearch extends React.Component {
         subcodeUnique: _.get(object, 'subcodeUnique', false),
         autoGeneratedCode: _.get(object, 'autoGeneratedCode', false),
         generatedCodePrefix: _.get(object, 'generatedCodePrefix'),
-        validationPlugin: _.get(object, 'validationPlugin.name')
+        validationPlugin: _.get(object, 'validationPlugin.name'),
+        modificationDate: _.get(object, 'modificationDate')
       }))
 
     this.setState({
@@ -114,7 +115,8 @@ class TypeSearch extends React.Component {
         },
         code: _.get(object, 'code'),
         description: _.get(object, 'description'),
-        validationPlugin: _.get(object, 'validationPlugin.name')
+        validationPlugin: _.get(object, 'validationPlugin.name'),
+        modificationDate: _.get(object, 'modificationDate')
       }))
 
     this.setState({
@@ -148,7 +150,8 @@ class TypeSearch extends React.Component {
         validationPlugin: _.get(object, 'validationPlugin.name'),
         mainDataSetPattern: _.get(object, 'mainDataSetPattern'),
         mainDataSetPath: _.get(object, 'mainDataSetPath'),
-        disallowDeletion: _.get(object, 'disallowDeletion', false)
+        disallowDeletion: _.get(object, 'disallowDeletion', false),
+        modificationDate: _.get(object, 'modificationDate')
       }))
 
     this.setState({
@@ -175,7 +178,8 @@ class TypeSearch extends React.Component {
         id: _.get(object, 'code'),
         code: _.get(object, 'code'),
         description: _.get(object, 'description'),
-        validationPlugin: _.get(object, 'validationPlugin.name')
+        validationPlugin: _.get(object, 'validationPlugin.name'),
+        modificationDate: _.get(object, 'modificationDate')
       }))
 
     this.setState({
@@ -188,9 +192,12 @@ class TypeSearch extends React.Component {
       return
     }
 
+    const fo = new openbis.VocabularyFetchOptions()
+    fo.withRegistrator()
+
     const result = await openbis.searchVocabularies(
       new openbis.VocabularySearchCriteria(),
-      new openbis.VocabularyFetchOptions()
+      fo
     )
 
     const types = util
@@ -203,7 +210,10 @@ class TypeSearch extends React.Component {
         },
         code: object.code,
         description: object.description,
-        urlTemplate: object.urlTemplate
+        urlTemplate: object.urlTemplate,
+        registrator: _.get(object, 'registrator.userId'),
+        registrationDate: _.get(object, 'registrationDate'),
+        modificationDate: _.get(object, 'modificationDate')
       }))
 
     this.setState({
@@ -237,7 +247,9 @@ class TypeSearch extends React.Component {
         sampleType: _.get(object, 'sampleType.code'),
         schema: _.get(object, 'schema'),
         transformation: _.get(object, 'transformation'),
-        usages: _.get(propertyTypeUsages, object.code)
+        usages: _.get(propertyTypeUsages, object.code),
+        registrator: _.get(object, 'registrator.userId'),
+        registrationDate: _.get(object, 'registrationDate')
       }))
 
     this.setState({
@@ -250,6 +262,7 @@ class TypeSearch extends React.Component {
     fo.withVocabulary()
     fo.withMaterialType()
     fo.withSampleType()
+    fo.withRegistrator()
 
     const propertyTypes = await openbis.searchPropertyTypes(
       new openbis.PropertyTypeSearchCriteria(),
diff --git a/ui-admin/srcTest/js/components/types/form/vocabularytype/VocabularyTypeFormComponentAddTerm.test.js b/ui-admin/srcTest/js/components/types/form/vocabularytype/VocabularyTypeFormComponentAddTerm.test.js
index c14b0df3e1d..dcfaefd0ca0 100644
--- a/ui-admin/srcTest/js/components/types/form/vocabularytype/VocabularyTypeFormComponentAddTerm.test.js
+++ b/ui-admin/srcTest/js/components/types/form/vocabularytype/VocabularyTypeFormComponentAddTerm.test.js
@@ -21,7 +21,9 @@ async function testAddTerm() {
         { name: 'code', sort: 'asc' },
         { name: 'label', sort: null },
         { name: 'description', sort: null },
-        { name: 'official', sort: null }
+        { name: 'official', sort: null },
+        { name: 'registrator', sort: null },
+        { name: 'registrationDate', sort: null }
       ],
       rows: [
         fixture.TEST_TERM_1_DTO,
@@ -63,7 +65,9 @@ async function testAddTerm() {
         { name: 'code', sort: 'desc' },
         { name: 'label', sort: null },
         { name: 'description', sort: null },
-        { name: 'official', sort: null }
+        { name: 'official', sort: null },
+        { name: 'registrator', sort: null },
+        { name: 'registrationDate', sort: null }
       ],
       rows: [
         {
diff --git a/ui-admin/srcTest/js/components/types/form/vocabularytype/VocabularyTypeFormComponentLoad.test.js b/ui-admin/srcTest/js/components/types/form/vocabularytype/VocabularyTypeFormComponentLoad.test.js
index ee0e0a8b094..f66e74ef531 100644
--- a/ui-admin/srcTest/js/components/types/form/vocabularytype/VocabularyTypeFormComponentLoad.test.js
+++ b/ui-admin/srcTest/js/components/types/form/vocabularytype/VocabularyTypeFormComponentLoad.test.js
@@ -88,6 +88,18 @@ async function testLoadExisting() {
         label: 'Official',
         filter: null,
         sort: null
+      },
+      {
+        name: 'registrator',
+        label: 'Registrator',
+        filter: null,
+        sort: null
+      },
+      {
+        name: 'registrationDate',
+        label: 'Registration Date',
+        filter: null,
+        sort: null
       }
     ],
     rows: fixture.TEST_VOCABULARY_DTO.terms.map(term => ({
diff --git a/ui-admin/srcTest/js/components/types/form/vocabularytype/VocabularyTypeFormComponentSort.test.js b/ui-admin/srcTest/js/components/types/form/vocabularytype/VocabularyTypeFormComponentSort.test.js
index 2df4e2453ad..0c09354128b 100644
--- a/ui-admin/srcTest/js/components/types/form/vocabularytype/VocabularyTypeFormComponentSort.test.js
+++ b/ui-admin/srcTest/js/components/types/form/vocabularytype/VocabularyTypeFormComponentSort.test.js
@@ -41,7 +41,9 @@ async function testSort() {
         { name: 'code', sort: null },
         { name: 'label', sort: 'asc' },
         { name: 'description', sort: null },
-        { name: 'official', sort: null }
+        { name: 'official', sort: null },
+        { name: 'registrator', sort: null },
+        { name: 'registrationDate', sort: null }
       ],
       rows: [
         { values: { label: 'Term 1' } },
@@ -65,7 +67,9 @@ async function testSort() {
         { name: 'code', sort: null },
         { name: 'label', sort: 'desc' },
         { name: 'description', sort: null },
-        { name: 'official', sort: null }
+        { name: 'official', sort: null },
+        { name: 'registrator', sort: null },
+        { name: 'registrationDate', sort: null }
       ],
       rows: [
         { values: { label: 'term B' } },
diff --git a/ui-admin/srcTest/js/components/types/search/TypeSearchComponentLoad.test.js b/ui-admin/srcTest/js/components/types/search/TypeSearchComponentLoad.test.js
index 30997a45629..98206ebfc4a 100644
--- a/ui-admin/srcTest/js/components/types/search/TypeSearchComponentLoad.test.js
+++ b/ui-admin/srcTest/js/components/types/search/TypeSearchComponentLoad.test.js
@@ -87,6 +87,10 @@ async function testLoadWithSearchText(resultsFound) {
           {
             name: 'subcodeUnique',
             label: 'Unique Subcodes'
+          },
+          {
+            name: 'modificationDate',
+            label: 'Modification Date'
           }
         ],
         rows: [
@@ -115,6 +119,10 @@ async function testLoadWithSearchText(resultsFound) {
           {
             name: 'validationPlugin',
             label: 'Validation Plugin'
+          },
+          {
+            name: 'modificationDate',
+            label: 'Modification Date'
           }
         ],
         rows: [
@@ -152,6 +160,10 @@ async function testLoadWithSearchText(resultsFound) {
           {
             name: 'disallowDeletion',
             label: 'Disallow Deletion'
+          },
+          {
+            name: 'modificationDate',
+            label: 'Modification Date'
           }
         ],
         rows: [
@@ -180,6 +192,10 @@ async function testLoadWithSearchText(resultsFound) {
           {
             name: 'validationPlugin',
             label: 'Validation Plugin'
+          },
+          {
+            name: 'modificationDate',
+            label: 'Modification Date'
           }
         ],
         rows: [
@@ -205,6 +221,18 @@ async function testLoadWithSearchText(resultsFound) {
           {
             name: 'urlTemplate',
             label: 'URL Template'
+          },
+          {
+            name: 'registrator',
+            label: 'Registrator'
+          },
+          {
+            name: 'registrationDate',
+            label: 'Registration Date'
+          },
+          {
+            name: 'modificationDate',
+            label: 'Modification Date'
           }
         ],
         rows: [
@@ -258,6 +286,14 @@ async function testLoadWithSearchText(resultsFound) {
           {
             name: 'usages',
             label: 'Usages'
+          },
+          {
+            name: 'registrator',
+            label: 'Registrator'
+          },
+          {
+            name: 'registrationDate',
+            label: 'Registration Date'
           }
         ],
         rows: [
@@ -327,6 +363,10 @@ async function testLoadWithObjectType(resultsFound) {
         {
           name: 'subcodeUnique',
           label: 'Unique Subcodes'
+        },
+        {
+          name: 'modificationDate',
+          label: 'Modification Date'
         }
       ],
       rows: resultsFound
-- 
GitLab