Skip to content

Commit

Permalink
Merge pull request #1207 from visualize-admin/feat/login-ui
Browse files Browse the repository at this point in the history
feat: Login UI improvements
  • Loading branch information
bprusinowski authored Oct 10, 2023
2 parents d89c05e + 6b5410f commit 1ffddfc
Show file tree
Hide file tree
Showing 10 changed files with 316 additions and 107 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,5 @@ To configure Keycloak:
- KEYCLOAK_ISSUER: http://localhost:8080/realms/master
[keycloak-admin]: http://localhost:8080/admin/master/console/#/
Remember to add NEXTAUTH_SECRET variable to your .env file!
3 changes: 1 addition & 2 deletions app/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ import { DataSourceMenu } from "@/components/data-source-menu";
import Flex from "@/components/flex";
import { LanguageMenu } from "@/components/language-menu";
import { SOURCE_OPTIONS } from "@/domain/datasource/constants";

import LoginMenu from "./login-menu";
import { LoginMenu } from "@/login/components/login-menu";

const DEFAULT_HEADER_PROGRESS = 100;

Expand Down
6 changes: 3 additions & 3 deletions app/configurator/components/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { makeStyles } from "@mui/styles";
import clsx from "clsx";
import React from "react";

import { HEADER_HEIGHT } from "@/components/header";
import { DRAWER_WIDTH } from "@/configurator/components/drawer";

