Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions apps/web/ce/components/projects/create/attributes.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { FC } from "react";
import { Controller, useFormContext } from "react-hook-form";
// plane imports
import { NETWORK_CHOICES, ETabIndices } from "@plane/constants";
Expand Down Expand Up @@ -79,7 +78,7 @@ function ProjectAttributes(props: Props) {
placeholder={t("lead")}
multiple={false}
buttonVariant="border-with-text"
tabIndex={5}
tabIndex={getIndex("lead")}
/>
</div>
);
Expand Down
19 changes: 9 additions & 10 deletions apps/web/ce/components/projects/create/root.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import { useState } from "react";
import { PROJECT_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { observer } from "mobx-react";
import { useState } from "react";
import { FormProvider, useForm } from "react-hook-form";
import { PROJECT_TRACKER_EVENTS, RANDOM_EMOJI_CODES } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
// ui
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { EFileAssetType } from "@plane/types";
import type { IProject } from "@plane/types";
// constants
import ProjectCommonAttributes from "@/components/project/create/common-attributes";
import ProjectCreateHeader from "@/components/project/create/header";
import ProjectCreateButtons from "@/components/project/create/project-create-buttons";
// hooks
import { DEFAULT_COVER_IMAGE_URL, getCoverImageType, uploadCoverImage } from "@/helpers/cover-image.helper";
import { getCoverImageType, uploadCoverImage } from "@/helpers/cover-image.helper";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useProject } from "@/hooks/store/use-project";
import { usePlatformOS } from "@/hooks/use-platform-os";
// plane web types
import type { TProject } from "@/plane-web/types/projects";
import ProjectAttributes from "./attributes";
import { ProjectAttributes } from "./attributes";
import { getProjectFormValues } from "./utils";

