Skip to content

[DSpace-CRIS] Configurable Layout of Entity/Item pages#5963

Draft
FrancescoMolinaro wants to merge 7 commits into
DSpace:mainfrom
4Science:task/main/DURACOM-507
Draft

[DSpace-CRIS] Configurable Layout of Entity/Item pages#5963
FrancescoMolinaro wants to merge 7 commits into
DSpace:mainfrom
4Science:task/main/DURACOM-507

Conversation

@FrancescoMolinaro

@FrancescoMolinaro FrancescoMolinaro commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

References

Issue: DSpace/DSpace#11779
Backend: DSpace/DSpace#12789

Description

The Dynamic layout (ex CRIS layout) allows to manage the visualization and access to the item data in a more fine-grain way than the default DSpace.

The layout is organized in an excel file and the item information is organized over two levels, tabs and boxes. Each tab can contain one or more boxes organized in a sort of grid composed by rows and cells. The same box can be eventually shared between multiple tabs with a specific order in each tab. A box represents the minimal unit of information about an item that can be visualized and protected.

If an entity type is not defined in the excel file the default DSpace layout is displayed.

Basic examples:

image image image

Vertical and horizontal Layout

It is possible to have a main leading tab always visible and to organize the remaining tabs with a layout having two different orientations : vertical and horizontal. In the horizontal layout the tabs are arranged inside a top navbar, while in the vertical one they are arranged within a lateral sidebar.

Only tabs and boxes that contain data visible to the current user are listed. If a tab only contains boxes without visible data or that are flagged as minor, such tab is not listed at all.

In both vertical and horizontal layout when only one tab is available sidebar and navbar are not displayed.

It’s possible to use one of the two layout (vertical or horizontal) differently depending on the type of entity. To select the layout, the DSpace angular application provide an itemPage settings under the layout property in the environment file (src/environments/environment.common.ts), e.g.

itemPage: { Person: { orientation: 'horizontal' }, default: { orientation: 'vertical' }, },

Tab grid system

In order to have a more flexible way to arrange boxes within a tab a grid system is used. The grid system uses a series of rows and cells to layout and align boxes, following these rules :

  • Every row can contains one or more cells

  • Every cell can contain one or more boxes

  • All cells inside the same row are displayed one next to the other

  • All boxes inside the same cell are displayed one below the other

Example:

image

Tab and Box models

The tabs are represented by the org.dspace.layout.DynamicLayoutTab java class and exposed in the REST layer via the org.dspace.app.rest.model.DynamicLayoutTabRest. The boxes are represented by the org.dspace.layout.DynamicLayoutBox java class and exposed in the REST layer via the org.dspace.app.rest.model.DynamicLayoutBoxRest and org.dspace.app.rest.model.DynamicLayoutBoxConfigurationRest. The later one, in particular, is the extension point to plug the different types of boxes in the platform.

Tabs and Boxes are bound to a specific Entity Type and share the following attributes:

  • shortname. It is an alias of the Id used to refer to the tab / box from configuration files, without the need to hardcode the database generated Id

  • label. It is the label, or the i18n key, to use to present the section to the user. In case you want to use the header as a translation key, the complete i18n key used by the system has the prefix layout.tab.header. for the tab, and layout.box.header. for the box

  • security. It can have one of the following values:

0 → public. Everyone can access the data contained in the tab (if the security is not overridden by the box security), or box

1 → administrator. Only system administrator can access the data

2 → owner only. Only the owner of the item can access the data. Please note that the concept of item owner is specific of DSpace-CRIS and it is different from the submitter. The item owner is defined by the dspace.object.owner metadata

3 → owner and administrator. Only the owner of the item and the system administrator can access the data

4 → custom policy. The list of people and groups that can access the data are defined in other metadata of the item itself. The metadata to use are defined in the securityMetadata attribute that contains a list of reference to metadata fields that are expected to be configured with the EPersonAuthority or GroupAuthority

  • leading. It can be true or false. If true, the tab is shown on the top of the item’s page and remains there even if the user browse the other tabs

  • priority. Attribute that is used to sort them in ascending order

  • rows. It contains the configuration of the grid used to display boxes beloging to the current tab. Each row is composed by cells that contains the list of boxes. Boxes have a specific order inside each cell that include them.

  • container. It can be true or false. If true, the box is show as a collapsible panel, otherwise it has no container and is always visible

  • collapsed. When true, and box container property is set to true, the box panle start collapsed, and the user need to open it to see the actual data

  • minor. It is true when the box should not be used to determine if a tab actually has content or not

  • style. It is added to the CSS classes of the generated html element that contains the tab or box to allow further customization via CSS

  • configuration. It contains additional information used to render the data in the appropriate way

