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

Add filter for operations and make filtering case insensitive #3876

Open
ocdevops opened this issue Nov 7, 2017 · 20 comments
Open

Add filter for operations and make filtering case insensitive #3876

ocdevops opened this issue Nov 7, 2017 · 20 comments

Comments

@ocdevops
Copy link

ocdevops commented Nov 7, 2017

Feature request: add filter for operations and make it case insensitive

@webron
Copy link
Contributor

webron commented Nov 7, 2017

Check out the filter parameter - https://github.com/swagger-api/swagger-ui#parameters.

@ocdevops
Copy link
Author

ocdevops commented Nov 7, 2017

It filters only in the tag name not in the name or the description of the operations, and filtering is case sensitive.

@ocdevops
Copy link
Author

Hi,
will you add these features to the UI in the future?

@webron
Copy link
Contributor

webron commented Nov 21, 2017

Can't say, but it's not a high priority.

@ocdevops
Copy link
Author

Ok, thanks for your response.

@Falx
Copy link

Falx commented Aug 13, 2018

A bit late, but for those who want at least case insensitive tag search. Just add this plugin:

const CaseInsensitiveFilterPlugin = function (system) {
    return {
        fn: {
            opsFilter: (taggedOps, phrase) => {
                return taggedOps.filter((tagObj, tag) => tag.toLowerCase().indexOf(phrase.toLowerCase()) !== -1);
            }
        }
    }
};

In your Swagger configuration object, add your new plugin, like so:

{
    ...,
    plugins: [
        CaseInsensitiveFilterPlugin
    ],
    ...
}

Now you've overwritten the default filter function, with a new case insensitive one.

@ben5Kuda
Copy link

ben5Kuda commented Sep 6, 2018

@Falx when i inject my own custom index page i do not see the search bar anymore even though i have EnableFilter() option. Is there a way to add the plugin by injecting it as JavaScript or what am i missing. I am using SwashBuckleCore

@Falx
Copy link

Falx commented Sep 7, 2018

Sorry, I don't really understand your problem. I just added the plugin following the Configuration docs at https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/#plugin-system

The only custom part is the plugin itself which only overwrites the standard used opsFilter with a new version that used .toLowerCase() to check equality.

It is in javascript..

@kranthi0099
Copy link

kranthi0099 commented Jan 21, 2019

@Falx
i've added ur plugin in index.html.
but cant perform the case insensitive search.

<script>
window.onload = function() {
  
  // Build a system
const CaseInsensitiveFilterPlugin = function (system) {
    return {
        fn: {
            opsFilter: (taggedOps, phrase) => {
                return taggedOps.filter((tagObj, tag) => tag.toLowerCase().indexOf(phrase.toLowerCase()) !== -1);
            }
        }
    }
};

  const ui = SwaggerUIBundle({
    url: "xxxxx.json",
    dom_id: '#swagger-ui',
    deepLinking: true,
    filter: true,
    presets: [
      SwaggerUIBundle.presets.apis,
      SwaggerUIStandalonePreset
    ],
    plugins: [
      SwaggerUIBundle.plugins.DownloadUrl,
     CaseInsensitiveFilterPlugin
    ],
    layout: "StandaloneLayout"
  })

  window.ui = ui
}
</script>

can u specify where i'm doing wrong....?

@Falx
Copy link

Falx commented Jan 21, 2019

Honestly, this looks right to me.. Only difference I can spot, is that I don't include the SwaggerUIStandalonePreset. That's it really..
I also don't use the layout: "StandaloneLayout", but I did customize the layout, so that's normal.

@kranthi0099
Copy link

@Falx
is the value passing to filter is true or it should be some string..??

@ben5Kuda
Copy link

@Falx Thanks it worked for me. Sorry forgot to mention.

@kranthi0099
Copy link

hi @ben5Kuda
can u say is there anything wrong in my above code...?
not able to do the case Insensitive filter

@Falx
Copy link

Falx commented Jan 22, 2019

is the value passing to filter is true or it should be some string..??

Just true, like you did, should be fine (that's what's in my code too).

@ben5Kuda
Copy link

@krekam I used your code as is, and could not replicate your issue. I was able to get the case insensitive filter to work. if it still isn't working my guess is you are using the default index.html page and not the custom one.