const useStyles = makeStyles((theme: Theme) => ({
Expand All @@ -28,10 +29,9 @@ const useStyles = makeStyles((theme: Theme) => ({
},
panelLayout: {
position: "fixed",
// FIXME replace 96px with actual header size
top: 96,
top: HEADER_HEIGHT,
width: "100%",
height: "calc(100vh - 96px)",
height: `calc(100vh - ${HEADER_HEIGHT}px)`,
display: "grid",
gridTemplateColumns: `${DRAWER_WIDTH}px minmax(22rem, 1fr)`,
gridTemplateRows: "auto minmax(0, 1fr)",
Expand Down
21 changes: 12 additions & 9 deletions app/db/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import { Config, Prisma, User } from "@prisma/client";

import { ChartConfig } from "@/configurator";
import { ChartConfig, ConfiguratorStatePublished } from "@/configurator";
import { migrateConfiguratorState } from "@/utils/chart-config/versioning";

import { createChartId } from "../utils/create-chart-id";
Expand Down Expand Up @@ -57,13 +57,16 @@ const ensureFiltersOrder = (chartConfig: ChartConfig) => {
};
};

type ChartJsonConfig = {
dataSet: string;
chartConfig: Prisma.JsonObject;
};

const parseDbConfig = (d: Config) => {
const data = d.data as ChartJsonConfig;
const parseDbConfig = (
d: Config
): {
id: number;
key: string;
data: ConfiguratorStatePublished;
created_at: Date;
user_id: number | null;
} => {
const data = d.data as ConfiguratorStatePublished;
const migratedData = migrateConfiguratorState(data);

return {
Expand All @@ -84,7 +87,7 @@ const parseDbConfig = (d: Config) => {
export const getConfig = async (key: string) => {
const config = await prisma.config.findFirst({
where: {
key: key,
key,
},
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Box, Button, Typography } from "@mui/material";
import { getProviders, signIn, signOut, useSession } from "next-auth/react";
import { getProviders, signIn, useSession } from "next-auth/react";
import Link from "next/link";
import { useEffect, useState } from "react";

Expand All @@ -12,63 +12,49 @@ const useProviders = () => {
status: "loading",
data: undefined as Providers | undefined,
});

useEffect(() => {
const run = async () => {
const providers = await getProviders();
setState({ status: "loaded", data: providers });
};

run();
}, []);

return state;
};

function LoginMenu() {
export const LoginMenu = () => {
const { data: session, status: sessionStatus } = useSession();
const { data: providers, status: providersStatus } = useProviders();

if (sessionStatus === "loading" || providersStatus === "loading") {
return null;
}

if (!providers || !Object.keys(providers).length) {
return null;
}

return (
<Box sx={{ alignItems: "center", display: "flex" }}>
{session ? (
<>
<Typography variant="body2">
Signed in as{" "}
<Link href="/profile" legacyBehavior>
{session.user?.name}
</Link>{" "}
{" - "}
</Typography>
<Button
variant="text"
color="primary"
size="small"
onClick={async () => await signOut()}
>
Sign out
</Button>
</>
<Typography variant="body2">
<Link href="/profile" legacyBehavior>
{session.user?.name}
</Link>{" "}
</Typography>
) : (
<>
<Typography variant="body2">
Not signed in
{" - "}
</Typography>
<Button
variant="text"
color="primary"
size="small"
onClick={() => signIn("keycloak")}
>
Sign in
</Button>
</>
<Button
variant="text"
color="primary"
size="small"
onClick={() => signIn("keycloak")}
>
Sign in
</Button>
)}
</Box>
);
}

export default LoginMenu;
};
88 changes: 88 additions & 0 deletions app/login/components/profile-content-tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { TabContext, TabList, TabPanel } from "@mui/lab";
import { Box, Tab, Theme, Typography } from "@mui/material";
import { makeStyles } from "@mui/styles";
import clsx from "clsx";
import React from "react";

import { ParsedConfig } from "@/db/config";
import { ProfileVisualizationsTable } from "@/login/components/profile-tables";
import { useRootStyles } from "@/login/utils";
import useEvent from "@/utils/use-event";

const useStyles = makeStyles<Theme>((theme) => ({
section: {
marginTop: theme.spacing(6),
},
tabList: {
minHeight: "fit-content",

"& .MuiTabs-flexContainer": {
height: "fit-content",
},
},
tabPanel: {
padding: 0,
},
tabPanelContent: {
padding: theme.spacing(6),
},
tab: {
height: 48,
minHeight: 0,
padding: "0 1rem",
textTransform: "none",
},
}));

type ProfileContentTabsProps = {
userConfigs: ParsedConfig[];
};

export const ProfileContentTabs = (props: ProfileContentTabsProps) => {
const { userConfigs } = props;
const [value, setValue] = React.useState("Home");
const handleChange = useEvent((_: React.SyntheticEvent, v: string) => {
setValue(v);
});
const rootClasses = useRootStyles();
const classes = useStyles();

return (
<TabContext value={value}>
<Box className={clsx(rootClasses.section, classes.section)}>
<Box className={rootClasses.sectionContent}>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<TabList className={classes.tabList} onChange={handleChange}>
{["Home", "My visualizations", "My favorite datasets"].map(
(d) => (
<Tab key={d} className={classes.tab} label={d} value={d} />
)
)}
</TabList>
</Box>
</Box>
</Box>
<TabPanel className={classes.tabPanel} value="Home">
<Box className={classes.tabPanelContent}>
<ProfileVisualizationsTable userConfigs={userConfigs} />
</Box>
</TabPanel>
<TabPanel className={classes.tabPanel} value="My visualizations">
<Box
className={classes.tabPanelContent}
sx={{ bgcolor: "background.paper" }}
>
<ProfileVisualizationsTable userConfigs={userConfigs} />
</Box>
</TabPanel>
<TabPanel className={classes.tabPanel} value="My favorite datasets">
<Box
className={classes.tabPanelContent}
sx={{ bgcolor: "background.paper" }}
>
<Typography variant="h2">My favorite datasets</Typography>
</Box>
</TabPanel>
</TabContext>
);
};
54 changes: 54 additions & 0 deletions app/login/components/profile-header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Box, Button, Link, Theme, Typography } from "@mui/material";
import { makeStyles } from "@mui/styles";
import { User } from "@prisma/client";
import clsx from "clsx";
import { signOut } from "next-auth/react";

import { useRootStyles } from "@/login/utils";

const useStyles = makeStyles<Theme>((theme) => ({
section: {
paddingTop: theme.spacing(6),
backgroundColor: theme.palette.muted.main,
},
topRow: {
display: "flex",
alignItems: "center",
justifyContent: "space-between",
},
browseButton: {
width: "fit-content",
},
}));

type ProfileHeaderProps = {
user: User;
};

export const ProfileHeader = (props: ProfileHeaderProps) => {
const { user } = props;
const rootClasses = useRootStyles();
const classes = useStyles();

return (
<Box className={clsx(rootClasses.section, classes.section)}>
<Box className={rootClasses.sectionContent}>
<Box className={classes.topRow}>
<Typography variant="h1">{user.name}</Typography>
<Button component={Link} href="/browse">
Browse all datasets
</Button>
</Box>
<Button
className={classes.browseButton}
variant="text"
color="primary"
size="small"
onClick={async () => await signOut()}
>
Log out
</Button>
</Box>
</Box>
);
};
Loading

1 comment on commit 1ffddfc

@vercel
Copy link

@vercel vercel bot commented on 1ffddfc Oct 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

visualization-tool – ./

visualization-tool-alpha.vercel.app
visualization-tool-ixt1.vercel.app
visualization-tool-git-main-ixt1.vercel.app

Please sign in to comment.