Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Multi-project interface

    I want to build an application class (subclassing isc.TabSet) that contains a tab for a project. Each project contains multiple grids and forms, but I want all these grids and forms to use the project ID in its data URL (or request parameters). I have created a single RestDataSource instance with a fixed ID that I pass as the "dataSource" property of the ListGrid instance.

    How can I instruct the data source to uses the project ID when it does a request?

    #2
    If the projectId causes the result of a "fetch" to differ, then it needs to be treated as criteria. Otherwise, you will potentially have cross-talk between the separate project tabs, such as a record being added in one tab appearing in grids in other tabs via ResultSet cache sync.

    Once projected is treated as criteria (and as a DataSource field), how that criteria is sent is based on your settings on RestDataSource. However, you haven't mentioned anything about your current settings, so we can't comment.

    Comment


      #3
      Each record in the database has a "project_id" column and each data source instance has a corresponding field. Right now, I've created a custom DataSource class, subclassing RestDataSource. It has a "dataURL" property containing a string like "/{project_id}/orders{.format}" and I now have overridden "getDataURL()" in it to change the URL last-minute, but I'm doubting if this is the right way. I've tried something with criteria, but that didn't quite work out so far. If I could have a "dataURL" property like "/orders.json" would be fine because then I wouldn't need to change it.
      Last edited by wallytax; 12 Mar 2024, 11:10.

      Comment


        #4
        I want to know if it's correct to use only one data source instance (with a fixed ID) for the whole application (per model). So I configure ListGrids with the "dataSource" property set to this fixed ID.

        Comment


          #5
          As we've covered, if passing projectId changes the results, then it must be criteria, period. There is no possibility of your code being correct until projectId is properly represented as a criterion.

          Once projectId is properly represented as criteria, it could be passed to the server in the URL or in some other way - the client-side UI widgets and ResultSet do not care and do not know anything about how server comms work.

          But again, there is the simple rule: if it changes the results from a DataSource, it's criteria. So when you say "I've tried something with criteria, but that didn't quite work out so far" - go back to whatever that effort way, that's the right approach.

          Comment


            #6
            So how can I pass the project ID as criterion to the request? Thus a request made from components like ListGrid, ValuesManager, DynamicForm, ComboBoxItem (also from editable grids).

            Comment


              #7
              We're not sure we understand the thrust of the question.. all of these components are positively bristling with APIs related to providing criteria. To name just one: listGrid.implicitCriteria gives you a way to specify criteria that the end user doesn't see.

              Perhaps what you are really hoping for is something like: is there a way I can take a whole hierarchy of components and say: anything in here that calls this particular DataSource should always have this particular criterion added?

              Comment


                #8
                That last sentence is exactly what I mean. Is this possible? If not, there's probably no need from customers to have this functionality. I have multiple customer projects where I have this set-up. This works, because I use a data source instance per project and that data source instance is passed through in that hierarchy of components. But I found out that this prevents components from cleaning up when destroyed. Therefore the approach with the ID (a string) as value for the "dataSource" seems better.

                I will attempt to build it the way as described above. Thanks for the explanation!

                Comment


                  #9
                  If you create a separate DataSource instance per project, this will not cause leaking so long as you destroy() that DataSource instance (there's no way for the system to magically know you're done with it). Also, even if your code leaks the DataSource, the components will still be cleaned up so long as you destroy() them.

                  As far as the better approach (where projectId is treated as criteria), the straightforward approach is to create your tab views as a custom component, which is initialized with a projectId and arranges for each of its subcomponents to provide that projectId in criteria (listGrid.implicitCriteria for example, and selectItem.pickListCriteria, etc).

                  Comment


                    #10
                    I'm exactly doing that: the tab views are custom components showing a grid and opening forms when creating/editing records. I've already managed to use the implicitCriteria for ListGrid. But I have two additional questions:
                    1. I've noticed that ComboBoxItem has an "optionCriteria" property and a "pickListCriteria". Do they act similar? I've now decided to pass the project ID to "optionCriteria".
                    2. The forms I mentioned above are actually ValuesManagers containing DynamicForms so that I can use group titles and borders (like <FIELDSET> and <LEGEND> tags in HTML). Is it possible to pass the project ID as well? It's not 100% required I guess because I'm retrieving individual records by their idea. I would probably only need to pass the project ID when creating new records.

                    Comment


                      #11
                      Hi wallytax,

                      is your application a multi tenant application? Then you also should make sure that your serverside always enforces the tenant_id/project_id criteria in each and every request (also add/update/delete) or make this distinction somewhere else (Application server, different DBs/schemas per tenant, DB Login+RLS).
                      At the same time, when you do this, from a SmartClient clientside perspective the whole dataset is the project_id-restricted dataset and the need for these criteria is less.

                      "optionCriteria" and "pickListCriteria": One is for ID-lookups ("fetchMissingValueReply"), the other for picklist display. In a lot of cases this is the same and one of these is the default for the other one if not specified (not sure which way around).

                      Best regards
                      Blama

                      Comment


                        #12
                        Hi Blama, thanks for your reply.

                        I didn't want to bother you with the details of my application, but perhaps a little background might be beneficial. The application isn't a multi-tenant. Basically, it's for a company having several (web)shops, all with their own customers, products, etc. but with a central purchasing organization, which is shown as the last tab.

                        Each record in the database has a "site_code" column (a string). What I called "project ID" above actually is this site code. In each tab, I only want to see the results for that (web)shop (or purchasing organization). However, in the tab of the purchasing organization, there are situations that I want to filter for all customers (thus independent of the (web)shop).

                        Employees working for the company have access to all tabs, but there is some authorization involved, but not specific to a single (web)shop. Therefore I use one generated (based on authenticated user), global data source instance. The fields in it are already limited based on the user's rights.

                        Hope this makes sense.

                        Comment


                          #13
                          Hi wallytax,

                          ah, yes. In this case I'd somehow store the site_code in a top-level component and pass it around/have it available in the child ListGrids etc, where you use it as implicitCriteria, perhaps even more declarative with dynamicCriteria (I never tried this myself, but it looks great).
                          You could do it even higher up in the chain in DataSource.implicitCriteria. This means separate DataSources client side of course, and I don't know what is easier.

                          Best regards
                          Blama

                          Comment


                            #14
                            That last sentence is not yet what I'm doing right now, because I don't have different rights per (web)shop and thus the model definition is the same for all (web)shops. If however, I decide to do this, I would probably store the site code inside of the "dataURL", which prevents the need to use implicit criteria. If my attempt to rebuild the current application (I'm not 100% finished) fails, I will fall back to this option, meaning a different data source instance per shop/model combination, and then having a id like "<MODEL>_<SHOP>_DS". Each main tab component will then pass that ID to the grid and forms inside it. And I need a global instance as well (without the shop) for the situation where I want to be able to filter on all customers.

                            I have no experience with dynamic criteria either, but I will have a look on it. Thanks for that suggestion.

                            Comment


                              #15
                              With the 1st suggestion (site_code in a top-level component and pass it around) you'd only need one instance of every DataSource (and no special dataURLs) - implicitCriteria for every shop specific DataBoundComponent and no implicitCriteria for the all-shops overview.

                              Comment

                              Working...
                              X