Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flyout and Footer API design document #8052

Merged
merged 4 commits into from
Jun 21, 2023
Merged

Conversation

davidfischer
Copy link
Contributor

@davidfischer davidfischer commented Mar 25, 2021

This is a design document for using APIv3 in order to generate the flyout (version selector) menu. This is purely a proposal at this point to get everyone on the same page with respect to goals and how it could be implemented.

The main goals are to:

  • Give themes and projects a way to control the flyout menu. More than just CSS styling, they could take the raw data and put it into the navigation or other menus. For example, this would allow building Django's version selector menu instead of using RTD's default. A custom Sphinx or MkDocs theme could take on this work or a project could override it themselves.
  • Use the new APIv3 endpoint instead of an undocumented APIv2 endpoint that we're trying to deprecate.
  • Provide a baseline for overriding various other aspects of how Read the Docs customizes documentation.

For easier reading, there's a link to the document.

Closes #7748

@davidfischer davidfischer requested a review from a team March 25, 2021 20:19
.. code-block:: javascript

window.readthedocs = window.readthedocs || {};
window.readthedocs.customizations = {disable_custom_search: true, disable_version_selector: true};
Copy link
Member

Choose a reason for hiding this comment

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

we already do this, but we haven't document them. I like more the name you are proposing here p:

READTHEDOCS_DATA.features.docsearch_disabled

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I know we do this. I like the idea a lot but I wish it was easier for users to control as well as documented. The way it is now can run into race conditions with us defining these features and users setting them.

.. code-block:: javascript

window.readthedocs = window.readthedocs || {};
window.readthedocs.integration_version_selector = function () {};
Copy link
Member

Choose a reason for hiding this comment

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

I'd name this custom_version_selector maybe? Wasn't obvious for me that this was a custom function to inject the footer.

Copy link
Member

Choose a reason for hiding this comment

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

I'd also call it something other than version_selector since it does a lot more than that.



Overlap with existing API endpoints
-----------------------------------
Copy link
Member

Choose a reason for hiding this comment

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

Just a note here that we are using the proxied endpoint of the footer, this /_/api/v2/footer_html, this allow us to share the same domain with some advantages:

  • avoid being blocked by some extensions
  • Allow to cache the response (docs are served from cloudflare)
  • Allow to use the auth backends in .com

And, I've been having some ideas around our APIs... here is an extract from #8039

We should probably make a distinction between our general API that handles Read the Docs resources,
vs our APIs that expose features (like server side search, footer, and embed, all of them proxied).
This way we can version each endpoint separately.

I do agree that the footer shares a lot with the projects/ endpoint. Proxying api v3 may be a little of a problem, because it relies heavily on resolving URLs from the dashboard, but in proxito we don't have the url patterns from the main 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.

This is a very good point. Maybe we don't need all the APIv3 endpoints but we can have an endpoint that just returns the same data as the APIv3 endpoint and shares code.

Copy link
Member

@humitos humitos left a comment

Choose a reason for hiding this comment

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

The proposal looks good to me. I don't have too many comments on the JS implementation side, but seems it will work to me.

I'm not convinced that it's a good idea to share the APIv3 endpoint for the flyout to a regular endpoint. I think having independence and granular control here is better.

docs/development/design/flyout-redesign.rst Outdated Show resolved Hide resolved
Comment on lines +57 to +58
Currently, there are separate API endpoints for translations and downloads,
but ideally all the data needed to generate a version selector would be available from a single API.
Copy link
Member

Choose a reason for hiding this comment

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

It seems that we could implement ?expand=translations,subrpojects and we would have everything we need with one API call: https://readthedocs.org/api/v3/projects/docs/?expand=active_versions,translations,subprojects

One downside that has using this endpoint is that we will be returning much data than we need and that could slow down the response time.

Another thing to consider is that APIv3 is authenticated-only, and we require anonymous access for the flyout.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sold on the idea of sharing the endpoint for the flyout than a regular endpoint. In the future we may want to add extra data to /api/v3/projects/ and we may be blocked because it increases the response time by some milliseconds that are not acceptable for the flyout endpoint.

I think that having an independent endpoint with more control over it is a win here and will avoid headaches in the future.

Copy link
Member

Choose a reason for hiding this comment

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

Agreed here. I think we want a dedicated API just for this use, but it could share code for sure. The footer API is large enough of a use-case to make it special.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also agree here, one flyout API seems like the best method. We don't yet have a good pattern for injecting an API access token into the build process, and this would be needed for all of the authenticated API endpoints.

Co-authored-by: Manuel Kaufmann <humitos@gmail.com>
Copy link
Member

@ericholscher ericholscher left a comment