@shockey
Copy link
Contributor

shockey commented Jan 24, 2019

Chiming in here - if anyone would like to port @Falx's case-insensitive plugin into a pull request, we'd be happy to accept the change into the core project.

@hocklo
Copy link

hocklo commented Aug 7, 2019

Hi guys,

Maybe I reach late to the conversation but I'm thinking that the main problem is produced by swagger-ui. The swagger-ui are using the tags to group the operations, from my point of view this is not correct because tags are used to filter to. I'm thinking that the best approach can be generate a property to group the methods and maintain the tags for filtering. With this way we can tag every path with any information like operation name, some word, http method , whatever..

Regards,

@manoj-apare
Copy link

manoj-apare commented Jun 28, 2020

Hi,

I have figured out a way to filter operations based on path, summary (title) and description. Here is the code:

const AdvancedFilterPlugin = function (system) {
  return {
    fn: {
      opsFilter: function (taggedOps, phrase) {
        phrase = phrase.toLowerCase()
        var normalTaggedOps = JSON.parse(JSON.stringify(taggedOps));
        for (tagObj in normalTaggedOps) {
          var operations = normalTaggedOps[tagObj].operations;
          var i = operations.length;
          while (i--) {
            var operation = operations[i].operation;
            var parameters = "";
            var responses = "";
            var requestBody = "";
            if(typeof operation.parameters !== 'undefined'){
              parameters = JSON.stringify(operation.parameters).toLowerCase();
            }
            if(typeof operation.responses !== 'undefined'){
              responses = JSON.stringify(operation.responses).toLowerCase();
            }
            if(typeof operation.requestBody !== 'undefined'){
              requestBody=JSON.stringify(operation.requestBody).toLowerCase();
            }
            if ((operations[i].path.toLowerCase().indexOf(phrase) === -1)
              && (operation.summary.toLowerCase().indexOf(phrase) === -1)
              && (operation.description.toLowerCase().indexOf(phrase) === -1)
              && (parameters.indexOf(phrase) === -1)
              && (responses.indexOf(phrase) === -1)
              && (requestBody.indexOf(phrase) === -1)
            ) {
              operations.splice(i, 1);
            }
          }
          if (operations.length == 0 ) {
            delete normalTaggedOps[tagObj];
          }
          else {
            normalTaggedOps[tagObj].operations = operations;
          }
        }
        return system.Im.fromJS(normalTaggedOps);
      }
    }
  };
};

In your Swagger configuration object, add your new plugin, like so mentioned in #3876 (comment)

@MithrilMan
Copy link

@manoj-apare nice, you have just to add a check if operation.summary and operation.description aren't undefined
and maybe alter the textbox placeholder that says "Filter by tag"

@ConorDMurphy
Copy link

I ran into the issue that the tags were out of order when using system.Im.fromJS like @manoj-apare

Below is a variation on this that worked for me.

const AdvancedFilterPlugin = function (system) {
    return {
        fn: {
            opsFilter: function (taggedOps, phrase) {
                phrase = phrase.toLowerCase()
                //first filter out all actions that don't meet the search criteria
                var filteredActions = taggedOps.map((tagObj) => {
                    tagObj._root.entries[1][1] = tagObj._root.entries[1][1].filter((operationObj) => {
                        var op = JSON.parse(JSON.stringify(operationObj));
                        var summary = "";
                        var description = "";
                        if (typeof op.operation.summary !== 'undefined') {
                            summary = JSON.stringify(op.operation.summary).toLowerCase();
                        }
                        if (typeof op.operation.description !== 'undefined') {
                            description = JSON.stringify(op.operation.description).toLowerCase();
                        }
                        if ((op.path.toLowerCase().indexOf(phrase) === -1)
                            && (summary.indexOf(phrase) === -1)
                            && (description.indexOf(phrase) === -1)
                        ) {
                            return false;
                        } else {
                            return true;
                        }
                    });
                    return tagObj;
                });
                //then filter any Tags with no actions remaining
                return filteredActions.filter((tagObj) => {
                    return (tagObj._root.entries[1][1].size > 0);
                });
            }
        }
    };
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants