Skip to main content

InstanceGridForCustomWidget

  • The InstanceGridForCustomWidget component is wrapper component that manages data fetching, filtering, sorting, pagination, and passes the processed data and configuration to InstanceGrid or InstanceGridV2 for rendering a customizable, attribute-driven grid.
  • The component renders either: InstanceGrid: Classic grid (server-side pagination mode) InstanceGridV2: Modern grid with virtualization, supports both server and client modes for pagination mode.
  • It displays the UI of InstanceGrid or InstanceGridV2, depending on widget configuration.
  • Supports filtering, CSV export, bulk actions, quick edit, and QR sticker printing.
  • It Can be used in dashboard, view, or home layout of a custom widget.

Props

  1. configuration

    • Type: object
    • Description: Widget/grid configuration, including fields, filters, sort, page size, etc.
  2. instanceTypeName

    • Type: string
    • Description: Name of the instance type being displayed.
  3. canCreateInstance

    • Type: boolean
    • Description: Whether the user can create new instances.
  4. numberOfLoadingRows

    • Type: number
    • Description: Number of skeleton rows to show while loading.
  5. isSortable

    • Type: boolean
    • Default: true
    • Description: Enables or disables sorting functionality.
  6. compact

    • Type: boolean
    • Description: Determines if the grid should use a compact layout.
  7. gridDetails

    • Type: object
    • Description: Additional grid configuration (e.g., versioning, view config).
  8. shrinkToFit

    • Type: boolean
    • Description: Adjusts column widths to fit the grid.
  9. directRelatedInstance

    • Type: object
    • Description: Data for directly related instances.
  10. sourceInstanceDetails

    • Type: object
    • Description: Details about the source instance for the grid.
  11. relatedTypeName

    • Type: string
    • Description: The type of related instances displayed in the grid.
  12. widgetId

    • Type: string
    • Description: The unique ID of the widget.
  13. isFilterVisible

    • Type: boolean
    • Default: false
    • Description: Whether to show the filter UI.
  14. baseUrl

    • Type: string
    • Description: Custom API endpoint for programmatic data fetching.
  15. programData

    • Type: object
    • Description: Additional data to send with the custom program API call.
  16. otherUIComponents

    • Type: function
    • Description: Function that returns additional UI components to render in the grid header.
  17. isStandardGrid

    • Type: boolean
    • Default: true
    • Description: If true, uses standard grid data fetching; otherwise, uses custom program API.
  18. widgetView

    • Type: string
    • Default: Grid
    • Description: Defines which grid version to render (Grid or GridV2).

Notes

  • otherUIComponents allows you to inject custom buttons or controls into the grid header.
  • For custom program API fetching, set baseUrl and programData and set isStandardGrid={false}.
  • In case of fetching data through custom program then for sorting and pagination we have to pass data in key-value pair format.

Response Data Structure require for Grid V2 In case of fetching data through custom program

  • Custom program response must be in below format
[
{
id: 'abc-123',
name: 'Sample',
attr1: 'foo',
attr2: 42
// ...other attributes as key-value pairs
},
// ...
]

Usage Example: Instance grid V2 - Fetching data through custom program

