RapiDoc icon indicating copy to clipboard operation
RapiDoc copied to clipboard

Route prefix to support hash location

Open Aloren opened this issue 3 years ago • 7 comments

I have a single page containing multiple rapi doc elements:

                <rapi-doc
                        id="rapidoc-service-x"
                        update-route="true"
                        route-prefix="#tab-service-x/"
                        render-style="read"
                        ... other configs ommitted...
                ></rapi-doc>

I use hashlocation to show API documentation (activate specific rapidoc element) for a specific service.

The following url is created when specific operation is selected:

http://localhost:8080/#tab-service-x/post-/smth/-smth1-/smth2

And unfortunately this url does not scroll to the specific operation. I've looked into how the scrollTo method is used:

this.scrollTo(window.location.hash.substring(1));

and it's implementation:

async scrollTo(elementId, expandPath = true, scrollNavItemToView = true) {
... other code ommitted...
      const contentEl = this.shadowRoot.getElementById(elementId);
      if (contentEl) {
        isValidElementId = true;
        contentEl.scrollIntoView({ behavior: 'auto', block: 'start' });
      } else {
        isValidElementId = false;
      }

So according to the following code, rapidoc is not able to find the element due to tab-service-x/ in the hash. As I understand, route-prefix is not intended to be used as hash-location prefix now. But is it possible to support such behavior?

Aloren avatar Jan 21 '22 13:01 Aloren

for testing pick the build from dist folder

mrin9 avatar Jan 23 '22 10:01 mrin9

Wow, that was super fast :) Thanks a lot, I will check that on Monday 👍

Aloren avatar Jan 23 '22 21:01 Aloren

Hi @mrin9. I've checked and it looks like the following method also requires a change.

  async afterSpecParsedAndValidated(spec) {
  ....
    // On first time Spec load, try to navigate to location hash if provided
    const locationHash = window.location.hash?.substring(1);
    if (locationHash) {
      if (this.renderStyle === 'view') {
        this.expandAndGotoOperation(locationHash, true, true);
      } else {
        this.scrollTo(locationHash);
      }
  ....

Aloren avatar Jan 24 '22 11:01 Aloren

I've created a short demo that demonstrates that it looks like some more changes are needed:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta http-equiv="Content-Type" content="text/html"/>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/flatly/bootstrap.min.css" integrity="sha384-JJl14kOPjuUj+o0fDTJGBSCDKpu1A4BuCmARIetHUvTVmopvVZITFd4AhRMJIlz7" crossorigin="anonymous">

    <script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script>
    <script src="https://unpkg.com/[email protected]/dist/rapidoc-min.js" crossorigin="anonymous"></script>
</head>
<body>

<header>
    <nav class="navbar navbar-dark bg-dark">
        <div class="container-fluid">
            <form class="d-flex">
                <button
                        onclick="
                        document.getElementById('rapidoc-pets').setAttribute('spec-url', 'https://petstore.swagger.io/v2/swagger.json')"
                        type="button" class="btn btn-primary">Set spec url</button>
            </form>

        </div>
    </nav>
</header>

<main>

    <div class="row">

        <div class="list-group rounded-0 d-none" id="services-swagger-list" role="tablist">
            <a class="list-group-item list-group-item-action active"
               id="list-pets"
               href="#tab-pets"
               data-bs-toggle="list" role="tab">pets</a>
        </div>

        <div class="tab-content" id="nav-tabContent">
            <div class="tab-pane active show"
                 id="tab-pets"
                 role="tabpanel">

                <rapi-doc
                        id="rapidoc-pets"
                        route-prefix="#tab-pets/"
                        update-route="true"
                        render-style="read"

                        allow-authentication="false"
                        allow-server-selection="false"
                        show-header="false"
                        show-info="true"
                        allow-spec-file-load="false"
                        allow-spec-url-load="false"
                ></rapi-doc>

            </div>
        </div>
    </div>
</main>
</body>

</html>

Steps to reproduce:

  1. Open demo html page.
  2. Press Set spec url button. (We have lots of services, so we need to load specs only when requsted for specific service. This is how I emulated such behavior).
  3. Add hashlocation to the url #tab-pets/post-/user.
  4. Reload the page.

Actual result: Page is opened with first operation selected. Expected result: Create user API definition gets opened.

I've tried changing afterSpecParsedAndValidated method to fix the issue:

    const locationHash = window.location.hash?.substring(1);
    if (locationHash) {
      const regEx = new RegExp(`^${this.routePrefix}`, 'i');
      const elementId = window.location.hash.replace(regEx, '');
      if (this.renderStyle === 'view') {
        this.expandAndGotoOperation(elementId, true, true);
      } else {
        this.scrollTo(elementId);
      }

Although it looks to me like a fix, this does not work for a read render-style. This change works only for focused render-style. With read render style page scrolls to the required place and after that scrolls to the overview section.

Aloren avatar Jan 24 '22 16:01 Aloren

thanks for testing it out and proposing a solution, let me check it at my end how best it can be addressed. This is happening due to a race condition created my intersection observer and the code you suggested

mrin9 avatar Jan 25 '22 08:01 mrin9

Thanks. I've had an idea that this was some kind of race condition, because when I was debugging read render style -- everything worked as expected, without debugging -- it did not work. :D

Aloren avatar Jan 25 '22 12:01 Aloren

@Aloren I hope you are doing fine. Sorry for whats happening at Kyiv, Ukraine

mrin9 avatar Mar 27 '22 04:03 mrin9