Skip to content

Commit

Permalink
chore: user auth layer (#749)
Browse files Browse the repository at this point in the history
* chore: use estimate points hook created

* chore: user auth layer

* fix: build error
  • Loading branch information
aaryan610 committed Apr 8, 2023
1 parent 3fe3260 commit 1026ae3
Show file tree
Hide file tree
Showing 20 changed files with 600 additions and 484 deletions.
14 changes: 13 additions & 1 deletion apps/app/components/core/board-view/single-issue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ import useToast from "hooks/use-toast";
import {
ViewAssigneeSelect,
ViewDueDateSelect,
ViewEstimateSelect,
ViewPrioritySelect,
ViewStateSelect,
} from "components/issues/view-select";
} from "components/issues";
// ui
import { ContextMenu, CustomMenu } from "components/ui";
// icons
Expand All @@ -48,6 +49,7 @@ import {
MODULE_ISSUES_WITH_PARAMS,
PROJECT_ISSUES_LIST_WITH_PARAMS,
} from "constants/fetch-keys";
import useEstimateOption from "hooks/use-estimate-option";

type Props = {
type?: string;
Expand Down Expand Up @@ -90,6 +92,8 @@ export const SingleBoardIssue: React.FC<Props> = ({

const { orderBy, params } = useIssuesView();

const { estimateValue } = useEstimateOption(issue.estimate_point);

const router = useRouter();
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;

Expand Down Expand Up @@ -342,6 +346,14 @@ export const SingleBoardIssue: React.FC<Props> = ({
selfPositioned
/>
)}
{properties.estimate && (
<ViewEstimateSelect
issue={issue}
partialUpdateIssue={partialUpdateIssue}
isNotAllowed={isNotAllowed}
selfPositioned
/>
)}
</div>
</div>
</div>
Expand Down
151 changes: 82 additions & 69 deletions apps/app/components/estimates/single-estimate.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,41 @@
import React, { useState } from "react";

// ui
import { CustomMenu, PrimaryButton } from "components/ui";
// types
import { IEstimate, IProject } from "types";
//icons
import { PencilIcon, TrashIcon, SquaresPlusIcon, ListBulletIcon } from "@heroicons/react/24/outline";

import useSWR, { mutate } from "swr";
import { useRouter } from "next/router";

import useToast from "hooks/use-toast";
import useSWR from "swr";

// services
import estimatesService from "services/estimates.service";
import projectService from "services/project.service";

import { EstimatePointsModal } from "./estimate-points-modal";
import { useRouter } from "next/router";

// hooks
import useToast from "hooks/use-toast";
import useProjectDetails from "hooks/use-project-details";
// components
import { EstimatePointsModal } from "components/estimates";
// ui
import { CustomMenu } from "components/ui";
//icons
import {
PencilIcon,
TrashIcon,
SquaresPlusIcon,
ListBulletIcon,
} from "@heroicons/react/24/outline";
// types
import { IEstimate, IProject } from "types";
// fetch-keys
import { ESTIMATE_POINTS_LIST } from "constants/fetch-keys";
import { PlusIcon } from "components/icons";

interface IEstimatePoints {
key: string;
value: string;
}

type Props = {
estimate: IEstimate;
editEstimate: (estimate: IEstimate) => void;
handleEstimateDelete: (estimateId: string) => void;
activeEstimate: IEstimate | null;
setActiveEstimate: React.Dispatch<React.SetStateAction<IEstimate | null>>;
};

export const SingleEstimate: React.FC<Props> = ({
estimate,
editEstimate,
handleEstimateDelete,
activeEstimate,
setActiveEstimate,
}) => {
const [isEstimatePointsModalOpen, setIsEstimatePointsModalOpen] = useState(false);

Expand All @@ -47,6 +44,8 @@ export const SingleEstimate: React.FC<Props> = ({

const { setToastAlert } = useToast();

const { projectDetails, mutateProjectDetails } = useProjectDetails();

const { data: estimatePoints } = useSWR(
workspaceSlug && projectId ? ESTIMATE_POINTS_LIST(estimate.id) : null,
workspaceSlug && projectId
Expand All @@ -59,12 +58,19 @@ export const SingleEstimate: React.FC<Props> = ({
: null
);

const handleActiveEstimate = async () => {
if (!workspaceSlug || !projectId || !estimate) return;
const payload: Partial<IProject> = {
const handleUseEstimate = async () => {
if (!workspaceSlug || !projectId) return;

const payload = {
estimate: estimate.id,
};
setActiveEstimate(estimate);

mutateProjectDetails((prevData) => {
if (!prevData) return prevData;

return { ...prevData, estimate: estimate.id };
}, false);

await projectService
.updateProject(workspaceSlug as string, projectId as string, payload)
.catch(() => {
Expand All @@ -77,56 +83,63 @@ export const SingleEstimate: React.FC<Props> = ({
};

return (
<div className="divide-y">
<>
<EstimatePointsModal
isOpen={isEstimatePointsModalOpen}
estimate={estimate}
onClose={() => setIsEstimatePointsModalOpen(false)}
/>
<div className="gap-2 space-y-3 my-3 bg-white">
<div className="gap-2 py-3">
<div className="flex justify-between items-center">
<div className="items-start">
<h6 className="font-medium text-base w-[40vw] truncate">{estimate.name}</h6>
<div>
<h6 className="flex items-center gap-2 font-medium text-base w-[40vw] truncate">
{estimate.name}
{projectDetails?.estimate && projectDetails?.estimate === estimate.id && (
<span className="capitalize px-2 py-0.5 text-xs rounded bg-green-100 text-green-500">
In use
</span>
)}
</h6>
<p className="font-sm text-gray-400 font-normal text-[14px] w-[40vw] truncate">
{estimate.description}
</p>
</div>
<div className="flex items-center gap-8">
<CustomMenu ellipsis>
<CustomMenu.MenuItem onClick={handleActiveEstimate}>
<span className="flex items-center justify-start gap-2">
<SquaresPlusIcon className="h-4 w-4" />
<CustomMenu ellipsis>
{projectDetails?.estimate && projectDetails?.estimate !== estimate.id && (
<CustomMenu.MenuItem onClick={handleUseEstimate}>
<div className="flex items-center justify-start gap-2">
<SquaresPlusIcon className="h-3.5 w-3.5" />
<span>Use estimate</span>
</span>
</div>
</CustomMenu.MenuItem>
<CustomMenu.MenuItem onClick={() => setIsEstimatePointsModalOpen(true)}>
<span className="flex items-center justify-start gap-2">
<ListBulletIcon className="h-4 w-4" />
{estimatePoints?.length === 8 ? "Update points" : "Create points"}
</span>
</CustomMenu.MenuItem>
<CustomMenu.MenuItem
onClick={() => {
editEstimate(estimate);
}}
>
<span className="flex items-center justify-start gap-2">
<PencilIcon className="h-4 w-4" />
<span>Edit estimate</span>
</span>
</CustomMenu.MenuItem>
<CustomMenu.MenuItem
onClick={() => {
handleEstimateDelete(estimate.id);
}}
>
<span className="flex items-center justify-start gap-2">
<TrashIcon className="h-4 w-4" />
<span>Delete estimate</span>
</span>
</CustomMenu.MenuItem>
</CustomMenu>
</div>
)}
<CustomMenu.MenuItem onClick={() => setIsEstimatePointsModalOpen(true)}>
<div className="flex items-center justify-start gap-2">
<ListBulletIcon className="h-3.5 w-3.5" />
<span>{estimatePoints?.length === 8 ? "Update points" : "Create points"}</span>
</div>
</CustomMenu.MenuItem>
<CustomMenu.MenuItem
onClick={() => {
editEstimate(estimate);
}}
>
<div className="flex items-center justify-start gap-2">
<PencilIcon className="h-3.5 w-3.5" />
<span>Edit estimate</span>
</div>
</CustomMenu.MenuItem>
<CustomMenu.MenuItem
onClick={() => {
handleEstimateDelete(estimate.id);
}}
>
<div className="flex items-center justify-start gap-2">
<TrashIcon className="h-3.5 w-3.5" />
<span>Delete estimate</span>
</div>
</CustomMenu.MenuItem>
</CustomMenu>
</div>
{estimatePoints && estimatePoints.length > 0 ? (
<div className="flex gap-2">
Expand All @@ -140,11 +153,11 @@ export const SingleEstimate: React.FC<Props> = ({
{estimatePoints.length > 0 && ")"}
</div>
) : (
<div>
<p className= " text-sm text-gray-300">No estimate points</p>
</div>
<div>
<p className=" text-sm text-gray-300">No estimate points</p>
</div>
)}
</div>
</div>
</>
);
};
1 change: 1 addition & 0 deletions apps/app/components/issues/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from "./comment";
export * from "./sidebar-select";
export * from "./view-select";
export * from "./activity";
export * from "./delete-issue-modal";
export * from "./description-form";
Expand Down
69 changes: 69 additions & 0 deletions apps/app/components/issues/view-select/estimate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from "react";

// ui
import { CustomSelect, Tooltip } from "components/ui";
// icons
import { getPriorityIcon } from "components/icons/priority-icon";
// types
import { IIssue } from "types";
// constants
import { PRIORITIES } from "constants/project";
// services
import trackEventServices from "services/track-event.service";
import useEstimateOption from "hooks/use-estimate-option";

type Props = {
issue: IIssue;
partialUpdateIssue: (formData: Partial<IIssue>) => void;
position?: "left" | "right";
selfPositioned?: boolean;
isNotAllowed: boolean;
};

export const ViewEstimateSelect: React.FC<Props> = ({
issue,
partialUpdateIssue,
position = "left",
selfPositioned = false,
isNotAllowed,
}) => {
const { isEstimateActive, estimatePoints, estimateValue } = useEstimateOption(
issue.estimate_point
);

return (
<CustomSelect
value={issue.priority}
onChange={(data: string) => {
partialUpdateIssue({ priority: data, state: issue.state, target_date: issue.target_date });
trackEventServices.trackIssuePartialPropertyUpdateEvent(
{
workspaceSlug: issue.workspace_detail.slug,
workspaceId: issue.workspace_detail.id,
projectId: issue.project_detail.id,
projectIdentifier: issue.project_detail.identifier,
projectName: issue.project_detail.name,
issueId: issue.id,
},
"ISSUE_PROPERTY_UPDATE_PRIORITY"
);
}}
label={
<Tooltip tooltipHeading="Estimate" tooltipContent={estimateValue}>
<>{estimateValue}</>
</Tooltip>
}
maxHeight="md"
noChevron
disabled={isNotAllowed}
position={position}
selfPositioned={selfPositioned}
>
{estimatePoints?.map((estimate) => (
<CustomSelect.Option key={estimate.id} value={estimate.key} className="capitalize">
<>{estimate.value}</>
</CustomSelect.Option>
))}
</CustomSelect>
);
};
1 change: 1 addition & 0 deletions apps/app/components/issues/view-select/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./assignee";
export * from "./due-date";
export * from "./estimate";
export * from "./priority";
export * from "./state";
13 changes: 2 additions & 11 deletions apps/app/contexts/user.context.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import React, { createContext, ReactElement } from "react";
// next
import { useRouter } from "next/router";
// swr

import useSWR, { KeyedMutator } from "swr";

// services
import userService from "services/user.service";
// constants
import { CURRENT_USER } from "constants/fetch-keys";

// types
import type { IUser } from "types";

Expand All @@ -22,18 +20,11 @@ interface IUserContextProps {
export const UserContext = createContext<IUserContextProps>({} as IUserContextProps);

export const UserProvider = ({ children }: { children: ReactElement }) => {
const router = useRouter();

// API to fetch user information
const { data, error, mutate } = useSWR<IUser>(CURRENT_USER, () => userService.currentUser(), {
shouldRetryOnError: false,
});

if (error) {
router.push("/signin");
return null;
}

return (
<UserContext.Provider
value={{
Expand Down
Loading

1 comment on commit 1026ae3

@vercel
Copy link

@vercel vercel bot commented on 1026ae3 Apr 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

plane-dev – ./apps/app

plane-dev-caravel.vercel.app
plane-dev-git-develop-caravel.vercel.app
plane-dev.vercel.app

Please sign in to comment.