DataConnectors icon indicating copy to clipboard operation
DataConnectors copied to clipboard

How to set up nested OData feeds, or navigation by database?

Open qwertie opened this issue 2 years ago • 0 comments

I have basically the same question as PowerBISDK here.

We want a workflow like this:

  1. User is asked for tenant name, which is used to construct an initial URL
  2. User choose either (A) our scenarios table, or (B) a specific scenario (ideally: we show the list of scenarios, but if there are many scenarios, the user can use the keyboard to search for one by name).
  3. Scenarios are basically mini-databases. So if the user chooses a specific scenario, then user must choose table(s) within that scenario. All scenarios have the same tables.

Power BI appears to be potentially able to support 2B in two ways:

  1. Each scenario is a navigation table nested within an outer navigation table in the "Navigator" window.
  2. Since all scenarios have the same tables, the user could choose a table first, which would actually be an M function instead of a table, and then a dropdown list on the right side of the "Navigator" appears, from which the user selects a scenario, and then a preview table appears.

But I can't figure out how to get either of these approaches to work.

For starters, an OData.Feed by itself works, but it breaks when placed inside a navigation table:

image

"We cannot convert the value null to type Logical"

Here's my code so far, but I have ~no experience in M. Can you tell me where to go from here? I think we would prefer the first version of the workflow, in which the treeview on the left contains the list of scenarios (mini-databases), because there is a search box on the left which the user could use to find a scenario.

[DataSource.Kind="BarreleyeAuth", Publish="BarreleyePowerBI.Publish"]
shared BarreleyePowerBI.Contents = (optional tenant as text) =>
    let
        domainURL = "https://" & (
            if Text.Length(tenant) > 0 then 
                "barreleye.azurewebsites.net/" & tenant else "https://localhost:5001"),
        
        o = OData.Feed(domainURL),
        s = Web.Contents(domainURL, [ RelativePath = "odata/oscenario" ]),
        j = Json.Document(s),

        objects = #table(
          {"Name",      "Key",   "Data",                   "ItemKind", "ItemName", "IsLeaf"},{
          {"Test",      "test",  ExampleNavTable("Child"), "Table",    "Table",    false},
          {"Scenarios", "scena", j,                        "Table",    "Table",    false},
          {"OData",     "odata", o,                        "Table",    "Table",    false}
        }),
        NavTable = Table.ToNavigationTable(objects, {"Key"}, "Name", "Data", "ItemKind", "ItemName", "IsLeaf")
    in
        NavTable;

ExampleNavTable = (message as text) as table => 
    let
        objects = #table(
            {"Name",  "Key",   "Data",                           "ItemKind", "ItemName", "IsLeaf"},{
            {"Item1", "item1", #table({"Column1"}, {{message}}), "Table",    "Table",    true},
            {"Item2", "item2", #table({"Column1"}, {{message}}), "Table",    "Table",    true}
        }),
        NavTable = Table.ToNavigationTable(objects, {"Key"}, "Name", "Data", "ItemKind", "ItemName", "IsLeaf")
    in
        NavTable;

BarreleyeAuth = [
    Authentication = [
        Aad = [
            AuthorizationUri = "https://login.microsoftonline.com/common/oauth2/authorize",
            Resource = "93f198af-b514-4e9f-bf99-7809d335d27f" // Azure AD resource value for your service - Guid or URL
        ]
    ],
    Label = Extension.LoadString("DataSourceLabel")
];
...

qwertie avatar Nov 25 '21 15:11 qwertie