twskj / pretty-swag

Pretty UI for Swagger spec
MIT License
122 stars 20 forks source link

How to document parts of my single API parameter? #50

Closed Maaartinus closed 6 years ago

Maaartinus commented 6 years ago

This may be a feature-request or just a blindness on my side.

All my POST request have a single JSON argument in the POST body. For example, for updates, it's the desired new state of the entity like

{
    "id": 76682889,
    "email": "...@...",
    "firstname": "Mad",
    "surname": "Max",
    "zipcode": "12345"
}

This argument is obviously required, but it consists of required and optional parts, which itself should be documented. I can't see how to express it in the input JSON.

"User_UPDATE": {
  "type": "object",
  "required": ["id", "email"],    // This seems to work with swagger-codegen, but not with pretty-swag
  "properties": {
    "id": {
      "type": "integer",
      "format": "int32"
                                  // This fields has documentation, how can I express it?
    }
    ...
}
twskj commented 6 years ago

Hey thanks for reporting.

I want to keep the schema panel area clean and minimal so developer can easily and quickly copy and paste the payload. Also I don't have a good way to display if fields are required. In my opinion, adding * to key is somewhat confusing but I am open to suggestions.

We could add a short comment next to the field by adding description on that particular object.

If there is a need of thorough detail, I would suggest to put it on method level description which support markdown and more space.

Would this more or less suit your need?

"User_UPDATE": {
  "type": "object",
  "required": ["id", "email"],
  "properties": {
    "id": {
      "type": "integer",
      "format": "int32",
      "description": "required"
    }
    ...
}
Maaartinus commented 6 years ago

In my opinion, adding * to key is somewhat confusing but I am open to suggestions.

Adding * is pretty commonplace and very compact. I saw it in an alike application and it was in red and I'd be really happy with something like this.

A short description next to the field would suffice most of the time, but you could allow longer description showing in color and with expandable eclipses or a mouse-over hint. This would be perfect:

"email": "string", // email gets validated against RFC ...
twskj commented 6 years ago

Say if we choose to add * in our schema like so:

{
    "email*": "string",          // Put * before closing quotation this is the confusing part I referred to
                                // One could ask a question "Is this key has * in name or it need to be removed ?" 
    "name"*: "string"          // Put * after closing quotation
}

The step required developers to use this schema would be:

  1. Copy schema
  2. Paste it either to the payload panel below or their IDE
  3. Mass find/replace to remove *.

Step 3 is what I feel like an unnecessary step Your thought on this?

PS. I agree with you on the longer description just have to find time to work on that.

Maaartinus commented 6 years ago

What about

{
    "email": "string"*,          // Put * after closing quotation of the TYPE as this is a required string
}

Actually, the star could be inside the quotes, too, as there's no confusion about the name. Making it red should make clear that it's not part of the type.

Can't you use a trick so it doesn't get copied? Would CSS ::after selector help?

Otherwise, what about adding a copy link which would hide the problematic parts and mark the to be copied text, so copying wouldn't require marking the whole text manually?

I agree with you on the longer description just have to find time to work on that.

I'd contribute it, but I can't figure out how it all works. If you do anything in this area, I guess, I'll be able to finish it.

twskj commented 6 years ago

I like the idea of putting * after value in quotation I should be able to add that in.

The color and handle long desc implementation is a little tricky because currently folding functionality is implemented in text based and display result using <pre>.

If we were to convert this to html based, we need to look at getSchema function (in the generated html). It takes schema (json string) and bracket folding state and return appropriate string. If you have a look and have a working product I'm more than happy to merge 👍

twskj commented 6 years ago

I am still deciding how to handle if the field is an object or an array. None of what we have discussed seems to work well

"category": {*            
     "id": "integer",
     "name": "string"
}
"category": *{            
     "id": "integer",
     "name": "string"
}
"category": {           
     "id": "integer",
     "name": "string"
}*
"category": {           
     "id": "integer",
     "name": "string"
*}

Few points worth mention:

I'll be looking for a good approach and update here. Any suggestions are welcome.

Maaartinus commented 6 years ago

The color and handle long desc implementation is a little tricky because currently folding functionality is implemented in text based and display result using <pre>.

My problem is the tokens containing \n, which makes ::after show the star on the next line.

As a hack, I used ::before instead. This looks a bit strange, but with the star being red and non-copyable, there's no confusion. Moreover, it makes the information nicely aligned.

Few points worth mention: ...

You're right with all of them. I like "category": {* ...} most, as the trailing star is probably most clear and easiest to spot. For copy&paste, "category": {...}* would be best, but I still hope that using ::after will be possible.

What I tried, is not worth a PR; here you can see it all:

<style>.required::before{content:"*";color:red;}</style>

<td><p class="lpad5px"><pre><span v-for="token in getSchema(param.schema,param.schemaState)" v-bind:class="{pointer: isFoldable(token),required:token.required}" @click="schemaClicked(token,param.schemaState)">{{token.val}}</span></pre></p></td>

In getSchema, I'm missing the information about what's mandatory.

twskj commented 6 years ago

So I come up with a prove of concept like your suggestion here using ::after. And to my surprise, I just realized that * won't be copied when placing it in css ::after 🎉 I'll try to put together a solution for this and probably going to place * outside of the double quotation of required keys. Also since we are going to implement it html way I'll delegate the work to livedoc instead of getSchema

POC:

<html>
<style>
    .required::after {
        content: "*";
        width: 8px;
        height: 8px;
        color: red;
    }
</style>
<body>
    <pre>{
    "<span class="required">hello</span>": {
    <span class="required">    "key1"</span>: "val1",
        "key2": "val2"
    }
}</pre>
</body>
</html>
twskj commented 6 years ago

Turned out I like * in quotation more. What is your opinion?

image

Maaartinus commented 6 years ago

I don't care... putting it into the quotation may be problematic, as ::after possibly allocate no space for the star, so it may end up with the * and the closing " at the same place. I don't know.

For me, any place in the first line would do, even ::before.

Maaartinus commented 6 years ago

I did some changes in https://github.com/Maaartinus/livedoc, which were requested from me and which you may or mayn't like, but I have no idea how to pass the needed information around the stringly-typed schema.

I'd like to show both required as a star and some additional info for some fields. I saw, there are some comments, but I'm unsure how to do it.

Do you think you'll get to it anytime soon?

twskj commented 6 years ago

Should be able to work on this on the weekend. Very close to release. I just need to handle folding part.

twskj commented 6 years ago

Also thanks for those changes. I'll pull it in.

twskj commented 6 years ago

I rolled out in the latest (0.1.152) and will roll out another patch that incorporate your branch soon. Check it out and let me know.

Maaartinus commented 6 years ago

@twskj The required star works well and the highlighting is a nice bonus. :+1:

Somehow, I can't get the comments on fields working. I saw a screenshot somewhere showing that it works, but no matter where I put description in my JSON, nothing happens. Could you show me a small example JSON?

twskj commented 6 years ago

It actually just put text in description field of object type like so:

"properties": {
    "id": {
        "type": "integer",
        "format": "int64",
        "description": "This is going to be a comment"
    },
    "name": {
        "type": "string",
        "example": "doggie"
    }
}

The generated html should contains your comment in schema

 "schema": "{\n   \"id\": \"int64\",     /* This is going to be a comment */\n   \"category\": {\n      \"id\": \"int64\",\n      \"name\": \"string\"\n   },\n   \"name\": \"string\",\n   \"photoUrls\": [\n      \"string\"\n   ],\n   \"tags\": [\n      {\n         \"id\": \"int64\",\n         \"name\": \"string\"\n      }\n   ],\n   \"status\": \"string\"     /* pet status in the store */\n}"

If it doesn't show up, that's probably a bug :-)

Maaartinus commented 6 years ago

@twskj My bad, it works. I must have done something wrong as I tried it (twice!).