Skip to main content

User Context Display Widget Pattern

Overview

A widget that displays information about the currently logged-in user, sourced entirely from pageContext.userData. No API calls required — the platform injects the user's profile instance data directly into pageContext.

When to Use

  • Show a user profile card on a Home layout or a View layout tab
  • Display logged-in user details (name, designation, contact) as part of a personalized dashboard
  • Show user-specific information that doesn't require a separate API fetch

Applicable Layout Types

TargetNotes
HomePageProfile card on home page
ViewLayoutUser info panel on an instance view tab
AnyCan be placed anywhere

userData Shape

pageContext.userData = {
userId: string,
name: string, // Display name (e.g. "John Doe")
email: string,
roles: string[], // Role names assigned to the user
isAdmin: boolean,
typeInstanceId: string, // ID of the UserProfile instance
pictureUrl: string, // URL of user's avatar image
profile: { // Full UserProfile instance object
id: string,
name: string,
instanceTypeName: string, // 'UserProfile'
attributes: AttributeObject[], // UserProfile attribute values
state: object,
lifecycle: object,
},
}

Pattern Structure

  1. Destructure userData from pageContext
  2. Access userData.profile.attributes and find each attribute by name
  3. Use Enums.AttributeTypes for type-safe value extraction, or access the typed value field directly
  4. Render a display-only card — no onAttributeEdit, no API calls

Code Example

function UserProfileDetailsWidget(pageContext) {
const { protrakUtils, protrakComponents } =
React.useContext(customWidgetContext);
const { Enums } = protrakUtils;
const { Text, Box, H2, H4, Label } = protrakComponents;

const { userData } = pageContext;

// Guard: profile may not be loaded yet
if (!userData || !userData.profile) {
return null;
}

const profileAttrs = userData.profile.attributes || [];

// Helper: find an attribute by name and extract its display value
const getAttrValue = (attrName) => {
const attr = profileAttrs.find((a) => a.name === attrName);
if (!attr) return '-';

switch (attr.type) {
case Enums.AttributeTypes.Text:
return attr.textValue || '-';
case Enums.AttributeTypes.Numeric:
case Enums.AttributeTypes.Currency:
return attr.numericValue ?? '-';
case Enums.AttributeTypes.Boolean:
return attr.booleanValue ? 'Yes' : 'No';
case Enums.AttributeTypes.Date:
case Enums.AttributeTypes.DateTime:
return attr.dateValue || '-';
case Enums.AttributeTypes.Picklist:
return (attr.arrayValue || []).join(', ') || '-';
case Enums.AttributeTypes.Reference:
return (
(attr.referenceValues || []).map((r) => r.name).join(', ') || '-'
);
default:
return '-';
}
};

const firstName = getAttrValue('STANDARDFirstName');
const lastName = getAttrValue('STANDARDLastName');
const contact = getAttrValue('STANDARDPhone');
const designation = getAttrValue('STANDARDDesignation');

return (
<Box style={{ display: 'flex', flexDirection: 'column', margin: '1rem' }}>
<H2>{userData.name}</H2>
<div style={{ marginTop: '0.5rem' }}>
<Text>
<b>First Name:</b> {firstName}
</Text>
<Text>
<b>Last Name:</b> {lastName}
</Text>
<Text>
<b>Contact:</b> {contact}
</Text>
<Text>
<b>Designation:</b> {designation}
</Text>
</div>
</Box>
);
}

Accessing All userData Properties

const { userData } = pageContext;

// Basic user info (always available)
userData.name; // "John Doe"
userData.email; // "john@company.com"
userData.roles; // ["Admin", "Project Manager"]
userData.isAdmin; // true/false
userData.pictureUrl; // avatar URL

// UserProfile instance attributes (requires profile to be loaded)
const profileAttrs = userData.profile?.attributes || [];
const phone = profileAttrs.find((a) => a.name === 'STANDARDPhone')?.textValue;

Checking User Roles

A common pattern for role-based rendering inside any widget:

const { userData } = pageContext;
const roles = userData?.roles || [];

const isAdmin = roles.includes('Admin');
const isManager = roles.includes('Project Manager');
const canViewSensitiveData = ['Admin', 'Finance', 'Management'].some((r) =>
roles.includes(r)
);

if (!canViewSensitiveData) {
return <span>Access Restricted</span>;
}

Real Examples

  • UserProfileDetailsWidget.js — Construction360, MountMeru