function InstanceGridV2CustomWidget(pageContext) {
const { protrakUtils, protrakComponents } =
React.useContext(customWidgetContext);
const { InstanceGridForCustomWidget, Container, Spinner, Box, Dropdown } =
protrakComponents;
const { useTypeLayoutConfig, useProtrakApi, protrakApiClient } = protrakUtils;
let configuration = pageContext?.currentWidgetConfig;
configuration = {
...configuration,
fields: [
{
fieldType: "Attribute",
attributeType: "DateTime",
label: "CreatedDate",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "Created",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Attribute",
attributeType: "User",
label: "Creator",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "Creator",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Attribute",
attributeType: "Text",
label: "Description",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "Description",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Actions",
attributeType: "Text",
label: "Actions",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "Actions",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [
{
id: "8321f283-e0aa-4896-a101-b05400511fcc",
actionType: "PromoteAction",
relationDirection: "To",
canCreateRelatedType: false,
},
{
id: "32021261-2a40-4b0a-8c7b-b05400511fcc",
actionType: "QuickEdit",
relationDirection: "To",
canCreateRelatedType: false,
},
{
id: "5da2b23d-9018-4bff-9135-b05400511fcc",
actionType: "Edit",
relationDirection: "To",
canCreateRelatedType: false,
},
{
id: "31662aa6-df93-44b4-a4e0-b05400511fcc",
actionType: "Delete",
relationDirection: "To",
canCreateRelatedType: false,
},
{
id: "b498da58-ab7b-47a5-8fb5-b05400511fcc",
actionType: "ViewDetails",
relationDirection: "To",
canCreateRelatedType: false,
},
{
id: "4ab571e7-c51c-43be-a7d1-b05400511fcc",
actionType: "OpenInNewTab",
relationDirection: "To",
canCreateRelatedType: false,
},
],
formatConditions: [],
},
{
fieldType: "Name",
attributeType: "Text",
label: "Name",
isVisible: true,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "name",
isRequired: true,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Attribute",
attributeType: "DateTime",
label: "ModifiedDate",
isVisible: true,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "modified",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Lifecycle",
attributeType: "Lifecycle",
label: "Lifecycle",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "Lifecycle",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Attribute",
attributeType: "Text",
label: "GeofenceCenter",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "GeofenceCenter",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Attribute",
attributeType: "Text",
label: "GeofenceRadius",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "GeofenceRadius",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Attribute",
attributeType: "Picklist",
label: "Action Type",
isVisible: true,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "taskActionType",
isRequired: false,
options: [
{
name: "ManageContent",
displayName: "Manage Content",
disabled: false,
},
{
name: "KeyRotationRequest",
displayName: "Key Rotation",
disabled: false,
},
{
name: "SecurityAlert",
displayName: "Security Alerts",
disabled: false,
},
{
name: "ConfigurationArtifact",
displayName: "Configuration Artifacts",
disabled: false,
},
{
name: "UpdatePolicy",
displayName: "Update Policies",
disabled: false,
},
{
name: "BatchCertificate",
displayName: "Batch Certificates",
disabled: false,
},
],
regExErrorMessage: "",
isMultiselect: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
editor: "Default",
renderer: "Default",
},
{
fieldType: "State",
attributeType: "Text",
label: "State",
isVisible: true,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "State",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Attribute",
attributeType: "User",
label: "Modifier",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "Modifier",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
],
};

return (
<InstanceGridForCustomWidget
key={"InstanceGridForCustomWidget"}
isStandardGrid={false}
configuration={configuration}
canCreateInstance={"true"}
numberOfLoadingRows={10}
baseUrl={"programs/DynamicTypeCustomDashboard/executeCommonProgram"}
widgetView={'GridV2'}
/>
);
}

UI: InstanceGridV2

InstanceGrid

Usage Example 1 - Dashboard layout

function MemberDeviceInstanceGridForDashboardLayout(pageContext) {
const { protrakUtils, protrakComponents } =
React.useContext(customWidgetContext);
const { InstanceGridForCustomWidget, Container, Spinner, Box, Dropdown } =
protrakComponents;
const { useTypeLayoutConfig, useProtrakApi, protrakApiClient } = protrakUtils;
const [selectedOption, setSelectedOption] = React.useState({});
const [baseUrl, setBaseUrl] = React.useState(
'programs/SolrConnectorCommonProgram/executeCommonProgram'
);
const [picklistOptions, setPicklistOptions] = React.useState({
label: '',
value: '00000000-0000-0000-0000-000000000000',
});

const __getInstanceDetailsPromise__ = React.useCallback(
async ({ protrakApiClient, authContext }) => {
const apiUrl =
'instances?attributes[0]=Actions&attributes[1]=Name&attributes[3]=Modified&attributes[4]=Created&attributes[5]=TrackingInfo&attributes[6]=QRCode&getAllowedOperations=true&getAllowedActions=true&sortBy=Modified&isSortByDescending=true&instanceTypeName=DynamicGroups&getOnlyActionableInstances=false&skip=0&take=9999';

let res = await protrakApiClient(apiUrl, {}, authContext);
return res;
},
[]
);

const { state: response } = useProtrakApi({
promiseFn: __getInstanceDetailsPromise__,
protrakApiClient,
});

React.useEffect(() => {
if (response.isFulfilled && response.data && response.data.items) {
const formattedItems = response.data.items.map((item) => ({
label: item.name,
value: item.id,
}));

setPicklistOptions(formattedItems);
}
}, [response.isFulfilled, response.data]);

const dashboardConfig = useTypeLayoutConfig('MemberDevice', 'dashboard');
let configuration = {};

if (
(dashboardConfig.isLoading && !dashboardConfig.data) ||
response.isLoading
) {
return (
<Container>
<Spinner />
</Container>
);
}

if (dashboardConfig.isFulfilled && dashboardConfig.data) {
const widget = dashboardConfig.data.widgets.find(function (widget) {
return widget.name == 'MemberDeviceDashboard';
});
const objToPush = {
canCreateInstance: dashboardConfig.data.canCreateInstance,
typeName: dashboardConfig.data.typeName,
typePluralName: dashboardConfig.data.typePluralName,
typeSingularName: dashboardConfig.data.typeSingularName,
};
configuration = { ...widget, ...objToPush };
}

if (dashboardConfig.isError || response.isError) {
return (
<Container>
<h3>Server error!</h3>
</Container>
);
}

return (
<InstanceGridForCustomWidget
key={
selectedOption
? selectedOption.value
: "MemberDeviceInstanceGridForDashboardLayout"
}
isStandardGrid={false}
configuration={configuration}
canCreateInstance={'true'}
numberOfLoadingRows={10}
baseUrl={baseUrl}
programData={selectedOption && selectedOption.value}
isFilterVisible={false}
otherUIComponents={() => {
return (
<Box width={'40%'} direction={'column'} marginLeft={'1rem'}>
<Dropdown
defaultValues={selectedOption}
placeholder={'Select Dynamic Group'}
picklistOptions={picklistOptions}
onValueChange={(option) => {
if (option === null) {
setSelectedOption({
label: '',
value: '00000000-0000-0000-0000-000000000000',
});
setBaseUrl(
'programs/SolrConnectorCommonProgram/executeCommonProgram'
);
} else {
setSelectedOption(option);
setBaseUrl(
'programs/SolrConnectorCommonProgram/executeCommonProgram'
);
}
}}
isMultiselect={false}
isClearable={true}
/>
</Box>
);
}}
/>
);
}

UI: InstanceGrid

InstanceGrid

Usage Example 2 : View layout

function DynamicGroupsInstanceGridForViewLayout(pageContext) {
const { protrakUtils, protrakComponents } =
React.useContext(customWidgetContext);
const {
InstanceGridForCustomWidget,
Button,
ButtonEnums,
Container,
Spinner,
} = protrakComponents;
const { useTypeLayoutConfig } = protrakUtils;
const [baseUrl, setBaseUrl] = React.useState(
'programs/SolrConnectorCommonProgram/executeCommonProgram'
);
const [programData, setProgramData] = React.useState(
'00000000-0000-0000-0000-000000000000'
);
const dashboardConfig = useTypeLayoutConfig('MemberDevice', 'dashboard');
let configuration = {};

if (dashboardConfig.isLoading && !dashboardConfig.data) {
return (
<Container>
<Spinner />
</Container>
);
}

if (dashboardConfig.isFulfilled && dashboardConfig.data) {
const widget = dashboardConfig.data.widgets.find(function (widget) {
return widget.name == 'MemberDeviceDashboard';
});
const objToPush = {
canCreateInstance: dashboardConfig.data.canCreateInstance,
typeName: dashboardConfig.data.typeName,
typePluralName: dashboardConfig.data.typePluralName,
typeSingularName: dashboardConfig.data.typeSingularName,
};
configuration = { ...widget, ...objToPush };
}

return (
<InstanceGridForCustomWidget
isStandardGrid={false}
configuration={configuration}
canCreateInstance={pageContext.layoutConfig.canCreateInstance}
isFilterVisible={false}
baseUrl={baseUrl}
programData={programData}
otherUIComponents={() => {
return (
<Button
text={'Evaluate Rule'}
outline
appearance={ButtonEnums.Appearance.Transparent}
size={ButtonEnums.Size.Small}
onClick={() => {
setBaseUrl(
'programs/SolrConnectorCommonProgram/executeCommonProgram'
);
setProgramData(pageContext.instanceId);
}}
style={{ marginLeft: '1rem' }}
/>
);
}}
/>
);
}

UI: InstanceGrid

InstanceGrid2