feat: now user can edit view (#793)

* feat: now user can edit view

* fix: build error
This commit is contained in:
Saheb Giri 2023-04-12 15:33:21 +05:30 committed by GitHub
parent 0f9812cf2c
commit 032ef831b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 69 additions and 70 deletions

View File

@ -401,7 +401,7 @@ export const IssuesView: React.FC<Props> = ({
<CreateUpdateViewModal <CreateUpdateViewModal
isOpen={createViewModal !== null} isOpen={createViewModal !== null}
handleClose={() => setCreateViewModal(null)} handleClose={() => setCreateViewModal(null)}
preLoadedData={createViewModal} data={createViewModal}
/> />
<CreateUpdateIssueModal <CreateUpdateIssueModal
isOpen={createIssueModal && preloadedData?.actionType === "createIssue"} isOpen={createIssueModal && preloadedData?.actionType === "createIssue"}

View File

@ -1,4 +1,4 @@
import React, { useRef, useState } from "react"; import React, { useState } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
@ -21,12 +21,11 @@ import { VIEWS_LIST } from "constants/fetch-keys";
type Props = { type Props = {
isOpen: boolean; isOpen: boolean;
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
data: IView | null; data: IView | null;
onClose: () => void;
onSuccess?: () => void;
}; };
export const DeleteViewModal: React.FC<Props> = ({ isOpen, data, onClose, onSuccess }) => { export const DeleteViewModal: React.FC<Props> = ({ isOpen, data, setIsOpen }) => {
const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const router = useRouter(); const router = useRouter();
@ -35,14 +34,14 @@ export const DeleteViewModal: React.FC<Props> = ({ isOpen, data, onClose, onSucc
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
const handleClose = () => { const handleClose = () => {
setIsOpen(false);
setIsDeleteLoading(false); setIsDeleteLoading(false);
onClose();
}; };
const handleDeletion = async () => { const handleDeletion = async () => {
setIsDeleteLoading(true); setIsDeleteLoading(true);
if (!workspaceSlug || !data || !projectId) return; if (!workspaceSlug || !data || !projectId) return;
await viewsService await viewsService
.deleteView(workspaceSlug as string, projectId as string, data.id) .deleteView(workspaceSlug as string, projectId as string, data.id)
.then(() => { .then(() => {
@ -50,8 +49,6 @@ export const DeleteViewModal: React.FC<Props> = ({ isOpen, data, onClose, onSucc
views?.filter((view) => view.id !== data.id) views?.filter((view) => view.id !== data.id)
); );
if (onSuccess) onSuccess();
handleClose(); handleClose();
setToastAlert({ setToastAlert({
@ -66,6 +63,8 @@ export const DeleteViewModal: React.FC<Props> = ({ isOpen, data, onClose, onSucc
title: "Error!", title: "Error!",
message: "View could not be deleted. Please try again.", message: "View could not be deleted. Please try again.",
}); });
})
.finally(() => {
setIsDeleteLoading(false); setIsDeleteLoading(false);
}); });
}; };
@ -111,10 +110,9 @@ export const DeleteViewModal: React.FC<Props> = ({ isOpen, data, onClose, onSucc
</Dialog.Title> </Dialog.Title>
<div className="mt-2"> <div className="mt-2">
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
Are you sure you want to delete view- {" "} Are you sure you want to delete view-{" "}
<span className="font-bold">{data?.name}</span> <span className="font-bold">{data?.name}</span>? All of the data related
? All of the data related to the view will be permanently removed. to the view will be permanently removed. This action cannot be undone.
This action cannot be undone.
</p> </p>
</div> </div>
</div> </div>

View File

@ -1,8 +1,5 @@
import { useEffect } from "react"; import { useEffect } from "react";
import { useRouter } from "next/router";
import useSWR from "swr";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
// ui // ui
@ -11,11 +8,6 @@ import { Input, PrimaryButton, SecondaryButton, TextArea } from "components/ui";
import { FilterList } from "components/core"; import { FilterList } from "components/core";
// types // types
import { IView } from "types"; import { IView } from "types";
// constant
import { STATE_LIST } from "constants/fetch-keys";
// services
import stateService from "services/state.service";
// components // components
import { SelectFilters } from "components/views"; import { SelectFilters } from "components/views";
@ -23,8 +15,7 @@ type Props = {
handleFormSubmit: (values: IView) => Promise<void>; handleFormSubmit: (values: IView) => Promise<void>;
handleClose: () => void; handleClose: () => void;
status: boolean; status: boolean;
data?: IView; data?: IView | null;
preLoadedData?: Partial<IView> | null;
}; };
const defaultValues: Partial<IView> = { const defaultValues: Partial<IView> = {
@ -32,13 +23,7 @@ const defaultValues: Partial<IView> = {
description: "", description: "",
}; };
export const ViewForm: React.FC<Props> = ({ export const ViewForm: React.FC<Props> = ({ handleFormSubmit, handleClose, status, data }) => {
handleFormSubmit,
handleClose,
status,
data,
preLoadedData,
}) => {
const { const {
register, register,
formState: { errors, isSubmitting }, formState: { errors, isSubmitting },
@ -49,6 +34,7 @@ export const ViewForm: React.FC<Props> = ({
} = useForm<IView>({ } = useForm<IView>({
defaultValues, defaultValues,
}); });
const filters = watch("query");
const handleCreateUpdateView = async (formData: IView) => { const handleCreateUpdateView = async (formData: IView) => {
await handleFormSubmit(formData); await handleFormSubmit(formData);
@ -66,13 +52,10 @@ export const ViewForm: React.FC<Props> = ({
}, [data, reset]); }, [data, reset]);
useEffect(() => { useEffect(() => {
reset({ if (status && data) {
...defaultValues, setValue("query", data.query_data);
...preLoadedData, }
}); }, [data, status, setValue]);
}, [preLoadedData, reset]);
const filters = watch("query");
return ( return (
<form onSubmit={handleSubmit(handleCreateUpdateView)}> <form onSubmit={handleSubmit(handleCreateUpdateView)}>
@ -84,18 +67,19 @@ export const ViewForm: React.FC<Props> = ({
<div> <div>
<Input <Input
id="name" id="name"
label="Name"
name="name" name="name"
type="name" type="name"
placeholder="Enter name" placeholder="Title"
autoComplete="off" autoComplete="off"
mode="transparent"
className="resize-none text-xl"
error={errors.name} error={errors.name}
register={register} register={register}
validations={{ validations={{
required: "Name is required", required: "Title is required",
maxLength: { maxLength: {
value: 255, value: 255,
message: "Name should be less than 255 characters", message: "Title should be less than 255 characters",
}, },
}} }}
/> />
@ -104,8 +88,9 @@ export const ViewForm: React.FC<Props> = ({
<TextArea <TextArea
id="description" id="description"
name="description" name="description"
label="Description" placeholder="Description"
placeholder="Enter description" className="h-32 resize-none text-sm"
mode="transparent"
error={errors.description} error={errors.description}
register={register} register={register}
/> />

View File

@ -20,16 +20,10 @@ import { VIEWS_LIST } from "constants/fetch-keys";
type Props = { type Props = {
isOpen: boolean; isOpen: boolean;
handleClose: () => void; handleClose: () => void;
data?: IView; data?: IView | null;
preLoadedData?: Partial<IView> | null;
}; };
export const CreateUpdateViewModal: React.FC<Props> = ({ export const CreateUpdateViewModal: React.FC<Props> = ({ isOpen, handleClose, data }) => {
isOpen,
handleClose,
data,
preLoadedData,
}) => {
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId } = router.query; const { workspaceSlug, projectId } = router.query;
@ -66,14 +60,18 @@ export const CreateUpdateViewModal: React.FC<Props> = ({
}; };
const updateView = async (payload: IView) => { const updateView = async (payload: IView) => {
const payloadData = {
...payload,
query_data: payload.query,
};
await viewsService await viewsService
.updateView(workspaceSlug as string, projectId as string, data?.id ?? "", payload) .updateView(workspaceSlug as string, projectId as string, data?.id ?? "", payloadData)
.then((res) => { .then((res) => {
mutate<IView[]>( mutate<IView[]>(
VIEWS_LIST(projectId as string), VIEWS_LIST(projectId as string),
(prevData) => (prevData) =>
prevData?.map((p) => { prevData?.map((p) => {
if (p.id === res.id) return { ...p, ...payload }; if (p.id === res.id) return { ...p, ...payloadData };
return p; return p;
}), }),
@ -135,7 +133,6 @@ export const CreateUpdateViewModal: React.FC<Props> = ({
handleClose={handleClose} handleClose={handleClose}
status={data ? true : false} status={data ? true : false}
data={data} data={data}
preLoadedData={preLoadedData}
/> />
</Dialog.Panel> </Dialog.Panel>
</Transition.Child> </Transition.Child>

View File

@ -1,4 +1,4 @@
import React, { useState } from "react"; import React from "react";
import { mutate } from "swr"; import { mutate } from "swr";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
@ -22,10 +22,11 @@ import { renderShortDate, renderShortTime } from "helpers/date-time.helper";
type Props = { type Props = {
view: IView; view: IView;
setSelectedView: React.Dispatch<React.SetStateAction<IView | null>>; handleEditView: () => void;
handleDeleteView: () => void;
}; };
export const SingleViewItem: React.FC<Props> = ({ view, setSelectedView }) => { export const SingleViewItem: React.FC<Props> = ({ view, handleEditView, handleDeleteView }) => {
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId } = router.query; const { workspaceSlug, projectId } = router.query;
@ -134,23 +135,23 @@ export const SingleViewItem: React.FC<Props> = ({ view, setSelectedView }) => {
</button> </button>
)} )}
<CustomMenu width="auto" verticalEllipsis> <CustomMenu width="auto" verticalEllipsis>
{/* <CustomMenu.MenuItem <CustomMenu.MenuItem
onClick={(e: any) => { onClick={(e: any) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
// handleEditView(); handleEditView();
}} }}
> >
<span className="flex items-center justify-start gap-2"> <span className="flex items-center justify-start gap-2">
<PencilIcon className="h-3.5 w-3.5" /> <PencilIcon className="h-3.5 w-3.5" />
<span>Edit View</span> <span>Edit View</span>
</span> </span>
</CustomMenu.MenuItem> */} </CustomMenu.MenuItem>
<CustomMenu.MenuItem <CustomMenu.MenuItem
onClick={(e: any) => { onClick={(e: any) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
setSelectedView(view); handleDeleteView();
}} }}
> >
<span className="flex items-center justify-start gap-2"> <span className="flex items-center justify-start gap-2">

View File

@ -25,8 +25,11 @@ import { IView } from "types";
import type { NextPage } from "next"; import type { NextPage } from "next";
const ProjectViews: NextPage = () => { const ProjectViews: NextPage = () => {
const [isCreateViewModalOpen, setIsCreateViewModalOpen] = useState(false); const [createUpdateViewModal, setCreateUpdateViewModal] = useState(false);
const [selectedView, setSelectedView] = useState<IView | null>(null); const [selectedViewToUpdate, setSelectedViewToUpdate] = useState<IView | null>(null);
const [deleteViewModal, setDeleteViewModal] = useState(false);
const [selectedViewToDelete, setSelectedViewToDelete] = useState<IView | null>(null);
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId } = router.query; const { workspaceSlug, projectId } = router.query;
@ -45,6 +48,16 @@ const ProjectViews: NextPage = () => {
: null : null
); );
const handleEditView = (view: IView) => {
setSelectedViewToUpdate(view);
setCreateUpdateViewModal(true);
};
const handleDeleteView = (view: IView) => {
setSelectedViewToDelete(view);
setDeleteViewModal(true);
};
return ( return (
<ProjectAuthorizationWrapper <ProjectAuthorizationWrapper
meta={{ meta={{
@ -73,14 +86,14 @@ const ProjectViews: NextPage = () => {
} }
> >
<CreateUpdateViewModal <CreateUpdateViewModal
isOpen={isCreateViewModalOpen} isOpen={createUpdateViewModal}
handleClose={() => setIsCreateViewModalOpen(false)} handleClose={() => setCreateUpdateViewModal(false)}
data={selectedViewToUpdate}
/> />
<DeleteViewModal <DeleteViewModal
isOpen={!!selectedView} isOpen={deleteViewModal}
data={selectedView} data={selectedViewToDelete}
onClose={() => setSelectedView(null)} setIsOpen={setDeleteViewModal}
onSuccess={() => setSelectedView(null)}
/> />
{views ? ( {views ? (
views.length > 0 ? ( views.length > 0 ? (
@ -88,7 +101,12 @@ const ProjectViews: NextPage = () => {
<h3 className="text-3xl font-semibold text-black">Views</h3> <h3 className="text-3xl font-semibold text-black">Views</h3>
<ul role="list" className="divide-y"> <ul role="list" className="divide-y">
{views.map((view) => ( {views.map((view) => (
<SingleViewItem key={view.id} view={view} setSelectedView={setSelectedView} /> <SingleViewItem
key={view.id}
view={view}
handleEditView={() => handleEditView(view)}
handleDeleteView={() => handleDeleteView(view)}
/>
))} ))}
</ul> </ul>
</div> </div>