Skip to content

Commit 8737722

Browse files
authored
Merge pull request #1845 from jetstreamapp/refactor/shared-ui-navbar-components
refactor: extract shared UI component changes ahead of analysis-tools feature
2 parents 8b2ad21 + 931a204 commit 8737722

33 files changed

Lines changed: 650 additions & 162 deletions

libs/icon-factory/src/lib/icon-factory.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ import StandardIcon_Apex from './icons/standard/Apex';
2323
import StandardIcon_AssetRelationship from './icons/standard/AssetRelationship';
2424
import StandardIcon_Billing from './icons/standard/Billing';
2525
import StandardIcon_BundleConfig from './icons/standard/BundleConfig';
26+
import StandardIcon_Chart from './icons/standard/Chart';
2627
import StandardIcon_ConnectedApps from './icons/standard/ConnectedApps';
28+
import StandardIcon_Customers from './icons/standard/Customers';
29+
import StandardIcon_CustomerPortalUsers from './icons/standard/CustomerPortalUsers';
2730
import StandardIcon_DataStreams from './icons/standard/DataStreams';
2831
import StandardIcon_EmployeeOrganization from './icons/standard/EmployeeOrganization';
2932
import StandardIcon_Entity from './icons/standard/Entity';
@@ -32,6 +35,8 @@ import StandardIcon_Feed from './icons/standard/Feed';
3235
import StandardIcon_Feedback from './icons/standard/Feedback';
3336
import StandardIcon_Form from './icons/standard/Form';
3437
import StandardIcon_Formula from './icons/standard/Formula';
38+
import StandardIcon_Groups from './icons/standard/Groups';
39+
import StandardIcon_Incident from './icons/standard/Incident';
3540
import StandardIcon_MultiPicklist from './icons/standard/MultiPicklist';
3641
import StandardIcon_Opportunity from './icons/standard/Opportunity';
3742
import StandardIcon_Outcome from './icons/standard/Outcome';
@@ -56,6 +61,8 @@ import UtilityIcon_Announcement from './icons/utility/Announcement';
5661
import UtilityIcon_Apex from './icons/utility/Apex';
5762
import UtilityIcon_ApexPlugin from './icons/utility/ApexPlugin';
5863
import UtilityIcon_Archive from './icons/utility/Archive';
64+
import UtilityIcon_ArrowLeft from './icons/utility/ArrowLeft';
65+
import UtilityIcon_ArrowRight from './icons/utility/ArrowRight';
5966
import UtilityIcon_Arrowdown from './icons/utility/Arrowdown';
6067
import UtilityIcon_Arrowup from './icons/utility/Arrowup';
6168
import UtilityIcon_Back from './icons/utility/Back';
@@ -90,6 +97,7 @@ import UtilityIcon_ExpandAll from './icons/utility/ExpandAll';
9097
import UtilityIcon_ExpandAlt from './icons/utility/ExpandAlt';
9198
import UtilityIcon_Fallback from './icons/utility/Fallback';
9299
import UtilityIcon_Favorite from './icons/utility/Favorite';
100+
import UtilityIcon_Feed from './icons/utility/Feed';
93101
import UtilityIcon_File from './icons/utility/File';
94102
import UtilityIcon_Filter from './icons/utility/Filter';
95103
import UtilityIcon_FilterList from './icons/utility/FilterList';
@@ -203,7 +211,10 @@ const standardIcons = {
203211
asset_relationship: StandardIcon_AssetRelationship,
204212
billing: StandardIcon_Billing,
205213
bundle_config: StandardIcon_BundleConfig,
214+
chart: StandardIcon_Chart,
206215
connected_apps: StandardIcon_ConnectedApps,
216+
customers: StandardIcon_Customers,
217+
customer_portal_users: StandardIcon_CustomerPortalUsers,
207218
data_streams: StandardIcon_DataStreams,
208219
employee_organization: StandardIcon_EmployeeOrganization,
209220
entity: StandardIcon_Entity,
@@ -212,6 +223,8 @@ const standardIcons = {
212223
feedback: StandardIcon_Feedback,
213224
form: StandardIcon_Form,
214225
formula: StandardIcon_Formula,
226+
groups: StandardIcon_Groups,
227+
incident: StandardIcon_Incident,
215228
multi_picklist: StandardIcon_MultiPicklist,
216229
opportunity: StandardIcon_Opportunity,
217230
outcome: StandardIcon_Outcome,
@@ -254,6 +267,8 @@ const utilityIcons = {
254267
apex_plugin: UtilityIcon_ApexPlugin,
255268
apex: UtilityIcon_Apex,
256269
archive: UtilityIcon_Archive,
270+
arrow_left: UtilityIcon_ArrowLeft,
271+
arrow_right: UtilityIcon_ArrowRight,
257272
arrowdown: UtilityIcon_Arrowdown,
258273
arrowup: UtilityIcon_Arrowup,
259274
back: UtilityIcon_Back,
@@ -288,6 +303,7 @@ const utilityIcons = {
288303
expand_alt: UtilityIcon_ExpandAlt,
289304
fallback: UtilityIcon_Fallback,
290305
favorite: UtilityIcon_Favorite,
306+
feed: UtilityIcon_Feed,
291307
file: UtilityIcon_File,
292308
filter: UtilityIcon_Filter,
293309
filterList: UtilityIcon_FilterList,

libs/shared/ui-core/src/app/HeaderNavbar.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ import { RecordSearchPopover } from '../record/RecordSearchPopover';
2626
import { UserSearchPopover } from '../record/UserSearchPopover';
2727
import HeaderDonatePopover from './HeaderDonatePopover';
2828
import HeaderHelpPopover from './HeaderHelpPopover';
29-
import { HeaderNavbarItems } from './HeaderNavbarItems';
30-
import { HeaderNavbarBillingUserItems } from './HeaderNavbarReadOnlyUserItems';
29+
import { useHeaderNavbarItems } from './HeaderNavbarItems';
30+
import { headerNavbarBillingUserItems } from './HeaderNavbarReadOnlyUserItems';
3131
import HeaderUpdateNotification from './HeaderUpdateNotification';
3232
import LogoPro from './jetstream-logo-pro-200w.png';
3333
import Logo from './jetstream-logo-v1-200w.png';
@@ -149,6 +149,7 @@ export const HeaderNavbar = ({
149149
const colorScheme: ColorScheme = userPreferences?.colorScheme ?? 'light';
150150
const [enableNotifications, setEnableNotifications] = useState(false);
151151
const [userMenuItems, setUserMenuItems] = useState<DropDownItem[]>([]);
152+
const navbarItems = useHeaderNavbarItems();
152153

153154
function handleUserMenuSelection(id: string) {
154155
switch (id) {
@@ -311,10 +312,7 @@ export const HeaderNavbar = ({
311312
isEmbeddedApp={isEmbeddedApp}
312313
onUserMenuItemSelected={handleUserMenuSelection}
313314
>
314-
<Navbar>
315-
{isReadOnlyUser && <HeaderNavbarBillingUserItems />}
316-
{!isReadOnlyUser && <HeaderNavbarItems />}
317-
</Navbar>
315+
<Navbar items={isReadOnlyUser ? headerNavbarBillingUserItems : navbarItems} />
318316
</Header>
319317
</Fragment>
320318
);

libs/shared/ui-core/src/app/HeaderNavbarItems.tsx

Lines changed: 68 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,31 @@
11
import { APP_ROUTES } from '@jetstream/shared/ui-router';
2-
import { NavbarItem, NavbarItemWaffle, NavbarMenuItems } from '@jetstream/ui';
2+
import type { NavbarItemConfig } from '@jetstream/ui';
3+
import { useMemo } from 'react';
34

4-
export const HeaderNavbarItems = () => {
5-
return (
6-
<>
7-
<NavbarItemWaffle path={APP_ROUTES.HOME.ROUTE} search={APP_ROUTES.HOME.SEARCH_PARAM} title="Home" assistiveText="Home Page" />
8-
<NavbarItem
9-
path={APP_ROUTES.QUERY.ROUTE}
10-
search={APP_ROUTES.QUERY.SEARCH_PARAM}
11-
title={APP_ROUTES.QUERY.DESCRIPTION}
12-
label={APP_ROUTES.QUERY.TITLE}
13-
/>
14-
15-
<NavbarMenuItems
16-
label="Load Records"
17-
items={[
5+
export function useHeaderNavbarItems(): NavbarItemConfig[] {
6+
return useMemo<NavbarItemConfig[]>(
7+
() => [
8+
{
9+
id: 'home',
10+
type: 'waffle',
11+
path: APP_ROUTES.HOME.ROUTE,
12+
search: APP_ROUTES.HOME.SEARCH_PARAM,
13+
title: 'Home',
14+
assistiveText: 'Home Page',
15+
},
16+
{
17+
id: 'query',
18+
type: 'item',
19+
path: APP_ROUTES.QUERY.ROUTE,
20+
search: APP_ROUTES.QUERY.SEARCH_PARAM,
21+
title: APP_ROUTES.QUERY.DESCRIPTION,
22+
label: APP_ROUTES.QUERY.TITLE,
23+
},
24+
{
25+
id: 'load-records',
26+
type: 'menu',
27+
label: 'Load Records',
28+
items: [
1829
{
1930
id: 'load',
2031
path: APP_ROUTES.LOAD.ROUTE,
@@ -43,25 +54,29 @@ export const HeaderNavbarItems = () => {
4354
title: APP_ROUTES.LOAD_CREATE_RECORD.DESCRIPTION,
4455
label: APP_ROUTES.LOAD_CREATE_RECORD.TITLE,
4556
},
46-
]}
47-
/>
48-
49-
<NavbarItem
50-
path={APP_ROUTES.AUTOMATION_CONTROL.ROUTE}
51-
search={APP_ROUTES.AUTOMATION_CONTROL.SEARCH_PARAM}
52-
title={APP_ROUTES.AUTOMATION_CONTROL.DESCRIPTION}
53-
label={APP_ROUTES.AUTOMATION_CONTROL.TITLE}
54-
/>
55-
<NavbarItem
56-
path={APP_ROUTES.PERMISSION_MANAGER.ROUTE}
57-
search={APP_ROUTES.PERMISSION_MANAGER.SEARCH_PARAM}
58-
title={APP_ROUTES.PERMISSION_MANAGER.DESCRIPTION}
59-
label={APP_ROUTES.PERMISSION_MANAGER.TITLE}
60-
/>
61-
62-
<NavbarMenuItems
63-
label="Deploy Metadata"
64-
items={[
57+
],
58+
},
59+
{
60+
id: 'automation-control',
61+
type: 'item',
62+
path: APP_ROUTES.AUTOMATION_CONTROL.ROUTE,
63+
search: APP_ROUTES.AUTOMATION_CONTROL.SEARCH_PARAM,
64+
title: APP_ROUTES.AUTOMATION_CONTROL.DESCRIPTION,
65+
label: APP_ROUTES.AUTOMATION_CONTROL.TITLE,
66+
},
67+
{
68+
id: 'permission-manager',
69+
type: 'item',
70+
path: APP_ROUTES.PERMISSION_MANAGER.ROUTE,
71+
search: APP_ROUTES.PERMISSION_MANAGER.SEARCH_PARAM,
72+
title: APP_ROUTES.PERMISSION_MANAGER.DESCRIPTION,
73+
label: APP_ROUTES.PERMISSION_MANAGER.TITLE,
74+
},
75+
{
76+
id: 'deploy-metadata',
77+
type: 'menu',
78+
label: 'Deploy Metadata',
79+
items: [
6580
{
6681
id: 'deploy-metadata',
6782
path: APP_ROUTES.DEPLOY_METADATA.ROUTE,
@@ -90,12 +105,13 @@ export const HeaderNavbarItems = () => {
90105
title: APP_ROUTES.FORMULA_EVALUATOR.DESCRIPTION,
91106
label: APP_ROUTES.FORMULA_EVALUATOR.TITLE,
92107
},
93-
]}
94-
/>
95-
96-
<NavbarMenuItems
97-
label="Developer Tools"
98-
items={[
108+
],
109+
},
110+
{
111+
id: 'developer-tools',
112+
type: 'menu',
113+
label: 'Developer Tools',
114+
items: [
99115
{
100116
id: 'apex',
101117
path: APP_ROUTES.ANON_APEX.ROUTE,
@@ -131,11 +147,13 @@ export const HeaderNavbarItems = () => {
131147
title: APP_ROUTES.PLATFORM_EVENT_MONITOR.DESCRIPTION,
132148
label: APP_ROUTES.PLATFORM_EVENT_MONITOR.TITLE,
133149
},
134-
]}
135-
/>
136-
<NavbarMenuItems
137-
label="Documentation &amp; Support"
138-
items={[
150+
],
151+
},
152+
{
153+
id: 'documentation-support',
154+
type: 'menu',
155+
label: 'Documentation & Support',
156+
items: [
139157
{
140158
id: 'feedback',
141159
path: APP_ROUTES.FEEDBACK_SUPPORT.ROUTE,
@@ -150,8 +168,9 @@ export const HeaderNavbarItems = () => {
150168
title: 'Documentation',
151169
label: 'Documentation',
152170
},
153-
]}
154-
/>
155-
</>
171+
],
172+
},
173+
],
174+
[],
156175
);
157-
};
176+
}
Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,37 @@
11
import { APP_ROUTES } from '@jetstream/shared/ui-router';
2-
import { NavbarItem, NavbarItemWaffle } from '@jetstream/ui';
2+
import type { NavbarItemConfig } from '@jetstream/ui';
33

4-
export const HeaderNavbarBillingUserItems = () => {
5-
return (
6-
<>
7-
<NavbarItemWaffle path={APP_ROUTES.HOME.ROUTE} search={APP_ROUTES.HOME.SEARCH_PARAM} title="Home" assistiveText="Home Page" />
8-
<NavbarItem
9-
path={APP_ROUTES.PROFILE.ROUTE}
10-
search={APP_ROUTES.PROFILE.SEARCH_PARAM}
11-
title={APP_ROUTES.PROFILE.DESCRIPTION}
12-
label={APP_ROUTES.PROFILE.TITLE}
13-
/>
14-
15-
<NavbarItem
16-
path={APP_ROUTES.BILLING.ROUTE}
17-
search={APP_ROUTES.BILLING.SEARCH_PARAM}
18-
title={APP_ROUTES.BILLING.DESCRIPTION}
19-
label={APP_ROUTES.BILLING.TITLE}
20-
/>
21-
22-
<NavbarItem
23-
path={APP_ROUTES.TEAM_DASHBOARD.ROUTE}
24-
search={APP_ROUTES.TEAM_DASHBOARD.SEARCH_PARAM}
25-
title={APP_ROUTES.TEAM_DASHBOARD.DESCRIPTION}
26-
label={APP_ROUTES.TEAM_DASHBOARD.TITLE}
27-
/>
28-
</>
29-
);
30-
};
4+
export const headerNavbarBillingUserItems: NavbarItemConfig[] = [
5+
{
6+
id: 'home',
7+
type: 'waffle',
8+
path: APP_ROUTES.HOME.ROUTE,
9+
search: APP_ROUTES.HOME.SEARCH_PARAM,
10+
title: 'Home',
11+
assistiveText: 'Home Page',
12+
},
13+
{
14+
id: 'profile',
15+
type: 'item',
16+
path: APP_ROUTES.PROFILE.ROUTE,
17+
search: APP_ROUTES.PROFILE.SEARCH_PARAM,
18+
title: APP_ROUTES.PROFILE.DESCRIPTION,
19+
label: APP_ROUTES.PROFILE.TITLE,
20+
},
21+
{
22+
id: 'billing',
23+
type: 'item',
24+
path: APP_ROUTES.BILLING.ROUTE,
25+
search: APP_ROUTES.BILLING.SEARCH_PARAM,
26+
title: APP_ROUTES.BILLING.DESCRIPTION,
27+
label: APP_ROUTES.BILLING.TITLE,
28+
},
29+
{
30+
id: 'team-dashboard',
31+
type: 'item',
32+
path: APP_ROUTES.TEAM_DASHBOARD.ROUTE,
33+
search: APP_ROUTES.TEAM_DASHBOARD.SEARCH_PARAM,
34+
title: APP_ROUTES.TEAM_DASHBOARD.DESCRIPTION,
35+
label: APP_ROUTES.TEAM_DASHBOARD.TITLE,
36+
},
37+
];

libs/shared/ui-core/src/create-fields/create-fields-load-utils.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { parseCustomFieldApiNameForTooling } from '@jetstream/shared/utils';
12
import { Field } from '@jetstream/types';
23
import { CustomFieldMetadata, FieldValues, SalesforceFieldType } from './create-fields-types';
34
import { getInitialValues } from './create-fields-utils';
@@ -338,11 +339,11 @@ export interface ExistingFieldRow {
338339

339340
/**
340341
* Returns the namespace prefix from a custom field API name, or null if non-namespaced.
341-
* e.g. "ns__MyField__c" => "ns", "MyField__c" => null
342+
* Uses {@link parseCustomFieldApiNameForTooling} so unmanaged names like `My_Field__c` are not mistaken for packaged fields.
342343
*/
343344
function getFieldNamespacePrefix(fieldName: string): string | null {
344-
const match = /^([A-Za-z0-9]+)__.+__c$/.exec(fieldName);
345-
return match ? match[1] : null;
345+
const parsed = parseCustomFieldApiNameForTooling(fieldName);
346+
return parsed?.namespacePrefix ?? null;
346347
}
347348

348349
/**

libs/shared/ui-core/src/load/LoadRecordsResultsModal.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
CopyToClipboardWithToolTip,
1414
DataTable,
1515
getRowTypeFromValue,
16+
getWrappedTextRowHeight,
1617
Grid,
1718
Icon,
1819
Modal,
@@ -33,7 +34,9 @@ const COL_WIDTH_MAP = {
3334
_errors: 450,
3435
};
3536

36-
const getRowHeight = ({ row }: { type: 'ROW' | 'GROUP'; row: any }) => (row?._errors ? 75 : 25);
37+
// Grow rows to fit their wrapped error message, tracking the live width of the _errors column on resize.
38+
const getRowHeight = ({ row, columnWidths }: { type: 'ROW' | 'GROUP'; row: any; columnWidths: Record<string, number> }) =>
39+
getWrappedTextRowHeight(row?._errors, columnWidths?.['_errors'] ?? COL_WIDTH_MAP._errors);
3740

3841
const getDefaultSelectedRows = (rows: any[], selectable: boolean): ReadonlySet<Key> =>
3942
selectable ? new Set(rows.map((_row, i) => `id-${i}`)) : new Set();
@@ -84,9 +87,12 @@ export const LoadRecordsResultsModal: FunctionComponent<LoadRecordsResultsModalP
8487
item === '_errors'
8588
? ({ row }) => (
8689
<p
90+
title={row?._errors}
8791
css={css`
8892
white-space: pre-wrap;
93+
overflow-wrap: anywhere;
8994
line-height: normal;
95+
overflow: hidden;
9096
`}
9197
>
9298
{row._errors && (

0 commit comments

Comments
 (0)