Nested tabs

It’s possible to have two or more tabs grouped by the same top menu entry. In this case the tab entries are displayed with a dropdown in the sidebar and navbar .

image

To configure the nested two or more tabs, the shortname property and label may contain the parent and child tabs concatenated by ::.

Following the previous example where we have two tabs, publications and fundigs, grouped by a the top level tab outputs , the configuration is like :

shortname -> label

outputs::publications -> Outputs::Publications

When relating boxes to nested tab, the shortname of the tab to use must include also the top level ( e.g. outputs::publications).

Box types

The most simple and used is named METADATA.
A metadata box is a collection of item metadata fields and selection criteria over the item bitstreams, organized in rows, each of which can contain one or more fields. Three types of fields exist (metadata and bitstream), their additional configuration options are exposed in an attribute with the same name than the fieldType:

  • METADATA. The field holds the values stored in an item metadata identified with the .[.] syntax that is exposed in the metadata attribute

  • METADATAGROUP. The field holds the values stored in a group of nested metadata identified with the .[.] syntax that is exposed in the metadata attribute

  • BITSTREAM. The field holds the bitstreams in a specific item bundle optionally matching a specific value for a metadata.

  • IIIFVIEWER. The field holds an embedded Mirador viewer. This is showed only if the metadata dspace.iiif.enabled is set to true.

The bitstream attribute is an object containing the:

  • bundle, the name of the bundle

  • metadataField and metadataValue, optional, the value of a specific bitstream metadata that will be used to filter which bitstreams are included in the field. If the metadataValue start with a ! the filter become negative (only return bitstreams that don’t match the criteria). It is also possible specify a regex puting the metadataValue between bracket (...regex...), or a negative regex !(...regex...)

Regardless to the fieldType, each field has the following attributes:

  • label. The textual label or i18n key to use as label for the field. In case you want to use the header as a translation key, the complete i18n key used by the system has the prefix layout.field.header.

  • rendering. The rendering strategy for the field. Examples are heading, text, longtext, dynamicref, identifier, date, link etc. for metadata field, and preview, thubmnail for bitstream field

  • styleLabel. The style attribute allows to set arbitrary css styles to the metadata’s label

  • styleValue. The style attribute allows to set arbitrary css styles to the metadata’s value

  • labelAsHeading. If true, the metadata value is displayed below the metadata label. If false, metadata value is displayed along the metadata label

  • valuesInline. If true, when a metadata has multiple values, they are displayed one along the others. If false, they are displayed one below the others

Another type of box present is the RELATION box.

This box is bound to a DiscoveryConfiguration that can be parameterized with the uuid of the item. The defaultFilterQueries of the DiscoveryConfiguration can contains the placeholder {0} that will be replaced at runtime with the uuid of the item. Please refer to next paragraph for further details about how to set and configure such queries.

Discovery queries are configured via discovery.xml file (/config/spring/api/discovery.xml) , in org.dspace.discovery.configuration.DiscoveryConfigurationService bean. A map’s entry for each relation is provided, standard pattern for key is RELATION... Entity and relationName must match to what reported in xls file, box sheet, ‘ENTITY’ and ‘SHORTNAME’ entries for each relation. For example, RELATION.Project.researchoutputs identifies the relation that will be used to populate 'researchoutupts' box configured in excel file for entity 'Project'.

The core part of DiscoveryConfiguration, for relation’s set up is defaultFilterQueries. This section contains one or more filter queries to be performed, given Item’s uuid, to find linked Items. In case many filter queries are provided, such queries are executed in sequence: the second query filters first query’s results and so on.

This is the query that retrieves projects related to a person: projectinvestigators_authority:{0}, where {0} is a placeholder for UUID of the person. In case of inverse relations, queries are more complex and a subquery is needed. For exampl,e this is the query that finds Projects belonging to every person affiliated to an OrgUnit, given OrgUnit UUID: '{'!join from=search.resourceid to=projectinvestigators_authority fromIndex=search'}'person.affiliation.name_authority:{0}.

