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

Tags side menu with markdown and object description #681

Merged
merged 16 commits into from Jul 29, 2019
Merged

Tags side menu with markdown and object description #681

merged 16 commits into from Jul 29, 2019

Conversation

nanov
Copy link
Contributor

@nanov nanov commented Oct 19, 2018

Pretty quick workaround to be able to add additional side menu sections to tags, in the same manner it is done in the info description object.

Also an component was added which prints a referenced object/schema, and optionally a referenced example.

Combining both one may achieve similar structure to the one Stripe uses for their own documentation.

@coveralls
Copy link

coveralls commented Oct 19, 2018

Coverage Status

Coverage increased (+0.2%) to 82.761% when pulling 748dcc6 on eCollect:tags-side-menu-and-object-description into 2f65f05 on Rebilly:master.

@cmeeren
Copy link

cmeeren commented Nov 14, 2018

Brilliant! Would love for this to get merged. But could it make more sense to use e.g. x-object-description, which could be a supported key in a Tag object and other relevant places?

@nanov
Copy link
Contributor Author

nanov commented Nov 14, 2018

The object-description tag is a pseudo html tag, it is used inside markdown descriptions, similar to the way security-definitions tag is being used.

That is why it not prefixed with an x-.

Additionally, sub-menus are created out of markdown headings so you could create richer endpoint menus with additional info beside endpoints.

Frankly, I don't know if tags are rendered if there are no endpoints inside them, but that should be an easy fix.

I am open to suggestions proposals n how to make this more useful.

@cmeeren
Copy link

cmeeren commented Nov 14, 2018

Can you give an example of how the tag/object is rendered?

@nanov
Copy link
Contributor Author

nanov commented Nov 14, 2018

You could clone this branch and run the demo.

They render as the same way as responses, not unlike what stripe does. :)

@cmeeren
Copy link

cmeeren commented Nov 14, 2018

Sorry, I'm not proficient in JS development. I have node installed, but I have no idea how to run the demo. If it's just a matter of running a few commands, could you give me the commands to run?

@nanov
Copy link
Contributor Author

nanov commented Nov 14, 2018

Sure, here is a step-by-step guide :

# clone ( my fork ) repository
git clone https://github.com/eCollect/ReDoc
# change to repository directory
cd ReDoc
# switch to this feature branch
git checkout tags-side-menu-and-object-description
# in case you don't have it, install yarn globally
npm i -g yarn
# install project dependencies - might take a minute or so
yarn install
# run the demo - might take a minute or so
yarn run start

Then you open your browser at http://localhost:9090.

Under Pet and Store you could see submenus "The Pet Object" and "The Store Object", this is more or less it.

I know notice an annoying spacing issue on the menu side which should be fixed, but the idea is pretty much the same.

@cmeeren
Copy link

cmeeren commented Nov 14, 2018

I get an error on yarn install:

C:\GH\ReDoc>yarn install
yarn install v1.12.3
[1/5] Validating package.json...
[2/5] Resolving packages...
[3/5] Fetching packages...
error webpack@4.18.1: The engine "node" is incompatible with this module. Expected version ">=6.11.5". Got "6.10.0"
error Found incompatible module
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

@nanov
Copy link
Contributor Author

nanov commented Nov 14, 2018

Ah, Windows... :/

I guess you have an old node version. I am not sure about how one may update his node on windows ( just downloading binaries ? ), an update ( and reopening terminal ) should do it.

@RomanHotsiy
Copy link
Member

Sorry for not looking into this. Super busy recent days 🙀
Will get to this as soon as find some time.

@cmeeren
Copy link

cmeeren commented Nov 14, 2018

Other build problems occurred. Likely nothing that can't easily be fixed, but I'll pass on the demo from this PR as it's only to satisfy my curiosity.

I'm super looking forward to this being merged/implemented in some form or another; I can probably shave my yaml files in half since I currently have duplicated the schema definitions as manual markdown tables in the tag descriptions.

@nanov
Copy link
Contributor Author

nanov commented Nov 14, 2018

I've deployed an online demo.

@cmeeren
Copy link

cmeeren commented Nov 14, 2018

Wow, thanks! It looks very good. Does it also render the object description, if any?

@cmeeren
Copy link

cmeeren commented Nov 14, 2018

