port full auth flow to cf workers

This commit is contained in:
41666 2020-12-05 03:09:20 -05:00
parent 9eeb946389
commit aad0987dce
50 changed files with 551 additions and 1167 deletions

View file

@ -5,3 +5,6 @@ export const initialsFromName = (name: string) =>
.map((x) => x[0])
.join('')
.toUpperCase();
export const avatarHash = (id: string, hash: string) =>
`https://cdn.discordapp.com/icons/${id}/${hash}.webp?size=256`;

View file

@ -125,8 +125,8 @@ export const Bi: Variant = {
matchDay(new Date('2021-Sep-16'), new Date('2021-Sep-24'), currentDate),
sharedProps: {
circleFill: '#D60270',
circleOuterFill: '#9B4F96',
typeFill: '#0038A8',
circleOuterFill: '#0038A8',
typeFill: '#9B4F96',
},
tooltip: 'Being bi is a lot like a riding a bicycle since they can go both ways.',
Logomark: (props: DynamicLogoProps) => <Logomark {...props} {...Bi.sharedProps} />,
@ -276,7 +276,7 @@ export const BicycleDay: Variant = {
export const Christmas: Variant = {
// Dec 20-27
activeIf: (currentDate?: Date) =>
matchDay(new Date('2021-Dec-20'), new Date('2021-Dec-28'), currentDate),
true || matchDay(new Date('2021-Dec-20'), new Date('2021-Dec-28'), currentDate),
sharedProps: {
circleFill: palette.green200,
circleOuterFill: palette.red200,
@ -284,10 +284,14 @@ export const Christmas: Variant = {
},
tooltip: 'Have yourself a merry little Christmas~',
Logomark: (props: DynamicLogoProps) => (
<Logomark {...props} {...Christmas.sharedProps} />
<SparkleOverlay strokeColor={'white'}>
<Logomark {...props} {...Christmas.sharedProps} />
</SparkleOverlay>
),
Logotype: (props: DynamicLogoProps) => (
<Logotype {...props} {...Christmas.sharedProps} />
<SparkleOverlay strokeColor={'white'}>
<Logotype {...props} {...Christmas.sharedProps} />
</SparkleOverlay>
),
};

View file

@ -2,52 +2,37 @@ import Link from 'next/link';
import * as React from 'react';
import { GoStar, GoZap } from 'react-icons/go';
import ReactTooltip from 'react-tooltip';
import { hasPermission, permissions } from 'roleypoly/common/utils/hasPermission';
import { GuildSlug, UserGuildPermissions } from 'roleypoly/common/types';
import { sortBy } from 'roleypoly/common/utils/sortBy';
import { GuildEnumeration, PresentableGuild, Role } from 'roleypoly/common/types';
import { NavSlug } from 'roleypoly/design-system/molecules/nav-slug';
import { GuildNavItem } from './GuildNav.styled';
type Props = {
guildEnumeration: GuildEnumeration;
guilds: GuildSlug[];
};
const tooltipId = 'guildnav';
const Badges = (props: { guild: PresentableGuild }) => {
const Badges = (props: { guild: GuildSlug }) => {
return React.useMemo(() => {
if (!props.guild.member) {
return null;
}
const roles = props.guild.member.rolesList
.map((id) => {
if (!props.guild.roles) {
return undefined;
}
return props.guild.roles.rolesList.find((role) => role.id === id);
})
.filter((x) => !!x) as Role[];
if (hasPermission(roles, permissions.ADMINISTRATOR)) {
if (props.guild.permissionLevel === UserGuildPermissions.Admin) {
return <GoStar data-tip="Administrator" data-for={tooltipId} />;
}
if (hasPermission(roles, permissions.MANAGE_ROLES)) {
if (props.guild.permissionLevel === UserGuildPermissions.Manager) {
return <GoZap data-tip="Role Editor" data-for={tooltipId} />;
}
return null;
}, [props.guild]);
}, [props.guild.permissionLevel]);
};
export const GuildNav = (props: Props) => (
<div>
{sortBy(props.guildEnumeration.guildsList, 'id').map((guild) => (
{sortBy(props.guilds, 'id').map((guild) => (
<Link href={`/s/${guild.id}`} passHref>
<GuildNavItem>
<NavSlug guild={guild.guild || null} key={guild.id} />
<NavSlug guild={guild || null} key={guild.id} />
<Badges guild={guild} />
</GuildNavItem>
</Link>

View file

@ -1,16 +1,23 @@
import * as React from 'react';
import { Guild } from 'roleypoly/common/types';
import { GoOrganization } from 'react-icons/go';
import { GuildSlug } from 'roleypoly/common/types';
import { Avatar, utils } from 'roleypoly/design-system/atoms/avatar';
import { SlugContainer, SlugName } from './NavSlug.styled';
import { GoOrganization } from 'react-icons/go';
type Props = {
guild: Guild | null;
guild: GuildSlug | null;
};
export const NavSlug = (props: Props) => (
<SlugContainer>
<Avatar src={props.guild?.icon} deliberatelyEmpty={!props.guild} size={35}>
<Avatar
src={
(props.guild && utils.avatarHash(props.guild.id, props.guild.icon)) ||
undefined
}
deliberatelyEmpty={!props.guild}
size={35}
>
{props.guild ? utils.initialsFromName(props.guild.name) : <GoOrganization />}
</Avatar>
<SlugName>{props.guild?.name || <>Your Guilds</>}</SlugName>

View file

@ -1,27 +1,27 @@
import * as React from 'react';
import * as Masthead from 'roleypoly/design-system/organisms/masthead';
import { RoleypolyUser, GuildEnumeration } from 'roleypoly/common/types';
import { Footer } from 'roleypoly/design-system/molecules/footer';
import { Content, GlobalStyles } from './AppShell.styled';
import { GlobalStyleColors } from 'roleypoly/design-system/atoms/colors';
import { Scrollbars } from 'react-custom-scrollbars';
import { DiscordUser, GuildSlug } from 'roleypoly/common/types';
import { GlobalStyleColors } from 'roleypoly/design-system/atoms/colors';
import { Footer } from 'roleypoly/design-system/molecules/footer';
import * as Masthead from 'roleypoly/design-system/organisms/masthead';
import { Content, GlobalStyles } from './AppShell.styled';
type AppShellProps = {
export type AppShellProps = {
children: React.ReactNode;
user: RoleypolyUser | null;
user?: DiscordUser;
showFooter?: boolean;
small?: boolean;
activeGuildId?: string | null;
guildEnumeration?: GuildEnumeration;
guilds?: GuildSlug[];
};
export const AppShell = (props: AppShellProps) => (
<>
<GlobalStyles />
<GlobalStyleColors />
{props.user !== null ? (
{props.user ? (
<Masthead.Authed
guildEnumeration={props.guildEnumeration || { guildsList: [] }}
guilds={props.guilds || []}
activeGuildId={props.activeGuildId || null}
user={props.user}
/>

View file

@ -1,7 +1,13 @@
import Link from 'next/link';
import * as React from 'react';
import { GoOrganization } from 'react-icons/go';
import { GuildEnumeration, RoleypolyUser } from 'roleypoly/common/types';
import { Guilds } from 'roleypoly/backend-worker/utils/kv';
import {
DiscordUser,
GuildEnumeration,
GuildSlug,
RoleypolyUser,
} from 'roleypoly/common/types';
import { guildEnum } from 'roleypoly/common/types/storyData';
import { DynamicLogomark } from 'roleypoly/design-system/atoms/branding';
import { Popover } from 'roleypoly/design-system/atoms/popover';
@ -20,9 +26,9 @@ import {
} from './Masthead.styled';
type Props = {
user: RoleypolyUser;
user?: DiscordUser;
activeGuildId: string | null;
guildEnumeration: GuildEnumeration;
guilds: GuildSlug[];
};
export const Authed = (props: Props) => {
@ -47,9 +53,9 @@ export const Authed = (props: Props) => {
>
<NavSlug
guild={
guildEnum.guildsList.find(
(g) => g.id === props.activeGuildId
)?.guild || null
props.guilds.find(
(guild) => guild.id === props.activeGuildId
) || null
}
/>
</InteractionBase>
@ -65,7 +71,7 @@ export const Authed = (props: Props) => {
active={serverPopoverState}
onExit={() => setServerPopoverState(false)}
>
<GuildNav guildEnumeration={props.guildEnumeration} />
<GuildNav guilds={props.guilds} />
</Popover>
</MastheadLeft>
<MastheadRight>
@ -76,9 +82,7 @@ export const Authed = (props: Props) => {
}}
hide={!userPopoverState}
>
{props.user.discorduser && (
<UserAvatarGroup user={props.user.discorduser} />
)}
{props.user && <UserAvatarGroup user={props.user} />}
</InteractionBase>
<Popover
headContent={<></>}
@ -87,9 +91,7 @@ export const Authed = (props: Props) => {
active={userPopoverState}
onExit={() => setUserPopoverState(false)}
>
{props.user.discorduser && (
<UserPopover user={props.user.discorduser} />
)}
{props.user && <UserPopover user={props.user} />}
</Popover>
</MastheadRight>
</MastheadAlignment>

View file

@ -6,7 +6,7 @@ import * as React from 'react';
export type AuthLoginProps = PreauthProps;
export const AuthLogin = (props: AuthLoginProps) => (
<AppShell showFooter user={null}>
<AppShell showFooter user={undefined}>
<Hero topSpacing={100} bottomSpacing={175}>
<Preauth {...props} />
</Hero>

View file

@ -1,15 +1,15 @@
import * as React from 'react';
import { AppShell } from 'roleypoly/design-system/organisms/app-shell';
import { HelpPageBase } from 'roleypoly/design-system/molecules/help-page-base';
import { RoleypolyUser } from 'roleypoly/common/types';
import { DiscordUser } from 'roleypoly/common/types';
type HelpPageProps = {
user: RoleypolyUser | null;
user: DiscordUser | null;
children: React.ReactNode;
};
export const HelpPageTemplate = (props: HelpPageProps) => (
<AppShell user={props.user || null}>
<AppShell user={props.user || undefined}>
<HelpPageBase>{props.children}</HelpPageBase>
</AppShell>
);

View file

@ -3,7 +3,7 @@ import { AppShell } from 'roleypoly/design-system/organisms/app-shell';
import { Landing } from 'roleypoly/design-system/organisms/landing';
export const LandingTemplate = () => (
<AppShell showFooter user={null}>
<AppShell showFooter>
<Landing />
</AppShell>
);

View file

@ -6,11 +6,7 @@ import {
RolePickerProps,
} from 'roleypoly/design-system/organisms/role-picker';
export type RolePickerTemplateProps = RolePickerProps & {
user: RoleypolyUser;
guildEnumeration?: GuildEnumeration;
activeGuildId?: string;
};
export type RolePickerTemplateProps = RolePickerProps & AppShellProps;
export const RolePickerTemplate = (props: RolePickerTemplateProps) => {
const { user, ...pickerProps } = props;
@ -18,7 +14,8 @@ export const RolePickerTemplate = (props: RolePickerTemplateProps) => {
<AppShell
guildEnumeration={props.guildEnumeration}
activeGuildId={props.activeGuildId}
user={user}
user={user.discorduser}
guilds={user.guilds}
small
>
<RolePicker {...pickerProps} />