Another type of box available is the COLLECTIONS box.

The COLLECTIONS box shows the owning collection of an item, and all mapped collections:
It is possible to customise the appearance of this box through the property collectionsBox in the default.app.config.ts.

image

Box grid system

In a very similar way to what we have for tabs, the grid system is used also to locate metadata within a metadata box. The grid system uses a series of rows and cells to layout and align metadata, following these rules:

  • Every row can contains one or more cells

  • Every cell can contain one or more metadata

  • All cells inside the same row are displayed one next to the other

  • All metadata inside the same cell are displayed one below the other

Rendering Types

The rendering types are different ways of displaying the metadata to the user, each of them is connected to a different UI component and offers a different functionality.
The available types are descripted in the following table:

Field type Subtypes Description
heading Heading field.
text Text field.
longtext Long text field.
link label, email Supports a clickable URL or email address. To add a label to a URL, use [Link label](URL) with the link.label rendering. To add a clickable email address, insert the email address in the field with the link.email rendering.
date Date field.
bcdate Used for BCE dates; renders negative years showing "B.C." for negative dates. (GLAM only).
identifier hdl, doi, scopus, researcherid, mailto, ror Identifier field supporting common persistent identifier types.
dynamicref first3.last1 Used for long author lists.
thumbnail Thumbnail field.
attachment Attachment field.
advancedattachment Advanced attachment field.
tag Tag field.
valuepair <value_pairs_name> or <vocabulary_name> Renders values from a configured value pair or vocabulary.
orcid ORCID field.
table METADATAGROUP Table field rendered from a metadata group.
inline METADATAGROUP Inline field rendered from a metadata group.
authoritylink Renders personal links with labels.
html Renders the field content as HTML, displaying the full text.
longhtml Renders the field content as HTML, truncating long text with a Show more button.
cclicense METADATAGROUP Renders the license as a clickable badge.
cclicensefull METADATAGROUP Renders the license as a clickable badge with extended license details displayed alongside it.

Security of the metadata

The dynamic layout allows a more granular control of the security. It is possible to configure which metadata are available to different users. Out of box the dynamic layout behavior mimic the one implemented by DSpace, metadata are generally available to any user (anonymous) with the only exception of the metadata listed in the configuration files with the key metadata.hide..[.] = true

When the dynamic layout defines tabs or boxes that have a limited access the metadata used in these tabs / boxes are checked in details and a user will be able to retrieve them via API, so in the UI, only if the user has the right to access such metadata via at least one box. This mean that metadata not used in the dynamic layout are generally public but can still be restricted to the administrators using the metadata.hide. configuration keys.

A special project named preventMetadataSecurity exists to skip the evaluation of the granular security logic where appropriate. This is the case when a large number of items are retrieved to show just a limited amount of data that are known to be not controversial. Indeed, if the client specify this projection in the REST request only the metadata listed under the configuration key metadata.publicField are returned without wasting time in further check . This mean that using such projection also authorized users are unable to retrieve potential sensible data.

The dynamic layout goes a step further and other than providing a granular security at the level of individual metadata field it is also able to define a further access rule to decide which individual metadata values are visible to a specific user.

This is configured in the metadata-security.cfg file where this feature can be enabled for all the metadata or a specific subset, defining the default configuration (usually no further restriction as in a basic DSpace) for metadata that are not explicitly mentioned. The exact meaning of the different metadata value security level is defined in the spring-dspace-security-metadata.xml file and by default offer

  • level 0: everyone (that is granted to see the metadata field)
  • level 1: member of the group “Trusted” (can be configured)
  • level 2: administrators.

Dynamic Layout Tool Sheets

The Dynamic Layout configuration is organized into multiple sheets. Each sheet defines a specific aspect of the UI layout.

tab

Defines all tabs that should be created.

Column Description
Entity Label of the Entity Type to which the tab belongs. A tab's Shortname must be unique within the entity. This column can also contain a custom filter (see the Custom Filter section).
Shortname Unique identifier of the tab, used by other sheets and configuration.
Label Human-readable tab name or an i18n key (see i18n conventions).
Priority Tabs are ordered by ascending priority.
Leading y or n. If y, the tab remains fixed at the top of the item page while browsing other tabs. If no tab is marked as leading, all tabs are placed below the page header and the details section scrolls out of view.
Security Defines who can access the tab.

