Skip to content

Commit a29692b

Browse files
committed
refactor: update organization selectors and dropdown component for consistency
1 parent cdfbe99 commit a29692b

File tree

3 files changed

+53
-41
lines changed

3 files changed

+53
-41
lines changed

app/client/src/ce/pages/Applications/index.tsx

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ import {
102102
getIsFetchingMyOrganizations,
103103
getMyOrganizations,
104104
getOrganizationPermissions,
105-
activeOrganisationId,
106105
shouldShowLicenseBanner,
106+
activeOrganizationId,
107107
} from "ee/selectors/organizationSelectors";
108108
import { getWorkflowsList } from "ee/selectors/workflowSelectors";
109109
import {
@@ -145,8 +145,8 @@ import {
145145
import OldRepoLimitExceededErrorModal from "pages/Editor/gitSync/RepoLimitExceededErrorModal";
146146
import { trackCurrentDomain } from "utils/multiOrgDomains";
147147
import OrganizationDropdown from "components/OrganizationDropdown";
148-
import { fetchMyOrganizations } from "ce/actions/organizationActions";
149-
import type { Organization } from "ce/api/OrganizationApi";
148+
import { fetchMyOrganizations } from "ee/actions/organizationActions";
149+
import type { Organization } from "ee/api/OrganizationApi";
150150
import { useIsCloudBillingEnabled } from "hooks";
151151

152152
function GitModals() {
@@ -454,8 +454,8 @@ export function LeftPane(props: LeftPaneProps) {
454454
const {
455455
activeWorkspaceId,
456456
isBannerVisible = false,
457-
isFetchingWorkspaces,
458457
isFetchingOrganizations,
458+
isFetchingWorkspaces,
459459
activeOrganizationId,
460460
workspaces = [],
461461
organizations = [],
@@ -467,17 +467,19 @@ export function LeftPane(props: LeftPaneProps) {
467467

468468
return (
469469
<LeftPaneWrapper isBannerVisible={isBannerVisible}>
470-
{isCloudBillingEnabled && !isFetchingOrganizations && (
471-
<OrganizationDropdown
472-
organizations={organizations}
473-
selectedOrganization={
474-
organizations.find(
475-
(organization) =>
476-
organization.organizationId === activeOrganizationId,
477-
) || organizations[0]
478-
}
479-
/>
480-
)}
470+
{isCloudBillingEnabled &&
471+
!isFetchingOrganizations &&
472+
organizations.length > 0 && (
473+
<OrganizationDropdown
474+
organizations={organizations}
475+
selectedOrganization={
476+
organizations.find(
477+
(organization) =>
478+
organization.organizationId === activeOrganizationId,
479+
) || organizations[0]
480+
}
481+
/>
482+
)}
481483
<LeftPaneSection
482484
heading={createMessage(WORKSPACES_HEADING)}
483485
isBannerVisible={isBannerVisible}
@@ -1019,7 +1021,7 @@ export const ApplictionsMainPage = (props: any) => {
10191021
const isBannerVisible = showBanner && (isHomePage || isLicensePage);
10201022
const organizations = useSelector(getMyOrganizations);
10211023
const isFetchingOrganizations = useSelector(getIsFetchingMyOrganizations);
1022-
const currentOrganizationId = useSelector(activeOrganisationId);
1024+
const currentOrganizationId = useSelector(activeOrganizationId);
10231025

10241026
// TODO: Fix this the next time the file is edited
10251027
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -1088,8 +1090,8 @@ export const ApplictionsMainPage = (props: any) => {
10881090
return (
10891091
<PageWrapper displayName="Applications">
10901092
<LeftPane
1091-
activeWorkspaceId={activeWorkspaceId}
10921093
activeOrganizationId={currentOrganizationId}
1094+
activeWorkspaceId={activeWorkspaceId}
10931095
isBannerVisible={isBannerVisible}
10941096
isFetchingOrganizations={isFetchingOrganizations}
10951097
isFetchingWorkspaces={isFetchingWorkspaces}

app/client/src/ce/selectors/organizationSelectors.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,6 @@ export const getIsFetchingMyOrganizations = (state: DefaultRootState) => {
7676
return state.organization?.isFetchingMyOrganizations || false;
7777
};
7878

79-
export const activeOrganisationId = (state: DefaultRootState) => {
79+
export const activeOrganizationId = (state: DefaultRootState) => {
8080
return state.organization?.tenantId;
8181
};

app/client/src/components/OrganizationDropdown.tsx

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Avatar, Icon } from "@appsmith/ads";
2-
import type { Organization } from "ce/api/OrganizationApi";
3-
import { createMessage, PENDING_INVITATIONS } from "ce/constants/messages";
2+
import type { Organization } from "ee/api/OrganizationApi";
3+
import { createMessage, PENDING_INVITATIONS } from "ee/constants/messages";
44
import React, { useCallback, useEffect, useRef, useState } from "react";
55
import styled from "styled-components";
66

@@ -36,7 +36,9 @@ const TriggerContent = styled.div`
3636
`;
3737

3838
const TriggerText = styled.span`
39-
truncate: true;
39+
overflow: hidden;
40+
text-overflow: ellipsis;
41+
white-space: nowrap;
4042
font-weight: 400;
4143
`;
4244

@@ -136,28 +138,30 @@ export interface PendingInvitation {
136138
}
137139

138140
export interface OrganizationDropdownProps {
139-
selectedOrganization: Organization;
140-
organizations: Organization[];
141141
"data-testid"?: string;
142+
organizations: Organization[];
143+
selectedOrganization: Organization;
142144
}
143145

144146
const OrganizationDropdown: React.FC<OrganizationDropdownProps> = ({
145-
selectedOrganization,
146-
organizations = [],
147147
"data-testid": testId,
148+
organizations = [],
149+
selectedOrganization,
148150
}) => {
149151
const [isOpen, setIsOpen] = useState(false);
150152
const dropdownRef = useRef<HTMLDivElement>(null);
151153
const triggerRef = useRef<HTMLButtonElement>(null);
152-
const activeOrganizations = organizations.filter(
154+
const safeOrganizations = organizations || [];
155+
const activeOrganizations = safeOrganizations.filter(
153156
(org) => org.state === "ACTIVE",
154157
);
155-
const pendingInvitations = organizations.filter(
158+
const pendingInvitations = safeOrganizations.filter(
156159
(org) => org.state === "INVITED",
157160
);
158161

159162
const generateInitials = (name: string): string => {
160163
if (!name) return "";
164+
161165
return name.charAt(0).toUpperCase();
162166
};
163167

@@ -171,6 +175,7 @@ const OrganizationDropdown: React.FC<OrganizationDropdownProps> = ({
171175

172176
window.open(url, "_blank", "noopener,noreferrer");
173177
}
178+
174179
setIsOpen(false);
175180
}, []);
176181

@@ -193,8 +198,10 @@ const OrganizationDropdown: React.FC<OrganizationDropdownProps> = ({
193198

194199
if (isOpen) {
195200
document.addEventListener("mousedown", handleClickOutside);
196-
return () =>
201+
202+
return () => {
197203
document.removeEventListener("mousedown", handleClickOutside);
204+
};
198205
}
199206
}, [isOpen]);
200207

@@ -203,23 +210,23 @@ const OrganizationDropdown: React.FC<OrganizationDropdownProps> = ({
203210
const renderOrgAvatar = (orgName: string) => {
204211
return (
205212
<Avatar
206-
label={generateInitials(orgName)}
207213
firstLetter={generateInitials(orgName)}
214+
label={generateInitials(orgName)}
208215
size="sm"
209216
/>
210217
);
211218
};
212219

213220
return (
214-
<DropdownContainer ref={dropdownRef} data-testid={testId}>
221+
<DropdownContainer data-testid={testId} ref={dropdownRef}>
215222
<DropdownTrigger
216-
ref={triggerRef}
217-
type="button"
218-
onClick={handleToggle}
219-
onKeyDown={handleKeyDown}
220223
aria-expanded={isOpen}
221224
aria-haspopup="listbox"
222225
aria-label={`Current organization: ${displayText}`}
226+
onClick={handleToggle}
227+
onKeyDown={handleKeyDown}
228+
ref={triggerRef}
229+
type="button"
223230
>
224231
<TriggerContent>
225232
{renderOrgAvatar(displayText)}
@@ -228,28 +235,30 @@ const OrganizationDropdown: React.FC<OrganizationDropdownProps> = ({
228235
<Icon name="dropdown" size="md" />
229236
</DropdownTrigger>
230237

231-
<DropdownMenu isOpen={isOpen} role="listbox" aria-label="Organizations">
238+
<DropdownMenu aria-label="Organizations" isOpen={isOpen} role="listbox">
232239
{activeOrganizations
233240
.slice()
234241
.sort((a, b) => {
235242
const aIsSelected =
236243
a.organizationId === selectedOrganization?.organizationId;
244+
237245
const bIsSelected =
238246
b.organizationId === selectedOrganization?.organizationId;
239247

240248
if (aIsSelected && !bIsSelected) return -1;
249+
241250
if (!aIsSelected && bIsSelected) return 1;
251+
242252
return 0;
243253
})
244254
.map((org) => {
245255
const isSelected =
246256
org.organizationId === selectedOrganization?.organizationId;
247257
return (
248258
<MenuItem
249-
key={org.organizationId}
250-
role="option"
251-
tabIndex={0}
259+
aria-selected={isSelected}
252260
isSelected={isSelected}
261+
key={org.organizationId}
253262
onClick={!isSelected ? () => handleSelect(org) : undefined}
254263
onKeyDown={
255264
!isSelected
@@ -261,7 +270,8 @@ const OrganizationDropdown: React.FC<OrganizationDropdownProps> = ({
261270
}
262271
: undefined
263272
}
264-
aria-selected={isSelected}
273+
role="option"
274+
tabIndex={0}
265275
>
266276
{renderOrgAvatar(org.organizationName)}
267277
<MenuItemText>
@@ -272,9 +282,9 @@ const OrganizationDropdown: React.FC<OrganizationDropdownProps> = ({
272282

273283
{!isSelected && (
274284
<MenuItemIcon
285+
className="hover-icon color-fg-muted"
275286
name="share-box-line"
276287
size="md"
277-
className="hover-icon color-fg-muted"
278288
/>
279289
)}
280290
</MenuItem>
@@ -295,9 +305,9 @@ const OrganizationDropdown: React.FC<OrganizationDropdownProps> = ({
295305
<MenuItemText>{invitation.organizationName}</MenuItemText>
296306

297307
<MenuItemIcon
308+
className="hover-icon color-fg-muted"
298309
name="share-box-line"
299310
size="md"
300-
className="hover-icon color-fg-muted"
301311
/>
302312
</MenuItem>
303313
))}

0 commit comments

Comments
 (0)