Hello there, I'm currently trying to dynamically f...
# gooddata-ui
b
Hello there, I'm currently trying to dynamically filter an embed dashboard based on a attribute. The filter is set within the dashboard through GD UI, but I'd like to "filter" the available values for that filter attribute. Now the catch: those values should be filtered based on something that's outside GD, ie: different App contexts should be able to embed the same dashboard, with the same attribute as filter, but the available values in the filter should be altered based on the App context.
So I have a few questions: 1. I tried with the AttributeFilter, but it seems to only work with Insights, not Dashboard, so I've went with the extraPlugins route to alter the Dashboard at runtime, does it sound good or is there a better alternative? 2. To dispatch filter commands from within the dashboard, I need to get the filterLocalId, is there any way to access it from within a plugin? I've tried to get it from ctx.filterContextRef but it seems empty if I don't pass it explicitely to the Dashboard loader 3. I've tried to setup a locked filter directly in the Dashboard, but as soon as I change the filters through a dispatch command, it shows the "reset filter" option, any way to alter that behavior (without hidding all the filter bar)?
Here's the code for reference:
Copy code
const DashboardFiltersWidget: CustomDashboardWidgetComponent = (
  props: React.PropsWithChildren<
    IDashboardWidgetProps & {
      widget?: ExtendedDashboardWidget & {
        filterContextRef?: ObjRef;
      };
    }
  >,
) => {
  const { currentStore } = useUser();
  const changeAttributeFilterSelectionCmd = useDispatchDashboardCommand(
    changeAttributeFilterSelection,
  );

  useEffect(() => {
    console.log(props.widget?.filterContextRef);
    if (currentStore?.name) {
      changeAttributeFilterSelectionCmd(
        "3aa72b67107f46baa03eb260257a7ebb", // How to get it dynamically ?
        {
          uris: ["stores.name"],
          values: [currentStore.name],
        },
        "IN",
      );
    }
  }, [currentStore?.name]);
  return null;
};

class DashboardFiltersPlugin extends DashboardPluginV1 {
  author = "LiveCrew";
  displayName = "Hidden dashboard filters";
  version = "1.0";
  register: DashboardPluginV1["register"] = (ctx, customize) => {
    customize
      .customWidgets()
      .addCustomWidget("DashboardFilters", DashboardFiltersWidget);
    customize.layout().customizeFluidLayout((_, customizer) => {
      customizer.addSection(
        0,
        newDashboardSection(
          undefined,
          newDashboardItem(
            newCustomWidget("DashboardFilters", "DashboardFilters", {
              filterContextRef: ctx.filterContextRef,
            }),
            {
              xl: {
                gridWidth: 12,
                gridHeight: 0.1,
              },
            },
          ),
        ),
      );
    });
  };
}

export const DashboardFilters: IEmbeddedPlugin = {
  factory: () => new DashboardFiltersPlugin(),
  parameters: "filterContextRef",
};
f
Hi Bastien, I checked our archive and it looks like you are using GD.UI with GoodData Cloud, correct? Could you just confirm whether you are using the latest version of the SDK (v10)?
b
Yes to all > "sdk-backend-tiger": "^10.0.0", > "sdk-ui-dashboard": "^10.0.0", > "sdk-ui-loaders": "^10.0.0",
(sry for the unexpected @)
f
Thank you! I’m reaching out to our Technical Support team for some help here, please hang in there and we’ll come back with an update soon 🙂
b
Thank you 👍
r
Hey Bastien, Radek from the Technical team here, lemme have a look! 🙂
Alrighty, some answers: 1. This is a good approach for this for sure! 2. Checking into the filterLocalId still 🙂 3. CSS could be a good option here, I tested this briefly and setting
visibility: hidden
on
.dash-filters-reset
is a super simple way to prevent it from popping up - this comes with the usual disclaimer that the CSS is always subject to change, but I personally can't see a reason for this one to change
b
Hey Radek, thanks for the answer, the 3. is actually a simple yet efficient idea, I'll give it a try. I don't get the 2. though, currently the filterLocalId is generated by gooddata when creating the dashboard. Now, let's say I want to apply the same logic to multiple dashboards (they are basically the same dashboard across different workspaces) with the same generic component, how can I access the filterLocalId (either from within the register method of the plugin, or inside the React component used as plugin) used by the Dashboard that will load the plugin? My only guess so far is to do it the other way, ie: create a specific and identical filterContext with a static localId inside the wanted dashboards so I can directly reference that given localId. But a more dynamic approach would have been great.
r
Yeah, I see what you're getting at 🙂 Can't say I know off the top of my head, but I'm sure either me or the devs can find a way, so stay tuned!
👌 1
Hmm, I think it should be possible to dig the ID out using selectFilterContextDefinition, this returns a IFilterContextDefinition type that includes an identifier - historically it looks like the issue is less being able to get the filter ID, and more the fact that it's referred to as
filterLocalId
in the filter context, and elsewhere you get anything in the range of "identifier" to "localIdentifier" at best 😅
b
Hello, thanks to your input I'm slowly progressing but I still have a few questions: • all the selectAnything commands require the DashboardState as param, but I can't find a way to access it, either from within the plugin props or during the plugin register phase • is there a DispatchDashboardCommand or something similar to modify the filter options instead of the filter selection? (as in: in the backend the dashboard have an attribute filter on Foo, with available options: A, B, C, D, how to locally display only B & C in the filter dashboard?)
👀 1
r
Hey Bastien, apologies for the delay! I'm currently checking this with the SDK devs; have you had any luck untangling this in the meantime, or are you still in the same spot? 🙂
b
Hello, I went the other way: I'm creating filterContext dynamically based on the user needs and it actually works correctly in the embed dashboard. Now I have a new, yet somehow related issue: the users can share the same dashboard and the same datasource but with different filterContexts so each of them see a different part of the data. The problem being: when creating a PDF export (either through the SDK or a direct api call), I can't understand if/how it's possible to pass a specific filterContext to the export. I tried a few things along those lines:
Copy code
const {
  data: { exportResult },
} = await gooddataExport.createPdfExport({
  workspaceId,
  pdfExportRequest: {
    dashboardId,
    fileName: `${dashboardId}-${filterId}.pdf`,
    metadata: {
      filters: [filterId],
    },
  },
});
The metadata part is poorly typed, but I saw in the export response that it exposes used filters in the metadata, so I guess it should be possible to pass a specific filterContext (either with the filterContextId or the actual content)
r
Hey there Bastien, for the PDF exports, this is a really good question - I'll go ahead and ask the devs, and I'll keep you posted 🙂
Hi again Bastien, I'm back with dev feedback!
Essentially, you need to provide filters fully, not by their IDs. You can take inspiration from here - GitHub ref.
The convert function is an identity, but notice omitting the all-time filter and finally the base types here.
I hope these are helpful pointers for your implementation! If not, please let me know and I'll try to get more details 🙂