-
Notifications
You must be signed in to change notification settings - Fork 45
fix(admin): Admin org design fixes #1799
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
0e359b3
ee74ebd
dd1af6e
33d4b56
46df968
2a49926
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ import { | |
| Flex, | ||
| Text, | ||
| Menu, | ||
| IconButton, | ||
| } from "@raystack/apsara"; | ||
| import type { DataTableColumnDef } from "@raystack/apsara"; | ||
| import type { | ||
|
|
@@ -45,13 +46,15 @@ interface AddMemberDropdownProps { | |
| eligibleMembers: User[]; | ||
| isLoading: boolean; | ||
| setSearchQuery: (query: string) => void; | ||
| disabled?: boolean; | ||
| } | ||
|
|
||
| function AddMemberDropdown({ | ||
| onAddMember, | ||
| eligibleMembers, | ||
| isLoading, | ||
| setSearchQuery, | ||
| disabled, | ||
| }: AddMemberDropdownProps) { | ||
| const t = useTerminology(); | ||
| return ( | ||
|
|
@@ -60,7 +63,7 @@ function AddMemberDropdown({ | |
| autocompleteMode="manual" | ||
| onInputValueChange={setSearchQuery} | ||
| > | ||
| <Menu.SubmenuTrigger data-test-id="add-members"> | ||
| <Menu.SubmenuTrigger disabled={disabled} data-test-id="add-members"> | ||
| Add {t.member({ case: "lower" })} | ||
| </Menu.SubmenuTrigger> | ||
| <Menu.SubmenuContent> | ||
|
|
@@ -96,12 +99,14 @@ function ProjectActionsContent({ | |
| project, | ||
| handleProjectUpdate, | ||
| handleRenameOptionOpen, | ||
| canAddMember, | ||
| }: { | ||
| project: SearchOrganizationProjectsResponse_OrganizationProject; | ||
| handleProjectUpdate: ( | ||
| project: SearchOrganizationProjectsResponse_OrganizationProject, | ||
| ) => void; | ||
| handleRenameOptionOpen: () => void; | ||
| canAddMember: boolean; | ||
| }) { | ||
| const t = useTerminology(); | ||
| const handleRenameOptionClick = (e: React.MouseEvent<HTMLDivElement>) => { | ||
|
|
@@ -130,6 +135,7 @@ function ProjectActionsContent({ | |
| eligibleMembers={eligibleMembers} | ||
| isLoading={isLoading} | ||
| setSearchQuery={setSearchQuery} | ||
| disabled={!canAddMember} | ||
| /> | ||
| <Menu.Item | ||
| onClick={handleRenameOptionClick} | ||
|
|
@@ -144,17 +150,19 @@ function ProjectActionsContent({ | |
| function ProjectActions({ | ||
| project, | ||
| handleProjectUpdate, | ||
| canAddMember, | ||
| }: { | ||
| project: SearchOrganizationProjectsResponse_OrganizationProject; | ||
| handleProjectUpdate: ( | ||
| project: SearchOrganizationProjectsResponse_OrganizationProject, | ||
| ) => void; | ||
| canAddMember: boolean; | ||
| }) { | ||
| const [open, setOpen] = useState(false); | ||
|
|
||
| const [isRenameDialogOpen, setIsRenameDialogOpen] = useState(false); | ||
|
|
||
| const preventClickBubbling = (e: React.MouseEvent<SVGElement>) => { | ||
| const preventClickBubbling = (e: React.MouseEvent) => { | ||
| e.stopPropagation(); | ||
| }; | ||
|
|
||
|
|
@@ -182,17 +190,21 @@ function ProjectActions({ | |
| <Menu open={open} onOpenChange={handleOpen}> | ||
| <Menu.Trigger | ||
| render={ | ||
| <DotsHorizontalIcon | ||
| <IconButton | ||
| size={3} | ||
| onClick={preventClickBubbling} | ||
| data-test-id="admin-project-actions" | ||
| /> | ||
| > | ||
| <DotsHorizontalIcon /> | ||
| </IconButton> | ||
|
Comment on lines
+193
to
+199
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "Files:"
git ls-files | rg 'web/sdk/admin/views/organizations/details/projects/(columns|members/columns)\.tsx$|IconButton|DotsHorizontalIcon' || true
echo
echo "Target snippets:"
for f in \
web/sdk/admin/views/organizations/details/projects/columns.tsx \
web/sdk/admin/views/organizations/details/projects/members/columns.tsx
do
if [ -f "$f" ]; then
echo "--- $f"
sed -n '160,215p' "$f"
echo "--- $f members"
sed -n '80,125p' "$f"
fi
done
echo
echo "IconButton definitions/usages nearby:"
rg -n "function IconButton|const IconButton|IconButton|DotsHorizontalIcon|aria-label|title=" web/sdk/admin | head -200 || trueRepository: raystack/frontier Length of output: 16491 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Read-only behavioral/structural probe for icon-only button accessibility indicators.
python3 - <<'PY'
import re, pathlib
xs = {
"web/sdk/admin/views/organizations/details/projects/columns.tsx": (188, 204),
"web/sdk/admin/views/organizations/details/projects/members/columns.tsx": (97, 113),
}
for path, (start, end) in xs.items():
text = pathlib.Path(path).read_text()
lines = text.splitlines()
block = "\n".join(lines[start-1:end])
print(f"--- {path}: lines {start}-{end}")
print(block)
print("contains aria-label/aria-labelledby:", bool(re.search(r"aria-(label|labelled-by)\s*=", block)))
print("contains title:", bool(re.search(r"\btitle\s*=", block)))
print("contains IconButton:", "IconButton" in block)
print("contains icon trigger:", bool(re.search(r"<(DotsHorizontalIcon)|<.*Icon", block, re.S)))
PYRepository: raystack/frontier Length of output: 1552 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "IconButton packages/usages:"
rg -n 'from "`@raystack/apsara`"|from .*apsara.*|IconButton' package.json web/sdk/admin/package.json pnpm-lock.yaml package-lock.json yarn.lock 2>/dev/null || true
echo
rg -n 'export .*IconButton|const IconButton|function IconButton|IconButton =|IconButton(' . --glob '!node_modules' --glob '!dist' --glob '!build' | head -300
echo
echo "Imports in target files:"
sed -n '1,30p' web/sdk/admin/views/organizations/details/projects/columns.tsx
sed -n '1,30p' web/sdk/admin/views/organizations/details/projects/members/columns.tsxRepository: raystack/frontier Length of output: 397 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "Imports in target files:"
sed -n '1,30p' web/sdk/admin/views/organizations/details/projects/columns.tsx
sed -n '1,30p' web/sdk/admin/views/organizations/details/projects/members/columns.tsx
echo
echo "IconButton usages in target package paths:"
rg -n 'from "`@raystack/apsara`"|IconButton|title=/aria-label=|data-test-id="admin-project-(actions|member-action-menu)"' web/sdk/admin/views/organizations/details/projects/columns.tsx web/sdk/admin/views/organizations/details/projects/members/columns.tsx
echo
echo "Local IconButton-like component definitions excluding generated/package dirs:"
rg -n 'const IconButton|function IconButton|export .*IconButton|IconButton\s*=' web/sdk . --glob '!node_modules' --glob '!dist' --glob '!build' --glob '!*.lock' | head -200Repository: raystack/frontier Length of output: 3299 🌐 Web query:
💡 Result: In the Citations:
Add accessible names to both icon-only action triggers. Both triggers render only
📍 Affects 2 files
|
||
| } | ||
| /> | ||
| <Menu.Content className={styles["table-action-dropdown"]}> | ||
| <ProjectActionsContent | ||
| project={project} | ||
| handleProjectUpdate={handleProjectUpdate} | ||
| handleRenameOptionOpen={handleRenameOptionOpen} | ||
| canAddMember={canAddMember} | ||
| /> | ||
| </Menu.Content> | ||
| </Menu> | ||
|
|
@@ -216,6 +228,10 @@ export const getColumns = ({ | |
| SearchOrganizationProjectsResponse_OrganizationProject, | ||
| unknown | ||
| >[] => { | ||
| // Adding a project member requires searching org members. With a single org | ||
| // member there is no one to add, so the action is disabled until more members | ||
| // are invited. | ||
| const canAddMember = Object.keys(orgMembersMap).length > 1; | ||
| return [ | ||
| { | ||
| accessorKey: "title", | ||
|
|
@@ -289,6 +305,7 @@ export const getColumns = ({ | |
| <ProjectActions | ||
| project={row?.original} | ||
| handleProjectUpdate={handleProjectUpdate} | ||
| canAddMember={canAddMember} | ||
| /> | ||
| ); | ||
| }, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Normalize all member-facing role labels.
The table uses
formatRoleTitle, but the filter options at Lines 99-101 and assignment actions at Lines 154-167 still render rawrole.title. This leaves users seeing inconsistent values such asOwnerin the table andOrganization Ownerelsewhere. Apply the helper to those display labels while preserving the raw title in API payloads.Also applies to: 47-50