Skip to content

Commit 5f36219

Browse files
committed
refactor: update the sidebar and remove the topbar
1 parent b848b31 commit 5f36219

24 files changed

Lines changed: 379 additions & 403 deletions

backend/users/middleware.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def middleware(request: HttpRequest) -> HttpResponse:
4040
language=_extract_language(request),
4141
# Lazily computed properties:
4242
isAuthenticated=lambda: request.user.is_authenticated,
43-
user=lambda: User.to_dict(request.user) if request.user.is_authenticated else None,
43+
user=lambda: User.to_json(request.user) if request.user.is_authenticated else None,
4444
)
4545
return get_response(request)
4646

backend/users/models.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from django.forms.models import model_to_dict
1111
from django.utils.translation import gettext as _
1212

13+
from tools.display import format_dates
1314
from tools.utils.choices import CommonLabelValueChoices
1415

1516

@@ -119,6 +120,20 @@ class Meta:
119120
def to_dict(self):
120121
return model_to_dict(self, exclude=("password", "is_superuser", "is_staff", "groups", "user_permissions"))
121122

123+
def to_json(self):
124+
return {
125+
"id": self.id,
126+
"firstName": self.first_name,
127+
"lastName": self.last_name,
128+
"fullName": self.name,
129+
"email": self.email,
130+
"roleLabel": RoleChoices(self.main_role).label,
131+
"roleValue": RoleChoices(self.main_role).value,
132+
"addedSince": format_dates.short_date(self.date_joined),
133+
"lastActivity": format_dates.short_datetime(self.last_login),
134+
"ngohubId": self.ngohub_id,
135+
}
136+
122137
def __str__(self):
123138
return self.email
124139

backend/users/views/team/listing.py

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,37 +11,29 @@
1111
from django.urls import reverse
1212
from django.utils.translation import gettext_lazy as _
1313
from django.views.decorators.cache import cache_control
14-
1514
from tools.data_models.filtering import FilterField, FilterItem
16-
from tools.display import format_dates as display_dates
1715
from tools.display.url_build import build_ngohub_url
1816
from tools.utils.filtering import build_filters_display, build_filters_mapping, filter_qs
1917
from tools.utils.pagination import paginate_queryset
2018
from tools.utils.search import search
2119
from tools.utils.serializers import inertia_enhanced
2220
from tools.utils.sort_parser import parse_order_parameter
21+
2322
from users.forms import AddTeamUserForm
2423
from users.models import RoleChoices, User
2524

2625
logger = logging.getLogger(__name__)
2726

2827

2928
def _serialize_users(users_page: Page[User], user_id: int) -> List[Dict]:
30-
return [
31-
{
32-
"id": user.id,
33-
"firstName": user.first_name,
34-
"lastName": user.last_name,
35-
"email": user.email,
36-
"isCurrentUser": user.id == user_id,
37-
"roleLabel": RoleChoices(user.main_role).label,
38-
"roleValue": RoleChoices(user.main_role).value,
39-
"addedSince": display_dates.short_date(user.date_joined),
40-
"lastActivity": display_dates.short_datetime(user.last_login),
41-
"ngohubId": user.ngohub_id,
42-
}
43-
for user in users_page
44-
]
29+
users = []
30+
for user in users_page:
31+
new_user = user.to_json()
32+
new_user["isCurrentUser"] = bool(user.id == user_id)
33+
34+
users.append(new_user)
35+
36+
return users
4537

4638

4739
def _get_filter_options() -> List[FilterField]:

frontend/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"@radix-ui/react-avatar": "^1.1.10",
2525
"@radix-ui/react-checkbox": "^1.3.2",
2626
"@radix-ui/react-collapsible": "^1.1.11",
27-
"@radix-ui/react-dialog": "^1.1.14",
27+
"@radix-ui/react-dialog": "^1.1.15",
2828
"@radix-ui/react-dropdown-menu": "^2.1.15",
2929
"@radix-ui/react-label": "^2.1.7",
3030
"@radix-ui/react-popover": "^1.1.14",
@@ -33,7 +33,7 @@
3333
"@radix-ui/react-slot": "^1.2.3",
3434
"@radix-ui/react-switch": "^1.2.5",
3535
"@radix-ui/react-tabs": "^1.1.12",
36-
"@radix-ui/react-tooltip": "^1.2.7",
36+
"@radix-ui/react-tooltip": "^1.2.8",
3737
"@tailwindcss/vite": "^4.1.10",
3838
"@tanstack/react-table": "^8.21.3",
3939
"class-variance-authority": "^0.7.1",
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { SidebarContextProps } from "@/components/types/sidebarContextProps";
2+
import * as React from "react";
3+
4+
export const SidebarContext = React.createContext<SidebarContextProps | null>(null);
5+
6+
function useSidebar() {
7+
const context = React.useContext(SidebarContext);
8+
if (!context) {
9+
throw new Error("useSidebar must be used within a SidebarProvider.");
10+
}
11+
12+
return context;
13+
}
14+
15+
export { useSidebar };

frontend/src/components/paul/app-sidebar.tsx