Also, what does it do regarding properties that are read-only and write-only? I suggest it should show both (since they're part of the object and it's rendered outside any request/response context), but that the members should be marked read-only or write-only.

@nanov
Copy link
Contributor Author

nanov commented Nov 14, 2018

To answer your both questions.

Does it also render the object description, if any?

As it is injected with markdown, you could write any description you wish ( actually rendering the root object description might be an idea, need to take a look ).

What does it do regarding properties that are read-only and write-only?

It renders the same thing, as if this schema is used in response, this means it is omitting write-only options ( a those are, normally, a prat of the request, not the model ).
One thing i wanted to add is to now show the required caption. It is not a problem to expose both options to the component so the user may decide what to render depending on his use-case.

@cmeeren
Copy link

cmeeren commented Nov 14, 2018

Thanks! I suggest allowing the user to render both read-only and write-only properties, if desired. I really need that in order to use this feature. As you say, normally that property would be part of a request and not a model, but there are exceptions, such as when following the JSON-API standard which is fairly strict about everything needing to be part of a resource. A good example of a write-only property is a password field on a user resource. It's conceptually part of the resource and should be listed as a property that can be used, but it will of course never be returned in responses.

(One could argue exactly how to represent password changes in an API and how the choice of JSON-API vs. another standard influences that; that is besides the point here. I'm just saying there are valid use-cases requiring write-only properties as part of the conceptual model, which should be shown in the model rendering. And for APIs already in production, the discussion would be a moot point anyway.)

Furthermore, I strongly suggest that read-only and write-only properties are marked in some way, e.g. in the same way as required. (For example, required, read-only could be shown beneath the name of a property marked with readOnly: true and required: true.)

@nanov
Copy link
Contributor Author

nanov commented Nov 14, 2018

So I have added showReadOnly and showWriteOnly options ( the default is to show readOnly and not to show writeOnly ).
I will add labels to those as soon as i find the time.

@cmeeren
Copy link

cmeeren commented Nov 14, 2018

Brilliant, thanks! Really looking forward to this 😊

@viralanomaly
Copy link
Contributor

The ability to print an object would be amazingly useful to me. Hopefully @RomanGotsiy can get to it soon!

@FlorianSW
Copy link

It would be useful to not only have a tag where I can specify one object to be rendered but also a tag (maybe "just" without schemaRef) which then renders all objects into the current section. That would allow one to have (just in the description block) an overview of all models and objects used in the API.

What do you think and do you think that this should be part of this PR or a separate one? :)

@nanov
Copy link
Contributor Author

nanov commented Nov 26, 2018

Technically it is not a problem to implement this, the question which exact "objects" ( ie. schemas ) should the tag render. As the "components/schemas" section contains all the schemas ( including ones that are only referenced by others but not used directly, or even unused ones ), the list of the schemas is really specific. Additionally you may want those schemas in a certain order, which again needs to be setup somehow.

I think it is a lot easier, and makes more sense, to get this generated programmatically on side that generates the specification, or be done manually.

@cmeeren
Copy link

cmeeren commented Dec 3, 2018

Aside from the assumedly trivial yarn.lock conflict, are there any outstanding issues here, or can it be merged? There's a lot of people eagerly awaiting this (#134)! 😁

@cmeeren
Copy link

cmeeren commented Jan 7, 2019

@RomanGotsiy Is this waiting for anything in particular?

@Jarema
Copy link

Jarema commented Jan 14, 2019

@RomanGotsiy any change of merging this soon?
Lot of people waits for it, me including :). Actually, I need it so much I'm considering using fork.

@RomanHotsiy
Copy link
Member

@Jarema @cmeeren @nanov

Sorry for the delay. I am a bit busy right now and this PR needs careful reviewing.
I will get to this ASAP (hopefully till the end of Jan).

Thanks for pinging me here! If I don't review it till the end of Jan ping me again, please 🤜

@tomq42
Copy link

tomq42 commented Feb 1, 2019

+1 for this. It gives exactly the result I'm after.

Just a thought. Any reason why doing it this way round, rather than putting a custom extension on the schema of the form x-schema-tags or whatever that then causes it to be rendered like an operation would?

I need the result that this gives me though, so I'll use a fork with this in it for now.

@nanov
Copy link
Contributor Author

nanov commented Feb 1, 2019

@tomq42 Could you explain you idea more in detail, as I am not really sure I get it.

