Skip to main content

Target type CustomAction

The custom widget can be rendered in the Bulk Action Button Renderer to handle custom bulk actions.

Coding Guidelines

  • pageContext: The pageContext provided to the CustomWidget has the following content:
{
displayName: string, // The display name of the custom action
selectedInstances: array, // Array of selected items
currentWidgetConfig: object, // Configuration of the current widget
}

Typical Use Cases

  • Used to display custom widgets for bulk actions in the dashboard and relation widget.
  • Allows users to define and execute custom bulk actions dynamically.
  • Provides flexibility to implement custom UI and functionality for bulk actions.
  • Typically used for actions requiring additional business logic, validations, or data processing.

Example Usage

function ExportDFJsonCustomBulkAction(pageContext) {
const { protrakComponents } = React.useContext(customWidgetContext);
const { useAuthContext, toQueryString, protrakApiClient } =
React.useContext(customWidgetContext).protrakUtils;

const { ButtonEnums, Button, ProtrakFontAwesomeIcon, Spinner } =
protrakComponents;
const authContext = useAuthContext();
const [isLoading, setIsLoading] = React.useState(false);

const DYNAMIC_FORM_JSON_ATTR_NAME = 'STANDARDDynamicFormJson';

function parseJsonSafe(jsonString) {
try {
return JSON.parse(jsonString);
} catch {
return null;
}
}

const getDFInstancesData = React.useCallback(
async (id) => {
const instanceData = await getInstance({
instanceId: id,
protrakApiClient,
toQueryString,
authContext,
});
return instanceData;
},
[authContext, protrakApiClient, toQueryString]
);

const downloadJsonFile = async () => {
const resultJsons = [];
const isTemplateJsonPresent =
pageContext.selectedInstances.length > 0 &&
pageContext.selectedInstances[0]?.attributes?.some(
(attribute) => attribute.name === DYNAMIC_FORM_JSON_ATTR_NAME
);

if (isTemplateJsonPresent) {
pageContext.selectedInstances.forEach((instance) => {
const dfJson =
instance.attributes.find(
(attribute) => attribute.name === DYNAMIC_FORM_JSON_ATTR_NAME
)?.textValue || null;

const dfJsonData = parseJsonSafe(dfJson);
dfJsonData && resultJsons.push(dfJsonData);
});
} else {
const instancePromises = pageContext.selectedInstances.map(
async (instance) => {
const instanceData = await getDFInstancesData(instance.id);
const dfJson =
instanceData?.data?.attributes.find(
(attribute) => attribute.name === DYNAMIC_FORM_JSON_ATTR_NAME
)?.textValue || null;

const dfJsonData = parseJsonSafe(dfJson);
if (dfJsonData) {
resultJsons.push(dfJsonData);
}
}
);

await Promise.all(instancePromises);
}
console.log(resultJsons);
setIsLoading(false);
const blob = new Blob([JSON.stringify(resultJsons, null, 2)], {
type: 'application/json',
});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'Export_data.json';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};

const downloadDFJsonData = React.useCallback(async () => {
setIsLoading(true);
const updatedItems = await downloadJsonFile();
}, [downloadJsonFile]);

return (
<Button
appearance={ButtonEnums.Appearance.TransparentWithHover}
size={ButtonEnums.Size.Large}
style={{
width: 'fit-content',
color: 'var(--font-color-primary-light)',
borderRadius: '0',
}}
title={pageContext.displayName}
onClick={() => {
downloadDFJsonData();
}}
>
{isLoading ? (
<Spinner />
) : (
<ProtrakFontAwesomeIcon
className="fa-solid fa-file-export"
title="Export Jsons"
aria-hidden="true"
style={{ fontSize: '1.8rem', padding: '0.5rem' }}
/>
)}
</Button>
);
}

async function getInstance({ instanceId, protrakApiClient, authContext }) {
const INSTANCES = `instances/${instanceId}?attributes[0]=Name&attributes[1]=STANDARDDynamicFormJson`;
const response = await protrakApiClient(INSTANCES, {}, authContext);
return response;
}

Here's a UI of how this custom widget looks like for custom action for exporting data.

CustomAction