fix: prefetching personalityInfo on profile page

This commit is contained in:
dan13ram
2022-01-26 20:41:43 +05:30
committed by dan13ram
parent df9899bd8c
commit 32a6405de4
9 changed files with 83 additions and 45 deletions

View File

@@ -96,7 +96,7 @@ jobs:
- name: Build Backend Container
uses: mattes/cached-docker-build-action@v1
with:
args: ". -f ./docker/backend/Dockerfile --tag ${{env.BACKEND_TAG}} --build-arg GRAPHQL_URL=${{env.GRAPHQL_URL}}"
args: '. -f ./docker/backend/Dockerfile --tag ${{env.BACKEND_TAG}} --build-arg GRAPHQL_URL=${{env.GRAPHQL_URL}}'
cache_key: "${{hashFiles('packages/backend/**')}}"
- name: Push Backend Container
@@ -129,7 +129,7 @@ jobs:
- name: Build Hasura Container
uses: mattes/cached-docker-build-action@v1
with:
args: "./hasura -f ./hasura/Dockerfile --tag ${{env.HASURA_TAG}} --build-arg BACKEND_HOST=${{env.BACKEND_HOST}} --build-arg BACKEND_PROTOCOL=https"
args: './hasura -f ./hasura/Dockerfile --tag ${{env.HASURA_TAG}} --build-arg BACKEND_HOST=${{env.BACKEND_HOST}} --build-arg BACKEND_PROTOCOL=https'
cache_key: "${{hashFiles('hasura/**')}}"
- name: Push Hasura Container
@@ -163,7 +163,7 @@ jobs:
- name: Build Frontend Container
uses: mattes/cached-docker-build-action@v1
with:
args: ". -f ./docker/frontend/Dockerfile --tag ${{env.FRONTEND_TAG}} --build-arg GRAPHQL_URL=${{env.GRAPHQL_URL}}"
args: '. -f ./docker/frontend/Dockerfile --tag ${{env.FRONTEND_TAG}} --build-arg GRAPHQL_URL=${{env.GRAPHQL_URL}}'
cache_key: "${{hashFiles('packages/web/**', 'packages/design-system/**')}}"
- name: Push Frontend Container

View File