Choose a reason for hiding this comment

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

This is a good start. I think we probably need to clarify our names a good bit here, but I like the general approach here. I don't know enough about JS to really judge alternative implementations though. I know our ad client works in a much more complicated way, but I'm not sure if that's because it's used on more sites, or why that design was chosen.

In particular, I think we need to clarify and standardize on names for:

  • What this API is called. footer isn't really correct. I think probably it's flyout_data or something like that? dynamicproject_data`?
  • What the flyout is called? I think we generally standardized on flyout but this doc uses version_selector. Should we remove flyout for the various composite parts?

I'm sure there's more named needed, but those were the two obvious ones. Names are hard.

.. code-block:: javascript

window.readthedocs = window.readthedocs || {};
window.readthedocs.integration_version_selector = function () {};
Copy link
Member

Choose a reason for hiding this comment

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

I'd also call it something other than version_selector since it does a lot more than that.

Comment on lines +57 to +58
Currently, there are separate API endpoints for translations and downloads,
but ideally all the data needed to generate a version selector would be available from a single API.
Copy link
Member

Choose a reason for hiding this comment

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

Agreed here. I think we want a dedicated API just for this use, but it could share code for sure. The footer API is large enough of a use-case to make it special.

Copy link
Contributor

@agjohnson agjohnson left a comment

Choose a reason for hiding this comment

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

I'm still considering the effects of using global state to configure the client. Generally, having a fully instantiated object is a more expected pattern and an easier pattern to work with if the user wants to extend functionality instead of replace it.


// This first line helps handle the case where the project/theme's overrides
// are executed before the readthedocs global is defined.
window.readthedocs = window.readthedocs || {};
Copy link
Contributor

Choose a reason for hiding this comment

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

One seemingly common use case that is not supported by this current proposal is extending the flyout display function/method. If a theme wants the flyout, but also wants to inject a version selector somewhere else in the UI, there is no way to extend this functionality, only override it.

That is, the user is expected to define a window.readthedocs.integration_version_selector to customize the display process, but there is no way to call the parent window.readthedocs.integration_version_selector function -- it isn't defined until after it is inspected by our client.

This could either be a reason to use a different pattern than defining overrides as global state, or we would need to require more granular override points for users.

Comment on lines +57 to +58
Currently, there are separate API endpoints for translations and downloads,
but ideally all the data needed to generate a version selector would be available from a single API.
Copy link
Contributor

Choose a reason for hiding this comment

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

Also agree here, one flyout API seems like the best method. We don't yet have a good pattern for injecting an API access token into the build process, and this would be needed for all of the authenticated API endpoints.

* This proposal doesn't involve creating an integration point to control custom search.
That could happen at a later date.
* This proposal doesn't rework how the version selector looks either on the RTD Sphinx theme
or on other themes by default. Any restyling can be done independently of this.
Copy link
Contributor

Choose a reason for hiding this comment

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

Also, for this proposal to work for commercial users that are currently manipulating the flyout via CSS rules, we have to output the exact same DOM structure that we would normally return with the HTML blob. This is a little unfortunate, as the DOM structure could already stand to be designed better. We can adapt this later, but this might also hint at some support for multiple versions of DOM output.

@stale
Copy link

stale bot commented Jun 2, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@humitos
Copy link
Member

humitos commented Jun 13, 2023

Things have changed considerably here with the introduction of the addons in https://github.com/readthedocs/readthedocs-client. I think it's safe to close this PR or, if we want, merge and close so we don't loose the document. Maybe adding a note in the top of it linking to the addons repository?

@agjohnson
Copy link
Contributor

Maybe we just keep this available for reference on this branch? Merging this could be confusing for anyone that comes across this first, as we deviated from this plan a bit. I agree adding a note would help either way though 👍

@humitos humitos requested a review from a team as a code owner June 21, 2023 13:49
@humitos humitos requested a review from benjaoming June 21, 2023 13:49
@humitos
Copy link
Member

humitos commented Jun 21, 2023

I updated the warning note and I will merge it after that.

@humitos humitos enabled auto-merge (squash) June 21, 2023 13:50
Copy link
Member

@humitos humitos left a comment

Choose a reason for hiding this comment

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

I'm approving this PR so it gets merged automatically after the check pass. Note that this work is not implemented and most of it was replaced by https://github.com/readthedocs/readthedocs-client and its new endpoint (/_/readthedocs-config/)

@humitos humitos merged commit 463e106 into main Jun 21, 2023
@humitos humitos deleted the davidfischer/flyout-design-doc branch June 21, 2023 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Accepted Accepted issue on our roadmap
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Make our documentation page APIs more user friendly
5 participants