dsternlicht / RESTool

RESTool is an open source UI tool for managing RESTful APIs. It could save you time developing your own internal tools. A live example:
https://dsternlicht.github.io/RESTool/
MIT License
478 stars 120 forks source link

How to handle n to n and 1 to n relationships? #115

Open laudibert opened 4 years ago

laudibert commented 4 years ago

Hello,

I think a great but difficult feature to design here would be to handle a generic way to handle and display n to n and 1 to n relationships between resources.

It can already be done in a simple way if an API is handling that relationship by having a intermediate resources between the linked resources. For example a student and a classroom being linked through a subscription resource.

But this is not always the case. You often fin APIs dealing with those relationships via routes like /classrooms/:id/students and /students/:id/classrooms. The need would then be to have the possibility to go into a new page by clicking on a resource. In this example, on the page students, you would have the ability to navigate on the details of one student and there have displayed the content of the get one route /students/:id as well as its list of classrooms via /students/:id/classrooms.

What do you think about this ?

dsternlicht commented 4 years ago

@laudibert I totally agree that it's missing. At the moment, how I handle it is by adding a field dynamically that links to another page of the app (with a dynamic configuration).

Will it work for you as well?

laudibert commented 4 years ago

I'm not sure how it would work, would you care to elaborate or give an example ?

Does it mean that have a column with a link like http://localhost/calssrooms/101/students ? If so, how do you configure that target page ?

dsternlicht commented 4 years ago

If you use the dynamic configuration (config.js instead of config.json) you may use the dataTransform function in order to dynamically add a field. For instance:

dataTransform: (items) => {
    items.map((item) => {
         item.urlToClassroom = `#/classroom/${item.classroomId}`;
         return item;
    })
    return items;
}

Then, in the fields, simply add a new field with the name urlToClassroom.

Hope that helps!

laudibert commented 4 years ago

Ah ok, but then I'm guessing the url generated lead to a page that needs to be implemented "manually" rather than with RESTool right ?

Do you have any plan in the future to include a way to be able to configure the targeted pages like, in this example, #/classroom/${item.classroomId}?

dsternlicht commented 4 years ago

No, it could be another page in RESTool that handles classrooms. If you use the #, it will open up the page in RESTool.

laudibert commented 4 years ago

Ah ok I think I got you, but the configuration for the pages #/classroom/${item.classroomId} would have to be done for each classroomId then right ? That's what is missing at the moment no ? A way to configure pages that have a variable within their path right ?

dsternlicht commented 4 years ago

That’s right! This is why I added the dataTransform example that allows you to iterate on all items with their data.

laudibert commented 4 years ago

Ok ! Then an idea here on how to implement something that allows you not to have to configure pages for each id would be to add the possibility to configure pages with parameters within their id and making them hidden in the menu maybe ?

The configuration could look something like this:

{
  name: "Classroom students",
  id: "classrooms/:id/students",
  description: "Students of one specific classroom.",
  methods: {
    getAll: {
      label: "Get All",
      url: "/classrooms/:id/students",
      display: {
        type: "table",
        fields: [...]
      }
    },
  }
}

It would probably be very useful then to have some sort of way to generate the description and the name of the page dynamically by calling the root resource, /classroom/:id in this example.

What do you think ?

dsternlicht commented 4 years ago

Hmm I'm sorry, but how is it different from the current page configuration? 🤔

laudibert commented 4 years ago

Well then I am probably doing something wrong, but having something like .../:id/... in the id field does not work for me. If it's supposed to , would you mind providing an example ?

Another thing, that is not that important though, would be to provide an option like "hidden": true" to hide the reference of the page in the menu ?

dsternlicht commented 4 years ago

That's a nice idea too :)

As for the example:

dataTransform: (items) => {
    items.map((item) => {
         item.urlToClassroom = `#/classroom/${item.classroomId}`;
         return item;
    })
    return items;
}
laudibert commented 4 years ago

Sorry I was not clear on what I was missing to understand how to make this work. I did get your dataTransform example to have a link for each classroom page. My problem is about having a configuration that handles the router dynamically with :id.

{
  name: "Classroom students",
  id: "classrooms/:id/students", // This is what does not work for me
  description: "Students of one specific classroom.",
  methods: { ... }
}

The page generated by this page configuration does not work as when I click on its menu link, I end up on #/classrooms instead.

Also, when clicking on the link generated by the dataTransform column on the #/classrooms page, that will be something like #/classrooms/101/students on a row, the app redirects me automatically towards the #/classrooms page instead of #/classrooms/101/students.

I don't really understand what is happening there but it was my assumption that the RESTool just did not support pages configuration with dynamic parameters in their path.

See what I mean ? Is my conf just bugged ? Or is it in fact not supposed to work ?

dsternlicht commented 4 years ago

@laudibert oh, now I get it. you want to view a single item...

In that case, you're right, RESTool don't support it, but it should be easy enough to add it!