Skip to content

Conversation

shashankbrgowda
Copy link
Contributor

@shashankbrgowda shashankbrgowda commented Sep 10, 2025

This PR introduces an intermediate redirect page for Resolver and Rapid Resolver stable ID redirects.

Details

  • Added rapid stable Id /rapid/id/{stable_id} redirect endpoint similar to existing resolver stable id redirect endpoint
  • Opens an Intermediate page for rapid stable Id redirect
  • For resolver stable Id redirect endpoint, If there are multiple results from metadata API then return an Intermediate page

@shashankbrgowda shashankbrgowda changed the title resolver id and rapid id page Resolver and Rapid resolver stable id redirect Intermediate page Sep 10, 2025
@shashankbrgowda shashankbrgowda changed the title Resolver and Rapid resolver stable id redirect Intermediate page Resolver and Rapid resolver stable Id redirect Intermediate page Sep 10, 2025
@shashankbrgowda shashankbrgowda marked this pull request as ready for review September 11, 2025 08:10
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="/static/css/rapid_page.css">
Copy link

Choose a reason for hiding this comment

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

Is this a template page for non-rapid urls? Why does it have the rapid css link?

@@ -0,0 +1,23 @@
<!doctype html>
Copy link

@azangru azangru Sep 11, 2025

Choose a reason for hiding this comment

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

These two html pages have very similar heads. Would it make sense to extract the common parts into reusable partials?

{% elif item.type %}
{{ item.type.kind }} - {{ item.type.value }},
{% endif %}
</span>
Copy link

Choose a reason for hiding this comment

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

http://0.0.0.0:8001/rapid/id/LOC122384268

Image

We probably don't want this empty space if there's no content for this block.

@azangru
Copy link

azangru commented Sep 11, 2025

