Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
31bc4a0
Add css for .lk-popover-behind-modal to adjust z-index
cnathe Apr 9, 2026
04c9a6b
7.29.3-fb-jobUiImprovements.0
cnathe Apr 9, 2026
928329c
EditInlineField prop for pullRight for pencil icon
cnathe Apr 9, 2026
3e97170
7.29.3-fb-jobUiImprovements.1
cnathe Apr 9, 2026
96aa8c9
Merge remote-tracking branch 'origin/develop' into fb_jobUiImprovements
cnathe Apr 10, 2026
1ba4d69
7.29.4-fb-jobUiImprovements.0
cnathe Apr 10, 2026
409fdc0
EditInlineField update for location of icon for pullRight
cnathe Apr 10, 2026
4beba6c
7.29.4-fb-jobUiImprovements.1
cnathe Apr 10, 2026
42210aa
UserDetailsPanel support for userId that is a group id
cnathe Apr 10, 2026
3e6cd6d
7.29.4-fb-jobUiImprovements.2
cnathe Apr 10, 2026
b41818f
jest test updates to match changes
cnathe Apr 10, 2026
da6d3a9
7.29.4-fb-jobUiImprovements.3
cnathe Apr 13, 2026
ca12bfe
Merge remote-tracking branch 'origin/develop' into fb_jobUiImprovements
cnathe Apr 20, 2026
b8f8306
7.30.0-fb-jobUiImprovements.0
cnathe Apr 20, 2026
5f6ce3f
Merge remote-tracking branch 'origin/develop' into fb_jobUiImprovements
cnathe Apr 20, 2026
33a0742
7.31.0-fb-jobUiImprovements.0
cnathe Apr 20, 2026
d03d359
Merge remote-tracking branch 'origin/develop' into fb_jobUiImprovements
cnathe Apr 22, 2026
e27f3d3
Claude Code suggested changes
cnathe Apr 22, 2026
7f56c16
7.31.0-fb-jobUiImprovements.1
cnathe Apr 22, 2026
df53e62
add jest tests for UserDetailsPanel.test.tsx
cnathe Apr 22, 2026
7d1a697
Merge remote-tracking branch 'origin/develop' into fb_jobUiImprovements
cnathe Apr 22, 2026
34d4b66
7.31.1-fb-jobUiImprovements.0
cnathe Apr 22, 2026
7c448d5
Merge remote-tracking branch 'origin/develop' into fb_jobUiImprovements
cnathe Apr 23, 2026
99ad432
7.31.2-fb-jobUiImprovements.0
cnathe Apr 23, 2026
054df50
jest test name update
cnathe Apr 23, 2026
923cd42
detail header wrap for long values
cnathe Apr 23, 2026
0a9dd4f
7.31.2-fb-jobUiImprovements.1
cnathe Apr 23, 2026
c142115
Merge remote-tracking branch 'origin/develop' into fb_jobUiImprovements
cnathe Apr 24, 2026
f52fc78
7.32.0-fb-jobUiImprovements.0
cnathe Apr 24, 2026
c3b2210
npm run lint-branch-fix
cnathe Apr 24, 2026
9f3c0ca
Update release notes with version number and release date
cnathe Apr 24, 2026
1e6ce42
7.33.0
cnathe Apr 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/components/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@labkey/components",
"version": "7.32.0",
"version": "7.33.0",
"description": "Components, models, actions, and utility functions for LabKey applications and pages",
"sideEffects": false,
"files": [
Expand Down
7 changes: 7 additions & 0 deletions packages/components/releaseNotes/components.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# @labkey/components
Components, models, actions, and utility functions for LabKey applications and pages

### version 7.33.0
*Released*: 24 April 2026
- Workflow UI updates
- Add css for .lk-popover-behind-modal to adjust z-index
- EditInlineField prop for pullRight for pencil icon
- UserDetailsPanel support for userId that is a group id

### version 7.32.0
*Released*: 23 April 2026
- Add EMPTY_COMPOUND_WARNING
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('EditInlineField', () => {
},
};

function validate(editing = false, allowEdit = true, type?: Record<string, number>): void {
function validate(editing = false, allowEdit = true, type?: Record<string, number>, pullRight?: boolean): void {
expect(document.querySelectorAll('.edit-inline-field__label')).toHaveLength(!editing ? 1 : 0);
expect(document.querySelectorAll('.edit-inline-field__toggle')).toHaveLength(!editing && allowEdit ? 1 : 0);
expect(document.querySelectorAll('.fa-pencil')).toHaveLength(!editing && allowEdit ? 1 : 0);
Expand All @@ -47,6 +47,8 @@ describe('EditInlineField', () => {
expect(document.querySelectorAll('input')).toHaveLength(type?.text ?? type?.date ?? 0);

expect(document.querySelectorAll('.user-link')).toHaveLength(type?.user ?? 0);

expect(document.querySelectorAll('.pull-right')).toHaveLength(pullRight ? 1 : 0);
}

test('default props', async () => {
Expand Down Expand Up @@ -163,15 +165,15 @@ describe('EditInlineField', () => {
renderWithAppContext(
<EditInlineField
{...DEFAULT_PROPS}
type="date"
value="2022-08-11 18:00:00"
column={
new QueryColumn({
format: 'MM/dd/YYYY HH:mm:ss',
caption: 'DateField',
rangeURI: DATETIME_RANGE_URI,
})
}
type="date"
value="2022-08-11 18:00:00"
/>,
{ serverContext: SERVER_CONTEXT, appContext: APP_CONTEXT }
);
Expand All @@ -186,15 +188,15 @@ describe('EditInlineField', () => {
renderWithAppContext(
<EditInlineField
{...DEFAULT_PROPS}
type="date"
value="2022-08-11 18:00:00.123"
column={
new QueryColumn({
format: 'MM/dd/YYYY HH:mm:ss',
caption: 'DateField',
rangeURI: DATETIME_RANGE_URI,
})
}
type="date"
value="2022-08-11 18:00:00.123"
/>,
{ serverContext: SERVER_CONTEXT, appContext: APP_CONTEXT }
);
Expand All @@ -211,7 +213,6 @@ describe('EditInlineField', () => {
renderWithAppContext(
<EditInlineField
{...DEFAULT_PROPS}
value="18:00:00.1234"
column={
new QueryColumn({
format: 'hh:mm a',
Expand All @@ -220,6 +221,7 @@ describe('EditInlineField', () => {
rangeURI: TIME_RANGE_URI,
})
}
value="18:00:00.1234"
/>,
{ serverContext: SERVER_CONTEXT, appContext: APP_CONTEXT }
);
Expand Down Expand Up @@ -280,4 +282,16 @@ describe('EditInlineField', () => {
expect(document.querySelectorAll('input[name="t$De$Sst"]')).toHaveLength(1);
expect(document.querySelectorAll('input[name="t.e/st"]')).toHaveLength(0);
});

test('pullRight', async () => {
renderWithAppContext(<EditInlineField {...DEFAULT_PROPS} pullRight />, {
serverContext: SERVER_CONTEXT,
appContext: APP_CONTEXT,
});
validate(false, true, undefined, true);
expect(document.querySelector('.edit-inline-field__placeholder')).toHaveTextContent('');
expect(document.querySelectorAll('.fa-pencil')).toHaveLength(1);
await userEvent.click(document.querySelector('.edit-inline-field__toggle'));
validate(true, true, { text: 1 }, false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ interface Props {
name: string;
onChange?: (name: string, newValue: any) => void;
placeholder?: string;
pullRight?: boolean;
startDate?: Date;
tooltip?: string; // only shown when component has a label and is allowEdit
type: string;
Expand All @@ -52,6 +53,7 @@ export const EditInlineField: FC<Props> = memo(props => {
name,
onChange,
placeholder,
pullRight,
startDate,
tooltip,
type,
Expand Down Expand Up @@ -313,8 +315,9 @@ export const EditInlineField: FC<Props> = memo(props => {
onKeyDown={toggleKeyDown}
tabIndex={1}
>
{allowEdit && pullRight && <i className="fa fa-pencil pull-right" />}
{!isUser && displayValue}
{allowEdit && <i className="fa fa-pencil" />}
{allowEdit && !pullRight && <i className="fa fa-pencil" />}
</span>
</>
)}
Expand Down
16 changes: 16 additions & 0 deletions packages/components/src/internal/components/permissions/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { APPLICATION_ROLES_DESCRIPTIONS, APPLICATION_ROLES_LABELS } from '../adm

import { Principal, SecurityPolicy, SecurityRole } from './models';
import { executeSql } from '../../query/executeSql';
import { selectRows } from '../../query/selectRows';
import { SCHEMAS } from '../../schemas';

export function processGetRolesResponse(rawRoles: any): List<SecurityRole> {
let roles = List<SecurityRole>();
Expand Down Expand Up @@ -47,6 +49,20 @@ export async function getPrincipals(): Promise<List<Principal>> {
return result.rows.reduce<List<Principal>>((p, row) => p.push(Principal.createFromSelectRow(fromJS(row))), List());
}

export async function getPrincipalById(principalId: number): Promise<Principal | undefined> {
const results = await selectRows({
columns: ['UserId', 'Name', 'Type'],
schemaQuery: SCHEMAS.CORE_TABLES.PRINCIPALS,
filterArray: [Filter.create('UserId', principalId)],
});

if (results.rows.length === 1) {
const row = results.rows[0];
return Principal.createFromSelectRow(fromJS(row));
}
return undefined;
}

export function getInactiveUsers(): Promise<List<Principal>> {
return new Promise((resolve, reject) => {
selectRowsDeprecated({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,18 @@ describe('Principal model', () => {
expect(sortedPrincipals.get(1)).toBe(USER1);
expect(sortedPrincipals.get(2)).toBe(GROUP);
});

test('isGroup', () => {
expect(GROUP.isGroup()).toBeTruthy();
expect(USER1.isGroup()).toBeFalsy();
expect(USER2.isGroup()).toBeFalsy();
});

test('isUser', () => {
expect(GROUP.isUser()).toBeFalsy();
expect(USER1.isUser()).toBeTruthy();
expect(USER2.isUser()).toBeTruthy();
});
});

describe('SecurityRole model', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ export class Principal extends Record({
.toList()
);
}

isGroup(): boolean {
return this.type === 'g';
}

isUser(): boolean {
return this.type === 'u';
}
}

export class SecurityRole extends Record({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Container } from '../base/models/Container';
import {
fetchContainers,
fetchContainerSecurityPolicy,
getPrincipalById,
getUserLimitSettings,
processGetRolesResponse,
UserLimitSettings,
Expand Down Expand Up @@ -76,6 +77,7 @@ export interface SecurityAPIWrapper {
getDeletionSummaries: (containerPath?: string) => Promise<Summary[]>;
getGroupMemberships: () => Promise<GroupMembership[]>;
getInheritedContainers: (container: Container) => Promise<string[]>;
getPrincipalById: (principalId: number) => Promise<Principal | undefined>;
getUserLimitSettings: (containerPath?: string) => Promise<UserLimitSettings>;
getUserPermissions: (options: GetUserPermissionsOptions) => Promise<string[]>;
getUserProperties: (userId: number) => Promise<any>;
Expand Down Expand Up @@ -284,6 +286,8 @@ export class ServerSecurityAPIWrapper implements SecurityAPIWrapper {
}, []);
};

getPrincipalById = getPrincipalById;

getUserLimitSettings = getUserLimitSettings;

getUserPermissions = (options: GetUserPermissionsOptions): Promise<string[]> => {
Expand Down Expand Up @@ -437,6 +441,7 @@ export function getSecurityTestAPIWrapper(
getAuditLogDate: mockFn(),
getDeletionSummaries: mockFn(),
getGroupMemberships: mockFn(),
getPrincipalById: mockFn(),
getUserLimitSettings: mockFn(),
getUserPermissions: mockFn(),
getUserProperties: mockFn(),
Expand Down
Loading
Loading