forked from github/plane
refractor: added types to workspace and project services, naming convention
This commit is contained in:
parent
9c33c3c87f
commit
fe7284b9b0
4
apps/app/.env.example
Normal file
4
apps/app/.env.example
Normal file
@ -0,0 +1,4 @@
|
||||
NEXT_PUBLIC_API_BASE_URL = "<-- endpoint goes here -->"
|
||||
NEXT_PUBLIC_GOOGLE_CLIENTID = "<-- google client id goes here -->"
|
||||
NEXT_PUBLIC_GITHUB_ID = "<-- github id goes here -->"
|
||||
NEXT_PUBLIC_APP_ENVIRONMENT=development
|
@ -7,7 +7,7 @@ import { useForm } from "react-hook-form";
|
||||
// headless ui
|
||||
import { Combobox, Dialog, Transition } from "@headlessui/react";
|
||||
// services
|
||||
import issuesServices from "lib/services/issues.services";
|
||||
import issuesServices from "lib/services/issues.service";
|
||||
// hooks
|
||||
import useUser from "lib/hooks/useUser";
|
||||
// icons
|
||||
|
@ -8,7 +8,7 @@ import { SubmitHandler, useForm } from "react-hook-form";
|
||||
// headless ui
|
||||
import { Combobox, Dialog, Transition } from "@headlessui/react";
|
||||
// services
|
||||
import issuesServices from "lib/services/issues.services";
|
||||
import issuesServices from "lib/services/issues.service";
|
||||
// hooks
|
||||
import useUser from "lib/hooks/useUser";
|
||||
import useTheme from "lib/hooks/useTheme";
|
||||
@ -22,7 +22,7 @@ import {
|
||||
} from "@heroicons/react/24/outline";
|
||||
// components
|
||||
import ShortcutsModal from "components/command-palette/shortcuts";
|
||||
import CreateProjectModal from "components/project/CreateProjectModal";
|
||||
import CreateProjectModal from "components/project/create-project-modal";
|
||||
import CreateUpdateIssuesModal from "components/project/issues/CreateUpdateIssueModal";
|
||||
import CreateUpdateCycleModal from "components/project/cycles/CreateUpdateCyclesModal";
|
||||
// ui
|
||||
|
@ -20,7 +20,7 @@ import { Button, Select, TextArea } from "ui";
|
||||
import { ChevronDownIcon, CheckIcon } from "@heroicons/react/20/solid";
|
||||
|
||||
// types
|
||||
import { ProjectMember, WorkspaceMember } from "types";
|
||||
import { IProjectMemberInvitation } from "types";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
@ -28,6 +28,11 @@ type Props = {
|
||||
members: any[];
|
||||
};
|
||||
|
||||
type ProjectMember = IProjectMemberInvitation & {
|
||||
member_id: string;
|
||||
user_id: string;
|
||||
};
|
||||
|
||||
const defaultValues: Partial<ProjectMember> = {
|
||||
email: "",
|
||||
message: "",
|
||||
@ -49,7 +54,7 @@ const SendProjectInvitationModal: React.FC<Props> = ({ isOpen, setIsOpen, member
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const { data: people } = useSWR<WorkspaceMember[]>(
|
||||
const { data: people } = useSWR(
|
||||
activeWorkspace ? WORKSPACE_MEMBERS(activeWorkspace.slug) : null,
|
||||
activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null,
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
// swr
|
||||
import useSWR, { mutate } from "swr";
|
||||
// react hook form
|
||||
@ -8,6 +8,8 @@ import { Dialog, Transition } from "@headlessui/react";
|
||||
// services
|
||||
import projectServices from "lib/services/project.service";
|
||||
import workspaceService from "lib/services/workspace.service";
|
||||
// common
|
||||
import { createSimilarString } from "constants/common";
|
||||
// constants
|
||||
import { NETWORK_CHOICES } from "constants/";
|
||||
// fetch keys
|
||||
@ -18,7 +20,7 @@ import useToast from "lib/hooks/useToast";
|
||||
// ui
|
||||
import { Button, Input, TextArea, Select } from "ui";
|
||||
// types
|
||||
import { IProject, WorkspaceMember } from "types";
|
||||
import { IProject } from "types";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
@ -60,7 +62,7 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
|
||||
|
||||
const { activeWorkspace, user } = useUser();
|
||||
|
||||
const { data: workspaceMembers } = useSWR<WorkspaceMember[]>(
|
||||
const { data: workspaceMembers } = useSWR(
|
||||
activeWorkspace ? WORKSPACE_MEMBERS(activeWorkspace.slug) : null,
|
||||
activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null,
|
||||
{
|
||||
@ -68,6 +70,8 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
|
||||
}
|
||||
);
|
||||
|
||||
const [recommendedIdentifier, setRecommendedIdentifier] = useState<string[]>([]);
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const [isChangeIdentifierRequired, setIsChangeIdentifierRequired] = useState(true);
|
||||
@ -78,6 +82,7 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
|
||||
handleSubmit,
|
||||
reset,
|
||||
setError,
|
||||
clearErrors,
|
||||
watch,
|
||||
setValue,
|
||||
} = useForm<IProject>({
|
||||
@ -125,12 +130,6 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
|
||||
const projectName = watch("name") ?? "";
|
||||
const projectIdentifier = watch("identifier") ?? "";
|
||||
|
||||
useEffect(() => {
|
||||
if (projectName && isChangeIdentifierRequired) {
|
||||
setValue("identifier", projectName.replace(/ /g, "-").toUpperCase().substring(0, 3));
|
||||
}
|
||||
}, [projectName, projectIdentifier, setValue, isChangeIdentifierRequired]);
|
||||
|
||||
if (workspaceMembers) {
|
||||
const isMember = workspaceMembers.find((member) => member.member.id === user?.id);
|
||||
const isGuest = workspaceMembers.find(
|
||||
@ -140,6 +139,30 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
|
||||
if ((!isMember || isGuest) && isOpen) return <IsGuestCondition setIsOpen={setIsOpen} />;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (projectName && isChangeIdentifierRequired) {
|
||||
setValue("identifier", projectName.replace(/ /g, "").toUpperCase().substring(0, 3));
|
||||
}
|
||||
}, [projectName, projectIdentifier, setValue, isChangeIdentifierRequired]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!projectName) return;
|
||||
const suggestedIdentifier = createSimilarString(
|
||||
projectName.replace(/ /g, "").toUpperCase().substring(0, 3)
|
||||
);
|
||||
|
||||
setRecommendedIdentifier([
|
||||
suggestedIdentifier + Math.floor(Math.random() * 101),
|
||||
suggestedIdentifier + Math.floor(Math.random() * 101),
|
||||
projectIdentifier.toUpperCase().substring(0, 3) + Math.floor(Math.random() * 101),
|
||||
projectIdentifier.toUpperCase().substring(0, 3) + Math.floor(Math.random() * 101),
|
||||
]);
|
||||
}, [errors.identifier]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => setIsChangeIdentifierRequired(true);
|
||||
}, [isOpen]);
|
||||
|
||||
return (
|
||||
<Transition.Root show={isOpen} as={React.Fragment}>
|
||||
<Dialog as="div" className="relative z-10" onClose={handleClose}>
|
||||
@ -239,6 +262,27 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
|
||||
},
|
||||
}}
|
||||
/>
|
||||
{errors.identifier && (
|
||||
<div className="mt-2">
|
||||
<p>Ops! Identifier is already taken. Try one of the following:</p>
|
||||
<div className="flex gap-x-2">
|
||||
{recommendedIdentifier.map((identifier) => (
|
||||
<button
|
||||
key={identifier}
|
||||
type="button"
|
||||
className="text-sm text-gray-500 hover:text-gray-700 border p-2 py-0.5 rounded"
|
||||
onClick={() => {
|
||||
clearErrors("identifier");
|
||||
setValue("identifier", identifier);
|
||||
setIsChangeIdentifierRequired(false);
|
||||
}}
|
||||
>
|
||||
{identifier}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -4,7 +4,7 @@ import { mutate } from "swr";
|
||||
// headless ui
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
// services
|
||||
import cycleService from "lib/services/cycles.services";
|
||||
import cycleService from "lib/services/cycles.service";
|
||||
// fetch api
|
||||
import { CYCLE_LIST } from "constants/fetch-keys";
|
||||
// hooks
|
||||
|
@ -6,7 +6,7 @@ import { useForm } from "react-hook-form";
|
||||
// headless
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
// services
|
||||
import cycleService from "lib/services/cycles.services";
|
||||
import cycleService from "lib/services/cycles.service";
|
||||
// fetch keys
|
||||
import { CYCLE_LIST } from "constants/fetch-keys";
|
||||
// hooks
|
||||
|
@ -7,7 +7,7 @@ import { Combobox, Dialog, Transition } from "@headlessui/react";
|
||||
// ui
|
||||
import { Button } from "ui";
|
||||
// services
|
||||
import issuesServices from "lib/services/issues.services";
|
||||
import issuesServices from "lib/services/issues.service";
|
||||
// hooks
|
||||
import useUser from "lib/hooks/useUser";
|
||||
import useToast from "lib/hooks/useToast";
|
||||
|
@ -7,7 +7,7 @@ import useSWR, { mutate } from "swr";
|
||||
// headless ui
|
||||
import { Disclosure, Transition, Menu } from "@headlessui/react";
|
||||
// services
|
||||
import cycleServices from "lib/services/cycles.services";
|
||||
import cycleServices from "lib/services/cycles.service";
|
||||
// hooks
|
||||
import useUser from "lib/hooks/useUser";
|
||||
// components
|
||||
@ -22,7 +22,7 @@ import type { CycleViewProps as Props, CycleIssueResponse, IssueResponse } from
|
||||
import { CYCLE_ISSUES } from "constants/fetch-keys";
|
||||
// constants
|
||||
import { renderShortNumericDateFormat } from "constants/common";
|
||||
import issuesServices from "lib/services/issues.services";
|
||||
import issuesServices from "lib/services/issues.service";
|
||||
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
||||
import { Draggable } from "react-beautiful-dnd";
|
||||
|
||||
|
@ -7,8 +7,8 @@ import useSWR from "swr";
|
||||
import type { DropResult } from "react-beautiful-dnd";
|
||||
import { DragDropContext } from "react-beautiful-dnd";
|
||||
// services
|
||||
import stateServices from "lib/services/state.services";
|
||||
import issuesServices from "lib/services/issues.services";
|
||||
import stateServices from "lib/services/state.service";
|
||||
import issuesServices from "lib/services/issues.service";
|
||||
// hooks
|
||||
import useUser from "lib/hooks/useUser";
|
||||
// fetching keys
|
||||
@ -20,7 +20,7 @@ import CreateUpdateIssuesModal from "components/project/issues/CreateUpdateIssue
|
||||
// ui
|
||||
import { Spinner } from "ui";
|
||||
// types
|
||||
import type { IState, IIssue, Properties, NestedKeyOf, ProjectMember } from "types";
|
||||
import type { IState, IIssue, Properties, NestedKeyOf, IProjectMember } from "types";
|
||||
import ConfirmIssueDeletion from "../ConfirmIssueDeletion";
|
||||
import { TrashIcon } from "@heroicons/react/24/outline";
|
||||
|
||||
@ -30,7 +30,7 @@ type Props = {
|
||||
groupedByIssues: {
|
||||
[key: string]: IIssue[];
|
||||
};
|
||||
members: ProjectMember[] | undefined;
|
||||
members: IProjectMember[] | undefined;
|
||||
};
|
||||
|
||||
const BoardView: React.FC<Props> = ({ properties, selectedGroup, groupedByIssues, members }) => {
|
||||
|
@ -4,7 +4,7 @@ import { mutate } from "swr";
|
||||
// headless ui
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
// services
|
||||
import stateServices from "lib/services/state.services";
|
||||
import stateServices from "lib/services/state.service";
|
||||
// fetch api
|
||||
import { STATE_LIST } from "constants/fetch-keys";
|
||||
// hooks
|
||||
@ -43,7 +43,7 @@ const ConfirmStateDeletion: React.FC<Props> = ({ isOpen, setIsOpen, data }) => {
|
||||
mutate<IState[]>(
|
||||
STATE_LIST(data.project),
|
||||
(prevData) => prevData?.filter((state) => state.id !== data?.id),
|
||||
false,
|
||||
false
|
||||
);
|
||||
handleClose();
|
||||
})
|
||||
@ -98,18 +98,15 @@ const ConfirmStateDeletion: React.FC<Props> = ({ isOpen, setIsOpen, data }) => {
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||
<Dialog.Title
|
||||
as="h3"
|
||||
className="text-lg font-medium leading-6 text-gray-900"
|
||||
>
|
||||
<Dialog.Title as="h3" className="text-lg font-medium leading-6 text-gray-900">
|
||||
Delete State
|
||||
</Dialog.Title>
|
||||
<div className="mt-2">
|
||||
<p className="text-sm text-gray-500">
|
||||
Are you sure you want to delete state - {`"`}
|
||||
<span className="italic">{data?.name}</span>
|
||||
{`"`} ? All of the data related to the state will be
|
||||
permanently removed. This action cannot be undone.
|
||||
{`"`} ? All of the data related to the state will be permanently removed.
|
||||
This action cannot be undone.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -8,7 +8,7 @@ import { TwitterPicker } from "react-color";
|
||||
// headless
|
||||
import { Dialog, Popover, Transition } from "@headlessui/react";
|
||||
// services
|
||||
import stateService from "lib/services/state.services";
|
||||
import stateService from "lib/services/state.service";
|
||||
// fetch keys
|
||||
import { STATE_LIST } from "constants/fetch-keys";
|
||||
// hooks
|
||||
|
@ -6,7 +6,7 @@ import { Dialog, Transition } from "@headlessui/react";
|
||||
// fetching keys
|
||||
import { PROJECT_ISSUES_LIST } from "constants/fetch-keys";
|
||||
// services
|
||||
import issueServices from "lib/services/issues.services";
|
||||
import issueServices from "lib/services/issues.service";
|
||||
// hooks
|
||||
import useUser from "lib/hooks/useUser";
|
||||
import useToast from "lib/hooks/useToast";
|
||||
|
@ -11,7 +11,7 @@ import useUser from "lib/hooks/useUser";
|
||||
import { PROJECT_MEMBERS } from "constants/fetch-keys";
|
||||
// types
|
||||
import type { Control } from "react-hook-form";
|
||||
import type { IIssue, WorkspaceMember } from "types";
|
||||
import type { IIssue } from "types";
|
||||
import { UserIcon } from "@heroicons/react/24/outline";
|
||||
|
||||
import { SearchListbox } from "ui";
|
||||
@ -23,7 +23,7 @@ type Props = {
|
||||
const SelectAssignee: React.FC<Props> = ({ control }) => {
|
||||
const { activeWorkspace, activeProject } = useUser();
|
||||
|
||||
const { data: people } = useSWR<WorkspaceMember[]>(
|
||||
const { data: people } = useSWR(
|
||||
activeWorkspace && activeProject ? PROJECT_MEMBERS(activeProject.id) : null,
|
||||
activeWorkspace && activeProject
|
||||
? () => projectServices.projectMembers(activeWorkspace.slug, activeProject.id)
|
||||
|
@ -6,7 +6,7 @@ import { useForm, Controller } from "react-hook-form";
|
||||
// headless ui
|
||||
import { Listbox, Transition } from "@headlessui/react";
|
||||
// services
|
||||
import issuesServices from "lib/services/issues.services";
|
||||
import issuesServices from "lib/services/issues.service";
|
||||
// hooks
|
||||
import useUser from "lib/hooks/useUser";
|
||||
// fetching keys
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
// headless
|
||||
import { Dialog, Menu, Transition } from "@headlessui/react";
|
||||
// services
|
||||
import issuesServices from "lib/services/issues.services";
|
||||
import issuesServices from "lib/services/issues.service";
|
||||
// hooks
|
||||
import useUser from "lib/hooks/useUser";
|
||||
import useToast from "lib/hooks/useToast";
|
||||
|
@ -10,14 +10,14 @@ import { Listbox, Transition } from "@headlessui/react";
|
||||
// icons
|
||||
import { PencilIcon, TrashIcon } from "@heroicons/react/24/outline";
|
||||
// types
|
||||
import { IIssue, IssueResponse, NestedKeyOf, Properties, WorkspaceMember } from "types";
|
||||
import { IIssue, IssueResponse, NestedKeyOf, Properties } from "types";
|
||||
// hooks
|
||||
import useUser from "lib/hooks/useUser";
|
||||
// fetch keys
|
||||
import { PRIORITIES } from "constants/";
|
||||
import { PROJECT_ISSUES_LIST, WORKSPACE_MEMBERS } from "constants/fetch-keys";
|
||||
// services
|
||||
import issuesServices from "lib/services/issues.services";
|
||||
import issuesServices from "lib/services/issues.service";
|
||||
import workspaceService from "lib/services/workspace.service";
|
||||
// constants
|
||||
import { addSpaceIfCamelCase, classNames, renderShortNumericDateFormat } from "constants/common";
|
||||
@ -60,7 +60,7 @@ const ListView: React.FC<Props> = ({
|
||||
});
|
||||
};
|
||||
|
||||
const { data: people } = useSWR<WorkspaceMember[]>(
|
||||
const { data: people } = useSWR(
|
||||
activeWorkspace ? WORKSPACE_MEMBERS : null,
|
||||
activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null
|
||||
);
|
||||
|
@ -6,8 +6,8 @@ import { Listbox, Transition } from "@headlessui/react";
|
||||
// react hook form
|
||||
import { useForm, Controller, UseFormWatch } from "react-hook-form";
|
||||
// services
|
||||
import stateServices from "lib/services/state.services";
|
||||
import issuesServices from "lib/services/issues.services";
|
||||
import stateServices from "lib/services/state.service";
|
||||
import issuesServices from "lib/services/issues.service";
|
||||
import workspaceService from "lib/services/workspace.service";
|
||||
// hooks
|
||||
import useUser from "lib/hooks/useUser";
|
||||
@ -40,14 +40,7 @@ import {
|
||||
} from "@heroicons/react/24/outline";
|
||||
// types
|
||||
import type { Control } from "react-hook-form";
|
||||
import type {
|
||||
IIssue,
|
||||
IIssueLabels,
|
||||
IssueResponse,
|
||||
IState,
|
||||
NestedKeyOf,
|
||||
WorkspaceMember,
|
||||
} from "types";
|
||||
import type { IIssue, IIssueLabels, IssueResponse, IState, NestedKeyOf } from "types";
|
||||
import { TwitterPicker } from "react-color";
|
||||
import IssuesListModal from "components/project/issues/IssuesListModal";
|
||||
|
||||
@ -84,7 +77,7 @@ const IssueDetailSidebar: React.FC<Props> = ({
|
||||
: null
|
||||
);
|
||||
|
||||
const { data: people } = useSWR<WorkspaceMember[]>(
|
||||
const { data: people } = useSWR(
|
||||
activeWorkspace ? WORKSPACE_MEMBERS(activeWorkspace.slug) : null,
|
||||
activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null
|
||||
);
|
||||
|
@ -4,7 +4,7 @@ import { mutate } from "swr";
|
||||
// react hook form
|
||||
import { useForm } from "react-hook-form";
|
||||
// services
|
||||
import issuesServices from "lib/services/issues.services";
|
||||
import issuesServices from "lib/services/issues.service";
|
||||
// fetch keys
|
||||
import { PROJECT_ISSUES_COMMENTS } from "constants/fetch-keys";
|
||||
// components
|
||||
|
@ -8,7 +8,7 @@ import useUser from "lib/hooks/useUser";
|
||||
import { addSpaceIfCamelCase, classNames } from "constants/common";
|
||||
import { STATE_LIST } from "constants/fetch-keys";
|
||||
// services
|
||||
import stateServices from "lib/services/state.services";
|
||||
import stateServices from "lib/services/state.service";
|
||||
// ui
|
||||
import { Listbox, Transition } from "@headlessui/react";
|
||||
// types
|
||||
|
@ -15,7 +15,7 @@ import { Button } from "ui";
|
||||
// icons
|
||||
import { CheckIcon, ChevronDownIcon } from "@heroicons/react/24/outline";
|
||||
// types
|
||||
import { IProject, WorkspaceMember } from "types";
|
||||
import { IProject } from "types";
|
||||
// fetch-keys
|
||||
import { WORKSPACE_MEMBERS } from "constants/fetch-keys";
|
||||
|
||||
@ -27,7 +27,7 @@ type Props = {
|
||||
const ControlSettings: React.FC<Props> = ({ control, isSubmitting }) => {
|
||||
const { activeWorkspace } = useUser();
|
||||
|
||||
const { data: people } = useSWR<WorkspaceMember[]>(
|
||||
const { data: people } = useSWR(
|
||||
activeWorkspace ? WORKSPACE_MEMBERS : null,
|
||||
activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null
|
||||
);
|
||||
|
@ -7,7 +7,7 @@ import { Controller, SubmitHandler, useForm } from "react-hook-form";
|
||||
// react-color
|
||||
import { TwitterPicker } from "react-color";
|
||||
// services
|
||||
import issuesServices from "lib/services/issues.services";
|
||||
import issuesServices from "lib/services/issues.service";
|
||||
// hooks
|
||||
import useUser from "lib/hooks/useUser";
|
||||
// headless ui
|
||||
|
@ -14,7 +14,7 @@ import { Button, Input, TextArea, Select } from "ui";
|
||||
// hooks
|
||||
import useToast from "lib/hooks/useToast";
|
||||
// types
|
||||
import { WorkspaceMember } from "types";
|
||||
import { IWorkspaceMemberInvitation } from "types";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
@ -30,7 +30,7 @@ const ROLE = {
|
||||
20: "Admin",
|
||||
};
|
||||
|
||||
const defaultValues: Partial<WorkspaceMember> = {
|
||||
const defaultValues: Partial<IWorkspaceMemberInvitation> = {
|
||||
email: "",
|
||||
role: 5,
|
||||
message: "",
|
||||
@ -57,7 +57,7 @@ const SendWorkspaceInvitationModal: React.FC<Props> = ({
|
||||
formState: { errors, isSubmitting },
|
||||
handleSubmit,
|
||||
reset,
|
||||
} = useForm<WorkspaceMember>({
|
||||
} = useForm<IWorkspaceMemberInvitation>({
|
||||
defaultValues,
|
||||
reValidateMode: "onChange",
|
||||
mode: "all",
|
||||
|
@ -3,10 +3,10 @@ import Image from "next/image";
|
||||
// react
|
||||
import { useState } from "react";
|
||||
// types
|
||||
import { IWorkspaceInvitation } from "types";
|
||||
import { IWorkspaceMemberInvitation } from "types";
|
||||
|
||||
type Props = {
|
||||
invitation: IWorkspaceInvitation;
|
||||
invitation: IWorkspaceMemberInvitation;
|
||||
invitationsRespond: string[];
|
||||
handleInvitation: any;
|
||||
};
|
||||
|
@ -207,3 +207,12 @@ export const cosineSimilarity = (a: string, b: string) => {
|
||||
|
||||
return dotProduct / Math.sqrt(magnitudeA * magnitudeB);
|
||||
};
|
||||
|
||||
export const createSimilarString = (str: string) => {
|
||||
const shuffled = str
|
||||
.split("")
|
||||
.sort(() => Math.random() - 0.5)
|
||||
.join("");
|
||||
|
||||
return shuffled;
|
||||
};
|
||||
|
@ -6,9 +6,9 @@ import { useRouter } from "next/router";
|
||||
import useSWR from "swr";
|
||||
// services
|
||||
import userService from "lib/services/user.service";
|
||||
import issuesServices from "lib/services/issues.services";
|
||||
import stateServices from "lib/services/state.services";
|
||||
import sprintsServices from "lib/services/cycles.services";
|
||||
import issuesServices from "lib/services/issues.service";
|
||||
import stateServices from "lib/services/state.service";
|
||||
import sprintsServices from "lib/services/cycles.service";
|
||||
import projectServices from "lib/services/project.service";
|
||||
import workspaceService from "lib/services/workspace.service";
|
||||
// constants
|
||||
|
@ -8,7 +8,7 @@ import useUser from "lib/hooks/useUser";
|
||||
import Container from "layouts/Container";
|
||||
import Sidebar from "layouts/Navbar/Sidebar";
|
||||
// components
|
||||
import CreateProjectModal from "components/project/CreateProjectModal";
|
||||
import CreateProjectModal from "components/project/create-project-modal";
|
||||
// types
|
||||
import type { Props } from "./types";
|
||||
|
||||
|
@ -10,8 +10,6 @@ import authenticationService from "lib/services/authentication.service";
|
||||
import useUser from "lib/hooks/useUser";
|
||||
import useTheme from "lib/hooks/useTheme";
|
||||
import useToast from "lib/hooks/useToast";
|
||||
// components
|
||||
import CreateProjectModal from "components/project/CreateProjectModal";
|
||||
// headless ui
|
||||
import { Dialog, Disclosure, Menu, Transition } from "@headlessui/react";
|
||||
// icons
|
||||
@ -108,7 +106,6 @@ const userLinks = [
|
||||
|
||||
const Sidebar: React.FC = () => {
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||
const [isCreateProjectModal, setCreateProjectModal] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@ -124,7 +121,6 @@ const Sidebar: React.FC = () => {
|
||||
|
||||
return (
|
||||
<nav className="h-full">
|
||||
<CreateProjectModal isOpen={isCreateProjectModal} setIsOpen={setCreateProjectModal} />
|
||||
<Transition.Root show={sidebarOpen} as={React.Fragment}>
|
||||
<Dialog as="div" className="relative z-40 md:hidden" onClose={setSidebarOpen}>
|
||||
<Transition.Child
|
||||
@ -557,7 +553,13 @@ const Sidebar: React.FC = () => {
|
||||
<button
|
||||
type="button"
|
||||
className="group flex justify-center items-center gap-2 w-full rounded-md p-2 text-sm bg-theme text-white"
|
||||
onClick={() => setCreateProjectModal(true)}
|
||||
onClick={() => {
|
||||
const e = new KeyboardEvent("keydown", {
|
||||
ctrlKey: true,
|
||||
key: "p",
|
||||
});
|
||||
document.dispatchEvent(e);
|
||||
}}
|
||||
>
|
||||
<PlusIcon className="h-5 w-5" />
|
||||
{!sidebarCollapse && "Create Project"}
|
||||
|
@ -4,7 +4,7 @@ import useSWR from "swr";
|
||||
// api routes
|
||||
import { ISSUE_PROPERTIES_ENDPOINT } from "constants/api-routes";
|
||||
// services
|
||||
import issueServices from "lib/services/issues.services";
|
||||
import issueServices from "lib/services/issues.service";
|
||||
// hooks
|
||||
import useUser from "./useUser";
|
||||
// types
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
// services
|
||||
import APIService from "lib/services/api.service";
|
||||
// types
|
||||
import type { ProjectViewTheme } from "types";
|
||||
import type { IProject, IProjectMember, IProjectMemberInvitation, ProjectViewTheme } from "types";
|
||||
|
||||
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
||||
|
||||
@ -24,8 +24,8 @@ class ProjectServices extends APIService {
|
||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||
}
|
||||
|
||||
async createProject(workspace_slug: string, data: any): Promise<any> {
|
||||
return this.post(PROJECTS_ENDPOINT(workspace_slug), data)
|
||||
async createProject(workspacSlug: string, data: Partial<IProject>): Promise<IProject> {
|
||||
return this.post(PROJECTS_ENDPOINT(workspacSlug), data)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -48,8 +48,8 @@ class ProjectServices extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async getProjects(workspace_slug: string): Promise<any> {
|
||||
return this.get(PROJECTS_ENDPOINT(workspace_slug))
|
||||
async getProjects(workspacSlug: string): Promise<IProject[]> {
|
||||
return this.get(PROJECTS_ENDPOINT(workspacSlug))
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -58,8 +58,8 @@ class ProjectServices extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async getProject(workspace_slug: string, project_id: string): Promise<any> {
|
||||
return this.get(PROJECT_DETAIL(workspace_slug, project_id))
|
||||
async getProject(workspacSlug: string, projectId: string): Promise<IProject> {
|
||||
return this.get(PROJECT_DETAIL(workspacSlug, projectId))
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -68,8 +68,12 @@ class ProjectServices extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async updateProject(workspace_slug: string, project_id: string, data: any): Promise<any> {
|
||||
return this.patch(PROJECT_DETAIL(workspace_slug, project_id), data)
|
||||
async updateProject(
|
||||
workspacSlug: string,
|
||||
projectId: string,
|
||||
data: Partial<IProject>
|
||||
): Promise<IProject> {
|
||||
return this.patch(PROJECT_DETAIL(workspacSlug, projectId), data)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -78,8 +82,8 @@ class ProjectServices extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async deleteProject(workspace_slug: string, project_id: string): Promise<any> {
|
||||
return this.delete(PROJECT_DETAIL(workspace_slug, project_id))
|
||||
async deleteProject(workspacSlug: string, projectId: string): Promise<any> {
|
||||
return this.delete(PROJECT_DETAIL(workspacSlug, projectId))
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -88,8 +92,8 @@ class ProjectServices extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async inviteProject(workspace_slug: string, project_id: string, data: any): Promise<any> {
|
||||
return this.post(INVITE_PROJECT(workspace_slug, project_id), data)
|
||||
async inviteProject(workspacSlug: string, projectId: string, data: any): Promise<any> {
|
||||
return this.post(INVITE_PROJECT(workspacSlug, projectId), data)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -98,8 +102,8 @@ class ProjectServices extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async joinProject(workspace_slug: string, data: any): Promise<any> {
|
||||
return this.post(JOIN_PROJECT(workspace_slug), data)
|
||||
async joinProject(workspacSlug: string, data: any): Promise<any> {
|
||||
return this.post(JOIN_PROJECT(workspacSlug), data)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -118,8 +122,8 @@ class ProjectServices extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async projectMembers(workspace_slug: string, project_id: string): Promise<any> {
|
||||
return this.get(PROJECT_MEMBERS(workspace_slug, project_id))
|
||||
async projectMembers(workspacSlug: string, projectId: string): Promise<IProjectMember[]> {
|
||||
return this.get(PROJECT_MEMBERS(workspacSlug, projectId))
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -129,12 +133,12 @@ class ProjectServices extends APIService {
|
||||
}
|
||||
|
||||
async updateProjectMember(
|
||||
workspace_slug: string,
|
||||
project_id: string,
|
||||
workspacSlug: string,
|
||||
projectId: string,
|
||||
memberId: string,
|
||||
data: any
|
||||
): Promise<any> {
|
||||
return this.put(PROJECT_MEMBER_DETAIL(workspace_slug, project_id, memberId), data)
|
||||
data: Partial<IProjectMember>
|
||||
): Promise<IProjectMember> {
|
||||
return this.put(PROJECT_MEMBER_DETAIL(workspacSlug, projectId, memberId), data)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -144,11 +148,11 @@ class ProjectServices extends APIService {
|
||||
}
|
||||
|
||||
async deleteProjectMember(
|
||||
workspace_slug: string,
|
||||
project_id: string,
|
||||
workspacSlug: string,
|
||||
projectId: string,
|
||||
memberId: string
|
||||
): Promise<any> {
|
||||
return this.delete(PROJECT_MEMBER_DETAIL(workspace_slug, project_id, memberId))
|
||||
return this.delete(PROJECT_MEMBER_DETAIL(workspacSlug, projectId, memberId))
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -157,8 +161,11 @@ class ProjectServices extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async projectInvitations(workspace_slug: string, project_id: string): Promise<any> {
|
||||
return this.get(PROJECT_INVITATIONS(workspace_slug, project_id))
|
||||
async projectInvitations(
|
||||
workspacSlug: string,
|
||||
projectId: string
|
||||
): Promise<IProjectMemberInvitation[]> {
|
||||
return this.get(PROJECT_INVITATIONS(workspacSlug, projectId))
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -168,11 +175,11 @@ class ProjectServices extends APIService {
|
||||
}
|
||||
|
||||
async updateProjectInvitation(
|
||||
workspace_slug: string,
|
||||
project_id: string,
|
||||
invitation_id: string
|
||||
workspacSlug: string,
|
||||
projectId: string,
|
||||
invitationId: string
|
||||
): Promise<any> {
|
||||
return this.put(PROJECT_INVITATION_DETAIL(workspace_slug, project_id, invitation_id))
|
||||
return this.put(PROJECT_INVITATION_DETAIL(workspacSlug, projectId, invitationId))
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -182,11 +189,11 @@ class ProjectServices extends APIService {
|
||||
}
|
||||
|
||||
async deleteProjectInvitation(
|
||||
workspace_slug: string,
|
||||
project_id: string,
|
||||
invitation_id: string
|
||||
workspacSlug: string,
|
||||
projectId: string,
|
||||
invitationId: string
|
||||
): Promise<any> {
|
||||
return this.delete(PROJECT_INVITATION_DETAIL(workspace_slug, project_id, invitation_id))
|
||||
return this.delete(PROJECT_INVITATION_DETAIL(workspacSlug, projectId, invitationId))
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -196,11 +203,11 @@ class ProjectServices extends APIService {
|
||||
}
|
||||
|
||||
async setProjectView(
|
||||
workspace_slug: string,
|
||||
project_id: string,
|
||||
workspacSlug: string,
|
||||
projectId: string,
|
||||
data: ProjectViewTheme
|
||||
): Promise<any> {
|
||||
await this.patch(PROJECT_VIEW_ENDPOINT(workspace_slug, project_id), data)
|
||||
await this.patch(PROJECT_VIEW_ENDPOINT(workspacSlug, projectId), data)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
|
@ -17,12 +17,15 @@ import APIService from "lib/services/api.service";
|
||||
|
||||
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
||||
|
||||
// types
|
||||
import { IWorkspace, IWorkspaceMember, IWorkspaceMemberInvitation } from "types";
|
||||
|
||||
class WorkspaceService extends APIService {
|
||||
constructor() {
|
||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||
}
|
||||
|
||||
async userWorkspaces(): Promise<any> {
|
||||
async userWorkspaces(): Promise<IWorkspace[]> {
|
||||
return this.get(USER_WORKSPACES)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
@ -32,7 +35,7 @@ class WorkspaceService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async createWorkspace(data: any): Promise<any> {
|
||||
async createWorkspace(data: Partial<IWorkspace>): Promise<IWorkspace> {
|
||||
return this.post(WORKSPACES_ENDPOINT, data)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
@ -42,17 +45,8 @@ class WorkspaceService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async updateWorkspace(workspace_slug: string, data: any): Promise<any> {
|
||||
return this.patch(WORKSPACE_DETAIL(workspace_slug), data)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
async deleteWorkspace(workspace_slug: string): Promise<any> {
|
||||
return this.delete(WORKSPACE_DETAIL(workspace_slug))
|
||||
async updateWorkspace(workspaceSlug: string, data: Partial<IWorkspace>): Promise<IWorkspace> {
|
||||
return this.patch(WORKSPACE_DETAIL(workspaceSlug), data)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -61,8 +55,8 @@ class WorkspaceService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async inviteWorkspace(workspace_slug: string, data: any): Promise<any> {
|
||||
return this.post(INVITE_WORKSPACE(workspace_slug), data)
|
||||
async deleteWorkspace(workspaceSlug: string): Promise<any> {
|
||||
return this.delete(WORKSPACE_DETAIL(workspaceSlug))
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -70,8 +64,19 @@ class WorkspaceService extends APIService {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
async joinWorkspace(workspace_slug: string, InvitationId: string, data: any): Promise<any> {
|
||||
return this.post(JOIN_WORKSPACE(workspace_slug, InvitationId), data, {
|
||||
|
||||
async inviteWorkspace(workspaceSlug: string, data: any): Promise<any> {
|
||||
return this.post(INVITE_WORKSPACE(workspaceSlug), data)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async joinWorkspace(workspaceSlug: string, InvitationId: string, data: any): Promise<any> {
|
||||
return this.post(JOIN_WORKSPACE(workspaceSlug, InvitationId), data, {
|
||||
headers: {},
|
||||
})
|
||||
.then((response) => {
|
||||
@ -92,7 +97,7 @@ class WorkspaceService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async userWorkspaceInvitations(): Promise<any> {
|
||||
async userWorkspaceInvitations(): Promise<IWorkspaceMemberInvitation[]> {
|
||||
return this.get(USER_WORKSPACE_INVITATIONS)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
@ -102,8 +107,8 @@ class WorkspaceService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async workspaceMembers(workspace_slug: string): Promise<any> {
|
||||
return this.get(WORKSPACE_MEMBERS(workspace_slug))
|
||||
async workspaceMembers(workspaceSlug: string): Promise<IWorkspaceMember[]> {
|
||||
return this.get(WORKSPACE_MEMBERS(workspaceSlug))
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -112,8 +117,12 @@ class WorkspaceService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async updateWorkspaceMember(workspace_slug: string, memberId: string, data: any): Promise<any> {
|
||||
return this.put(WORKSPACE_MEMBER_DETAIL(workspace_slug, memberId), data)
|
||||
async updateWorkspaceMember(
|
||||
workspaceSlug: string,
|
||||
memberId: string,
|
||||
data: Partial<IWorkspaceMember>
|
||||
): Promise<IWorkspaceMember> {
|
||||
return this.put(WORKSPACE_MEMBER_DETAIL(workspaceSlug, memberId), data)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -122,8 +131,8 @@ class WorkspaceService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async deleteWorkspaceMember(workspace_slug: string, memberId: string): Promise<any> {
|
||||
return this.delete(WORKSPACE_MEMBER_DETAIL(workspace_slug, memberId))
|
||||
async deleteWorkspaceMember(workspaceSlug: string, memberId: string): Promise<any> {
|
||||
return this.delete(WORKSPACE_MEMBER_DETAIL(workspaceSlug, memberId))
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -132,8 +141,8 @@ class WorkspaceService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async workspaceInvitations(workspace_slug: string): Promise<any> {
|
||||
return this.get(WORKSPACE_INVITATIONS(workspace_slug))
|
||||
async workspaceInvitations(workspaceSlug: string): Promise<IWorkspaceMemberInvitation[]> {
|
||||
return this.get(WORKSPACE_INVITATIONS(workspaceSlug))
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -142,8 +151,8 @@ class WorkspaceService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async getWorkspaceInvitation(invitation_id: string): Promise<any> {
|
||||
return this.get(USER_WORKSPACE_INVITATION(invitation_id), { headers: {} })
|
||||
async getWorkspaceInvitation(invitationId: string): Promise<IWorkspaceMemberInvitation> {
|
||||
return this.get(USER_WORKSPACE_INVITATION(invitationId), { headers: {} })
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -152,8 +161,11 @@ class WorkspaceService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async updateWorkspaceInvitation(workspace_slug: string, invitation_id: string): Promise<any> {
|
||||
return this.put(WORKSPACE_INVITATION_DETAIL(workspace_slug, invitation_id))
|
||||
async updateWorkspaceInvitation(
|
||||
workspaceSlug: string,
|
||||
invitationId: string
|
||||
): Promise<IWorkspaceMemberInvitation> {
|
||||
return this.put(WORKSPACE_INVITATION_DETAIL(workspaceSlug, invitationId))
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
@ -161,8 +173,9 @@ class WorkspaceService extends APIService {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
async deleteWorkspaceInvitations(workspace_slug: string, invitation_id: string): Promise<any> {
|
||||
return this.delete(WORKSPACE_INVITATION_DETAIL(workspace_slug, invitation_id))
|
||||
|
||||
async deleteWorkspaceInvitations(workspaceSlug: string, invitationId: string): Promise<any> {
|
||||
return this.delete(WORKSPACE_INVITATION_DETAIL(workspaceSlug, invitationId))
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
|
@ -22,7 +22,7 @@ import { Button, Spinner, EmptySpace, EmptySpaceItem } from "ui";
|
||||
// icons
|
||||
import { CubeIcon, PlusIcon } from "@heroicons/react/24/outline";
|
||||
// types
|
||||
import type { IWorkspaceInvitation } from "types";
|
||||
import type { IWorkspaceMemberInvitation } from "types";
|
||||
import Link from "next/link";
|
||||
|
||||
const OnBoard: NextPage = () => {
|
||||
@ -32,13 +32,12 @@ const OnBoard: NextPage = () => {
|
||||
|
||||
const [invitationsRespond, setInvitationsRespond] = useState<string[]>([]);
|
||||
|
||||
const { data: invitations, mutate } = useSWR<IWorkspaceInvitation[]>(
|
||||
USER_WORKSPACE_INVITATIONS,
|
||||
() => workspaceService.userWorkspaceInvitations()
|
||||
const { data: invitations, mutate } = useSWR(USER_WORKSPACE_INVITATIONS, () =>
|
||||
workspaceService.userWorkspaceInvitations()
|
||||
);
|
||||
|
||||
const handleInvitation = (
|
||||
workspace_invitation: IWorkspaceInvitation,
|
||||
workspace_invitation: IWorkspaceMemberInvitation,
|
||||
action: "accepted" | "withdraw"
|
||||
) => {
|
||||
if (action === "accepted") {
|
||||
|
@ -18,7 +18,7 @@ import { USER_ISSUE } from "constants/fetch-keys";
|
||||
import { classNames } from "constants/common";
|
||||
// services
|
||||
import userService from "lib/services/user.service";
|
||||
import issuesServices from "lib/services/issues.services";
|
||||
import issuesServices from "lib/services/issues.service";
|
||||
// hoc
|
||||
import withAuth from "lib/hoc/withAuthWrapper";
|
||||
// components
|
||||
|
@ -14,11 +14,11 @@ import withAuth from "lib/hoc/withAuthWrapper";
|
||||
import AppLayout from "layouts/AppLayout";
|
||||
// services
|
||||
import userService from "lib/services/user.service";
|
||||
import fileServices from "lib/services/file.services";
|
||||
import fileServices from "lib/services/file.service";
|
||||
// ui
|
||||
import { BreadcrumbItem, Breadcrumbs, Button, Input, Spinner } from "ui";
|
||||
// types
|
||||
import type { IIssue, IUser, IWorkspaceInvitation } from "types";
|
||||
import type { IIssue, IUser, IWorkspaceMemberInvitation } from "types";
|
||||
import {
|
||||
ChevronRightIcon,
|
||||
ClipboardDocumentListIcon,
|
||||
@ -81,8 +81,9 @@ const Profile: NextPage = () => {
|
||||
myProfile ? () => userService.userIssues() : null
|
||||
);
|
||||
|
||||
const { data: invitations } = useSWR<IWorkspaceInvitation[]>(USER_WORKSPACE_INVITATIONS, () =>
|
||||
workspaceService.userWorkspaceInvitations()
|
||||
const { data: invitations } = useSWR<IWorkspaceMemberInvitation[]>(
|
||||
USER_WORKSPACE_INVITATIONS,
|
||||
() => workspaceService.userWorkspaceInvitations()
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -5,8 +5,8 @@ import type { NextPage } from "next";
|
||||
// swr
|
||||
import useSWR, { mutate } from "swr";
|
||||
// services
|
||||
import issuesServices from "lib/services/issues.services";
|
||||
import sprintService from "lib/services/cycles.services";
|
||||
import issuesServices from "lib/services/issues.service";
|
||||
import sprintService from "lib/services/cycles.service";
|
||||
// hooks
|
||||
import useUser from "lib/hooks/useUser";
|
||||
// fetching keys
|
||||
|
@ -11,7 +11,7 @@ import { Controller, useForm } from "react-hook-form";
|
||||
// headless ui
|
||||
import { Disclosure, Menu, Tab, Transition } from "@headlessui/react";
|
||||
// services
|
||||
import issuesServices from "lib/services/issues.services";
|
||||
import issuesServices from "lib/services/issues.service";
|
||||
// fetch keys
|
||||
import {
|
||||
PROJECT_ISSUES_ACTIVITY,
|
||||
|
@ -34,7 +34,7 @@ import HeaderButton from "ui/HeaderButton";
|
||||
import { ChevronDownIcon, ListBulletIcon, RectangleStackIcon } from "@heroicons/react/24/outline";
|
||||
import { PlusIcon, Squares2X2Icon } from "@heroicons/react/20/solid";
|
||||
// types
|
||||
import type { IIssue, Properties, NestedKeyOf, ProjectMember } from "types";
|
||||
import type { IIssue, Properties, NestedKeyOf } from "types";
|
||||
|
||||
const groupByOptions: Array<{ name: string; key: NestedKeyOf<IIssue> | null }> = [
|
||||
{ name: "State", key: "state_detail.name" },
|
||||
@ -86,7 +86,7 @@ const ProjectIssues: NextPage = () => {
|
||||
projectId as string
|
||||
);
|
||||
|
||||
const { data: members } = useSWR<ProjectMember[]>(
|
||||
const { data: members } = useSWR(
|
||||
activeWorkspace && activeProject
|
||||
? PROJECT_MEMBERS(activeWorkspace.slug, activeProject.id)
|
||||
: null,
|
||||
|
@ -111,8 +111,7 @@ const ProjectMembers: NextPage = () => {
|
||||
selectedRemoveMember
|
||||
);
|
||||
mutateMembers(
|
||||
(prevData: any[]) =>
|
||||
prevData?.filter((item: any) => item.id !== selectedRemoveMember),
|
||||
(prevData) => prevData?.filter((item: any) => item.id !== selectedRemoveMember),
|
||||
false
|
||||
);
|
||||
}
|
||||
@ -123,8 +122,7 @@ const ProjectMembers: NextPage = () => {
|
||||
selectedInviteRemoveMember
|
||||
);
|
||||
mutateInvitations(
|
||||
(prevData: any[]) =>
|
||||
prevData?.filter((item: any) => item.id !== selectedInviteRemoveMember),
|
||||
(prevData) => prevData?.filter((item: any) => item.id !== selectedInviteRemoveMember),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import withAuth from "lib/hoc/withAuthWrapper";
|
||||
// layouts
|
||||
import AppLayout from "layouts/AppLayout";
|
||||
// components
|
||||
import CreateProjectModal from "components/project/CreateProjectModal";
|
||||
import CreateProjectModal from "components/project/create-project-modal";
|
||||
import ConfirmProjectDeletion from "components/project/ConfirmProjectDeletion";
|
||||
// ui
|
||||
import { Button, Spinner } from "ui";
|
||||
|
@ -35,12 +35,12 @@ const WorkspaceInvitation: NextPage = () => {
|
||||
|
||||
const { user } = useUser();
|
||||
|
||||
const { data: invitationDetail, error } = useSWR(
|
||||
invitationId && WORKSPACE_INVITATION,
|
||||
() => invitationId && workspaceService.getWorkspaceInvitation(invitationId as string)
|
||||
const { data: invitationDetail, error } = useSWR(invitationId && WORKSPACE_INVITATION, () =>
|
||||
invitationId ? workspaceService.getWorkspaceInvitation(invitationId as string) : null
|
||||
);
|
||||
|
||||
const handleAccept = () => {
|
||||
if (!invitationDetail) return;
|
||||
workspaceService
|
||||
.joinWorkspace(invitationDetail.workspace.slug, invitationDetail.id, {
|
||||
accepted: true,
|
||||
|
@ -7,7 +7,7 @@ import { useForm } from "react-hook-form";
|
||||
import Dropzone from "react-dropzone";
|
||||
// services
|
||||
import workspaceService from "lib/services/workspace.service";
|
||||
import fileServices from "lib/services/file.services";
|
||||
import fileServices from "lib/services/file.service";
|
||||
// hoc
|
||||
import withAuth from "lib/hoc/withAuthWrapper";
|
||||
// layouts
|
||||
|
16
apps/app/types/invitation.d.ts
vendored
16
apps/app/types/invitation.d.ts
vendored
@ -1,16 +0,0 @@
|
||||
import { IWorkspace } from "./";
|
||||
|
||||
export interface IWorkspaceInvitation {
|
||||
id: string;
|
||||
workspace: IWorkspace;
|
||||
created_at: Date;
|
||||
updated_at: Date;
|
||||
email: string;
|
||||
accepted: boolean;
|
||||
token: string;
|
||||
message: string;
|
||||
responded_at: Date;
|
||||
role: number;
|
||||
created_by: null;
|
||||
updated_by: null;
|
||||
}
|
35
apps/app/types/projects.d.ts
vendored
35
apps/app/types/projects.d.ts
vendored
@ -1,4 +1,4 @@
|
||||
import type { IWorkspace } from "./";
|
||||
import type { IUserLite, IWorkspace } from "./";
|
||||
|
||||
export interface IProject {
|
||||
id: string;
|
||||
@ -23,3 +23,36 @@ type ProjectViewTheme = {
|
||||
filterIssue: "activeIssue" | "backlogIssue" | null;
|
||||
orderBy: NestedKeyOf<IIssue> | null;
|
||||
};
|
||||
|
||||
export interface IProjectMember {
|
||||
member: IUserLite;
|
||||
project: IProject;
|
||||
workspace: IWorkspace;
|
||||
comment: string;
|
||||
role: 5 | 10 | 15 | 20;
|
||||
view_props: ProjectViewTheme;
|
||||
|
||||
created_at: Date;
|
||||
updated_at: Date;
|
||||
created_by: string;
|
||||
updated_by: string;
|
||||
}
|
||||
|
||||
export interface IProjectMemberInvitation {
|
||||
id: string;
|
||||
|
||||
project: IProject;
|
||||
workspace: IWorkspace;
|
||||
|
||||
email: string;
|
||||
accepted: boolean;
|
||||
token: string;
|
||||
message: string;
|
||||
responded_at: Date;
|
||||
role: 5 | 10 | 15 | 20;
|
||||
|
||||
created_at: Date;
|
||||
updated_at: Date;
|
||||
created_by: string;
|
||||
updated_by: string;
|
||||
}
|
||||
|
8
apps/app/types/users.d.ts
vendored
8
apps/app/types/users.d.ts
vendored
@ -16,3 +16,11 @@ export interface IUser {
|
||||
token: string;
|
||||
[...rest: string]: any;
|
||||
}
|
||||
|
||||
export interface IUserLite {
|
||||
readonly id: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
email: string;
|
||||
avatar: string;
|
||||
}
|
||||
|
30
apps/app/types/workspace.d.ts
vendored
30
apps/app/types/workspace.d.ts
vendored
@ -1,4 +1,4 @@
|
||||
import type { IUser } from "./";
|
||||
import type { IUser, IUserLite } from "./";
|
||||
|
||||
export interface IWorkspace {
|
||||
readonly id: string;
|
||||
@ -13,26 +13,26 @@ export interface IWorkspace {
|
||||
company_size: number;
|
||||
}
|
||||
|
||||
export interface WorkspaceMember {
|
||||
export interface IWorkspaceMemberInvitation {
|
||||
readonly id: string;
|
||||
email: string;
|
||||
accepted: boolean;
|
||||
token: string;
|
||||
message: string;
|
||||
responded_at: Date;
|
||||
role: 5 | 10 | 15 | 20;
|
||||
member: IUser;
|
||||
workspace: IWorkspace | string;
|
||||
workspace: IWorkspace;
|
||||
}
|
||||
|
||||
export interface IWorkspaceMember {
|
||||
readonly id: string;
|
||||
user: IUserLite;
|
||||
workspace: IWorkspace;
|
||||
member: IUserLite;
|
||||
role: 5 | 10 | 15 | 20;
|
||||
company_role: string | null;
|
||||
created_at: Date;
|
||||
updated_at: Date;
|
||||
created_by: string;
|
||||
updated_by: string;
|
||||
}
|
||||
|
||||
export interface ProjectMember {
|
||||
readonly id: string;
|
||||
readonly project: string;
|
||||
email: string;
|
||||
message: string;
|
||||
role: 5 | 10 | 15 | 20;
|
||||
member: any;
|
||||
member_id: string;
|
||||
user_id: string;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user