Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web): support create beta project #451

Merged
merged 17 commits into from
Jun 1, 2023
Merged
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})` ?? `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",
keiya01 marked this conversation as resolved.
Show resolved Hide resolved
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,107 @@
import React, { useCallback } from "react";

// import Button from "@reearth/classic/components/atoms/Button";
KaWaite marked this conversation as resolved.
Show resolved Hide resolved
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";
// import fonts from "@reearth/services/theme/fonts";
KaWaite marked this conversation as resolved.
Show resolved Hide resolved

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();
console.log(open);
KaWaite marked this conversation as resolved.
Show resolved Hide resolved
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;
23 changes: 15 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,8 @@ const Project: React.FC<Props> = ({ className, project }) => {
</Text>
<Actions isHovered={isHovered}>
<ButtonWrapper>
<StyledLink to={`/edit/${sceneId}`}>
<StyledLink
to={project.projectType === "beta" ? `/scene/${sceneId}` : `/edit/${sceneId}`}>
nina992 marked this conversation as resolved.
Show resolved Hide resolved
<Button large buttonType="primary" icon="earthEditor" />
</StyledLink>
<Button large buttonType="primary" icon="preview" onClick={onPreviewOpen} />
Expand Down Expand Up @@ -86,13 +89,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
31 changes: 28 additions & 3 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 @@ -37,16 +41,31 @@ const QuickStart: React.FC<Props> = ({
const documentationUrl = window.REEARTH_CONFIG?.documentationUrl;
const t = useT();
const [projCreateOpen, setProjCreateOpen] = useState(false);
const [prjTypeSelectOpen, setPrjTypeSelectOpen] = useState(false);
const [workCreateOpen, setWorkCreateOpen] = useState(false);
const [projectType, setProjectType] = useState<ProjectType>("classic");
const theme = useTheme();
const isSmallWindow = useMedia("(max-width: 1024px)");

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

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

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

const isSmallWindow = useMedia("(max-width: 1024px)");
const handleProjectTypeSelect = (type: ProjectType) => {
setProjectType(type);
setProjCreateOpen(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()}>
nina992 marked this conversation as resolved.
Show resolved Hide resolved
<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}
projectType={projectType}
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