Lines changed: 76 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,96 @@
1-
import { ExpandableNav } from "@/components/paul/expandable-nav";
2-
import { SingleNav } from "@/components/paul/single-nav";
1+
import { NavExpandable } from "@/components/paul/nav-expandable";
2+
import { NavLogo } from "@/components/paul/nav-logo";
3+
import { NavUser } from "@/components/paul/nav-user";
34
import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarRail } from "@/components/ui/sidebar";
4-
import { apiGetUrls } from "@/constants/api-urls";
5+
import type { UserProps } from "@/types/user";
56
import {
67
CircleStackIcon as Database,
78
DocumentChartBarIcon as FileChartLine,
8-
HomeIcon as House,
9-
InformationCircleIcon as Info,
109
SparklesIcon as Zap,
1110
TableCellsIcon as Grid2X2Plus,
12-
UsersIcon as UsersRound,
1311
} from "@heroicons/react/24/outline";
1412
import * as React from "react";
1513
import { useTranslation } from "react-i18next";
1614

17-
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
15+
type AppSidebarProps = {
16+
user: UserProps | null | undefined;
17+
} & React.ComponentProps<typeof Sidebar>;
18+
19+
export function AppSidebar({ user, ...props }: AppSidebarProps) {
1820
const { t } = useTranslation();
1921

20-
const data = {
21-
navHome: [
22-
{
23-
title: t("navigation.home"),
24-
url: "/",
25-
icon: House,
26-
},
27-
],
28-
navMain: [
29-
{
30-
title: t("navigation.datasets"),
31-
url: "#",
32-
icon: Database,
33-
items: [
34-
{
35-
title: t("navigation.test1"),
36-
url: "#",
37-
},
38-
{
39-
title: t("navigation.test2"),
40-
url: "#",
41-
},
42-
],
43-
},
44-
{
45-
title: t("navigation.processedData"),
46-
url: "#",
47-
icon: FileChartLine,
48-
items: [
49-
{
50-
title: t("navigation.test1"),
51-
url: "#",
52-
},
53-
{
54-
title: t("navigation.test2"),
55-
url: "#",
56-
},
57-
],
58-
},
59-
{
60-
title: t("navigation.actions"),
61-
url: "#",
62-
icon: Zap,
63-
items: [
64-
{
65-
title: t("navigation.test1"),
66-
url: "#",
67-
},
68-
{
69-
title: t("navigation.test2"),
70-
url: "#",
71-
},
72-
],
73-
},
74-
{
75-
title: t("navigation.apps"),
76-
url: "#",
77-
icon: Grid2X2Plus,
78-
items: [
79-
{
80-
title: t("navigation.test1"),
81-
url: "#",
82-
},
83-
{
84-
title: t("navigation.test2"),
85-
url: "#",
86-
},
87-
],
88-
},
89-
],
90-
navMore: [
91-
{
92-
title: t("navigation.team"),
93-
url: apiGetUrls.teamIndex,
94-
icon: UsersRound,
95-
},
96-
{
97-
title: t("navigation.help"),
98-
url: "#",
99-
icon: Info,
100-
},
101-
],
102-
};
22+
const navMain = [
23+
{
24+
title: t("navigation.datasets"),
25+
url: "#",
26+
icon: Database,
27+
items: [
28+
{
29+
title: t("navigation.test1"),
30+
url: "#",
31+
},
32+
{
33+
title: t("navigation.test2"),
34+
url: "#",
35+
},
36+
],
37+
},
38+
{
39+
title: t("navigation.processedData"),
40+
url: "#",
41+
icon: FileChartLine,
42+
items: [
43+
{
44+
title: t("navigation.test1"),
45+
url: "#",
46+
},
47+
{
48+
title: t("navigation.test2"),
49+
url: "#",
50+
},
51+
],
52+
},
53+
{
54+
title: t("navigation.actions"),
55+
url: "#",
56+
icon: Zap,
57+
items: [
58+
{
59+
title: t("navigation.test1"),
60+
url: "#",
61+
},
62+
{
63+
title: t("navigation.test2"),
64+
url: "#",
65+
},
66+
],
67+
},
68+
{
69+
title: t("navigation.apps"),
70+
url: "#",
71+
icon: Grid2X2Plus,
72+
items: [
73+
{
74+
title: t("navigation.test1"),
75+
url: "#",
76+
},
77+
{
78+
title: t("navigation.test2"),
79+
url: "#",
80+
},
81+
],
82+
},
83+
];
10384

10485
return (
10586
<Sidebar collapsible="icon" {...props}>
106-
<SidebarHeader></SidebarHeader>
87+
<SidebarHeader>
88+
<NavLogo />
89+
</SidebarHeader>
10790
<SidebarContent>
108-
<SingleNav items={data.navHome} />
109-
<ExpandableNav items={data.navMain} />
91+
<NavExpandable items={navMain} />
11092
</SidebarContent>
111-
<SidebarFooter>
112-
<SingleNav items={data.navMore} />
113-
</SidebarFooter>
93+
<SidebarFooter>{user && <NavUser user={user} />}</SidebarFooter>
11494
<SidebarRail />
11595
</Sidebar>
11696
);

0 commit comments

Comments
 (0)