Skip to content

Commit

Permalink
Update auth admin design + add support for webhooks and openid connec…
Browse files Browse the repository at this point in the history
…t providers (#369)
  • Loading branch information
jaclarke authored Oct 31, 2024
1 parent 3276196 commit 1fbc3f3
Show file tree
Hide file tree
Showing 25 changed files with 2,598 additions and 1,785 deletions.
31 changes: 30 additions & 1 deletion shared/common/newui/button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import cn from "@edgedb/common/utils/classNames";

import styles from "./button.module.scss";
import Spinner from "../../ui/spinner";
import {PropsWithChildren} from "react";
import {CSSProperties, PropsWithChildren, useEffect, useState} from "react";

interface _BaseButtonProps {
className?: string;
Expand All @@ -12,6 +12,7 @@ interface _BaseButtonProps {
rightIcon?: JSX.Element;
disabled?: boolean;
loading?: boolean;
style?: CSSProperties;
}

export interface ButtonProps extends _BaseButtonProps {
Expand Down Expand Up @@ -107,3 +108,31 @@ export function LinkButton({
</a>
);
}

export function ConfirmButton({onClick, children, ...props}: ButtonProps) {
const [confirming, setConfirming] = useState(false);

useEffect(() => {
if (confirming) {
const timer = setTimeout(() => setConfirming(false), 1000);

return () => clearTimeout(timer);
}
}, [confirming]);

return (
<Button
onClick={() => {
if (confirming) {
setConfirming(false);
onClick?.();
} else {
setConfirming(true);
}
}}
{...props}
>
{confirming ? "Confirm?" : children}
</Button>
);
}
8 changes: 8 additions & 0 deletions shared/common/newui/checkbox/checkbox.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@
pointer-events: none;
}

&.readonly {
pointer-events: none;

.check {
opacity: 0.5;
}
}

@include darkTheme {
color: #ccc;

Expand Down
22 changes: 15 additions & 7 deletions shared/common/newui/checkbox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,40 @@ import cn from "@edgedb/common/utils/classNames";

import styles from "./checkbox.module.scss";

export interface CheckboxProps {
export type CheckboxProps<Readonly extends boolean> = {
className?: string;
label?: string | JSX.Element;
checked: boolean;
onChange: (checked: boolean) => void;
disabled?: boolean;
}
readOnly?: Readonly;
} & (Readonly extends true
? {
onChange?: (checked: boolean) => void;
}
: {
onChange: (checked: boolean) => void;
});

export function Checkbox({
export function Checkbox<Readonly extends boolean = false>({
className,
label,
checked,
onChange,
disabled,
}: CheckboxProps) {
readOnly,
}: CheckboxProps<Readonly>) {
return (
<label
className={cn(styles.checkbox, className, {
[styles.disabled]: !!disabled,
[styles.readonly]: !!readOnly,
})}
>
<input
type="checkbox"
checked={checked}
onChange={(e) => onChange(e.target.checked)}
disabled={disabled}
onChange={(e) => onChange?.(e.target.checked)}
disabled={disabled || readOnly}
/>
<div className={styles.check} />
{label}
Expand Down
5 changes: 5 additions & 0 deletions shared/common/newui/loadingSkeleton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import styles from "./loadingSkeleton.module.scss";

export function LoadingSkeleton({ className }: { className?: string }) {
return <div className={`${styles.loadingSkeleton} ${className ?? ""}`} />;
}
30 changes: 30 additions & 0 deletions shared/common/newui/loadingSkeleton/loadingSkeleton.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
@import "@edgedb/common/mixins.scss";

.loadingSkeleton {
border-radius: 8px;
background: var(--skeletonBg, #ededed);
background-image: linear-gradient(
90deg,
transparent,
var(--skeletonShimmer, #fafafa) 66%,
transparent
);
background-repeat: no-repeat;
background-size: 100px 100%;
animation: shimmer 2s infinite linear;

@include darkTheme {
--skeletonBg: #2d2d2d;
--skeletonShimmer: #3c3c3c;
}
}

@keyframes shimmer {
0% {
background-position: -100px;
}
50%,
100% {
background-position: calc(100% + 100px);
}
}
33 changes: 33 additions & 0 deletions shared/common/newui/panelTabs/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import cn from "@edgedb/common/utils/classNames";

import styles from "./panelTabs.module.scss";

export interface PanelTabsProps<TabId extends string> {
className?: string;
tabs: {id: TabId; label: string | JSX.Element}[];
selectedTabId: TabId;
setSelectedTabId: (id: TabId) => void;
}

export function PanelTabs<TabId extends string = string>({
className,
tabs,
selectedTabId,
setSelectedTabId,
}: PanelTabsProps<TabId>) {
return (
<div className={cn(styles.panelTabs, className)}>
{tabs.map((tab) => (
<div
key={tab.id}
className={cn(styles.tab, {
[styles.active]: selectedTabId === tab.id,
})}
onClick={() => setSelectedTabId(tab.id)}
>
{tab.label}
</div>
))}
</div>
);
}
94 changes: 94 additions & 0 deletions shared/common/newui/panelTabs/panelTabs.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
@import "@edgedb/common/mixins.scss";

.panelTabs {
grid-column: 1;
grid-row: 1;
display: flex;
flex-direction: column;
gap: 12px;
align-self: start;
position: sticky;
top: 0;
width: max-content;
justify-self: end;
text-align: end;
padding: 64px 24px;
z-index: 1;

.tab {
position: relative;
font-family: "Roboto Flex Variable", sans-serif;
color: var(--secondary_text_color);
text-decoration: none;
font-weight: 500;
padding: 12px 16px;
border-radius: 8px;
cursor: pointer;

&:hover {
background: #fff;
}

&.active {
color: var(--main_text_color);

&:after {
content: "";
position: absolute;
right: 1px;
top: 4px;
bottom: 4px;
width: 2px;
border-radius: 1px;
background: #a565cd;
}
}
}

@include darkTheme {
.tab:hover {
background: var(--Grey12);
}
}

@include isMobile {
border-bottom: 1px solid var(--Grey93, #ededed);
background: var(--Grey99, #fcfcfc);
box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.08);
flex-direction: row;
padding: 0;
width: 100%;
align-items: center;
justify-content: center;
height: 44px;
flex-shrink: 0;

.tab {
padding: 10px 12px;
border-radius: 6px;

&:hover {
background: var(--Grey95, #f2f2f2);
}

&.active:after {
left: 4px;
right: 4px;
top: auto;
bottom: -3px;
height: 2px;
width: auto;
}
}

@include darkTheme {
border-bottom: 1px solid var(--Grey22, #363636);
background: var(--Grey18, #2e2e2e);
box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.2);

.tab:hover {
background: var(--Grey14, #242424);
}
}
}
}
1 change: 1 addition & 0 deletions shared/common/newui/select/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
Select as _Select,
SelectProps as _SelectProps,
} from "@edgedb/common/ui/select";
export type {SelectItem, SelectItems} from "@edgedb/common/ui/select";

import styles from "./select.module.scss";

Expand Down
3 changes: 3 additions & 0 deletions shared/common/newui/textInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface TextInputProps extends FieldHeaderProps {
type?: "text" | "password" | "textarea";
error?: string | null;
prefix?: string;
suffixEl?: JSX.Element;
}

export const TextInput = forwardRef(function TextInput(
Expand All @@ -23,6 +24,7 @@ export const TextInput = forwardRef(function TextInput(
headerNote,
error,
prefix,
suffixEl,
...props
}: TextInputProps &
Omit<InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement>, "type">,
Expand Down Expand Up @@ -53,6 +55,7 @@ export const TextInput = forwardRef(function TextInput(
: undefined,
}}
/>
{suffixEl}
{error != null ? (
<div className={styles.error}>
<InfoIcon />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
.databasePage {
position: relative;
flex-grow: 1;
overflow: hidden;
min-height: 0;
display: grid;
padding: 0 16px 16px 0;
padding: 0 8px 8px 0;
grid-template-areas: "tabs session" "tabs content";
grid-template-columns: auto 1fr;
grid-template-rows: auto 1fr;
Expand Down
32 changes: 2 additions & 30 deletions shared/studio/tabs/ai/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {useEffect, useLayoutEffect, useState} from "react";
import {useEffect, useLayoutEffect} from "react";
import {Observer, observer} from "mobx-react-lite";

import cn from "@edgedb/common/utils/classNames";
Expand All @@ -15,7 +15,7 @@ import {PlaygroundTab} from "./playground";
import {PromptsTab} from "./prompts";

import styles from "./aiAdmin.module.scss";
import {Button, ButtonProps, WarningIcon} from "@edgedb/common/newui";
import {WarningIcon} from "@edgedb/common/newui";

const AIAdminPage = observer(function AIAdminPage() {
const state = useTabState(AIAdminState);
Expand Down Expand Up @@ -133,31 +133,3 @@ function AIAdminLayout() {
</div>
);
}

export function ConfirmButton({onClick, children, ...props}: ButtonProps) {
const [confirming, setConfirming] = useState(false);

useEffect(() => {
if (confirming) {
const timer = setTimeout(() => setConfirming(false), 1000);

return () => clearTimeout(timer);
}
}, [confirming]);

return (
<Button
onClick={() => {
if (confirming) {
setConfirming(false);
onClick?.();
} else {
setConfirming(true);
}
}}
{...props}
>
{confirming ? "Confirm?" : children}
</Button>
);
}
2 changes: 1 addition & 1 deletion shared/studio/tabs/ai/prompts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {observer} from "mobx-react-lite";
import cn from "@edgedb/common/utils/classNames";
import {
Button,
ConfirmButton,
ChevronDownIcon,
InfoIcon,
InfoTooltip,
Expand All @@ -16,7 +17,6 @@ import {AIAdminState, AIPromptDraft, PromptChatParticipantRole} from "./state";

import textStyles from "@edgedb/common/newui/textInput/textInput.module.scss";
import styles from "./aiAdmin.module.scss";
import {ConfirmButton} from ".";

export const PromptsTab = observer(function PromptTab() {
const state = useTabState(AIAdminState);
Expand Down
Loading

0 comments on commit 1fbc3f3

Please sign in to comment.