Skip to content

Conversation

@GBirkel
Copy link
Contributor

@GBirkel GBirkel commented Sep 9, 2025

This is a cleaned-up version of an earlier draft PR ( #2097 ).

Description

Add a field for generating dataset links based on admin-configured templates.

See #689 for details.

This has a companion PR for the front-end, which is still in draft form: SciCatProject/frontend#1910

Motivation

We get a lot of requests from users and researchers to provide a variety of different types of web-based tools that related directly to datasets. These can be pages that display visualization, pages that provide analysis tools (including AI/ML) and jupyter notebooks on particular JupyterHub instance. In all cases, we would want to take the user to the page with the dataset in context.

Changes:

  • New API endpoint: Datasets/[pid]/externallinks

This returns an array of objects, { url: string, title: string, description: string }. See ExternalLinkClass in the code for more detail.

  • New configuration entry, parsed from file datasetExternalLinkTemplates.json with an example template file.

Example of the content of this file:

[
  {
    "title": "Franzviewer II",
    "url_template": "https://franz.site.com/franzviewer?id=${dataset.pid}",
    "description_template": "View ${dataset.numberOfFiles} files in Franz' own personal viewer",
    "filter": "(dataset.type == 'derived') && dataset.owner.includes('Franz')"
  },
  {
    "title": "High Beam-Energy View",
    "url_template": "https://beamviewer.beamline.net/highenergy?id=${dataset.pid}",
    "description_template": "The high-energy beamviewer (value ${dataset.scientificMetadata?.beamEnergy?.value}) at beamCo",
    "filter": "(dataset.scientificMetadata?.beamEnergy?.value > 20)"
  }
]

The filter field is JavaScript, parsed into a function at run time, which is called with a dataset argument containing a full dataset record. If the function returns true, the given link applies to the given dataset.

The url_template and description_template fields are JavaScript-style format strings, which are passed the same dataset argument. The strings they emit go into the url and description objects returned by the API.

where: { datasetId: outputDataset.pid },
});
break;
if (includeFilters) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you care to elaborate on this change a bit?

return await this.convertCurrentToObsoleteSchema(outputDatasetDto);
}

// GET /datasets/:id/externallinks
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add new endpoints to the old v3 controller?

throw new NotFoundException(`Dataset #${id} not found`);
}

interface ExternalLinkTemplateConfig {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be nice to have interfaces/types in separate file, but that it just my subjective view.

}

return templates
.filter((d) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps a more descriptive variable name here?

// so there is no equivalent schema representation for it.

export class ExternalLinkClass {
@ApiProperty({
Copy link
Member

@emigun emigun Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could consider having these api properties automatically generated as we for example did in the samples module (if I remember correctly)

let me know if you want more information

@emigun
Copy link
Member

emigun commented Sep 17, 2025

I think tests are missing?

@minottic minottic marked this pull request as draft November 3, 2025 13:51
@minottic
Copy link
Member

minottic commented Nov 3, 2025

@GBirkel I have converted this to draft, as it did not have commits for the past month. Feel free to move it back to "ready for review" once you feel so or if I shouldn't have moved to draft

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants