Skip to content
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

Reduce information visible to regular users (non-adminstrators) #353

Merged
merged 11 commits into from
Mar 15, 2024
48 changes: 45 additions & 3 deletions src/app/(dashboard)/peers/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,24 @@ import useFetchApi from "@utils/api";
import { ExternalLinkIcon } from "lucide-react";
import React, { lazy, Suspense } from "react";
import PeerIcon from "@/assets/icons/PeerIcon";
import { useUsers } from "@/contexts/UsersProvider";
import { useLoggedInUser, useUsers } from "@/contexts/UsersProvider";
import { Peer } from "@/interfaces/Peer";
import PageContainer from "@/layouts/PageContainer";
import { SetupModalContent } from "@/modules/setup-netbird-modal/SetupModal";

const PeersTable = lazy(() => import("@/modules/peers/PeersTable"));

export default function Peers() {
const { isUser } = useLoggedInUser();

return (
<PageContainer>
{isUser ? <PeersDefaultView /> : <PeersView />}
</PageContainer>
);
}

function PeersView() {
const { data: peers, isLoading } = useFetchApi<Peer[]>("/peers");
const { users } = useUsers();

Expand All @@ -27,7 +38,7 @@ export default function Peers() {
});

return (
<PageContainer>
<>
<div className={"p-default py-6"}>
<Breadcrumbs>
<Breadcrumbs.Item
Expand Down Expand Up @@ -56,6 +67,37 @@ export default function Peers() {
<Suspense fallback={<SkeletonTable />}>
<PeersTable isLoading={isLoading} peers={peersWithUser} />
</Suspense>
</PageContainer>
</>
);
}

function PeersDefaultView() {
return (
<div className={"flex items-center justify-center flex-col"}>
<div className={"p-default py-6 max-w-3xl text-center"}>
<h1>Add new peer to your network</h1>
<Paragraph className={"inline"}>
To get started, install NetBird and log in using your email account.
After that you should be connected. If you have further questions
check out our{" "}
<InlineLink
href={"https://docs.netbird.io/how-to/getting-started#installation"}
target={"_blank"}
>
Installation Guide
<ExternalLinkIcon size={12} />
</InlineLink>
</Paragraph>
</div>
<div className={"px-3 pt-1 pb-8 max-w-3xl w-full"}>
<div
className={
"rounded-md border border-nb-gray-900/70 grid w-full bg-nb-gray-930/40 stepper-bg-variant"
}
>
<SetupModalContent header={false} footer={false} />
</div>
</div>
</div>
);
}
49 changes: 27 additions & 22 deletions src/app/(dashboard)/team/user/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function UserOverview({ user }: Props) {
const router = useRouter();
const userRequest = useApiCall<User>("/users");
const { mutate } = useSWRConfig();
const { loggedInUser, isOwnerOrAdmin } = useLoggedInUser();
const { loggedInUser, isOwnerOrAdmin, isUser } = useLoggedInUser();
const isLoggedInUser = loggedInUser ? loggedInUser?.id === user.id : false;

const initialGroups = user.auto_groups;
Expand Down Expand Up @@ -104,6 +104,7 @@ function UserOverview({ user }: Props) {
<Breadcrumbs.Item
href={"/team"}
label={"Team"}
disabled={isUser}
icon={<TeamIcon size={13} />}
/>

Expand All @@ -117,6 +118,7 @@ function UserOverview({ user }: Props) {
<Breadcrumbs.Item
href={"/team/users"}
label={"Users"}
disabled={isUser}
icon={<User2 size={16} />}
/>
)}
Expand Down Expand Up @@ -156,28 +158,30 @@ function UserOverview({ user }: Props) {
</h1>
</div>
</div>
<div className={"flex gap-4"}>
<Button
variant={"default"}
className={"w-full"}
onClick={() => {
user.is_service_user
? router.push("/team/service-users")
: router.push("/team/users");
}}
>
Cancel
</Button>
{!isUser && (
<div className={"flex gap-4"}>
<Button
variant={"default"}
className={"w-full"}
onClick={() => {
user.is_service_user
? router.push("/team/service-users")
: router.push("/team/users");
}}
>
Cancel
</Button>

<Button
variant={"primary"}
className={"w-full"}
disabled={!hasChanges}
onClick={save}
>
Save Changes
</Button>
</div>
<Button
variant={"primary"}
className={"w-full"}
disabled={!hasChanges}
onClick={save}
>
Save Changes
</Button>
</div>
)}
</div>

<div className={"flex gap-10 w-full mt-8 max-w-6xl"}>
Expand All @@ -190,6 +194,7 @@ function UserOverview({ user }: Props) {
Groups will be assigned to peers added by this user.
</HelpText>
<PeerGroupSelector
disabled={isUser}
onChange={setSelectedGroups}
values={selectedGroups}
/>
Expand Down
4 changes: 4 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,8 @@ p {
display: table;
position: relative;
width: 100%;
}

.stepper-bg-variant .step-circle {
@apply !border-[#1d2024];
}
16 changes: 14 additions & 2 deletions src/components/Breadcrumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,25 @@ type ItemProps = {
label: string;
icon?: React.ReactNode;
active?: boolean;
disabled?: boolean;
};

export const Item = ({ href, label, icon, active }: ItemProps) => {
export const Item = ({
href,
label,
icon,
active,
disabled = false,
}: ItemProps) => {
const router = useRouter();

return (
<div className={"flex items-center gap-2 group"}>
<div
className={cn(
"flex items-center gap-2 group",
disabled && "pointer-events-none",
)}
>
<ChevronRightIcon
size={16}
className={"text-nb-gray-400 group-first:hidden"}
Expand Down
1 change: 1 addition & 0 deletions src/components/PeerGroupSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ export function PeerGroupSelector({
"min-h-[46px] w-full relative items-center",
"border border-neutral-200 dark:border-nb-gray-700 justify-between py-2 px-3",
"rounded-md bg-white text-sm dark:bg-nb-gray-900/40 flex dark:text-neutral-400/70 text-neutral-500 cursor-pointer hover:dark:bg-nb-gray-900/50",
"disabled:pointer-events-none disabled:opacity-30",
)}
disabled={disabled}
ref={inputRef}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Steps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const Step = ({ children, step, line = true, center = false }: StepProps) => {
className={cn(
"h-[34px] w-[34px] shrink-0 rounded-full flex items-center justify-center font-medium text-xs relative z-0 border-4 transition-all",
"dark:bg-nb-gray-900 dark:text-nb-gray-400 dark:border-nb-gray dark:group-hover:bg-nb-gray-800",
"bg-nb-gray-100 text-nb-gray-400 border-white group-hover:bg-nb-gray-200",
"bg-nb-gray-100 text-nb-gray-400 border-white group-hover:bg-nb-gray-200 step-circle",
)}
>
{step}
Expand Down
11 changes: 11 additions & 0 deletions src/contexts/CountryProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import useFetchApi from "@utils/api";
import React, { useCallback } from "react";
import { useLoggedInUser } from "@/contexts/UsersProvider";
import { Country } from "@/interfaces/Country";
import { Peer } from "@/interfaces/Peer";

Expand All @@ -16,6 +17,16 @@ const CountryContext = React.createContext(
);

export default function CountryProvider({ children }: Props) {
const { isUser } = useLoggedInUser();

return isUser ? (
children
) : (
<CountryProviderContent>{children}</CountryProviderContent>
);
}

function CountryProviderContent({ children }: Props) {
const { data: countries, isLoading } = useFetchApi<Country[]>(
"/locations/countries",
false,
Expand Down
13 changes: 13 additions & 0 deletions src/contexts/GroupsProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import useFetchApi from "@utils/api";
import { usePathname } from "next/navigation";
import React, { useState } from "react";
import { useLoggedInUser } from "@/contexts/UsersProvider";
import { Group } from "@/interfaces/Group";

type Props = {
Expand All @@ -17,6 +19,17 @@ const GroupContext = React.createContext(
);

export default function GroupsProvider({ children }: Props) {
const path = usePathname();
const { isUser } = useLoggedInUser();

return isUser && path == "/peers" ? (
children
) : (
<GroupsProviderContent>{children}</GroupsProviderContent>
);
}

export function GroupsProviderContent({ children }: Props) {
const { data: groups, mutate, isLoading } = useFetchApi<Group[]>("/groups");
const [dropdownOptions, setDropdownOptions] = useState<Group[]>([]);

Expand Down
6 changes: 4 additions & 2 deletions src/layouts/DashboardLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import ApplicationProvider, {
} from "@/contexts/ApplicationProvider";
import CountryProvider from "@/contexts/CountryProvider";
import GroupsProvider from "@/contexts/GroupsProvider";
import UsersProvider from "@/contexts/UsersProvider";
import UsersProvider, { useLoggedInUser } from "@/contexts/UsersProvider";
import Navigation from "@/layouts/Navigation";
import Navbar, { headerHeight } from "./Header";

Expand All @@ -42,6 +42,7 @@ function DashboardPageContent({ children }: { children: React.ReactNode }) {
const { mobileNavOpen, toggleMobileNav } = useApplicationContext();
const isSm = useIsSm();
const isXs = useIsXs();
const { isUser } = useLoggedInUser();

const navOpenPageWidth = isSm ? "50%" : isXs ? "65%" : "80%";
const { bannerHeight } = useAnnouncement();
Expand Down Expand Up @@ -146,13 +147,14 @@ function DashboardPageContent({ children }: { children: React.ReactNode }) {
}}
>
<Navbar />

<div
className={"flex flex-row flex-grow"}
style={{
height: `calc(100vh - ${headerHeight + bannerHeight}px)`,
}}
>
<Navigation hideOnMobile />
{!isUser && <Navigation hideOnMobile />}
{children}
</div>
</motion.div>
Expand Down
8 changes: 7 additions & 1 deletion src/layouts/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import NetBirdLogo from "@/assets/netbird.svg";
import NetBirdLogoFull from "@/assets/netbird-full.svg";
import { useAnnouncement } from "@/contexts/AnnouncementProvider";
import { useApplicationContext } from "@/contexts/ApplicationProvider";
import { useLoggedInUser } from "@/contexts/UsersProvider";

export const headerHeight = 75;

Expand All @@ -39,6 +40,8 @@ export default function NavbarWithDropdown() {

const { toggleMobileNav } = useApplicationContext();
const { bannerHeight } = useAnnouncement();
const { isUser } = useLoggedInUser();

return (
<>
<div
Expand All @@ -57,7 +60,10 @@ export default function NavbarWithDropdown() {
>
<div className={"flex items-center gap-4 md:hidden"}>
<Button
className={"!px-3 md:hidden"}
className={cn(
"!px-3 md:hidden",
isUser && "opacity-0 pointer-events-none",
)}
variant={"default-outline"}
onClick={toggleMobileNav}
>
Expand Down
Loading
Loading