box

Defines all boxes displayed within tabs. Boxes are rendered in the order they appear.

Column Description
Entity Label of the Entity Type to which the box belongs. A box's Shortname must be unique within the entity. This column can also contain a custom filter.
Collapsed y or n. When y, the box is initially collapsed in the default theme.
Container y or n. When y, the box is rendered with its surrounding panel and title.
Type Box type. Available values are listed in the utilsdata sheet.
Shortname Unique identifier of the box.
Label Human-readable name or i18n key.
Minor y or n. Minor boxes are ignored when determining whether a tab contains visible content.
Security Defines who can access the box.
Style Extra UI styling information. In the default theme this becomes CSS classes (for example col-md-6).

tab2box

Associates boxes with tabs.

Column Description
Entity Used together with Tab to reference the tab sheet.
Tab References the tab Shortname.
Boxes Comma-separated list of box Shortname values defined in the box sheet.
Row Row where the boxes are placed. Boxes sharing the same row appear side by side.
Row_style Style applied to the row. Rows with the same number should use the same style.
Cell_style Style applied to the cell containing the boxes.

box2metadata

Configures metadata boxes and the fields they display.

Column Description
Entity References the entity.
Box References the box Shortname.
Row Row where the field is displayed.
Cell Cell within the row where the field is displayed.
Row_style Style applied to the row.
Cell_style Style applied to the cell.
FieldType Field type (METADATA, BITSTREAM, or METADATAGROUP).
Metadata Metadata key.
Value For BITSTREAM fields only, filters bitstreams by metadata value.
Bundle For BITSTREAM fields only, filters by bundle. Since versions 2023.02.08, 2024.02.02, and 2025.01.00, two bundles can be specified using <VIEW_BUNDLE>.<DOWNLOAD_BUNDLE> (for example ORIGINAL.BRANDED_PREVIEW).
Label Human-readable label or i18n key.
Rendering Custom rendering strategy for the field.
Style CSS classes applied to the field container.
Style_label CSS classes applied to the label.
Style_value CSS classes applied to the value.
Label_as_heading y or n. When y, the label is displayed above the value.
Values_inline y or n. When y, multiple values are shown inline; otherwise each value appears on a separate line.

metadatagroups

Defines nested metadata rendered as grouped fields.

Column Description
Entity Entity Type label.
Parent Parent metadata field. It must also exist in box2metadata with FieldType = METADATAGROUP.
FieldType Always METADATA.
Metadata Metadata key.
Value For BITSTREAM fields only, filters bitstreams by metadata value.
Bundle For BITSTREAM fields only, bundle filter. Supports <VIEW_BUNDLE>.<DOWNLOAD_BUNDLE> syntax.
Label Human-readable label or i18n key.
Rendering Custom rendering strategy.
Style_label CSS classes for the label.
Style_value CSS classes for the value.

tabpolicy and boxpolicy

Provide additional configuration for tabs and boxes using CUSTOM DATA security.

Column Description
Entity References the entity.
Shortname References the tab or box.
Metadata Metadata key (for example cris.policy.group) containing the users or groups allowed to access the tab or box.
Group Alternative to Metadata. Access is granted if the current user belongs to the specified group.
Alternative_to Name of the tab or box displayed when access to the configured one is denied.

utilsdata

This sheet is not processed by the tool.

It exists only as a reference to help populate the configuration workbook.


tab_i18n, box_i18n, metadata_i18n, metadatagroup_i18n

Contain i18n translations.

See the i18n conventions section for details.


Configuration Loading Process

The tool performs the following operations in order, stopping immediately if an error occurs:

  1. Validate the Excel configuration file, reporting inconsistencies such as:
    • Undefined entity types
    • Undefined metadata
    • Missing tabs or boxes referenced by association sheets
    • Other configuration errors
  2. Completely remove the existing Dynamic Layout configuration.
  3. Load the new configuration.

Instructions for Reviewers

To import the layout you can ran the following script:

