Skip to content

Commit

Permalink
feat(web): support create beta project (#451)
Browse files Browse the repository at this point in the history
Co-authored-by: nina992 <nouralali992@gmail.com>
Co-authored-by: Hiroki Isogai <prog@d2deck.com>
  • Loading branch information
3 people committed Jun 1, 2023
1 parent 16d7ace commit 7c89bfd
Show file tree
Hide file tree
Showing 37 changed files with 365 additions and 158 deletions.
1 change: 1 addition & 0 deletions web/e2e/utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const config = {
authClientId: process.env["REEARTH_WEB_AUTH0_CLIENT_ID"],
authUrl: process.env["REEARTH_WEB_AUTH0_DOMAIN"],
signUpSecret: process.env["REEARTH_WEB_E2E_SIGNUP_SECRET"],
developerMode: process.env["REEARTH_WEB_DEVELOPER_MODE"],
};

export type Config = typeof config;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions web/src/classic/components/molecules/Common/Header/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ProjectType } from "@reearth/types";

export type User = {
name: string;
};
Expand All @@ -15,4 +17,5 @@ export type Workspace = {
export type Project = {
id?: string;
name?: string;
projectType?: ProjectType;
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,26 @@ import React, { useCallback, useEffect } from "react";

import Button from "@reearth/classic/components/atoms/Button";
import Divider from "@reearth/classic/components/atoms/Divider";
import defaultBetaProjectImage from "@reearth/classic/components/atoms/Icon/Icons/defaultBetaProjectImage.png";
import defaultProjectImage from "@reearth/classic/components/atoms/Icon/Icons/defaultProjectImage.jpg";
import Loading from "@reearth/classic/components/atoms/Loading";
import Modal from "@reearth/classic/components/atoms/Modal";
import Text from "@reearth/classic/components/atoms/Text";
import defaultProjectImage from "@reearth/classic/components/molecules/Dashboard/defaultProjectImage.jpg";
import { useT } from "@reearth/services/i18n";
import { styled, useTheme } from "@reearth/services/theme";
import fonts from "@reearth/services/theme/fonts";
import { ProjectType } from "@reearth/types";

export interface FormValues {
name: string;
description: string;
imageUrl: string;
projectType: ProjectType;
}

export interface Props {
open?: boolean;
projectType?: ProjectType;
onClose?: (refetch?: boolean) => void;
onSubmit?: (values: FormValues) => Promise<void> | void;
selectedAsset?: string;
Expand All @@ -30,10 +34,12 @@ const initialValues: FormValues = {
name: "",
description: "",
imageUrl: "",
projectType: "classic",
};

const ProjectCreationModal: React.FC<Props> = ({
open,
projectType,
onClose,
onSubmit,
selectedAsset,
Expand Down Expand Up @@ -62,7 +68,10 @@ const ProjectCreationModal: React.FC<Props> = ({
if (selectedAsset) {
formik.setFieldValue("imageUrl", selectedAsset);
}
}, [selectedAsset]); // eslint-disable-line react-hooks/exhaustive-deps
if (projectType) {
formik.setFieldValue("projectType", projectType);
}
}, [selectedAsset, projectType]); // eslint-disable-line react-hooks/exhaustive-deps

const handleCreate = useCallback(async () => {
await formik.submitForm();
Expand Down Expand Up @@ -117,7 +126,11 @@ const ProjectCreationModal: React.FC<Props> = ({
<Text size="s" color={theme.main.text} otherProperties={{ margin: "14px 0" }}>
{t("Select thumbnail image")}
</Text>
<Thumbnail url={formik.values.imageUrl} onClick={toggleAssetModal} />
<Thumbnail
url={formik.values.imageUrl}
projectType={projectType}
onClick={toggleAssetModal}
/>
</FormInputWrapper>
</NewProjectForm>
{assetModal}
Expand Down Expand Up @@ -156,8 +169,13 @@ const StyledTextArea = styled.textarea`
padding: 5px;
`;

const Thumbnail = styled.div<{ url: string }>`
background-image: ${props => (props.url ? `url(${props.url})` : `url(${defaultProjectImage})`)};
const Thumbnail = styled.div<{ url: string; projectType?: ProjectType }>`
background-image: ${props =>
props.url
? `url(${props.url})`
: props.projectType === "beta"
? `url(${defaultBetaProjectImage})`
: `url(${defaultProjectImage})`};
background-size: cover;
background-position: center;
height: 242px;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { action } from "@storybook/addon-actions";
import { Meta, Story } from "@storybook/react";

import ProjectTypeSelectionModal, { Props } from ".";

export default {
title: "molecules/common/ProjectTypeSelectionModal",
component: ProjectTypeSelectionModal,
} as Meta;

export const Default: Story<Props> = args => (
<ProjectTypeSelectionModal
{...args}
open
onClose={action("onClose")}
onSubmit={action("onSubmit")}
/>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import React, { useCallback } from "react";

import Icon from "@reearth/classic/components/atoms/Icon";
import Modal from "@reearth/classic/components/atoms/Modal";
import Text from "@reearth/classic/components/atoms/Text";
import { useT } from "@reearth/services/i18n";
import { styled, useTheme } from "@reearth/services/theme";
import { ProjectType } from "@reearth/types";

export interface Props {
open?: boolean;
onClose?: () => void;
onSubmit?: (projectType: ProjectType) => void;
}

const ProjectTypeSelectionModal: React.FC<Props> = ({ open, onClose, onSubmit }) => {
const t = useT();
const theme = useTheme();
const handleTypeSelect = useCallback(
(projectType: ProjectType) => {
onSubmit?.(projectType);
onClose?.();
},
[onSubmit, onClose],
);

const handleCloseModal = useCallback(() => {
onClose?.();
}, [onClose]);

return (
<ModalWrapper isVisible={open} onClose={handleCloseModal}>
<TitleText size="xl" color={theme.other.white} weight={"bold"}>
{t("Choose Project Type")}
</TitleText>
<ProjectTypeContainer>
<ProjectTypeItem onClick={() => handleTypeSelect("classic")}>
<Icon icon="logo" size={101} />
<Text size="s" color={theme.other.white} weight={"bold"}>
{t("classic")}
</Text>
<HintText size="xs" color={theme.main.weak} weight="normal">
{t("Create project with classic UI")}
</HintText>
</ProjectTypeItem>
<ProjectTypeItem onClick={() => handleTypeSelect("beta")}>
<Icon icon="logoColorful" size={101} />
<Text size="s" color={theme.other.white} weight={"bold"}>
{t("Beta")}
</Text>
<HintText size="xs" color={theme.main.weak} weight="normal">
{t(
"Create project with the latest features and UI system (projects might break without prior notice)",
)}
</HintText>
</ProjectTypeItem>
</ProjectTypeContainer>
</ModalWrapper>
);
};

const ModalWrapper = styled(Modal)`
padding: 20px 32px 36px;
gap: 12px;
width: 756px;
height: 528px;
`;

const TitleText = styled(Text)`
margin-top: 56px;
text-align: center;
`;
const ProjectTypeContainer = styled.div`
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 32px 56px 32px 36px;
gap: 102px;
height: 373px;
`;

const ProjectTypeItem = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 20px;
gap: 12px;
width: 194px;
height: 194px;
border: 1px dashed #4a4a4a;
cursor: pointer;
`;

const HintText = styled(Text)`
margin-top: 12px;
width: 154px;
height: 42px;
line-height: 14px;
text-align: center;
`;

export default ProjectTypeSelectionModal;
25 changes: 17 additions & 8 deletions web/src/classic/components/molecules/Dashboard/Project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ import { useMedia } from "react-use";

import Button from "@reearth/classic/components/atoms/Button";
import Flex from "@reearth/classic/components/atoms/Flex";
import defaultBetaProjectImage from "@reearth/classic/components/atoms/Icon/Icons/defaultBetaProjectImage.png";
import defaultProjectImage from "@reearth/classic/components/atoms/Icon/Icons/defaultProjectImage.jpg";
import PublicationStatus from "@reearth/classic/components/atoms/PublicationStatus";
import Text from "@reearth/classic/components/atoms/Text";
import { Project as ProjectType } from "@reearth/classic/components/molecules/Dashboard/types";
import { Project as ProjectObjType } from "@reearth/classic/components/molecules/Dashboard/types";
import { useT } from "@reearth/services/i18n";
import { styled, useTheme } from "@reearth/services/theme";

import defaultProjectImage from "./defaultProjectImage.jpg";
import { ProjectType } from "@reearth/types";

export type Props = {
className?: string;
project: ProjectType;
project: ProjectObjType;
};

const Project: React.FC<Props> = ({ className, project }) => {
Expand All @@ -39,6 +40,7 @@ const Project: React.FC<Props> = ({ className, project }) => {
<StyledWrapper className={className}>
<Block
projectImage={image}
projectType={project.projectType}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}>
<Content isHovered={isHovered}>
Expand All @@ -47,7 +49,10 @@ const Project: React.FC<Props> = ({ className, project }) => {
</Text>
<Actions isHovered={isHovered}>
<ButtonWrapper>
<StyledLink to={`/edit/${sceneId}`}>
<StyledLink
to={
project.projectType === "beta" ? `/scene/${sceneId}/scene` : `/edit/${sceneId}`
}>
<Button large buttonType="primary" icon="earthEditor" />
</StyledLink>
<Button large buttonType="primary" icon="preview" onClick={onPreviewOpen} />
Expand Down Expand Up @@ -86,13 +91,17 @@ const StyledWrapper = styled.div`
}
`;

const Block = styled.div<{ projectImage?: string | null }>`
const Block = styled.div<{ projectImage?: string | null; projectType?: ProjectType }>`
display: flex;
height: 238px;
border-radius: 12px;
margin: 7px;
background-image: ${({ projectImage }) =>
projectImage ? `url(${projectImage})` : `url(${defaultProjectImage})`};
background-image: ${({ projectImage, projectType }) =>
projectImage
? `url(${projectImage})`
: projectType === "beta"
? `url(${defaultBetaProjectImage})`
: `url(${defaultProjectImage})`};
background-size: cover;
background-position: center;
${({ projectImage }) => !projectImage && "background-size: 560px 290px;"}
Expand Down
37 changes: 31 additions & 6 deletions web/src/classic/components/molecules/Dashboard/QuickStart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import WorkspaceCreationModal from "@reearth/classic/components/molecules/Common
import { useT } from "@reearth/services/i18n";
import { styled, useTheme, metrics, css } from "@reearth/services/theme";
import { metricsSizes } from "@reearth/services/theme/metrics";
import { ProjectType } from "@reearth/types";

import ProjectTypeSelectionModal from "../Common/ProjectTypeSelectionModal";

export interface Props {
className?: string;
Expand All @@ -20,6 +23,7 @@ export interface Props {
name: string;
description: string;
imageUrl: string;
projectType: ProjectType;
}) => Promise<void>;
toggleAssetModal?: () => void;
onAssetSelect?: (asset?: string) => void;
Expand All @@ -36,17 +40,32 @@ const QuickStart: React.FC<Props> = ({
}) => {
const documentationUrl = window.REEARTH_CONFIG?.documentationUrl;
const t = useT();
const [projCreateOpen, setProjCreateOpen] = useState(false);
const [prjCreateOpen, setPrjCreateOpen] = useState(false);
const [prjTypeSelectOpen, setPrjTypeSelectOpen] = useState(false);
const [workCreateOpen, setWorkCreateOpen] = useState(false);
const [prjectType, setPrjectType] = useState<ProjectType>("classic");
const theme = useTheme();
const isSmallWindow = useMedia("(max-width: 1024px)");

const handleCreateProjectClick = useCallback(() => {
if (window.REEARTH_CONFIG?.developerMode) setPrjTypeSelectOpen(true);
else setPrjCreateOpen(true);
}, []);

const handleProjModalClose = useCallback(() => {
setProjCreateOpen(false);
setPrjCreateOpen(false);
onAssetSelect?.();
}, [onAssetSelect]);

const theme = useTheme();
const handlePrjTypeSelectModalClose = useCallback(() => {
setPrjTypeSelectOpen(false);
setPrjCreateOpen(true);
}, []);

const isSmallWindow = useMedia("(max-width: 1024px)");
const handleProjectTypeSelect = (type: ProjectType) => {
setPrjectType(type);
setPrjCreateOpen(true);
};

return (
<StyledDashboardBlock className={className} grow={4}>
Expand All @@ -71,7 +90,7 @@ const QuickStart: React.FC<Props> = ({
align="center"
justify="center"
linearGradient={window.REEARTH_CONFIG?.brand?.background}
onClick={() => setProjCreateOpen(true)}>
onClick={handleCreateProjectClick}>
<StyledIcon icon="newProject" size={70} />
<Text size="m" weight="bold" customColor>
{t("New project")}
Expand All @@ -89,8 +108,14 @@ const QuickStart: React.FC<Props> = ({
</BannerButton>
</Flex>
</Content>
<ProjectTypeSelectionModal
open={prjTypeSelectOpen}
onClose={handlePrjTypeSelectModalClose}
onSubmit={handleProjectTypeSelect}
/>
<ProjectCreationModal
open={projCreateOpen}
open={prjCreateOpen}
projectType={prjectType}
onClose={handleProjModalClose}
onSubmit={onProjectCreate}
toggleAssetModal={toggleAssetModal}
Expand Down
2 changes: 2 additions & 0 deletions web/src/classic/components/molecules/Dashboard/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Status as StatusType } from "@reearth/classic/components/atoms/PublicationStatus";
import { ProjectType } from "@reearth/types";

export type User = {
name: string;
Expand Down Expand Up @@ -32,4 +33,5 @@ export type Project = {
description: string;
sceneId?: string;
updatedAt?: string;
projectType?: ProjectType;
};
Loading

0 comments on commit 7c89bfd

Please sign in to comment.