@@ -1,13 +1,12 @@
import { Box, ChakraProps, Flex } from '@metafam/ds';
import { Box, ChakraProps, Flex, Text } from '@metafam/ds';
import { FlexContainer } from 'components/Container';
import { Maybe } from 'graphql/autogen/types';
import {
colors,
getPersonalityInfo,
images,
PersonalityInfo,
} from 'graphql/queries/enums/getPersonalityInfo';
import { PersonalityOption } from 'graphql/types';
import React, { useEffect, useState } from 'react';
import React from 'react';
// This is just verbose, so I am pulling it out to
// save space in the main template
@@ -28,21 +27,16 @@ const maskImageStyle = ({ url }: { url: string }): Record<string, string> => ({
* combination below.
*/
export const ColorBar = ({
mask = 0,
mask = null,
personalityInfo: { parts, types },
...props
}: ChakraProps & { mask: number }): JSX.Element => {
const [parts, setParts] = useState<Array<PersonalityOption>>([]);
const [types, setTypes] = useState<Record<number, PersonalityOption>>({});
useEffect(() => {
const load = async () => {
const { parts: ps, types: ts } = await getPersonalityInfo();
setParts(ps);
setTypes(ts);
};
load();
}, []);
}: ChakraProps & {
mask: Maybe<number>;
personalityInfo: PersonalityInfo;
}): JSX.Element => {
if (mask === null) {
return <Text fontStyle="italic">Colors have not yet been chosen.</Text>;
}
return (
<Flex

View File

@@ -19,17 +19,19 @@ import BackgroundImage from 'assets/main-background.jpg';
import { FlexContainer } from 'components/Container';
import { PlayerSection } from 'components/Profile/PlayerSection';
import { PlayerFragmentFragment } from 'graphql/autogen/types';
import { PersonalityInfo } from 'graphql/queries/enums/getPersonalityInfo';
import React, { useCallback, useEffect, useState } from 'react';
import { BoxMetadata, BoxType } from 'utils/boxTypes';
type Props = FlexProps & {
player: PlayerFragmentFragment;
personalityInfo: PersonalityInfo;
boxList: BoxType[];
onAddBox: (arg0: BoxType, arg1: BoxMetadata) => void;
};
export const PlayerAddSection = React.forwardRef<HTMLDivElement, Props>(
({ player, boxList = [], onAddBox, ...props }, ref) => {
({ player, personalityInfo, boxList = [], onAddBox, ...props }, ref) => {
const { isOpen, onOpen, onClose } = useDisclosure();
const [boxType, setBoxType] = useState<Maybe<BoxType>>(null);
const [boxMetadata, setBoxMetadata] = useState<BoxMetadata>({});
@@ -167,6 +169,7 @@ export const PlayerAddSection = React.forwardRef<HTMLDivElement, Props>(
boxType,
boxMetadata,
player,
personalityInfo,
}}
/>
</Flex>

View File

@@ -3,17 +3,20 @@ import { FlexContainer } from 'components/Container';
import { ColorBar } from 'components/Player/ColorBar';
import { ProfileSection } from 'components/Profile/ProfileSection';
import { PlayerFragmentFragment } from 'graphql/autogen/types';
import { PersonalityInfo } from 'graphql/queries/enums/getPersonalityInfo';
import { useAnimateProfileChanges } from 'lib/hooks/players';
import React, { useState } from 'react';
import { BoxType } from 'utils/boxTypes';
type Props = {
player: PlayerFragmentFragment;
personalityInfo: PersonalityInfo;
isOwnProfile?: boolean;
canEdit?: boolean;
};
export const PlayerColorDisposition: React.FC<Props> = ({
player,
personalityInfo,
isOwnProfile,
canEdit,
}) => {
@@ -51,7 +54,7 @@ export const PlayerColorDisposition: React.FC<Props> = ({
fontWeight={600}
_focus={{ border: 'none' }}
>
<ColorBar {...{ mask }} />
<ColorBar {...{ mask, personalityInfo }} />
</Link>
</FlexContainer>
)}

View File

@@ -9,6 +9,7 @@ import { PlayerSkills } from 'components/Player/Section/PlayerSkills';
import { PlayerType } from 'components/Player/Section/PlayerType';
import { EmbeddedUrl } from 'components/Profile/EmbeddedUrlSection';
import { PlayerFragmentFragment } from 'graphql/autogen/types';
import { PersonalityInfo } from 'graphql/queries/enums/getPersonalityInfo';
import React from 'react';
import { FaTimes } from 'react-icons/fa';
import { BoxMetadata, BoxType, getBoxKey } from 'utils/boxTypes';
@@ -17,6 +18,7 @@ type Props = {
boxType: BoxType;
boxMetadata: BoxMetadata;
player: PlayerFragmentFragment;
personalityInfo: PersonalityInfo;
isOwnProfile?: boolean;
canEdit?: boolean;
onRemoveBox?: (boxKey: string) => void;
@@ -27,6 +29,7 @@ const PlayerSectionInner: React.FC<Props> = ({
boxType,
player,
isOwnProfile,
personalityInfo,
canEdit,
}) => {
switch (boxType) {
@@ -39,7 +42,11 @@ const PlayerSectionInner: React.FC<Props> = ({
case BoxType.PLAYER_DAO_MEMBERSHIPS:
return <PlayerMemberships {...{ player, isOwnProfile, canEdit }} />;
case BoxType.PLAYER_COLOR_DISPOSITION:
return <PlayerColorDisposition {...{ player, isOwnProfile, canEdit }} />;
return (
<PlayerColorDisposition
{...{ player, isOwnProfile, canEdit, personalityInfo }}
/>
);
case BoxType.PLAYER_TYPE:
return <PlayerType {...{ player, isOwnProfile, canEdit }} />;
case BoxType.PLAYER_ROLES:
@@ -57,7 +64,15 @@ const PlayerSectionInner: React.FC<Props> = ({
export const PlayerSection = React.forwardRef<HTMLDivElement, Props>(
(
{ boxMetadata, boxType, player, isOwnProfile, canEdit, onRemoveBox },
{
boxMetadata,
boxType,
player,
isOwnProfile,
canEdit,
onRemoveBox,
personalityInfo,
},
ref,
) => {
const boxKey = getBoxKey(boxType, boxMetadata);
@@ -73,7 +88,14 @@ export const PlayerSection = React.forwardRef<HTMLDivElement, Props>(
pos="relative"
>
<PlayerSectionInner
{...{ boxMetadata, boxType, player, isOwnProfile, canEdit }}
{...{
boxMetadata,
boxType,
player,
isOwnProfile,
canEdit,
personalityInfo,
}}
/>
{canEdit && (
<Flex

View File

@@ -23,8 +23,8 @@ import { Maybe } from 'graphql/autogen/types';
import {
getPersonalityInfo,
images as BaseImages,
PersonalityInfo,
} from 'graphql/queries/enums/getPersonalityInfo';
import { PersonalityOption } from 'graphql/types';
import { useUser, useWeb3 } from 'lib/hooks';
import React, { ReactElement, useEffect, useState } from 'react';
import { dispositionFor } from 'utils/playerHelpers';
@@ -47,9 +47,10 @@ export const SetupPersonalityType: React.FC<SetupPersonalityTypeProps> = ({
const [colorMask, setColorMask] = useState<Maybe<number> | undefined>(
player?.profile?.colorMask,
);
const [personalityTypes, setPersonalityTypes] = useState<{
[x: number]: PersonalityOption;
}>([]);
const [{ types, parts }, setPersonalityInfo] = useState<PersonalityInfo>({
types: {},
parts: [],
});
const isWizard = !isEdit;
const load = () => {
@@ -62,10 +63,8 @@ export const SetupPersonalityType: React.FC<SetupPersonalityTypeProps> = ({
useEffect(load, [player, colorMask]);
useEffect(() => {
const fetchInfo = async () => {
const { types } = await getPersonalityInfo();
setPersonalityTypes(types);
};
const fetchInfo = async () =>
setPersonalityInfo(await getPersonalityInfo());
fetchInfo();
}, []);
@@ -177,11 +176,11 @@ export const SetupPersonalityType: React.FC<SetupPersonalityTypeProps> = ({
wrap="wrap"
id="colors"
>
{Object.keys(personalityTypes).length &&
{Object.keys(types).length &&
Object.entries(BaseImages)
.reverse()
.map(([orig, image], idx) => {
const option = personalityTypes[parseInt(orig, 10)];
const option = types[parseInt(orig, 10)];
const { mask = 0 } = option ?? {};
const selected = ((colorMask ?? 0) & mask) > 0;
@@ -255,7 +254,12 @@ export const SetupPersonalityType: React.FC<SetupPersonalityTypeProps> = ({
})}
</FlexContainer>
<ColorBar mask={colorMask} mt={8} w="min(90vw, 30rem)" />
<ColorBar
mask={colorMask ?? null}
mt={8}
w="min(90vw, 30rem)"
personalityInfo={{ types, parts }}
/>
{isEdit && onClose && (
<ModalFooter mt={6}>

View File

@@ -45,10 +45,12 @@ export const colors: {
0b00001: { start: '#0E9651', end: '#9FD638' },
};
export const getPersonalityInfo = async (): Promise<{
export type PersonalityInfo = {
parts: Array<PersonalityOption>;
types: { [any: string]: PersonalityOption };
}> => {
types: { [x: number]: PersonalityOption };
};
export const getPersonalityInfo = async (): Promise<PersonalityInfo> => {
const { data, error } = await client.query(AspectsQuery).toPromise();
if (error) throw error;

View File

@@ -81,5 +81,5 @@ module.exports = withImages({
);
return config;
}
},
});

View File

@@ -30,6 +30,7 @@ import {
} from 'graphql/autogen/types';
import { getPlayer } from 'graphql/getPlayer';
import { getTopPlayerUsernames } from 'graphql/getPlayers';
import { getPersonalityInfo } from 'graphql/queries/enums/getPersonalityInfo';
import { useUser, useWeb3 } from 'lib/hooks';
import {
GetStaticPaths,
@@ -65,7 +66,10 @@ const ResponsiveGridLayout = WidthProvider(Responsive);
type Props = InferGetStaticPropsType<typeof getStaticProps>;
export const PlayerPage: React.FC<Props> = ({ player }): ReactElement => {
export const PlayerPage: React.FC<Props> = ({
player,
personalityInfo,
}): ReactElement => {
if (!player) return <Error statusCode={404} />;
return (
@@ -85,7 +89,7 @@ export const PlayerPage: React.FC<Props> = ({ player }): ReactElement => {
w="full"
/>
<Flex w="full" h="full" pt="3rem" direction="column" align="center">
<Grid {...{ player }} />
<Grid {...{ player, personalityInfo }} />
</Flex>
</PageContainer>
);
@@ -212,7 +216,10 @@ const useItemHeights = (items: HTMLElement[]): { [boxKey: string]: number } => {
return heights;
};
export const Grid: React.FC<Props> = ({ player: initPlayer }): ReactElement => {
export const Grid: React.FC<Props> = ({
player: initPlayer,
personalityInfo,
}): ReactElement => {
const [isOwnProfile, setIsOwnProfile] = useState(false);
const [, invalidateCache] = useInsertCacheInvalidationMutation();
const { user, fetching } = useUser();
@@ -493,7 +500,7 @@ export const Grid: React.FC<Props> = ({ player: initPlayer }): ReactElement => {
{boxType === BoxType.PLAYER_ADD_BOX ? (
<PlayerAddSection
boxList={availableBoxList}
{...{ player, onAddBox }}
{...{ player, onAddBox, personalityInfo }}
ref={(e) => {
itemsRef.current[i] = e as HTMLElement;
}}
@@ -505,6 +512,7 @@ export const Grid: React.FC<Props> = ({ player: initPlayer }): ReactElement => {
boxMetadata,
player,
isOwnProfile,
personalityInfo,
canEdit,
onRemoveBox,
}}
@@ -547,9 +555,11 @@ export const getStaticProps = async (
}
const player = await getPlayer(username);
const personalityInfo = await getPersonalityInfo();
return {
props: {
personalityInfo,
player: player ?? null, // must be serializable
key: username.toLowerCase(),
hideTopMenu: !player,