My idea was to leave it as free as possible in order to give the user ( ie. schema owner ) the freedom to structure his documentation as needed.

@tomq42
Copy link

tomq42 commented Feb 1, 2019

@nanov What I had looked for when I didn't realise I could do this to start with, was the ability to just put a tag on a schema. So the normal "operations" part of the output is built by listing the paths and method to get the operations, and then matching the "tag" values on each of those with the tags definition list (don't know which way round it goes, but my guess is it lists through /tags, then for each one lists through /paths and the contained operations and renders any that have a matching tag in their tags array).

What I naively tried was to do exactly the same, but put a tag on a schema in /components/schemas. However, the OpenAPI spec doesn't allow tag on a schema, but does allow extensions, so you could use a custom extension "x-schema-tag" or whatever. This seems to most closely follow the way that the operations are rendered.

My guess is that within each tag section it would render operations first, then render schemas. It would just list through /components/schemas in the same way it lists through /paths, and render the schemas that are tagged with the current tag in the same way it renders the operations tagged with the current tag. I can then choose to create a tag for just schemas, or I can mix then with the relevant operations.

@cmeeren
Copy link

cmeeren commented Feb 1, 2019

I am more in favor of the existing approach in this PR, which allows placing a tag exactly where one wants it in any description (e.g. in a tag description).

@nanov
Copy link
Contributor Author

nanov commented Jul 29, 2019

@RomanHotsiy let me know if you need any assistance ;)

@RomanHotsiy
Copy link
Member

RomanHotsiy commented Jul 29, 2019

@nanov I am thinking about renaming the component. ObjectDescription is not precise. I can confuse it with markdown description. Also, word Object is not how everyone calls schemas. What do you think about the following ideas:

  • ModelDetails
  • just Model
  • SchemaInfo
  • SchemaDetails
  • SchemaDefinition
  • SchemaView
  • SchemaExplorer
  • SchemaObject
  • just Schema

?

Personally, I prefer SchemaDefinition or just Schema

@nanov
Copy link
Contributor Author

nanov commented Jul 29, 2019

In my opinion it should definitely be something with Schema.

I would say Schema is too generic ( in case we'll want to add something else in the future ), so I'll stick to SchemaDefinition.

@RomanHotsiy RomanHotsiy merged commit ac41f0b into Redocly:master Jul 29, 2019
@RomanHotsiy
Copy link
Member

RomanHotsiy commented Jul 29, 2019

Great job @nanov! Sorry for so huuuge delay! It will be released later this week.

@cmeeren
Copy link

cmeeren commented Jul 30, 2019

Fantastic, can't wait! Will you add a note to the readme also on how it can be used?

@RomanHotsiy
Copy link
Member

Accidentally released it with wrong component name in rc.11 🙈

Fixed it in rc.12.

I will add docs later. Although, PR with README docs would be appreciated 🙏

@cmeeren
Copy link

cmeeren commented Jul 30, 2019

@nanov Could you just briefly describe basic usage?

@nanov
Copy link
Contributor Author

nanov commented Jul 31, 2019

Sure!

We could basically split it into two parts.

Adding submenus inside tag descriptions

One could build richer menus by adding (markdown) headings into tag descriptions. Basically it's the same functionality as in the main info.description property only that those menu sections will be available as submenus of the main tag menu section.

Example usage:

  - name: store_model
    x-displayName: The Order Object
    description: |
      The order objects contains all the needed information about your orders
      ## Late Orders
      Late orders are marked with a dedicated flag

Injecting Schema Definitions

The ability to inject desired schema (model/object) definitions into tag descriptions trough a dedicated SchemaDefinition tag.

The tag accepts the following properties :

name required type description example
schemaRef * string (json-pointer) a pointer to the desired schema #/components/schemas/Pet
exampleRef string / (json-pointer) optional pointer to a desired example #/components/examples/Order
showReadOnly boolean weather to show read-only properties ( defaults to true ) {false}
showWriteOnly boolean weather to show write-only properties ( defaults to false ) {true}

Example usage:

minimal:

<SchemaDefinition schemaRef="#/components/schemas/Pet" />

full

<SchemaDefinition schemaRef="#/components/schemas/Order" exampleRef="#/components/examples/Order" showReadOnly={true} showWriteOnly={true} />

@cmeeren
Copy link

cmeeren commented Jul 31, 2019

Thanks, it's working great! Would it be possible to add an option for auto-expanding child objects to some desired level? Even just one level would work great for e.g. JSON-API resources, since then the attribute, relationship, and link names would be visible and searchable by Ctrl-F (I know our API client devs use Ctrl-F to find stuff in the docs, which won't work if it's not expanded).

@nanov
Copy link
Contributor Author

nanov commented Jul 31, 2019

I am afraid this is out of the scope of this ( already merged ) PR, but I think you'll find a solution here.

@wyau7
Copy link

wyau7 commented Aug 12, 2019

@RomanHotsiy , @nanov - I'm not sure if this is addressed anywhere, but schemas with an external reference in allOf are not displaying (they show up blank). Can you let me know who I need to talk to on this? Thanks!

@nanov
Copy link
Contributor Author

nanov commented Aug 12, 2019

@wyau7 could you post your schema, or in ideally a repro.

@wyau7
Copy link

wyau7 commented Aug 12, 2019

@nanov - here's an example schema (located in a file called producer.yaml). I couldn't get the format to work in the comment, but the formatting is correct in the file. :)

