[COMMAND MENU ITEMS] Resolve object metadata label in dynamic command menu item label (#19211)

- Adds a resolveObjectMetadataLabel utility that returns the singular or
plural label from object metadata based on the number of selected
records (e.g., "person" vs "people").
- Exposes a pre-computed objectMetadataLabel string on
CommandMenuContextApi, making it available for label interpolation
(e.g., Delete ${capitalize(objectMetadataLabel)}).
This commit is contained in:
Raphaël Bosi
2026-04-01 17:02:24 +02:00
committed by GitHub
parent 19dd4d6c1b
commit 9054d3aef6
9 changed files with 131 additions and 2 deletions
@@ -29,6 +29,7 @@ const buildContext = (
targetObjectReadPermissions: {},
targetObjectWritePermissions: {},
objectMetadataItem: {},
objectMetadataLabel: '',
...overrides,
});
@@ -29,6 +29,7 @@ const buildContext = (
targetObjectReadPermissions: {},
targetObjectWritePermissions: {},
objectMetadataItem: {},
objectMetadataLabel: '',
...overrides,
});
@@ -313,4 +314,71 @@ describe('interpolateCommandMenuItemLabel', () => {
).toBe('Delete people');
});
});
describe('objectMetadataLabel interpolation', () => {
it('should resolve singular label with capitalize transform', () => {
const context = buildContext({
objectMetadataLabel: 'person',
});
expect(
interpolateCommandMenuItemLabel({
label: 'Delete ${capitalize(objectMetadataLabel)}',
context,
}),
).toBe('Delete Person');
});
it('should resolve plural label with capitalize transform', () => {
const context = buildContext({
objectMetadataLabel: 'companies',
});
expect(
interpolateCommandMenuItemLabel({
label: 'Export ${capitalize(objectMetadataLabel)}',
context,
}),
).toBe('Export Companies');
});
it('should resolve objectMetadataLabel without transform', () => {
const context = buildContext({
objectMetadataLabel: 'people',
});
expect(
interpolateCommandMenuItemLabel({
label: '${objectMetadataLabel} selected',
context,
}),
).toBe('people selected');
});
it('should resolve objectMetadataLabel with lowercase transform', () => {
const context = buildContext({
objectMetadataLabel: 'Person',
});
expect(
interpolateCommandMenuItemLabel({
label: 'Create ${lowercase(objectMetadataLabel)}',
context,
}),
).toBe('Create person');
});
it('should return empty segment when objectMetadataLabel is empty', () => {
const context = buildContext({
objectMetadataLabel: '',
});
expect(
interpolateCommandMenuItemLabel({
label: 'Delete ${capitalize(objectMetadataLabel)}',
context,
}),
).toBe('Delete ');
});
});
});
@@ -0,0 +1,35 @@
import { resolveObjectMetadataLabel } from '../resolveObjectMetadataLabel';
describe('resolveObjectMetadataLabel', () => {
const objectMetadataItem = {
labelSingular: 'person',
labelPlural: 'people',
};
it('should return labelSingular when numberOfSelectedRecords is 1', () => {
expect(
resolveObjectMetadataLabel({
objectMetadataItem,
numberOfSelectedRecords: 1,
}),
).toBe('person');
});
it('should return labelPlural when numberOfSelectedRecords is 0', () => {
expect(
resolveObjectMetadataLabel({
objectMetadataItem,
numberOfSelectedRecords: 0,
}),
).toBe('people');
});
it('should return labelPlural when numberOfSelectedRecords is greater than 1', () => {
expect(
resolveObjectMetadataLabel({
objectMetadataItem,
numberOfSelectedRecords: 5,
}),
).toBe('people');
});
});
@@ -0,0 +1,11 @@
export const resolveObjectMetadataLabel = ({
objectMetadataItem,
numberOfSelectedRecords,
}: {
objectMetadataItem: { labelSingular: string; labelPlural: string };
numberOfSelectedRecords: number;
}): string => {
return numberOfSelectedRecords === 1
? objectMetadataItem.labelSingular
: objectMetadataItem.labelPlural;
};