chore: reove unused files (#2567)

This commit is contained in:
Aaryan Khandelwal 2023-10-31 12:43:08 +05:30 committed by GitHub
parent 8072bbb559
commit 98716859d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 4 additions and 731 deletions

View File

@ -1,175 +0,0 @@
import React from "react";
// headless ui
import { Combobox } from "@headlessui/react";
// lucide icons
import { ChevronDown, Search, X, Check } from "lucide-react";
// hooks
import useDynamicDropdownPosition from "hooks/use-dynamic-dropdown";
interface IFiltersOption {
id: string;
title: string;
}
export interface IIssuePropertyState {
options: IFiltersOption[];
value?: any;
onChange?: (id: any, data: IFiltersOption) => void;
disabled?: boolean;
className?: string;
buttonClassName?: string;
optionsClassName?: string;
dropdownArrow?: boolean;
children?: any;
}
export const IssuePropertyState: React.FC<IIssuePropertyState> = ({
options,
value,
onChange,
disabled,
className,
buttonClassName,
optionsClassName,
dropdownArrow = true,
children,
}) => {
const dropdownBtn = React.useRef<any>(null);
const dropdownOptions = React.useRef<any>(null);
const [isOpen, setIsOpen] = React.useState<boolean>(false);
const [search, setSearch] = React.useState<string>("");
useDynamicDropdownPosition(isOpen, () => setIsOpen(false), dropdownBtn, dropdownOptions);
const selectedOption: IFiltersOption | null | undefined =
(value && options.find((person: IFiltersOption) => person.id === value)) || null;
const filteredOptions: IFiltersOption[] =
search === ""
? options && options.length > 0
? options
: []
: options && options.length > 0
? options.filter((person: IFiltersOption) =>
person.title.toLowerCase().replace(/\s+/g, "").includes(search.toLowerCase().replace(/\s+/g, ""))
)
: [];
return (
<Combobox
as="div"
className={`${className}`}
value={selectedOption && selectedOption.id}
onChange={(data: string) => {
if (onChange && selectedOption) onChange(data, selectedOption);
}}
disabled={disabled}
>
{({ open }: { open: boolean }) => {
if (open) {
if (!isOpen) setIsOpen(true);
} else if (isOpen) setIsOpen(false);
return (
<>
<Combobox.Button
ref={dropdownBtn}
type="button"
className={`flex items-center justify-between gap-1 w-full px-1 py-1 rounded-sm shadow-sm border border-custom-border-300 duration-300 outline-none ${
disabled ? "cursor-not-allowed text-custom-text-200" : "cursor-pointer hover:bg-custom-background-80"
} ${buttonClassName}`}
>
{children ? (
children
) : (
<div className="text-xs">{(selectedOption && selectedOption?.title) || "Select option"}</div>
)}
{dropdownArrow && !disabled && (
<div className="flex-shrink-0 w-[14px] h-[14px] flex justify-center items-center">
<ChevronDown width={14} strokeWidth={2} />
</div>
)}
</Combobox.Button>
{options && options.length > 0 ? (
<div className={`${open ? "fixed z-20 top-0 left-0 h-full w-full cursor-auto" : ""}`}>
<Combobox.Options
ref={dropdownOptions}
className={`absolute z-10 border border-custom-border-300 p-2 rounded bg-custom-background-100 text-xs shadow-lg focus:outline-none min-w-48 max-w-60 whitespace-nowrap mt-1 space-y-1 ${optionsClassName}`}
>
<div className="flex w-full items-center justify-start rounded border border-custom-border-200 bg-custom-background-90 px-1">
<div className="flex-shrink-0 flex justify-center items-center w-[16px] h-[16px] rounded-sm">
<Search width={12} strokeWidth={2} />
</div>
<div>
<Combobox.Input
className="w-full bg-transparent p-1 text-xs text-custom-text-200 placeholder:text-custom-text-400 focus:outline-none"
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search"
displayValue={(assigned: any) => assigned?.name}
/>
</div>
{search && search.length > 0 && (
<div
onClick={() => setSearch("")}
className="flex-shrink-0 flex justify-center items-center w-[16px] h-[16px] rounded-sm cursor-pointer hover:bg-custom-background-80"
>
<X width={12} strokeWidth={2} />
</div>
)}
</div>
<div className={`space-y-0.5 max-h-48 overflow-y-scroll`}>
{filteredOptions ? (
filteredOptions.length > 0 ? (
filteredOptions.map((option) => (
<Combobox.Option
key={option.id}
value={option.id}
className={({ active, selected }) =>
`cursor-pointer select-none truncate rounded px-1 py-1.5 ${
active || selected ? "bg-custom-background-80" : ""
} ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
}
>
{({ selected }) => (
<div className="flex justify-between items-center gap-1 w-full px-1">
<div className="line-clamp-1">{option.title}</div>
{selected && (
<div className="flex-shrink-0 w-[13px] h-[13px] flex justify-center items-center">
<Check width={13} strokeWidth={2} />
</div>
)}
</div>
)}
</Combobox.Option>
))
) : (
<span className="flex items-center gap-2 p-1">
<p className="text-left text-custom-text-200 ">No matching results</p>
</span>
)
) : (
<p className="text-center text-custom-text-200">Loading...</p>
)}
</div>
</Combobox.Options>
</div>
) : (
<p className="text-center text-custom-text-200">No options available.</p>
)}
</>
);
}}
</Combobox>
);
};

View File

@ -1,6 +1,6 @@
import { observer } from "mobx-react-lite";
// components
import { LabelSelect } from "components/project";
import { LabelSelect } from "components/labels";
// types
import { IIssueLabels } from "types";

View File

@ -1,7 +1,7 @@
import React from "react";
// components
import { LabelSelect } from "components/project";
import { LabelSelect } from "components/labels";
// hooks
import useSubIssue from "hooks/use-sub-issue";
// types

View File

@ -1,117 +0,0 @@
import React, { useState } from "react";
import { useRouter } from "next/router";
// services
import { TrackEventService } from "services/track_event.service";
// ui
import { AssigneesList, Avatar } from "components/ui";
import { CustomSearchSelect, Tooltip } from "@plane/ui";
import { User2 } from "lucide-react";
// types
import { IUser, IIssue } from "types";
// hooks
import useProjectMembers from "hooks/use-project-members";
type Props = {
issue: IIssue;
partialUpdateIssue: (formData: Partial<IIssue>, issue: IIssue) => void;
position?: "left" | "right";
tooltipPosition?: "top" | "bottom";
selfPositioned?: boolean;
customButton?: boolean;
user: IUser | undefined;
isNotAllowed: boolean;
};
const trackEventService = new TrackEventService();
export const ViewAssigneeSelect: React.FC<Props> = ({
issue,
partialUpdateIssue,
// position = "left",
// selfPositioned = false,
tooltipPosition = "top",
user,
isNotAllowed,
customButton = false,
}) => {
const [fetchAssignees, setFetchAssignees] = useState(false);
const router = useRouter();
const { workspaceSlug } = router.query;
const { members } = useProjectMembers(workspaceSlug?.toString(), issue.project, fetchAssignees);
const options = members?.map((member: any) => ({
value: member.member.id,
query: member.member.display_name,
content: (
<div className="flex items-center gap-2">
<Avatar user={member.member} />
{member.member.display_name}
</div>
),
}));
const assigneeLabel = (
<Tooltip
position={tooltipPosition}
tooltipHeading="Assignees"
tooltipContent={
issue.assignee_details.length > 0
? issue.assignee_details.map((assignee) => assignee?.display_name).join(", ")
: "No Assignee"
}
>
<div
className={`flex ${
isNotAllowed ? "cursor-not-allowed" : "cursor-pointer"
} items-center gap-2 text-custom-text-200`}
>
{issue.assignees && issue.assignees.length > 0 && Array.isArray(issue.assignees) ? (
<div className="-my-0.5 flex items-center justify-center gap-2">
<AssigneesList userIds={issue.assignees} length={3} showLength={true} />
</div>
) : (
<div className="flex items-center justify-center gap-2 px-1.5 py-1 rounded shadow-sm border border-custom-border-300">
<User2 className="h-4 w-4" />
</div>
)}
</div>
</Tooltip>
);
return (
<CustomSearchSelect
value={issue.assignees}
buttonClassName="!p-0"
onChange={(data: any) => {
const newData = issue.assignees ?? [];
if (newData.includes(data)) newData.splice(newData.indexOf(data), 1);
else newData.push(data);
partialUpdateIssue({ assignees: data }, issue);
trackEventService.trackIssuePartialPropertyUpdateEvent(
{
workspaceSlug,
workspaceId: issue.workspace,
projectId: issue.project_detail.id,
projectIdentifier: issue.project_detail.identifier,
projectName: issue.project_detail.name,
issueId: issue.id,
},
"ISSUE_PROPERTY_UPDATE_ASSIGNEE",
user as IUser
);
}}
options={options}
{...(customButton ? { customButton: assigneeLabel } : { label: assigneeLabel })}
multiple
noChevron
disabled={isNotAllowed}
onOpen={() => setFetchAssignees(true)}
width="w-full min-w-[12rem]"
/>
);
};

View File

@ -1,6 +1,3 @@
export * from "./assignee";
export * from "./due-date";
export * from "./estimate";
export * from "./label";
export * from "./priority";
export * from "./start-date";

View File

@ -1,154 +0,0 @@
import { useState, FC } from "react";
import { useRouter } from "next/router";
import useSWR from "swr";
// services
import { IssueLabelService } from "services/issue";
// component
import { CreateLabelModal } from "components/labels";
// ui
import { CustomSearchSelect, Tooltip } from "@plane/ui";
// icons
import { Plus, Tag } from "lucide-react";
// types
import { IUser, IIssue, IIssueLabels } from "types";
// fetch-keys
import { PROJECT_ISSUE_LABELS } from "constants/fetch-keys";
type Props = {
issue: IIssue;
partialUpdateIssue: (formData: Partial<IIssue>, issue: IIssue) => void;
position?: "left" | "right";
selfPositioned?: boolean;
tooltipPosition?: "top" | "bottom";
customButton?: boolean;
user: IUser | undefined;
isNotAllowed: boolean;
};
const issueLabelStore = new IssueLabelService();
export const ViewLabelSelect: FC<Props> = ({
issue,
partialUpdateIssue,
// position = "left",
// selfPositioned = false,
tooltipPosition = "top",
user,
isNotAllowed,
customButton = false,
}) => {
const [labelModal, setLabelModal] = useState(false);
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const { data: issueLabels } = useSWR<IIssueLabels[]>(
projectId ? PROJECT_ISSUE_LABELS(projectId.toString()) : null,
workspaceSlug && projectId
? () => issueLabelStore.getProjectIssueLabels(workspaceSlug as string, projectId as string)
: null
);
const options = issueLabels?.map((label) => ({
value: label.id,
query: label.name,
content: (
<div className="flex items-center justify-start gap-2">
<span
className="h-2.5 w-2.5 flex-shrink-0 rounded-full"
style={{
backgroundColor: label.color,
}}
/>
<span>{label.name}</span>
</div>
),
}));
const labelsLabel = (
<Tooltip
position={tooltipPosition}
tooltipHeading="Labels"
tooltipContent={
issue.labels.length > 0
? issue.labels
.map((labelId) => {
const label = issueLabels?.find((l) => l.id === labelId);
return label?.name ?? "";
})
.join(", ")
: "No label"
}
>
<div
className={`flex ${
isNotAllowed ? "cursor-not-allowed" : "cursor-pointer"
} items-center gap-2 text-custom-text-200`}
>
{issue.labels.length > 0 ? (
<>
{issue.labels.slice(0, 4).map((labelId, index) => {
const label = issueLabels?.find((l) => l.id === labelId);
return (
<div className={`flex h-4 w-4 rounded-full ${index ? "-ml-3.5" : ""}`}>
<span
className={`h-4 w-4 flex-shrink-0 rounded-full border group-hover:bg-custom-background-80 border-custom-border-200`}
style={{
backgroundColor: label?.color ?? "#000000",
}}
/>
</div>
);
})}
{issue.labels.length > 4 ? <span>+{issue.labels.length - 4}</span> : null}
</>
) : (
<>
<Tag className="h-3.5 w-3.5 text-custom-text-200" />
</>
)}
</div>
</Tooltip>
);
const footerOption = (
<button
type="button"
className="flex w-full select-none items-center rounded py-2 px-1 hover:bg-custom-background-80"
onClick={() => setLabelModal(true)}
>
<span className="flex items-center justify-start gap-1 text-custom-text-200">
<Plus className="h-4 w-4" aria-hidden="true" />
<span>Create New Label</span>
</span>
</button>
);
return (
<>
{projectId && (
<CreateLabelModal
isOpen={labelModal}
handleClose={() => setLabelModal(false)}
projectId={projectId.toString()}
user={user}
/>
)}
<CustomSearchSelect
value={issue.labels}
onChange={(data: string[]) => {
partialUpdateIssue({ labels: data }, issue);
}}
options={options}
{...(customButton ? { customButton: labelsLabel } : { label: labelsLabel })}
multiple
noChevron
disabled={isNotAllowed}
footerOption={footerOption}
width="w-full min-w-[12rem]"
/>
</>
);
};

View File

@ -1,106 +0,0 @@
import React from "react";
import { useRouter } from "next/router";
// services
import { TrackEventService } from "services/track_event.service";
// ui
import { CustomSelect, Tooltip, PriorityIcon } from "@plane/ui";
// helpers
import { capitalizeFirstLetter } from "helpers/string.helper";
// types
import { IUser, IIssue, TIssuePriorities } from "types";
// constants
import { PRIORITIES } from "constants/project";
type Props = {
issue: IIssue;
partialUpdateIssue: (formData: Partial<IIssue>, issue: IIssue) => void;
position?: "left" | "right";
tooltipPosition?: "top" | "bottom";
selfPositioned?: boolean;
noBorder?: boolean;
user: IUser | undefined;
isNotAllowed: boolean;
};
const trackEventService = new TrackEventService();
export const ViewPrioritySelect: React.FC<Props> = ({
issue,
partialUpdateIssue,
// position = "left",
tooltipPosition = "top",
// selfPositioned = false,
noBorder = false,
user,
isNotAllowed,
}) => {
const router = useRouter();
const { workspaceSlug } = router.query;
return (
<CustomSelect
value={issue.priority}
onChange={(data: TIssuePriorities) => {
partialUpdateIssue({ priority: data }, issue);
trackEventService.trackIssuePartialPropertyUpdateEvent(
{
workspaceSlug,
workspaceId: issue.workspace,
projectId: issue.project_detail.id,
projectIdentifier: issue.project_detail.identifier,
projectName: issue.project_detail.name,
issueId: issue.id,
},
"ISSUE_PROPERTY_UPDATE_PRIORITY",
user as IUser
);
}}
maxHeight="md"
customButton={
<button
type="button"
className={`grid place-items-center rounded ${isNotAllowed ? "cursor-not-allowed" : "cursor-pointer"} ${
noBorder ? "" : "h-6 w-6 border shadow-sm"
} ${
noBorder
? ""
: issue.priority === "urgent"
? "border-red-500/20 bg-red-500"
: "border-custom-border-300 bg-custom-background-100"
} items-center`}
>
<Tooltip tooltipHeading="Priority" tooltipContent={issue.priority ?? "None"} position={tooltipPosition}>
<span className="flex gap-1 items-center text-custom-text-200 text-xs">
<PriorityIcon
priority={issue.priority}
className={`h-3.5 w-3.5 ${
issue.priority === "urgent"
? "text-white"
: issue.priority === "high"
? "text-orange-500"
: issue.priority === "medium"
? "text-yellow-500"
: issue.priority === "low"
? "text-green-500"
: "text-custom-text-200"
}`}
/>
{noBorder ? capitalizeFirstLetter(issue.priority ?? "None") : ""}
</span>
</Tooltip>
</button>
}
noChevron
disabled={isNotAllowed}
>
{PRIORITIES?.map((priority) => (
<CustomSelect.Option key={priority} value={priority} className="capitalize">
<>
<PriorityIcon priority={priority} className="h-3.5 w-3.5" />
{priority ?? "None"}
</>
</CustomSelect.Option>
))}
</CustomSelect>
);
};

View File

@ -1,6 +1,7 @@
export * from "./create-label-modal";
export * from "./create-update-label-inline";
export * from "./delete-label-modal";
export * from "./label-select";
export * from "./labels-list-modal";
export * from "./single-label-group";
export * from "./single-label";

View File

@ -7,7 +7,6 @@ export * from "./delete-project-modal";
export * from "./form-loader";
export * from "./form";
export * from "./join-project-modal";
export * from "./label-select";
export * from "./leave-project-modal";
export * from "./member-select";
export * from "./members-select";

View File

@ -1,122 +0,0 @@
import { createContext, useCallback, useReducer, useEffect } from "react";
import { useRouter } from "next/router";
// swr
import useSWR from "swr";
// components
import ToastAlert from "components/toast-alert";
// hooks
import useUserAuth from "hooks/use-user-auth";
// services
import { ProjectService } from "services/project";
// fetch-keys
import { USER_PROJECT_VIEW } from "constants/fetch-keys";
// helper
import { applyTheme, unsetCustomCssVariables } from "helpers/theme.helper";
// constants
export const themeContext = createContext<ContextType>({} as ContextType);
// services
const projectService = new ProjectService();
type ThemeProps = {
collapsed: boolean;
};
type ReducerActionType = {
type: "TOGGLE_SIDEBAR" | "REHYDRATE_THEME";
payload?: Partial<ThemeProps>;
};
type ContextType = {
collapsed: boolean;
toggleCollapsed: () => void;
};
type StateType = {
collapsed: boolean;
};
type ReducerFunctionType = (state: StateType, action: ReducerActionType) => StateType;
export const initialState: StateType = {
collapsed: false,
};
export const reducer: ReducerFunctionType = (state, action) => {
const { type, payload } = action;
switch (type) {
case "TOGGLE_SIDEBAR":
const newState = {
...state,
collapsed: !state.collapsed,
};
localStorage.setItem("collapsed", JSON.stringify(newState.collapsed));
return newState;
case "REHYDRATE_THEME": {
let collapsed: any = localStorage.getItem("collapsed");
collapsed = collapsed ? JSON.parse(collapsed) : false;
return { ...initialState, ...payload, collapsed };
}
default: {
return state;
}
}
};
export const ThemeContextProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState);
const { user } = useUserAuth(null);
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const { data: myViewProps } = useSWR(
workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId as string) : null,
workspaceSlug && projectId
? () => projectService.projectMemberMe(workspaceSlug as string, projectId as string)
: null
);
const toggleCollapsed = useCallback(() => {
dispatch({
type: "TOGGLE_SIDEBAR",
});
}, []);
useEffect(() => {
dispatch({
type: "REHYDRATE_THEME",
payload: myViewProps?.view_props as any,
});
}, [myViewProps]);
useEffect(() => {
const theme = localStorage.getItem("theme");
if (theme) {
if (theme === "custom") {
if (user && user.theme.palette) {
applyTheme(
user.theme.palette !== ",,,," ? user.theme.palette : "#0d101b,#c5c5c5,#3f76ff,#0d101b,#c5c5c5",
user.theme.darkPalette
);
}
} else unsetCustomCssVariables();
}
}, [user]);
return (
<themeContext.Provider
value={{
collapsed: state.collapsed,
toggleCollapsed,
}}
>
<ToastAlert />
{children}
</themeContext.Provider>
);
};

View File

@ -1,50 +0,0 @@
import { FC, ReactElement, createContext } from "react";
import { useRouter } from "next/router";
import useSWR from "swr";
// services
import { WorkspaceService } from "services/workspace.service";
// types
import { IWorkspace } from "types";
// constants
import { USER_WORKSPACES } from "constants/fetch-keys";
export interface WorkspaceProviderProps {
children: ReactElement;
}
export interface WorkspaceContextProps {
workspaces: IWorkspace[];
activeWorkspace: IWorkspace | undefined;
mutateWorkspaces: () => void;
}
// services
const workspaceService = new WorkspaceService();
export const WorkspaceContext = createContext<WorkspaceContextProps>({} as WorkspaceContextProps);
export const WorkspaceProvider: FC<WorkspaceProviderProps> = (props) => {
const { children } = props;
// router
const router = useRouter();
const { workspaceSlug } = router.query;
// API to fetch user information
const { data = [], error, mutate } = useSWR<IWorkspace[]>(USER_WORKSPACES, () => workspaceService.userWorkspaces());
// active workspace
const activeWorkspace = data?.find((w) => w.slug === workspaceSlug);
return (
<WorkspaceContext.Provider
value={{
workspaces: error ? [] : data,
activeWorkspace,
mutateWorkspaces: mutate,
}}
>
{children}
</WorkspaceContext.Provider>
);
};