Producer:
allOf:
- $ref: 'admin.yaml#/components/schemas/Admin'
- properties:
title:
type: string

@nanov
Copy link
Contributor Author

nanov commented Aug 12, 2019

could you share your full schema?

** EDIT **
and please use yaml formatting if posting here, as this is vital for this format...

@wyau7
Copy link

wyau7 commented Aug 13, 2019

(producer.yaml)
Producer:
      allOf:
        - $ref: 'admin.yaml#/components/schemas/Admin'
        - properties:
            title:
              type: string

(admin.yaml)
Admin:
      required: [type,name,emailAddress]
      properties:
        id:
          type: integer
          readOnly: true
        type:
          description: readOnly after initial creation of Admin (AccountAdmin or Producer) resource
          type: string
          enum: [ACCOUNT,PRODUCER]
        name:
          $ref: 'shared.yaml#/components/schemas/Name'
        emailAddress:
          type: string

(shared.yaml)
Name:
      required:
        - firstName
        - lastName
      properties:
        firstName:
          type: string
        middleName:
          type: string
        lastName:
          type: string

@wyau7
Copy link

wyau7 commented Aug 13, 2019

@nanov - let me know if you need more information - thanks!

@HughKu
Copy link

HughKu commented Jun 21, 2020

Thanks. Is there any way of doing this by inputting JSON instead of YAML?

@Blacklands
Copy link

Blacklands commented Jun 28, 2020

I noticed that the description of the schema object itself (the description at the root level of the schema) is not rendered when using the <SchemaDefinition [...] /> tag.

Would it be possible to add this? If I (as a user) am looking at the existing schemas in the API, I would also want to see the descriptions for them.

Right now, as a workaround, I am copy-pasting the description in question next to the <SchemaDefinition [...] /> tag - but this is additional work and also error-prone.

Maybe another option for the tag could be added for this? Something like <SchemaDefinition [...] showRootDesc={true}|{false} />.

EDIT:
While reading through all the comments on this pull request again, I noticed that this was already mentioned once. Are there any plans to follow up on that, or was it dropped?

@RomanHotsiy
Copy link
Member

@Blacklands this is tracked in #720

@Blacklands
Copy link

@RomanHotsiy Apologies, I completely missed this issue. I even checked for other issues about this but I managed to overlook this one. Thank you!

@damianobarbati
Copy link

What is the current intended way to display models in generated docs without using React component?

@osamaramihafez
Copy link

osamaramihafez commented Jul 22, 2021

Is there an example of how this can be used with a json schema? Really new to redoc, but I'd love to have this feature added to a project. (never mind I just took the petstore example yaml file and converted it to json. You can see how it's used that way).

@fsargent
Copy link

@osamaramihafez

Is there an example of how this can be used with a json schema? Really new to redoc, but I'd love to have this feature added to a project. (never mind I just took the petstore example yaml file and converted it to json. You can see how it's used that way).

I had the exact same issue, and I've cracked it. You need to escape the quotes with \.
So in top level tags:

	"name": "create-verification-request",
"x-displayName": "Verification Request Schema",
"description": "<SchemaDefinition schemaRef=\"#/components/schemas/create-verification-request\" />"
,```

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.

None yet