export type TCreateProjectFormProps = {
Expand All @@ -37,7 +36,7 @@ export const CreateProjectForm = observer(function CreateProjectForm(props: TCre
const { t } = useTranslation();
const { addProjectToFavorites, createProject, updateProject } = useProject();
// states
const [isChangeInIdentifierRequired, setIsChangeInIdentifierRequired] = useState(true);
const [shouldAutoSyncIdentifier, setShouldAutoSyncIdentifier] = useState(true);
// form info
const methods = useForm<TProject>({
defaultValues: { ...getProjectFormValues(), ...data },
Expand Down Expand Up @@ -167,7 +166,7 @@ export const CreateProjectForm = observer(function CreateProjectForm(props: TCre

const handleClose = () => {
onClose();
setIsChangeInIdentifierRequired(true);
setShouldAutoSyncIdentifier(true);
setTimeout(() => {
reset();
}, 300);
Expand All @@ -182,8 +181,8 @@ export const CreateProjectForm = observer(function CreateProjectForm(props: TCre
<ProjectCommonAttributes
setValue={setValue}
isMobile={isMobile}
isChangeInIdentifierRequired={isChangeInIdentifierRequired}
setIsChangeInIdentifierRequired={setIsChangeInIdentifierRequired}
shouldAutoSyncIdentifier={shouldAutoSyncIdentifier}
setShouldAutoSyncIdentifier={setShouldAutoSyncIdentifier}
/>
<ProjectAttributes isMobile={isMobile} />
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
type TProjectTemplateDropdownSize = "xs" | "sm";

export type TProjectTemplateSelect = {
disabled?: boolean;
size?: TProjectTemplateDropdownSize;
placeholder?: string;
dropDownContainerClassName?: string;
handleModalClose: () => void;
onClick?: () => void;
};

// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function CreateProjectModal(props: Props) {
});

return (
<ModalCore isOpen={isOpen} position={EModalPosition.TOP} width={EModalWidth.XXL}>
<ModalCore isOpen={isOpen} position={EModalPosition.TOP} width={EModalWidth.XXXXL}>
{currentStep === EProjectCreationSteps.CREATE_PROJECT && (
<CreateProjectForm
setToFavorite={setToFavorite}
Expand Down
30 changes: 15 additions & 15 deletions apps/web/core/components/project/create/common-attributes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@ import type { TProject } from "@/plane-web/types/projects";
type Props = {
setValue: UseFormSetValue<TProject>;
isMobile: boolean;
isChangeInIdentifierRequired: boolean;
setIsChangeInIdentifierRequired: (value: boolean) => void;
shouldAutoSyncIdentifier: boolean;
setShouldAutoSyncIdentifier: (value: boolean) => void;
handleFormOnChange?: () => void;
};

function ProjectCommonAttributes(props: Props) {
const { setValue, isMobile, isChangeInIdentifierRequired, setIsChangeInIdentifierRequired, handleFormOnChange } =
props;
const { setValue, isMobile, shouldAutoSyncIdentifier, setShouldAutoSyncIdentifier, handleFormOnChange } = props;
const {
formState: { errors },
control,
Expand All @@ -33,21 +32,22 @@ function ProjectCommonAttributes(props: Props) {
const { getIndex } = getTabIndex(ETabIndices.PROJECT_CREATE, isMobile);
const { t } = useTranslation();

const handleNameChange = (onChange: (...event: any[]) => void) => (e: ChangeEvent<HTMLInputElement>) => {
if (!isChangeInIdentifierRequired) {
const handleNameChange =
(onChange: (event: ChangeEvent<HTMLInputElement>) => void) => (e: ChangeEvent<HTMLInputElement>) => {
if (!shouldAutoSyncIdentifier) {
onChange(e);
return;
}
if (e.target.value === "") setValue("identifier", "");
else setValue("identifier", projectIdentifierSanitizer(e.target.value).substring(0, 10));
onChange(e);
return;
}
if (e.target.value === "") setValue("identifier", "");
else setValue("identifier", projectIdentifierSanitizer(e.target.value).substring(0, 10));
onChange(e);
handleFormOnChange?.();
};
handleFormOnChange?.();
};
Comment thread
JayashTripathy marked this conversation as resolved.

const handleIdentifierChange = (onChange: any) => (e: ChangeEvent<HTMLInputElement>) => {
const handleIdentifierChange = (onChange: (value: string) => void) => (e: ChangeEvent<HTMLInputElement>) => {
const { value } = e.target;
const alphanumericValue = projectIdentifierSanitizer(value);
setIsChangeInIdentifierRequired(false);
setShouldAutoSyncIdentifier(false);
onChange(alphanumericValue);
handleFormOnChange?.();
};
Expand Down
39 changes: 26 additions & 13 deletions apps/web/core/components/project/create/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ import { ProjectTemplateSelect } from "@/plane-web/components/projects/create/te
type Props = {
handleClose: () => void;
isMobile?: boolean;
handleFormChange?: () => void;
isClosable?: boolean;
handleTemplateSelect?: () => void;
};

function ProjectCreateHeader(props: Props) {
const { handleClose, isMobile = false } = props;
const { watch, control } = useFormContext<IProject>();
const { handleClose, isMobile = false, handleFormChange, isClosable = true, handleTemplateSelect } = props;
const { watch, control, setValue } = useFormContext<IProject>();
const { t } = useTranslation();
// derived values
const coverImage = watch("cover_image_url");
Expand All @@ -38,22 +41,27 @@ function ProjectCreateHeader(props: Props) {
className="absolute left-0 top-0 h-full w-full rounded-lg"
/>
<div className="absolute left-2.5 top-2.5">
<ProjectTemplateSelect handleModalClose={handleClose} />
</div>
<div className="absolute right-2 top-2 p-2">
<button data-posthog="PROJECT_MODAL_CLOSE" type="button" onClick={handleClose} tabIndex={getIndex("close")}>
<CloseIcon className="h-5 w-5 text-on-color" />
</button>
<ProjectTemplateSelect onClick={handleTemplateSelect} />
</div>
{isClosable && (
<div className="absolute right-2 top-2 p-2">
<button data-posthog="PROJECT_MODAL_CLOSE" type="button" onClick={handleClose} tabIndex={getIndex("close")}>
<CloseIcon className="h-5 w-5 text-on-color" />
</button>
</div>
)}
<div className="absolute bottom-2 right-2">
<Controller
name="cover_image_url"
control={control}
render={({ field: { value, onChange } }) => (
<ImagePickerPopover
label={t("change_cover")}
onChange={(data) => {
onChange(data);
handleFormChange?.();
}}
control={control}
onChange={onChange}
value={value ?? null}
tabIndex={getIndex("cover_image")}
/>
Expand All @@ -72,7 +80,7 @@ function ProjectCreateHeader(props: Props) {
className="flex items-center justify-center"
buttonClassName="flex items-center justify-center"
label={
<span className="grid h-11 w-11 place-items-center rounded-md bg-layer-1">
<span className="grid h-11 w-11 place-items-center bg-layer-2 rounded-md border border-subtle">
<Logo logo={value} size={20} />
</span>
}
Expand All @@ -85,15 +93,20 @@ function ProjectCreateHeader(props: Props) {
};
else if (val?.type === "icon") logoValue = val.value;

onChange({
const newLogoProps = {
in_use: val?.type,
[val?.type]: logoValue,
};
setValue("logo_props", newLogoProps, {
shouldDirty: true,
});
onChange(newLogoProps);
handleFormChange?.();
setIsOpen(false);
}}
defaultIconColor={value.in_use && value.in_use === "icon" ? value.icon?.color : undefined}
defaultIconColor={value?.in_use && value.in_use === "icon" ? value.icon?.color : undefined}
defaultOpen={
value.in_use && value.in_use === "emoji" ? EmojiIconPickerTypes.EMOJI : EmojiIconPickerTypes.ICON
value?.in_use && value.in_use === "emoji" ? EmojiIconPickerTypes.EMOJI : EmojiIconPickerTypes.ICON
}
/>
)}
Expand Down
1 change: 1 addition & 0 deletions packages/types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,4 @@ export * from "./workspace-draft-issues/base";
export * from "./workspace-notifications";
export * from "./workspace-views";
export * from "./base-layouts";
export * from "./pagination";
15 changes: 15 additions & 0 deletions packages/types/src/pagination.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Generic paginated response type for API responses
export type TPaginatedResponse<T> = {
results: T;
grouped_by?: string | null;
sub_grouped_by?: string | null;
total_count?: number;
next_cursor?: string;
prev_cursor?: string;
next_page_results?: boolean;
prev_page_results?: boolean;
count?: number;
total_pages?: number;
total_results?: number;
extra_stats?: string | null;
};
Loading