./dspace dynamic-layout-tool -f ../etc/conftool/dynamic-layout-configuration.xls

or from the process page in the UI you can select the dynamic-layout-import script.

To test the functionality you can try and start by configuring one of the entity type available in DSpace and check that the dynamic layout work properly.

A basic layout of example can be found in the rest codebase under the name dynamic-layout-configuration.xls or attached to this PR.
dynamic-layout-configuration.xls

The i18n tabs in the excel are come with a function to generate labels based on a prefix, to do so you just need to drag the AUTOGENERATED I18N keys columns.
The labels can then be copied over to the json file in the UI project in case translations or customizations are needed.

List of changes in this PR:

Added new resolver to check whether tabs are available and dynamic layout can be loaded.
Added new decorators and static map for handling and parsing of tabs, boxes and rendering types.
Ported components for rendering types visualization.
Implemented layout matrix and loader components.
Ported UI configurations for layout elements customization.
Ported different boxes components.

Checklist

This checklist provides a reminder of what we are going to look for when reviewing your PR. You do not need to complete this checklist prior creating your PR (draft PRs are always welcome).
However, reviewers may request that you complete any actions in this list if you have not done so. If you are unsure about an item in the checklist, don't hesitate to ask. We're here to help!

  • My PR is created against the main branch of code (unless it is a backport or is fixing an issue specific to an older branch).
  • My PR is small in size (e.g. less than 1,000 lines of code, not including comments & specs/tests), or I have provided reasons as to why that's not possible.
  • My PR passes ESLint validation using npm run lint
  • My PR doesn't introduce circular dependencies (verified via npm run check-circ-deps)
  • My PR includes TypeDoc comments for all new (or modified) public methods and classes. It also includes TypeDoc for large or complex private methods.
  • My PR passes all specs/tests and includes new/updated specs or tests based on the Code Testing Guide.
  • My PR aligns with Accessibility guidelines if it makes changes to the user interface.
  • My PR uses i18n (internationalization) keys instead of hardcoded English text, to allow for translations.
  • My PR includes details on how to test it. I've provided clear instructions to reviewers on how to successfully test this fix or feature.
  • If my PR includes new libraries/dependencies (in package.json), I've made sure their licenses align with the DSpace BSD License based on the Licensing of Contributions documentation.
  • If my PR includes new features or configurations, I've provided basic technical documentation in the PR itself.
  • If my PR fixes an issue ticket, I've linked them together.

FrancescoMolinaro and others added 5 commits July 9, 2026 14:44
Remove DynamicLayoutConfig nesting and move urn, itemPage, metadataBox,
and collectionsBox properties directly under the layout interface to
eliminate unnecessary nesting levels.

Changes:
- Update layout-config.interfaces.ts: Remove DynamicLayoutConfig interface
  and add urn, itemPage, metadataBox, collectionsBox directly to LayoutConfig
- Update default-app-config.ts: Move dynamicLayout properties to top level
- Update environment.test.ts: Move dynamicLayout properties to top level
- Update component property access from layout.dynamicLayout.* to layout.*:
  * dynamic-layout-loader.component.ts
  * dynamic-layout-collection-box.component.ts
  * metadata-container.component.ts
  * resolver-strategy.service.ts
  * identifier.component.ts
- Update config.example.yml: Flatten structure and enhance documentation

Before:
  layout.dynamicLayout.urn
  layout.dynamicLayout.itemPage
  layout.dynamicLayout.metadataBox
  layout.dynamicLayout.collectionsBox

After:
  layout.urn
  layout.itemPage
  layout.metadataBox
  layout.collectionsBox

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…xt menu was, add min width for dynamic thumbnail component
@FrancescoMolinaro FrancescoMolinaro added the DSpace-CRIS merger This ticket/PR relates to the merger of DSpace-CRIS into DSpace. label Jul 16, 2026
@FrancescoMolinaro FrancescoMolinaro added this to the 11.0 milestone Jul 16, 2026
@lgeggleston lgeggleston moved this to 🙋 Needs Reviewers Assigned in DSpace 11.0 Release Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DSpace-CRIS merger This ticket/PR relates to the merger of DSpace-CRIS into DSpace. new feature

Projects

Status: 🙋 Needs Reviewers Assigned

Development

Successfully merging this pull request may close these issues.

3 participants