Another thing that I always end up complaining about is that I don't understand how the pages are supposed to work on different screen sizes. Sure; we don't expect most users to have small screens (although you don't need to have a small screen to have a small viewport); but what is the page supposed to do if that happens? Is it supposed to look this way?

responsive.mp4

P.S.: consider that on small screens, the tooltip will be in danger of doing this (yet another reason I am against this idea):

image

@@ -0,0 +1,35 @@
from typing import List
Copy link

@azangru azangru Sep 11, 2025

Choose a reason for hiding this comment

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

In a comment to a PR in amr-portal, @veidenberg was saying that list no longer needs to be imported from typing.

</div>
</div>

<script>
Copy link

Choose a reason for hiding this comment

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

I wonder: if css is served as a separate file, would it be worth moving js into its own file as well?

data-entity-viewer-url="{{ item.entity_viewer_url }}">
<span class="id-detail">{{ item.common_name }},</span>
<span class="id-detail id-detail-margin-left id-detail-italic">{{ item.scientific_name }},</span>
<span class="id-detail id-detail-margin-left id-detail-italic">
Copy link

Choose a reason for hiding this comment

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

Type isn't italic in the design (see XD). Same as on the beta site.

{% endif %}
</span>
<span class="id-detail id-detail-margin-left">{{ item.assembly.name }},</span>
<span class="id-detail id-detail-margin-left id-detail-tooltip">{{ item.assembly.accession_id }}</span>
Copy link

Choose a reason for hiding this comment

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

There is something going on with font sizes in the design. I can't tell what exactly, but something definitely is up.


.tooltip-content {
background: #fff;
border: 1px solid #ccc;
Copy link

Choose a reason for hiding this comment

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

Why? Is there a reason for this in the design?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed

padding: 12px;
border-radius: 1px;
position: relative;
background-color: #1b2c39;
Copy link

Choose a reason for hiding this comment

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

You may want to move this into a css custom property (on beta site, it is --color-black)

.id-detail {
font-size: 12px;
cursor: pointer;
color: var(--color-light-blue);
Copy link

Choose a reason for hiding this comment

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

Where did you get the value for this colour from? Isn't Andrea reusing the colour palette from the beta site?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

margin-top: 15px;
}

.id-detail {
Copy link

Choose a reason for hiding this comment

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

I would rename those id-detail classes. The elements on the page that have this class do not represent details of some id. They represent species, or genomes, or search matches, but not ids.

}

.id-detail {
font-size: 12px;
Copy link

Choose a reason for hiding this comment

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

Are you sure about the font size here? Compare with beta.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Checked. Its either 12px, 13px or 16px..


.id-detail {
font-size: 12px;
cursor: pointer;
Copy link

Choose a reason for hiding this comment

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

You wouldn't need this if the element were a link.

<script>
document.querySelectorAll('.id-detail-container').forEach(function(el) {
el.addEventListener('click', function(e) {
e.stopPropagation();
Copy link

Choose a reason for hiding this comment

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

why?


if (!e.target.classList.contains('id-detail')) return;

var tooltip = document.getElementById('tooltip');
Copy link

Choose a reason for hiding this comment

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

The front-end world today has largely rejected vars. The overall consensus is to use either let or const


window.addEventListener('resize', function() {
var tooltip = document.getElementById('tooltip');
if (tooltip) {
Copy link

Choose a reason for hiding this comment

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

why are you making this check in this function, but not in the first one?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated in all places

@@ -1,6 +1,6 @@
from enum import Enum
from typing import Optional, Literal, List, Dict, Annotated
Copy link

@veidenberg veidenberg Sep 12, 2025

Choose a reason for hiding this comment

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

No need to import Optional, List, Dict (builtin types) and Annotated (not used in code)

assembly: Assembly
scientific_name: str
common_name: str
assembly: Optional[Assembly] = None
Copy link

@veidenberg veidenberg Sep 12, 2025

Choose a reason for hiding this comment

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

assembly: Assembly | None = None recommended, same for all Optionals below

Copy link

Choose a reason for hiding this comment

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

Nice; python is looking more similar to typescript 🙂

message: Optional[str] = None
rapid_archive_url: Optional[str] = None

class Config:
Copy link

@veidenberg veidenberg Sep 12, 2025

Choose a reason for hiding this comment

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

Config class is deprecated, use ConfigDict instance instead (seems you even added ConfigDict import but stopped there :)

Suggested change
class Config:
model_config = ConfigDict(use_enum_values = True)

code: Optional[int] = None
message: Optional[str] = None
rapid_archive_url: Optional[str] = None
content: Optional[List[StableIdResolverContent]] = []
Copy link

@veidenberg veidenberg Sep 12, 2025

Choose a reason for hiding this comment

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

mutable default value (list) is not recommended as it can share state across the response instances. Use pydantic default_factory, or better yet, None (since it's a valid value here):

Suggested change
content: Optional[List[StableIdResolverContent]] = []
content: list[StableIdResolverContent] | None = None

content=None,
rapid_archive_url=rapid_archive_url
)
return HTMLResponse(generate_rapid_id_page(res))
Copy link

@veidenberg veidenberg Sep 12, 2025

Choose a reason for hiding this comment

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

did you mean to pass a model or dict to generate_rapid_id_page()? For dict use res.model_dump() (like you do on line 58 below).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not important for html response.. Changed to return object

For Json response its important to ignore certain fields

Copy link

@veidenberg veidenberg left a comment

Choose a reason for hiding this comment

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

Added few minor comments

@shashankbrgowda
Copy link
Contributor Author

Thanks @veidenberg @azangru

Updated the PR as per your suggestions

Copy link

@veidenberg veidenberg left a comment

Choose a reason for hiding this comment

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

Looks good to me (even with some Optionals still left behind:)

<div class="genome-detail-container"
data-genome-browser-url="{{ item.genome_browser_url }}"
data-entity-viewer-url="{{ item.entity_viewer_url }}">
<a href="{{ item.entity_viewer_url }}" class="genome-detail genome-detail-tooltip" aria-label="Show tooltip">
Copy link

Choose a reason for hiding this comment

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

Why this aria-label? Aria-label is something that the screen reader will speak out loud. Normally, for links, the screen reader would just speak the content of the link. Surely this is more useful than if it says "Show tooltip".

<div class="topbar">
<div class="topbar-left">
<div class="home-link">
<a href="https://beta.ensembl.org/">
Copy link

Choose a reason for hiding this comment

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

Now this link is where aria-label is appropriate, because it doesn't have any text content. Could you add aria-label="Ensembl home page" to it?

<div id="tooltip" style="display:none; position:absolute;" role="tooltip" aria-hidden="true">
<div class="tooltip-content">
<span class="tooltip-content-title">View in</span>
<a id="genome-browser-link" href="#" aria-label="Genome Browser link">
Copy link

@azangru azangru Sep 15, 2025

Choose a reason for hiding this comment

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

You do not need the word "link" in the aria-label. The screen reader already announces that this is a link.

Perhaps, to make the label slightly more descriptive, it could say "View in Genome Browser".

(Same for entity viewer)

--standard-gutter: 30px;
--global-padding-left: calc(var(--standard-gutter) * 4);
--color-light-blue: #33adff;
--color-light-blue: #0099ff;
Copy link

Choose a reason for hiding this comment

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

Could you please rename --color-light-blue to --color-blue, to keep consistency with colour names in beta?

.id-redirect-content {
margin-top: 30px;
text-align: center;
width: 100%;
Copy link

Choose a reason for hiding this comment

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

Why is this CSS rule needed?

const tooltip = document.getElementById('tooltip');
if (tooltip) {
tooltip.style.display = 'none';
tooltip.setAttribute('aria-hidden', 'true');
Copy link

Choose a reason for hiding this comment

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

Doesn't display: none already hide the tooltip from assistive technology?

const entityViewerLink = document.getElementById('entity-viewer-link');

if (genomeBrowserLink) {
genomeBrowserLink.href = el.dataset.genomeBrowserUrl || '#';
Copy link

Choose a reason for hiding this comment

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

Does || # imply that the genomeBrowserUrl may not exist? If yes, then why show the link element at all?

tooltip.setAttribute('aria-hidden', 'false');
const rect = target.getBoundingClientRect();
tooltip.style.top = (rect.top - 15 + window.scrollY) + 'px';
tooltip.style.left = (rect.right + 10 + window.scrollX) + 'px';
Copy link

Choose a reason for hiding this comment

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

Could you add an automatic focus on the first link? Something like:

const firstLink = tooltip.querySelector('a');
firstLink.focus();

@shashankbrgowda shashankbrgowda merged commit 9f9af9a into main Sep 15, 2025
1 check passed
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