mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fix: bug and auth fixes (#1224)
* fix: sign in and invitation page fixes * fix: project and workspace services track event fix * fix: user onboarding complete track event fix * fix: issue track event fix * fix: partial property , issue comment and mark as done issue track event fix * fix: bulk delete , move to cycle or module and issue label track event fix * fix: state , cycle and module track event fix * fix: pages and block track event fix * fix: integration , estimate , importer , analytics and gpt track event fix * fix: view track event fix * fix: build fix * fix: build fix
This commit is contained in:
parent
c127353281
commit
6f2a38ad66
@ -18,7 +18,7 @@ import { Loader, PrimaryButton } from "components/ui";
|
||||
// helpers
|
||||
import { convertResponseToBarGraphData } from "helpers/analytics.helper";
|
||||
// types
|
||||
import { IAnalyticsParams, IAnalyticsResponse } from "types";
|
||||
import { IAnalyticsParams, IAnalyticsResponse, ICurrentUserResponse } from "types";
|
||||
// fetch-keys
|
||||
import { ANALYTICS } from "constants/fetch-keys";
|
||||
|
||||
@ -29,6 +29,7 @@ type Props = {
|
||||
control: Control<IAnalyticsParams, any>;
|
||||
setValue: UseFormSetValue<IAnalyticsParams>;
|
||||
fullScreen: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const CustomAnalytics: React.FC<Props> = ({
|
||||
@ -38,6 +39,7 @@ export const CustomAnalytics: React.FC<Props> = ({
|
||||
control,
|
||||
setValue,
|
||||
fullScreen,
|
||||
user,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
@ -124,6 +126,7 @@ export const CustomAnalytics: React.FC<Props> = ({
|
||||
params={params}
|
||||
fullScreen={fullScreen}
|
||||
isProjectLevel={isProjectLevel}
|
||||
user={user}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -27,6 +27,7 @@ import { renderShortDate } from "helpers/date-time.helper";
|
||||
import {
|
||||
IAnalyticsParams,
|
||||
IAnalyticsResponse,
|
||||
ICurrentUserResponse,
|
||||
IExportAnalyticsFormData,
|
||||
IProject,
|
||||
IWorkspace,
|
||||
@ -41,6 +42,7 @@ type Props = {
|
||||
params: IAnalyticsParams;
|
||||
fullScreen: boolean;
|
||||
isProjectLevel: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const AnalyticsSidebar: React.FC<Props> = ({
|
||||
@ -48,6 +50,7 @@ export const AnalyticsSidebar: React.FC<Props> = ({
|
||||
params,
|
||||
fullScreen,
|
||||
isProjectLevel = false,
|
||||
user,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
||||
@ -138,7 +141,8 @@ export const AnalyticsSidebar: React.FC<Props> = ({
|
||||
? "MODULE_ANALYTICS_EXPORT"
|
||||
: projectId
|
||||
? "PROJECT_ANALYTICS_EXPORT"
|
||||
: "WORKSPACE_ANALYTICS_EXPORT"
|
||||
: "WORKSPACE_ANALYTICS_EXPORT",
|
||||
user
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -26,6 +26,7 @@ import {
|
||||
import { IAnalyticsParams, IWorkspace } from "types";
|
||||
// fetch-keys
|
||||
import { ANALYTICS, CYCLE_DETAILS, MODULE_DETAILS, PROJECT_DETAILS } from "constants/fetch-keys";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
@ -47,6 +48,8 @@ export const AnalyticsProjectModal: React.FC<Props> = ({ isOpen, onClose }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { control, watch, setValue } = useForm<IAnalyticsParams>({ defaultValues });
|
||||
|
||||
const params: IAnalyticsParams = {
|
||||
@ -136,7 +139,8 @@ export const AnalyticsProjectModal: React.FC<Props> = ({ isOpen, onClose }) => {
|
||||
|
||||
trackEventServices.trackAnalyticsEvent(
|
||||
eventPayload,
|
||||
cycleId ? `CYCLE_${eventType}` : moduleId ? `MODULE_${eventType}` : `PROJECT_${eventType}`
|
||||
cycleId ? `CYCLE_${eventType}` : moduleId ? `MODULE_${eventType}` : `PROJECT_${eventType}`,
|
||||
user
|
||||
);
|
||||
};
|
||||
|
||||
@ -210,6 +214,7 @@ export const AnalyticsProjectModal: React.FC<Props> = ({ isOpen, onClose }) => {
|
||||
control={control}
|
||||
setValue={setValue}
|
||||
fullScreen={fullScreen}
|
||||
user={user}
|
||||
/>
|
||||
</Tab.Panel>
|
||||
</Tab.Panels>
|
||||
|
@ -7,7 +7,7 @@ import { Command } from "cmdk";
|
||||
// services
|
||||
import issuesService from "services/issues.service";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
import { ICurrentUserResponse, IIssue } from "types";
|
||||
// constants
|
||||
import { ISSUE_DETAILS, PROJECT_ISSUES_ACTIVITY, PROJECT_MEMBERS } from "constants/fetch-keys";
|
||||
// icons
|
||||
@ -18,9 +18,10 @@ import { Avatar } from "components/ui";
|
||||
type Props = {
|
||||
setIsPaletteOpen: Dispatch<SetStateAction<boolean>>;
|
||||
issue: IIssue;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const ChangeIssueAssignee: React.FC<Props> = ({ setIsPaletteOpen, issue }) => {
|
||||
export const ChangeIssueAssignee: React.FC<Props> = ({ setIsPaletteOpen, issue, user }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, issueId } = router.query;
|
||||
|
||||
@ -71,7 +72,7 @@ export const ChangeIssueAssignee: React.FC<Props> = ({ setIsPaletteOpen, issue }
|
||||
|
||||
const payload = { ...formData };
|
||||
await issuesService
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload)
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
|
||||
.then(() => {
|
||||
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
||||
})
|
||||
|
@ -7,7 +7,7 @@ import { Command } from "cmdk";
|
||||
// services
|
||||
import issuesService from "services/issues.service";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
import { ICurrentUserResponse, IIssue } from "types";
|
||||
// constants
|
||||
import { ISSUE_DETAILS, PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys";
|
||||
import { PRIORITIES } from "constants/project";
|
||||
@ -17,9 +17,10 @@ import { CheckIcon, getPriorityIcon } from "components/icons";
|
||||
type Props = {
|
||||
setIsPaletteOpen: Dispatch<SetStateAction<boolean>>;
|
||||
issue: IIssue;
|
||||
user: ICurrentUserResponse;
|
||||
};
|
||||
|
||||
export const ChangeIssuePriority: React.FC<Props> = ({ setIsPaletteOpen, issue }) => {
|
||||
export const ChangeIssuePriority: React.FC<Props> = ({ setIsPaletteOpen, issue, user }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, issueId } = router.query;
|
||||
|
||||
@ -42,7 +43,7 @@ export const ChangeIssuePriority: React.FC<Props> = ({ setIsPaletteOpen, issue }
|
||||
|
||||
const payload = { ...formData };
|
||||
await issuesService
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload)
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
|
||||
.then(() => {
|
||||
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
||||
})
|
||||
|
@ -12,7 +12,7 @@ import { getStatesList } from "helpers/state.helper";
|
||||
import issuesService from "services/issues.service";
|
||||
import stateService from "services/state.service";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
import { ICurrentUserResponse, IIssue } from "types";
|
||||
// fetch keys
|
||||
import { ISSUE_DETAILS, PROJECT_ISSUES_ACTIVITY, STATES_LIST } from "constants/fetch-keys";
|
||||
// icons
|
||||
@ -21,9 +21,10 @@ import { CheckIcon, getStateGroupIcon } from "components/icons";
|
||||
type Props = {
|
||||
setIsPaletteOpen: Dispatch<SetStateAction<boolean>>;
|
||||
issue: IIssue;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const ChangeIssueState: React.FC<Props> = ({ setIsPaletteOpen, issue }) => {
|
||||
export const ChangeIssueState: React.FC<Props> = ({ setIsPaletteOpen, issue, user }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, issueId } = router.query;
|
||||
|
||||
@ -53,7 +54,7 @@ export const ChangeIssueState: React.FC<Props> = ({ setIsPaletteOpen, issue }) =
|
||||
|
||||
const payload = { ...formData };
|
||||
await issuesService
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload)
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
|
||||
.then(() => {
|
||||
mutateIssueDetails();
|
||||
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
||||
|
@ -136,7 +136,7 @@ export const CommandPalette: React.FC = () => {
|
||||
|
||||
const payload = { ...formData };
|
||||
await issuesService
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload)
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
|
||||
.then(() => {
|
||||
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
||||
mutate(ISSUE_DETAILS(issueId as string));
|
||||
@ -330,25 +330,33 @@ export const CommandPalette: React.FC = () => {
|
||||
<>
|
||||
<ShortcutsModal isOpen={isShortcutsModalOpen} setIsOpen={setIsShortcutsModalOpen} />
|
||||
{workspaceSlug && (
|
||||
<CreateProjectModal isOpen={isProjectModalOpen} setIsOpen={setIsProjectModalOpen} />
|
||||
<CreateProjectModal
|
||||
isOpen={isProjectModalOpen}
|
||||
setIsOpen={setIsProjectModalOpen}
|
||||
user={user}
|
||||
/>
|
||||
)}
|
||||
{projectId && (
|
||||
<>
|
||||
<CreateUpdateCycleModal
|
||||
isOpen={isCreateCycleModalOpen}
|
||||
handleClose={() => setIsCreateCycleModalOpen(false)}
|
||||
user={user}
|
||||
/>
|
||||
<CreateUpdateModuleModal
|
||||
isOpen={isCreateModuleModalOpen}
|
||||
setIsOpen={setIsCreateModuleModalOpen}
|
||||
user={user}
|
||||
/>
|
||||
<CreateUpdateViewModal
|
||||
handleClose={() => setIsCreateViewModalOpen(false)}
|
||||
isOpen={isCreateViewModalOpen}
|
||||
user={user}
|
||||
/>
|
||||
<CreateUpdatePageModal
|
||||
isOpen={isCreateUpdatePageModalOpen}
|
||||
handleClose={() => setIsCreateUpdatePageModalOpen(false)}
|
||||
user={user}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@ -357,6 +365,7 @@ export const CommandPalette: React.FC = () => {
|
||||
handleClose={() => setDeleteIssueModal(false)}
|
||||
isOpen={deleteIssueModal}
|
||||
data={issueDetails}
|
||||
user={user}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -367,6 +376,7 @@ export const CommandPalette: React.FC = () => {
|
||||
<BulkDeleteIssuesModal
|
||||
isOpen={isBulkDeleteIssuesModalOpen}
|
||||
setIsOpen={setIsBulkDeleteIssuesModalOpen}
|
||||
user={user}
|
||||
/>
|
||||
<Transition.Root
|
||||
show={isPaletteOpen}
|
||||
@ -854,6 +864,7 @@ export const CommandPalette: React.FC = () => {
|
||||
<ChangeIssueState
|
||||
issue={issueDetails}
|
||||
setIsPaletteOpen={setIsPaletteOpen}
|
||||
user={user}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@ -861,12 +872,14 @@ export const CommandPalette: React.FC = () => {
|
||||
<ChangeIssuePriority
|
||||
issue={issueDetails}
|
||||
setIsPaletteOpen={setIsPaletteOpen}
|
||||
user={user}
|
||||
/>
|
||||
)}
|
||||
{page === "change-issue-assignee" && issueDetails && (
|
||||
<ChangeIssueAssignee
|
||||
issue={issueDetails}
|
||||
setIsPaletteOpen={setIsPaletteOpen}
|
||||
user={user}
|
||||
/>
|
||||
)}
|
||||
{page === "change-interface-theme" && (
|
||||
|
@ -5,7 +5,7 @@ import { SingleBoard } from "components/core/board-view/single-board";
|
||||
// helpers
|
||||
import { addSpaceIfCamelCase } from "helpers/string.helper";
|
||||
// types
|
||||
import { IIssue, IState, UserAuth } from "types";
|
||||
import { ICurrentUserResponse, IIssue, IState, UserAuth } from "types";
|
||||
import { getStateGroupIcon } from "components/icons";
|
||||
|
||||
type Props = {
|
||||
@ -19,6 +19,7 @@ type Props = {
|
||||
handleTrashBox: (isDragging: boolean) => void;
|
||||
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
||||
isCompleted?: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
userAuth: UserAuth;
|
||||
};
|
||||
|
||||
@ -33,6 +34,7 @@ export const AllBoards: React.FC<Props> = ({
|
||||
handleTrashBox,
|
||||
removeIssue,
|
||||
isCompleted = false,
|
||||
user,
|
||||
userAuth,
|
||||
}) => {
|
||||
const {
|
||||
@ -65,6 +67,7 @@ export const AllBoards: React.FC<Props> = ({
|
||||
handleTrashBox={handleTrashBox}
|
||||
removeIssue={removeIssue}
|
||||
isCompleted={isCompleted}
|
||||
user={user}
|
||||
userAuth={userAuth}
|
||||
/>
|
||||
);
|
||||
|
@ -17,7 +17,7 @@ import { PlusIcon } from "@heroicons/react/24/outline";
|
||||
// helpers
|
||||
import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
|
||||
// types
|
||||
import { IIssue, IState, UserAuth } from "types";
|
||||
import { ICurrentUserResponse, IIssue, IState, UserAuth } from "types";
|
||||
|
||||
type Props = {
|
||||
type?: "issue" | "cycle" | "module";
|
||||
@ -31,6 +31,7 @@ type Props = {
|
||||
handleTrashBox: (isDragging: boolean) => void;
|
||||
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
||||
isCompleted?: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
userAuth: UserAuth;
|
||||
};
|
||||
|
||||
@ -46,6 +47,7 @@ export const SingleBoard: React.FC<Props> = ({
|
||||
handleTrashBox,
|
||||
removeIssue,
|
||||
isCompleted = false,
|
||||
user,
|
||||
userAuth,
|
||||
}) => {
|
||||
// collapse/expand
|
||||
@ -129,6 +131,7 @@ export const SingleBoard: React.FC<Props> = ({
|
||||
removeIssue(issue.bridge_id, issue.id);
|
||||
}}
|
||||
isCompleted={isCompleted}
|
||||
user={user}
|
||||
userAuth={userAuth}
|
||||
/>
|
||||
)}
|
||||
|
@ -44,7 +44,7 @@ import { LayerDiagonalIcon } from "components/icons";
|
||||
import { handleIssuesMutation } from "constants/issue";
|
||||
import { copyTextToClipboard, truncateText } from "helpers/string.helper";
|
||||
// types
|
||||
import { IIssue, Properties, TIssueGroupByOptions, UserAuth } from "types";
|
||||
import { ICurrentUserResponse, IIssue, Properties, TIssueGroupByOptions, UserAuth } from "types";
|
||||
// fetch-keys
|
||||
import {
|
||||
CYCLE_DETAILS,
|
||||
@ -69,6 +69,7 @@ type Props = {
|
||||
handleDeleteIssue: (issue: IIssue) => void;
|
||||
handleTrashBox: (isDragging: boolean) => void;
|
||||
isCompleted?: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
userAuth: UserAuth;
|
||||
};
|
||||
|
||||
@ -87,6 +88,7 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
||||
handleDeleteIssue,
|
||||
handleTrashBox,
|
||||
isCompleted = false,
|
||||
user,
|
||||
userAuth,
|
||||
}) => {
|
||||
// context menu
|
||||
@ -170,7 +172,7 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
||||
}
|
||||
|
||||
issuesService
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId, formData)
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId, formData, user)
|
||||
.then(() => {
|
||||
if (cycleId) {
|
||||
mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params));
|
||||
@ -342,6 +344,7 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
isNotAllowed={isNotAllowed}
|
||||
user={user}
|
||||
selfPositioned
|
||||
/>
|
||||
)}
|
||||
@ -350,6 +353,7 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
isNotAllowed={isNotAllowed}
|
||||
user={user}
|
||||
selfPositioned
|
||||
/>
|
||||
)}
|
||||
@ -357,6 +361,7 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
||||
<ViewDueDateSelect
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
user={user}
|
||||
isNotAllowed={isNotAllowed}
|
||||
/>
|
||||
)}
|
||||
@ -384,6 +389,7 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
isNotAllowed={isNotAllowed}
|
||||
tooltipPosition="left"
|
||||
user={user}
|
||||
selfPositioned
|
||||
/>
|
||||
)}
|
||||
@ -392,6 +398,7 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
isNotAllowed={isNotAllowed}
|
||||
user={user}
|
||||
selfPositioned
|
||||
/>
|
||||
)}
|
||||
|
@ -18,7 +18,7 @@ import { DangerButton, SecondaryButton } from "components/ui";
|
||||
import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
|
||||
import { LayerDiagonalIcon } from "components/icons";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
import { ICurrentUserResponse, IIssue } from "types";
|
||||
// fetch keys
|
||||
import { PROJECT_ISSUES_LIST } from "constants/fetch-keys";
|
||||
|
||||
@ -29,9 +29,10 @@ type FormInput = {
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const BulkDeleteIssuesModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
|
||||
export const BulkDeleteIssuesModal: React.FC<Props> = ({ isOpen, setIsOpen, user }) => {
|
||||
const [query, setQuery] = useState("");
|
||||
|
||||
const router = useRouter();
|
||||
@ -91,9 +92,14 @@ export const BulkDeleteIssuesModal: React.FC<Props> = ({ isOpen, setIsOpen }) =>
|
||||
|
||||
if (workspaceSlug && projectId) {
|
||||
await issuesServices
|
||||
.bulkDeleteIssues(workspaceSlug as string, projectId as string, {
|
||||
issue_ids: data.delete_issue_ids,
|
||||
})
|
||||
.bulkDeleteIssues(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
{
|
||||
issue_ids: data.delete_issue_ids,
|
||||
},
|
||||
user
|
||||
)
|
||||
.then((res) => {
|
||||
setToastAlert({
|
||||
title: "Success",
|
||||
|
@ -24,7 +24,7 @@ import {
|
||||
formatDate,
|
||||
} from "helpers/calendar.helper";
|
||||
// types
|
||||
import { ICalendarRange, IIssue, UserAuth } from "types";
|
||||
import { ICalendarRange, ICurrentUserResponse, IIssue, UserAuth } from "types";
|
||||
// fetch-keys
|
||||
import {
|
||||
CYCLE_ISSUES_WITH_PARAMS,
|
||||
@ -38,6 +38,7 @@ type Props = {
|
||||
handleDeleteIssue: (issue: IIssue) => void;
|
||||
addIssueToDate: (date: string) => void;
|
||||
isCompleted: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
userAuth: UserAuth;
|
||||
};
|
||||
|
||||
@ -46,6 +47,7 @@ export const CalendarView: React.FC<Props> = ({
|
||||
handleDeleteIssue,
|
||||
addIssueToDate,
|
||||
isCompleted = false,
|
||||
user,
|
||||
userAuth,
|
||||
}) => {
|
||||
const [showWeekEnds, setShowWeekEnds] = useState(false);
|
||||
@ -134,9 +136,15 @@ export const CalendarView: React.FC<Props> = ({
|
||||
);
|
||||
|
||||
issuesService
|
||||
.patchIssue(workspaceSlug as string, projectId as string, draggableId, {
|
||||
target_date: destination?.droppableId,
|
||||
})
|
||||
.patchIssue(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
draggableId,
|
||||
{
|
||||
target_date: destination?.droppableId,
|
||||
},
|
||||
user
|
||||
)
|
||||
.then(() => mutate(fetchKey));
|
||||
};
|
||||
|
||||
@ -219,6 +227,7 @@ export const CalendarView: React.FC<Props> = ({
|
||||
addIssueToDate={addIssueToDate}
|
||||
isMonthlyView={isMonthlyView}
|
||||
showWeekEnds={showWeekEnds}
|
||||
user={user}
|
||||
isNotAllowed={isNotAllowed}
|
||||
/>
|
||||
))}
|
||||
|
@ -10,7 +10,7 @@ import { PlusSmallIcon } from "@heroicons/react/24/outline";
|
||||
// helper
|
||||
import { formatDate } from "helpers/calendar.helper";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
import { ICurrentUserResponse, IIssue } from "types";
|
||||
|
||||
type Props = {
|
||||
handleEditIssue: (issue: IIssue) => void;
|
||||
@ -23,6 +23,7 @@ type Props = {
|
||||
addIssueToDate: (date: string) => void;
|
||||
isMonthlyView: boolean;
|
||||
showWeekEnds: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
isNotAllowed: boolean;
|
||||
};
|
||||
|
||||
@ -34,6 +35,7 @@ export const SingleCalendarDate: React.FC<Props> = ({
|
||||
addIssueToDate,
|
||||
isMonthlyView,
|
||||
showWeekEnds,
|
||||
user,
|
||||
isNotAllowed,
|
||||
}) => {
|
||||
const [showAllIssues, setShowAllIssues] = useState(false);
|
||||
@ -72,6 +74,7 @@ export const SingleCalendarDate: React.FC<Props> = ({
|
||||
issue={issue}
|
||||
handleEditIssue={handleEditIssue}
|
||||
handleDeleteIssue={handleDeleteIssue}
|
||||
user={user}
|
||||
isNotAllowed={isNotAllowed}
|
||||
/>
|
||||
)}
|
||||
|
@ -28,7 +28,7 @@ import { LayerDiagonalIcon } from "components/icons";
|
||||
// helper
|
||||
import { copyTextToClipboard, truncateText } from "helpers/string.helper";
|
||||
// type
|
||||
import { IIssue } from "types";
|
||||
import { ICurrentUserResponse, IIssue } from "types";
|
||||
// fetch-keys
|
||||
import {
|
||||
CYCLE_ISSUES_WITH_PARAMS,
|
||||
@ -44,6 +44,7 @@ type Props = {
|
||||
provided: DraggableProvided;
|
||||
snapshot: DraggableStateSnapshot;
|
||||
issue: IIssue;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
isNotAllowed: boolean;
|
||||
};
|
||||
|
||||
@ -54,6 +55,7 @@ export const SingleCalendarIssue: React.FC<Props> = ({
|
||||
provided,
|
||||
snapshot,
|
||||
issue,
|
||||
user,
|
||||
isNotAllowed,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
@ -95,7 +97,7 @@ export const SingleCalendarIssue: React.FC<Props> = ({
|
||||
);
|
||||
|
||||
issuesService
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, formData)
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, formData, user)
|
||||
.then(() => {
|
||||
mutate(fetchKey);
|
||||
})
|
||||
@ -183,6 +185,7 @@ export const SingleCalendarIssue: React.FC<Props> = ({
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
position="left"
|
||||
user={user}
|
||||
isNotAllowed={isNotAllowed}
|
||||
/>
|
||||
)}
|
||||
@ -192,6 +195,7 @@ export const SingleCalendarIssue: React.FC<Props> = ({
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
position="left"
|
||||
isNotAllowed={isNotAllowed}
|
||||
user={user}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -199,6 +203,7 @@ export const SingleCalendarIssue: React.FC<Props> = ({
|
||||
<ViewDueDateSelect
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
user={user}
|
||||
isNotAllowed={isNotAllowed}
|
||||
/>
|
||||
)}
|
||||
@ -227,6 +232,7 @@ export const SingleCalendarIssue: React.FC<Props> = ({
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
position="left"
|
||||
user={user}
|
||||
isNotAllowed={isNotAllowed}
|
||||
/>
|
||||
)}
|
||||
@ -235,6 +241,7 @@ export const SingleCalendarIssue: React.FC<Props> = ({
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
position="left"
|
||||
user={user}
|
||||
isNotAllowed={isNotAllowed}
|
||||
/>
|
||||
)}
|
||||
|
@ -10,6 +10,7 @@ import aiService from "services/ai.service";
|
||||
import trackEventServices from "services/track-event.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// ui
|
||||
import { Input, PrimaryButton, SecondaryButton } from "components/ui";
|
||||
|
||||
@ -60,6 +61,8 @@ export const GptAssistantModal: React.FC<Props> = ({
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const editorRef = useRef<any>(null);
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
@ -97,10 +100,15 @@ export const GptAssistantModal: React.FC<Props> = ({
|
||||
}
|
||||
|
||||
await aiService
|
||||
.createGptTask(workspaceSlug as string, projectId as string, {
|
||||
prompt: content && content !== "" ? content : htmlContent ?? "",
|
||||
task: formData.task,
|
||||
})
|
||||
.createGptTask(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
{
|
||||
prompt: content && content !== "" ? content : htmlContent ?? "",
|
||||
task: formData.task,
|
||||
},
|
||||
user
|
||||
)
|
||||
.then((res) => {
|
||||
setResponse(res.response_html);
|
||||
setFocus("task");
|
||||
@ -190,10 +198,15 @@ export const GptAssistantModal: React.FC<Props> = ({
|
||||
if (block)
|
||||
trackEventServices.trackUseGPTResponseEvent(
|
||||
block,
|
||||
"USE_GPT_RESPONSE_IN_PAGE_BLOCK"
|
||||
"USE_GPT_RESPONSE_IN_PAGE_BLOCK",
|
||||
user
|
||||
);
|
||||
else if (issue)
|
||||
trackEventServices.trackUseGPTResponseEvent(issue, "USE_GPT_RESPONSE_IN_ISSUE");
|
||||
trackEventServices.trackUseGPTResponseEvent(
|
||||
issue,
|
||||
"USE_GPT_RESPONSE_IN_ISSUE",
|
||||
user
|
||||
);
|
||||
}}
|
||||
>
|
||||
Use this response
|
||||
|
@ -17,6 +17,7 @@ import { useProjectMyMembership } from "contexts/project-member.context";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useIssuesView from "hooks/use-issues-view";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// components
|
||||
import { AllLists, AllBoards, FilterList, CalendarView, GanttChartView } from "components/core";
|
||||
import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
|
||||
@ -89,6 +90,8 @@ export const IssuesView: React.FC<Props> = ({
|
||||
|
||||
const { memberRole } = useProjectMyMembership();
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const {
|
||||
@ -220,11 +223,17 @@ export const IssuesView: React.FC<Props> = ({
|
||||
|
||||
// patch request
|
||||
issuesService
|
||||
.patchIssue(workspaceSlug as string, projectId as string, draggedItem.id, {
|
||||
priority: draggedItem.priority,
|
||||
state: draggedItem.state,
|
||||
sort_order: draggedItem.sort_order,
|
||||
})
|
||||
.patchIssue(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
draggedItem.id,
|
||||
{
|
||||
priority: draggedItem.priority,
|
||||
state: draggedItem.state,
|
||||
sort_order: draggedItem.sort_order,
|
||||
},
|
||||
user
|
||||
)
|
||||
.then((response) => {
|
||||
const sourceStateBeforeDrag = states.find((state) => state.name === source.droppableId);
|
||||
|
||||
@ -232,14 +241,17 @@ export const IssuesView: React.FC<Props> = ({
|
||||
sourceStateBeforeDrag?.group !== "completed" &&
|
||||
response?.state_detail?.group === "completed"
|
||||
)
|
||||
trackEventServices.trackIssueMarkedAsDoneEvent({
|
||||
workspaceSlug,
|
||||
workspaceId: draggedItem.workspace,
|
||||
projectName: draggedItem.project_detail.name,
|
||||
projectIdentifier: draggedItem.project_detail.identifier,
|
||||
projectId,
|
||||
issueId: draggedItem.id,
|
||||
});
|
||||
trackEventServices.trackIssueMarkedAsDoneEvent(
|
||||
{
|
||||
workspaceSlug,
|
||||
workspaceId: draggedItem.workspace,
|
||||
projectName: draggedItem.project_detail.name,
|
||||
projectIdentifier: draggedItem.project_detail.identifier,
|
||||
projectId,
|
||||
issueId: draggedItem.id,
|
||||
},
|
||||
user
|
||||
);
|
||||
|
||||
if (cycleId) {
|
||||
mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params));
|
||||
@ -419,6 +431,7 @@ export const IssuesView: React.FC<Props> = ({
|
||||
isOpen={createViewModal !== null}
|
||||
handleClose={() => setCreateViewModal(null)}
|
||||
preLoadedData={createViewModal}
|
||||
user={user}
|
||||
/>
|
||||
<CreateUpdateIssueModal
|
||||
isOpen={createIssueModal && preloadedData?.actionType === "createIssue"}
|
||||
@ -437,6 +450,7 @@ export const IssuesView: React.FC<Props> = ({
|
||||
handleClose={() => setDeleteIssueModal(false)}
|
||||
isOpen={deleteIssueModal}
|
||||
data={issueToDelete}
|
||||
user={user}
|
||||
/>
|
||||
<TransferIssuesModal
|
||||
handleClose={() => setTransferIssuesModal(false)}
|
||||
@ -508,6 +522,7 @@ export const IssuesView: React.FC<Props> = ({
|
||||
: null
|
||||
}
|
||||
isCompleted={isCompleted}
|
||||
user={user}
|
||||
userAuth={memberRole}
|
||||
/>
|
||||
) : issueView === "kanban" ? (
|
||||
@ -528,6 +543,7 @@ export const IssuesView: React.FC<Props> = ({
|
||||
: null
|
||||
}
|
||||
isCompleted={isCompleted}
|
||||
user={user}
|
||||
userAuth={memberRole}
|
||||
/>
|
||||
) : issueView === "calendar" ? (
|
||||
@ -536,6 +552,7 @@ export const IssuesView: React.FC<Props> = ({
|
||||
handleDeleteIssue={handleDeleteIssue}
|
||||
addIssueToDate={addIssueToDate}
|
||||
isCompleted={isCompleted}
|
||||
user={user}
|
||||
userAuth={memberRole}
|
||||
/>
|
||||
) : (
|
||||
|
@ -3,7 +3,7 @@ import useIssuesView from "hooks/use-issues-view";
|
||||
// components
|
||||
import { SingleList } from "components/core/list-view/single-list";
|
||||
// types
|
||||
import { IIssue, IState, UserAuth } from "types";
|
||||
import { ICurrentUserResponse, IIssue, IState, UserAuth } from "types";
|
||||
|
||||
// types
|
||||
type Props = {
|
||||
@ -16,6 +16,7 @@ type Props = {
|
||||
openIssuesListModal?: (() => void) | null;
|
||||
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
||||
isCompleted?: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
userAuth: UserAuth;
|
||||
};
|
||||
|
||||
@ -29,6 +30,7 @@ export const AllLists: React.FC<Props> = ({
|
||||
handleDeleteIssue,
|
||||
removeIssue,
|
||||
isCompleted = false,
|
||||
user,
|
||||
userAuth,
|
||||
}) => {
|
||||
const { groupedByIssues, groupByProperty: selectedGroup, showEmptyGroups } = useIssuesView();
|
||||
@ -58,6 +60,7 @@ export const AllLists: React.FC<Props> = ({
|
||||
openIssuesListModal={type !== "issue" ? openIssuesListModal : null}
|
||||
removeIssue={removeIssue}
|
||||
isCompleted={isCompleted}
|
||||
user={user}
|
||||
userAuth={userAuth}
|
||||
/>
|
||||
);
|
||||
|
@ -36,7 +36,7 @@ import { LayerDiagonalIcon } from "components/icons";
|
||||
import { copyTextToClipboard, truncateText } from "helpers/string.helper";
|
||||
import { handleIssuesMutation } from "constants/issue";
|
||||
// types
|
||||
import { IIssue, Properties, UserAuth } from "types";
|
||||
import { ICurrentUserResponse, IIssue, Properties, UserAuth } from "types";
|
||||
// fetch-keys
|
||||
import {
|
||||
CYCLE_DETAILS,
|
||||
@ -57,6 +57,7 @@ type Props = {
|
||||
removeIssue?: (() => void) | null;
|
||||
handleDeleteIssue: (issue: IIssue) => void;
|
||||
isCompleted?: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
userAuth: UserAuth;
|
||||
};
|
||||
|
||||
@ -71,6 +72,7 @@ export const SingleListIssue: React.FC<Props> = ({
|
||||
groupTitle,
|
||||
handleDeleteIssue,
|
||||
isCompleted = false,
|
||||
user,
|
||||
userAuth,
|
||||
}) => {
|
||||
// context menu
|
||||
@ -141,7 +143,7 @@ export const SingleListIssue: React.FC<Props> = ({
|
||||
);
|
||||
|
||||
issuesService
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId, formData)
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId, formData, user)
|
||||
.then(() => {
|
||||
if (cycleId) {
|
||||
mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params));
|
||||
@ -241,6 +243,7 @@ export const SingleListIssue: React.FC<Props> = ({
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
position="right"
|
||||
user={user}
|
||||
isNotAllowed={isNotAllowed}
|
||||
/>
|
||||
)}
|
||||
@ -249,6 +252,7 @@ export const SingleListIssue: React.FC<Props> = ({
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
position="right"
|
||||
user={user}
|
||||
isNotAllowed={isNotAllowed}
|
||||
/>
|
||||
)}
|
||||
@ -256,6 +260,7 @@ export const SingleListIssue: React.FC<Props> = ({
|
||||
<ViewDueDateSelect
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
user={user}
|
||||
isNotAllowed={isNotAllowed}
|
||||
/>
|
||||
)}
|
||||
@ -284,6 +289,7 @@ export const SingleListIssue: React.FC<Props> = ({
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
position="right"
|
||||
user={user}
|
||||
isNotAllowed={isNotAllowed}
|
||||
/>
|
||||
)}
|
||||
@ -292,6 +298,7 @@ export const SingleListIssue: React.FC<Props> = ({
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
position="right"
|
||||
user={user}
|
||||
isNotAllowed={isNotAllowed}
|
||||
/>
|
||||
)}
|
||||
|
@ -19,7 +19,14 @@ import { getPriorityIcon, getStateGroupIcon } from "components/icons";
|
||||
// helpers
|
||||
import { addSpaceIfCamelCase } from "helpers/string.helper";
|
||||
// types
|
||||
import { IIssue, IIssueLabels, IState, TIssueGroupByOptions, UserAuth } from "types";
|
||||
import {
|
||||
ICurrentUserResponse,
|
||||
IIssue,
|
||||
IIssueLabels,
|
||||
IState,
|
||||
TIssueGroupByOptions,
|
||||
UserAuth,
|
||||
} from "types";
|
||||
// fetch-keys
|
||||
import { PROJECT_ISSUE_LABELS, PROJECT_MEMBERS } from "constants/fetch-keys";
|
||||
|
||||
@ -39,6 +46,7 @@ type Props = {
|
||||
openIssuesListModal?: (() => void) | null;
|
||||
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
||||
isCompleted?: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
userAuth: UserAuth;
|
||||
};
|
||||
|
||||
@ -56,6 +64,7 @@ export const SingleList: React.FC<Props> = ({
|
||||
openIssuesListModal,
|
||||
removeIssue,
|
||||
isCompleted = false,
|
||||
user,
|
||||
userAuth,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
@ -208,6 +217,7 @@ export const SingleList: React.FC<Props> = ({
|
||||
removeIssue(issue.bridge_id, issue.id);
|
||||
}}
|
||||
isCompleted={isCompleted}
|
||||
user={user}
|
||||
userAuth={userAuth}
|
||||
/>
|
||||
))
|
||||
|
@ -8,6 +8,7 @@ import { mutate } from "swr";
|
||||
import cyclesService from "services/cycles.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// components
|
||||
import {
|
||||
CreateUpdateCycleModal,
|
||||
@ -48,6 +49,7 @@ export const CyclesView: React.FC<Props> = ({ cycles, viewType }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleEditCycle = (cycle: ICycle) => {
|
||||
@ -158,11 +160,13 @@ export const CyclesView: React.FC<Props> = ({ cycles, viewType }) => {
|
||||
isOpen={createUpdateCycleModal}
|
||||
handleClose={() => setCreateUpdateCycleModal(false)}
|
||||
data={selectedCycleToUpdate}
|
||||
user={user}
|
||||
/>
|
||||
<DeleteCycleModal
|
||||
isOpen={deleteCycleModal}
|
||||
setIsOpen={setDeleteCycleModal}
|
||||
data={selectedCycleToDelete}
|
||||
user={user}
|
||||
/>
|
||||
{cycles ? (
|
||||
cycles.length > 0 ? (
|
||||
|
@ -14,11 +14,12 @@ import { DangerButton, SecondaryButton } from "components/ui";
|
||||
// icons
|
||||
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
||||
// types
|
||||
import type { ICycle } from "types";
|
||||
import type { ICurrentUserResponse, ICycle } from "types";
|
||||
type TConfirmCycleDeletionProps = {
|
||||
isOpen: boolean;
|
||||
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
data?: ICycle | null;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
// fetch-keys
|
||||
import {
|
||||
@ -34,6 +35,7 @@ export const DeleteCycleModal: React.FC<TConfirmCycleDeletionProps> = ({
|
||||
isOpen,
|
||||
setIsOpen,
|
||||
data,
|
||||
user,
|
||||
}) => {
|
||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||
|
||||
@ -53,7 +55,7 @@ export const DeleteCycleModal: React.FC<TConfirmCycleDeletionProps> = ({
|
||||
setIsDeleteLoading(true);
|
||||
|
||||
await cycleService
|
||||
.deleteCycle(workspaceSlug as string, data.project, data.id)
|
||||
.deleteCycle(workspaceSlug as string, data.project, data.id, user)
|
||||
.then(() => {
|
||||
const cycleType = getDateRangeStatus(data.start_date, data.end_date);
|
||||
const fetchKey =
|
||||
|
@ -15,7 +15,7 @@ import { CycleForm } from "components/cycles";
|
||||
// helper
|
||||
import { getDateRangeStatus, isDateGreaterThanToday } from "helpers/date-time.helper";
|
||||
// types
|
||||
import type { ICycle } from "types";
|
||||
import type { ICurrentUserResponse, ICycle } from "types";
|
||||
// fetch keys
|
||||
import {
|
||||
COMPLETED_CYCLES_LIST,
|
||||
@ -30,12 +30,14 @@ type CycleModalProps = {
|
||||
isOpen: boolean;
|
||||
handleClose: () => void;
|
||||
data?: ICycle | null;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
|
||||
isOpen,
|
||||
handleClose,
|
||||
data,
|
||||
user,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
@ -46,7 +48,7 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
await cycleService
|
||||
.createCycle(workspaceSlug.toString(), projectId.toString(), payload)
|
||||
.createCycle(workspaceSlug.toString(), projectId.toString(), payload, user)
|
||||
.then((res) => {
|
||||
switch (getDateRangeStatus(res.start_date, res.end_date)) {
|
||||
case "completed":
|
||||
@ -84,7 +86,7 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
await cycleService
|
||||
.updateCycle(workspaceSlug.toString(), projectId.toString(), cycleId, payload)
|
||||
.updateCycle(workspaceSlug.toString(), projectId.toString(), cycleId, payload, user)
|
||||
.then((res) => {
|
||||
switch (getDateRangeStatus(data?.start_date, data?.end_date)) {
|
||||
case "completed":
|
||||
|
@ -4,6 +4,7 @@ import { useRouter } from "next/router";
|
||||
|
||||
import useSWR from "swr";
|
||||
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// headless ui
|
||||
import { Listbox, Transition } from "@headlessui/react";
|
||||
// icons
|
||||
@ -35,6 +36,8 @@ export const CycleSelect: React.FC<IssueCycleSelectProps> = ({
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { data: cycles } = useSWR(
|
||||
workspaceSlug && projectId ? CYCLES_LIST(projectId) : null,
|
||||
workspaceSlug && projectId
|
||||
@ -54,7 +57,11 @@ export const CycleSelect: React.FC<IssueCycleSelectProps> = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<CreateUpdateCycleModal isOpen={isCycleModalActive} handleClose={closeCycleModal} />
|
||||
<CreateUpdateCycleModal
|
||||
isOpen={isCycleModalActive}
|
||||
handleClose={closeCycleModal}
|
||||
user={user}
|
||||
/>
|
||||
<Listbox as="div" className="relative" value={value} onChange={onChange} multiple={multiple}>
|
||||
{({ open }) => (
|
||||
<>
|
||||
|
@ -39,7 +39,7 @@ import {
|
||||
renderShortDate,
|
||||
} from "helpers/date-time.helper";
|
||||
// types
|
||||
import { ICycle, IIssue } from "types";
|
||||
import { ICurrentUserResponse, ICycle, IIssue } from "types";
|
||||
// fetch-keys
|
||||
import { CYCLE_DETAILS, CYCLE_ISSUES } from "constants/fetch-keys";
|
||||
|
||||
@ -48,6 +48,7 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
cycleStatus: string;
|
||||
isCompleted: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const CycleDetailsSidebar: React.FC<Props> = ({
|
||||
@ -55,6 +56,7 @@ export const CycleDetailsSidebar: React.FC<Props> = ({
|
||||
isOpen,
|
||||
cycleStatus,
|
||||
isCompleted,
|
||||
user,
|
||||
}) => {
|
||||
const [cycleDeleteModal, setCycleDeleteModal] = useState(false);
|
||||
|
||||
@ -94,7 +96,7 @@ export const CycleDetailsSidebar: React.FC<Props> = ({
|
||||
);
|
||||
|
||||
cyclesService
|
||||
.patchCycle(workspaceSlug as string, projectId as string, cycleId as string, data)
|
||||
.patchCycle(workspaceSlug as string, projectId as string, cycleId as string, data, user)
|
||||
.then(() => mutate(CYCLE_DETAILS(cycleId as string)))
|
||||
.catch((e) => console.log(e));
|
||||
};
|
||||
@ -294,7 +296,12 @@ export const CycleDetailsSidebar: React.FC<Props> = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<DeleteCycleModal isOpen={cycleDeleteModal} setIsOpen={setCycleDeleteModal} data={cycle} />
|
||||
<DeleteCycleModal
|
||||
isOpen={cycleDeleteModal}
|
||||
setIsOpen={setCycleDeleteModal}
|
||||
data={cycle}
|
||||
user={user}
|
||||
/>
|
||||
<div
|
||||
className={`fixed top-[66px] ${
|
||||
isOpen ? "right-0" : "-right-[24rem]"
|
||||
|
@ -17,7 +17,7 @@ import { Input, PrimaryButton, SecondaryButton, TextArea } from "components/ui";
|
||||
// helpers
|
||||
import { checkDuplicates } from "helpers/array.helper";
|
||||
// types
|
||||
import { IEstimate, IEstimateFormData } from "types";
|
||||
import { ICurrentUserResponse, IEstimate, IEstimateFormData } from "types";
|
||||
// fetch-keys
|
||||
import { ESTIMATES_LIST, ESTIMATE_DETAILS } from "constants/fetch-keys";
|
||||
|
||||
@ -25,6 +25,7 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
handleClose: () => void;
|
||||
data?: IEstimate;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
type FormValues = {
|
||||
@ -49,7 +50,7 @@ const defaultValues: Partial<FormValues> = {
|
||||
value6: "",
|
||||
};
|
||||
|
||||
export const CreateUpdateEstimateModal: React.FC<Props> = ({ handleClose, data, isOpen }) => {
|
||||
export const CreateUpdateEstimateModal: React.FC<Props> = ({ handleClose, data, isOpen, user }) => {
|
||||
const {
|
||||
register,
|
||||
formState: { isSubmitting },
|
||||
@ -73,7 +74,7 @@ export const CreateUpdateEstimateModal: React.FC<Props> = ({ handleClose, data,
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
await estimatesService
|
||||
.createEstimate(workspaceSlug as string, projectId as string, payload)
|
||||
.createEstimate(workspaceSlug as string, projectId as string, payload, user)
|
||||
.then(() => {
|
||||
mutate(ESTIMATES_LIST(projectId as string));
|
||||
onClose();
|
||||
@ -118,7 +119,13 @@ export const CreateUpdateEstimateModal: React.FC<Props> = ({ handleClose, data,
|
||||
);
|
||||
|
||||
await estimatesService
|
||||
.patchEstimate(workspaceSlug as string, projectId as string, data?.id as string, payload)
|
||||
.patchEstimate(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
data?.id as string,
|
||||
payload,
|
||||
user
|
||||
)
|
||||
.then(() => {
|
||||
mutate(ESTIMATES_LIST(projectId.toString()));
|
||||
mutate(ESTIMATE_DETAILS(data.id));
|
||||
|
@ -16,15 +16,17 @@ import { PencilIcon, TrashIcon } from "@heroicons/react/24/outline";
|
||||
// helpers
|
||||
import { orderArrayBy } from "helpers/array.helper";
|
||||
// types
|
||||
import { IEstimate } from "types";
|
||||
import { ICurrentUserResponse, IEstimate } from "types";
|
||||
|
||||
type Props = {
|
||||
user: ICurrentUserResponse | undefined;
|
||||
estimate: IEstimate;
|
||||
editEstimate: (estimate: IEstimate) => void;
|
||||
handleEstimateDelete: (estimateId: string) => void;
|
||||
};
|
||||
|
||||
export const SingleEstimate: React.FC<Props> = ({
|
||||
user,
|
||||
estimate,
|
||||
editEstimate,
|
||||
handleEstimateDelete,
|
||||
@ -52,7 +54,7 @@ export const SingleEstimate: React.FC<Props> = ({
|
||||
}, false);
|
||||
|
||||
await projectService
|
||||
.updateProject(workspaceSlug as string, projectId as string, payload)
|
||||
.updateProject(workspaceSlug as string, projectId as string, payload, user)
|
||||
.catch(() => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
|
@ -15,7 +15,7 @@ import { DangerButton, Input, SecondaryButton } from "components/ui";
|
||||
// icons
|
||||
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
||||
// types
|
||||
import { IImporterService } from "types";
|
||||
import { ICurrentUserResponse, IImporterService } from "types";
|
||||
// fetch-keys
|
||||
import { IMPORTER_SERVICES_LIST } from "constants/fetch-keys";
|
||||
|
||||
@ -23,9 +23,10 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
handleClose: () => void;
|
||||
data: IImporterService | null;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const DeleteImportModal: React.FC<Props> = ({ isOpen, handleClose, data }) => {
|
||||
export const DeleteImportModal: React.FC<Props> = ({ isOpen, handleClose, data, user }) => {
|
||||
const [deleteLoading, setDeleteLoading] = useState(false);
|
||||
const [confirmDeleteImport, setConfirmDeleteImport] = useState(false);
|
||||
|
||||
@ -45,7 +46,7 @@ export const DeleteImportModal: React.FC<Props> = ({ isOpen, handleClose, data }
|
||||
false
|
||||
);
|
||||
|
||||
IntegrationService.deleteImporterService(workspaceSlug as string, data.service, data.id)
|
||||
IntegrationService.deleteImporterService(workspaceSlug as string, data.service, data.id, user)
|
||||
.catch(() =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
|
@ -27,7 +27,7 @@ import { ArrowLeftIcon, ListBulletIcon } from "@heroicons/react/24/outline";
|
||||
// images
|
||||
import GithubLogo from "public/services/github.png";
|
||||
// types
|
||||
import { IGithubRepoCollaborator, IGithubServiceImportFormData } from "types";
|
||||
import { ICurrentUserResponse, IGithubRepoCollaborator, IGithubServiceImportFormData } from "types";
|
||||
// fetch-keys
|
||||
import {
|
||||
APP_INTEGRATIONS,
|
||||
@ -89,7 +89,11 @@ const integrationWorkflowData = [
|
||||
},
|
||||
];
|
||||
|
||||
export const GithubImporterRoot = () => {
|
||||
type Props = {
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const GithubImporterRoot: React.FC<Props> = ({ user }) => {
|
||||
const [currentStep, setCurrentStep] = useState<IIntegrationData>({
|
||||
state: "import-configure",
|
||||
});
|
||||
@ -157,7 +161,7 @@ export const GithubImporterRoot = () => {
|
||||
project_id: formData.project,
|
||||
};
|
||||
|
||||
await GithubIntegrationService.createGithubServiceImport(workspaceSlug as string, payload)
|
||||
await GithubIntegrationService.createGithubServiceImport(workspaceSlug as string, payload, user)
|
||||
.then(() => {
|
||||
router.push(`/${workspaceSlug}/settings/import-export`);
|
||||
mutate(IMPORTER_SERVICES_LIST(workspaceSlug as string));
|
||||
|
@ -6,6 +6,8 @@ import { useRouter } from "next/router";
|
||||
|
||||
import useSWR, { mutate } from "swr";
|
||||
|
||||
// hooks
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// services
|
||||
import IntegrationService from "services/integration";
|
||||
// components
|
||||
@ -35,6 +37,8 @@ const IntegrationGuide = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, provider } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { data: importerServices } = useSWR(
|
||||
workspaceSlug ? IMPORTER_SERVICES_LIST(workspaceSlug as string) : null,
|
||||
workspaceSlug ? () => IntegrationService.getImporterServicesList(workspaceSlug as string) : null
|
||||
@ -51,6 +55,7 @@ const IntegrationGuide = () => {
|
||||
isOpen={deleteImportModal}
|
||||
handleClose={() => setDeleteImportModal(false)}
|
||||
data={importToDelete}
|
||||
user={user}
|
||||
/>
|
||||
<div className="h-full space-y-2">
|
||||
{!provider && (
|
||||
@ -156,8 +161,8 @@ const IntegrationGuide = () => {
|
||||
</>
|
||||
)}
|
||||
|
||||
{provider && provider === "github" && <GithubImporterRoot />}
|
||||
{provider && provider === "jira" && <JiraImporterRoot />}
|
||||
{provider && provider === "github" && <GithubImporterRoot user={user} />}
|
||||
{provider && provider === "jira" && <JiraImporterRoot user={user} />}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -35,7 +35,7 @@ import {
|
||||
|
||||
import JiraLogo from "public/services/jira.png";
|
||||
|
||||
import { IJiraImporterForm } from "types";
|
||||
import { ICurrentUserResponse, IJiraImporterForm } from "types";
|
||||
|
||||
const integrationWorkflowData: Array<{
|
||||
title: string;
|
||||
@ -64,7 +64,11 @@ const integrationWorkflowData: Array<{
|
||||
},
|
||||
];
|
||||
|
||||
export const JiraImporterRoot = () => {
|
||||
type Props = {
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const JiraImporterRoot: React.FC<Props> = ({ user }) => {
|
||||
const [currentStep, setCurrentStep] = useState<IJiraIntegrationData>({
|
||||
state: "import-configure",
|
||||
});
|
||||
@ -85,7 +89,7 @@ export const JiraImporterRoot = () => {
|
||||
if (!workspaceSlug) return;
|
||||
|
||||
await jiraImporterService
|
||||
.createJiraImporter(workspaceSlug.toString(), data)
|
||||
.createJiraImporter(workspaceSlug.toString(), data, user)
|
||||
.then(() => {
|
||||
mutate(IMPORTER_SERVICES_LIST(workspaceSlug.toString()));
|
||||
router.push(`/${workspaceSlug}/settings/import-export`);
|
||||
|
@ -27,7 +27,7 @@ import { Loader } from "components/ui";
|
||||
import { renderShortNumericDateFormat, timeAgo } from "helpers/date-time.helper";
|
||||
import { addSpaceIfCamelCase } from "helpers/string.helper";
|
||||
// types
|
||||
import { IIssueComment, IIssueLabels } from "types";
|
||||
import { ICurrentUserResponse, IIssueComment, IIssueLabels } from "types";
|
||||
import { PROJECT_ISSUES_ACTIVITY, PROJECT_ISSUE_LABELS } from "constants/fetch-keys";
|
||||
import useEstimateOption from "hooks/use-estimate-option";
|
||||
|
||||
@ -110,7 +110,11 @@ const activityDetails: {
|
||||
},
|
||||
};
|
||||
|
||||
export const IssueActivitySection: React.FC = () => {
|
||||
type Props = {
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const IssueActivitySection: React.FC<Props> = ({ user }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, issueId } = router.query;
|
||||
|
||||
@ -143,7 +147,8 @@ export const IssueActivitySection: React.FC = () => {
|
||||
projectId as string,
|
||||
issueId as string,
|
||||
comment.id,
|
||||
comment
|
||||
comment,
|
||||
user
|
||||
)
|
||||
.then((res) => {
|
||||
mutateIssueActivities();
|
||||
@ -160,7 +165,8 @@ export const IssueActivitySection: React.FC = () => {
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
issueId as string,
|
||||
commentId
|
||||
commentId,
|
||||
user
|
||||
)
|
||||
.then(() => mutateIssueActivities());
|
||||
};
|
||||
|
@ -14,7 +14,7 @@ import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Loader, SecondaryButton } from "components/ui";
|
||||
// types
|
||||
import type { IIssueComment } from "types";
|
||||
import type { ICurrentUserResponse, IIssueComment } from "types";
|
||||
// fetch-keys
|
||||
import { PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys";
|
||||
|
||||
@ -40,7 +40,11 @@ const defaultValues: Partial<IIssueComment> = {
|
||||
comment_html: "",
|
||||
};
|
||||
|
||||
export const AddComment: React.FC = () => {
|
||||
type Props = {
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const AddComment: React.FC<Props> = ({ user }) => {
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
@ -67,7 +71,13 @@ export const AddComment: React.FC = () => {
|
||||
)
|
||||
return;
|
||||
await issuesServices
|
||||
.createIssueComment(workspaceSlug as string, projectId as string, issueId as string, formData)
|
||||
.createIssueComment(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
issueId as string,
|
||||
formData,
|
||||
user
|
||||
)
|
||||
.then(() => {
|
||||
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
||||
reset(defaultValues);
|
||||
|
@ -17,7 +17,7 @@ import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
||||
// ui
|
||||
import { SecondaryButton, DangerButton } from "components/ui";
|
||||
// types
|
||||
import type { IIssue } from "types";
|
||||
import type { ICurrentUserResponse, IIssue } from "types";
|
||||
// fetch-keys
|
||||
import {
|
||||
CYCLE_ISSUES_WITH_PARAMS,
|
||||
@ -30,9 +30,10 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
handleClose: () => void;
|
||||
data: IIssue | null;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const DeleteIssueModal: React.FC<Props> = ({ isOpen, handleClose, data }) => {
|
||||
export const DeleteIssueModal: React.FC<Props> = ({ isOpen, handleClose, data, user }) => {
|
||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
@ -57,7 +58,7 @@ export const DeleteIssueModal: React.FC<Props> = ({ isOpen, handleClose, data })
|
||||
if (!workspaceSlug || !projectId || !data) return;
|
||||
|
||||
await issueServices
|
||||
.deleteIssue(workspaceSlug as string, projectId as string, data.id)
|
||||
.deleteIssue(workspaceSlug as string, projectId as string, data.id, user)
|
||||
.then(() => {
|
||||
if (issueView === "calendar") {
|
||||
const calendarFetchKey = cycleId
|
||||
|
@ -39,7 +39,7 @@ import { SparklesIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
||||
// helpers
|
||||
import { cosineSimilarity } from "helpers/string.helper";
|
||||
// types
|
||||
import type { IIssue } from "types";
|
||||
import type { ICurrentUserResponse, IIssue } from "types";
|
||||
// rich-text-editor
|
||||
const RemirrorRichTextEditor = dynamic(() => import("components/rich-text-editor"), {
|
||||
ssr: false,
|
||||
@ -91,6 +91,7 @@ export interface IssueFormProps {
|
||||
setCreateMore: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
handleClose: () => void;
|
||||
status: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
}
|
||||
|
||||
export const IssueForm: FC<IssueFormProps> = ({
|
||||
@ -103,6 +104,7 @@ export const IssueForm: FC<IssueFormProps> = ({
|
||||
setCreateMore,
|
||||
handleClose,
|
||||
status,
|
||||
user,
|
||||
}) => {
|
||||
// states
|
||||
const [mostSimilarIssue, setMostSimilarIssue] = useState<IIssue | undefined>();
|
||||
@ -177,10 +179,15 @@ export const IssueForm: FC<IssueFormProps> = ({
|
||||
setIAmFeelingLucky(true);
|
||||
|
||||
aiService
|
||||
.createGptTask(workspaceSlug as string, projectId as string, {
|
||||
prompt: issueName,
|
||||
task: "Generate a proper description for this issue in context of a project management software.",
|
||||
})
|
||||
.createGptTask(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
{
|
||||
prompt: issueName,
|
||||
task: "Generate a proper description for this issue in context of a project management software.",
|
||||
},
|
||||
user
|
||||
)
|
||||
.then((res) => {
|
||||
if (res.response === "")
|
||||
setToastAlert({
|
||||
@ -227,12 +234,18 @@ export const IssueForm: FC<IssueFormProps> = ({
|
||||
isOpen={stateModal}
|
||||
handleClose={() => setStateModal(false)}
|
||||
projectId={projectId}
|
||||
user={user}
|
||||
/>
|
||||
<CreateUpdateCycleModal
|
||||
isOpen={cycleModal}
|
||||
handleClose={() => setCycleModal(false)}
|
||||
user={user}
|
||||
/>
|
||||
<CreateUpdateCycleModal isOpen={cycleModal} handleClose={() => setCycleModal(false)} />
|
||||
<CreateLabelModal
|
||||
isOpen={labelModal}
|
||||
handleClose={() => setLabelModal(false)}
|
||||
projectId={projectId}
|
||||
user={user}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
@ -102,9 +102,15 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
await issuesService
|
||||
.addIssueToCycle(workspaceSlug as string, activeProject ?? "", cycleId, {
|
||||
issues: [issueId],
|
||||
})
|
||||
.addIssueToCycle(
|
||||
workspaceSlug as string,
|
||||
activeProject ?? "",
|
||||
cycleId,
|
||||
{
|
||||
issues: [issueId],
|
||||
},
|
||||
user
|
||||
)
|
||||
.then(() => {
|
||||
if (cycleId) {
|
||||
mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId, params));
|
||||
@ -117,9 +123,15 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
await modulesService
|
||||
.addIssuesToModule(workspaceSlug as string, activeProject ?? "", moduleId as string, {
|
||||
issues: [issueId],
|
||||
})
|
||||
.addIssuesToModule(
|
||||
workspaceSlug as string,
|
||||
activeProject ?? "",
|
||||
moduleId as string,
|
||||
{
|
||||
issues: [issueId],
|
||||
},
|
||||
user
|
||||
)
|
||||
.then(() => {
|
||||
if (moduleId) {
|
||||
mutate(MODULE_ISSUES_WITH_PARAMS(moduleId as string, params));
|
||||
@ -148,7 +160,7 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
|
||||
if (!workspaceSlug) return;
|
||||
|
||||
await issuesService
|
||||
.createIssues(workspaceSlug as string, activeProject ?? "", payload)
|
||||
.createIssues(workspaceSlug as string, activeProject ?? "", payload, user)
|
||||
.then(async (res) => {
|
||||
mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(activeProject ?? "", params));
|
||||
if (payload.cycle && payload.cycle !== "") await addIssueToCycle(res.id, payload.cycle);
|
||||
@ -180,7 +192,7 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
|
||||
|
||||
const updateIssue = async (payload: Partial<IIssue>) => {
|
||||
await issuesService
|
||||
.updateIssue(workspaceSlug as string, activeProject ?? "", data?.id ?? "", payload)
|
||||
.updateIssue(workspaceSlug as string, activeProject ?? "", data?.id ?? "", payload, user)
|
||||
.then((res) => {
|
||||
if (isUpdatingSingleIssue) {
|
||||
mutate<IIssue>(PROJECT_ISSUES_DETAILS, (prevData) => ({ ...prevData, ...res }), false);
|
||||
@ -261,6 +273,7 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
|
||||
projectId={activeProject ?? ""}
|
||||
setActiveProject={setActiveProject}
|
||||
status={data ? true : false}
|
||||
user={user}
|
||||
/>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
|
@ -7,6 +7,7 @@ import { mutate } from "swr";
|
||||
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// services
|
||||
import issuesService from "services/issues.service";
|
||||
// components
|
||||
@ -37,6 +38,9 @@ type Props = {
|
||||
export const MyIssuesListItem: React.FC<Props> = ({ issue, properties, projectId }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const partialUpdateIssue = useCallback(
|
||||
@ -55,7 +59,7 @@ export const MyIssuesListItem: React.FC<Props> = ({ issue, properties, projectId
|
||||
);
|
||||
|
||||
issuesService
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId, formData)
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId, formData, user)
|
||||
.then((res) => {
|
||||
mutate(USER_ISSUE(workspaceSlug as string));
|
||||
})
|
||||
@ -110,6 +114,7 @@ export const MyIssuesListItem: React.FC<Props> = ({ issue, properties, projectId
|
||||
<ViewPrioritySelect
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
user={user}
|
||||
isNotAllowed={isNotAllowed}
|
||||
/>
|
||||
)}
|
||||
@ -117,6 +122,7 @@ export const MyIssuesListItem: React.FC<Props> = ({ issue, properties, projectId
|
||||
<ViewStateSelect
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
user={user}
|
||||
isNotAllowed={isNotAllowed}
|
||||
/>
|
||||
)}
|
||||
@ -124,6 +130,7 @@ export const MyIssuesListItem: React.FC<Props> = ({ issue, properties, projectId
|
||||
<ViewDueDateSelect
|
||||
issue={issue}
|
||||
partialUpdateIssue={partialUpdateIssue}
|
||||
user={user}
|
||||
isNotAllowed={isNotAllowed}
|
||||
/>
|
||||
)}
|
||||
|
@ -12,6 +12,7 @@ import { TwitterPicker } from "react-color";
|
||||
import { Popover, Listbox, Transition } from "@headlessui/react";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// services
|
||||
import issuesService from "services/issues.service";
|
||||
import modulesService from "services/modules.service";
|
||||
@ -76,6 +77,8 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, issueId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { memberRole } = useProjectMyMembership();
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
@ -110,7 +113,7 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
|
||||
const handleNewLabel = (formData: any) => {
|
||||
if (!workspaceSlug || !projectId || isSubmitting) return;
|
||||
issuesService
|
||||
.createIssueLabel(workspaceSlug as string, projectId as string, formData)
|
||||
.createIssueLabel(workspaceSlug as string, projectId as string, formData, user)
|
||||
.then((res) => {
|
||||
reset(defaultValues);
|
||||
issueLabelMutate((prevData) => [...(prevData ?? []), res], false);
|
||||
@ -124,9 +127,15 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
|
||||
if (!workspaceSlug || !projectId || !issueDetail) return;
|
||||
|
||||
issuesService
|
||||
.addIssueToCycle(workspaceSlug as string, projectId as string, cycleDetails.id, {
|
||||
issues: [issueDetail.id],
|
||||
})
|
||||
.addIssueToCycle(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
cycleDetails.id,
|
||||
{
|
||||
issues: [issueDetail.id],
|
||||
},
|
||||
user
|
||||
)
|
||||
.then((res) => {
|
||||
mutate(ISSUE_DETAILS(issueId as string));
|
||||
});
|
||||
@ -139,9 +148,15 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
|
||||
if (!workspaceSlug || !projectId || !issueDetail) return;
|
||||
|
||||
modulesService
|
||||
.addIssuesToModule(workspaceSlug as string, projectId as string, moduleDetail.id, {
|
||||
issues: [issueDetail.id],
|
||||
})
|
||||
.addIssuesToModule(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
moduleDetail.id,
|
||||
{
|
||||
issues: [issueDetail.id],
|
||||
},
|
||||
user
|
||||
)
|
||||
.then((res) => {
|
||||
mutate(ISSUE_DETAILS(issueId as string));
|
||||
});
|
||||
@ -228,6 +243,7 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
|
||||
handleClose={() => setDeleteIssueModal(false)}
|
||||
isOpen={deleteIssueModal}
|
||||
data={issueDetail ?? null}
|
||||
user={user}
|
||||
/>
|
||||
<div className="sticky top-5 w-full divide-y-2 divide-brand-base">
|
||||
<div className="flex items-center justify-between pb-3">
|
||||
|
@ -21,15 +21,16 @@ import { ChevronRightIcon, PlusIcon, XMarkIcon } from "@heroicons/react/24/outli
|
||||
// helpers
|
||||
import { orderArrayBy } from "helpers/array.helper";
|
||||
// types
|
||||
import { IIssue, ISubIssueResponse } from "types";
|
||||
import { ICurrentUserResponse, IIssue, ISubIssueResponse } from "types";
|
||||
// fetch-keys
|
||||
import { PROJECT_ISSUES_LIST, SUB_ISSUES } from "constants/fetch-keys";
|
||||
|
||||
type Props = {
|
||||
parentIssue: IIssue;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const SubIssuesList: FC<Props> = ({ parentIssue }) => {
|
||||
export const SubIssuesList: FC<Props> = ({ parentIssue, user }) => {
|
||||
// states
|
||||
const [createIssueModal, setCreateIssueModal] = useState(false);
|
||||
const [subIssuesListModal, setSubIssuesListModal] = useState(false);
|
||||
@ -134,7 +135,7 @@ export const SubIssuesList: FC<Props> = ({ parentIssue }) => {
|
||||
);
|
||||
|
||||
issuesService
|
||||
.patchIssue(workspaceSlug.toString(), projectId.toString(), issueId, { parent: null })
|
||||
.patchIssue(workspaceSlug.toString(), projectId.toString(), issueId, { parent: null }, user)
|
||||
.then((res) => {
|
||||
mutate(SUB_ISSUES(parentIssue.id ?? ""));
|
||||
|
||||
|
@ -12,7 +12,7 @@ import { AssigneesList, Avatar, CustomSearchSelect, Tooltip } from "components/u
|
||||
// icons
|
||||
import { UserGroupIcon } from "@heroicons/react/24/outline";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
import { ICurrentUserResponse, IIssue } from "types";
|
||||
// fetch-keys
|
||||
import { PROJECT_MEMBERS } from "constants/fetch-keys";
|
||||
|
||||
@ -22,6 +22,7 @@ type Props = {
|
||||
position?: "left" | "right";
|
||||
selfPositioned?: boolean;
|
||||
tooltipPosition?: "left" | "right";
|
||||
user: ICurrentUserResponse | undefined;
|
||||
isNotAllowed: boolean;
|
||||
};
|
||||
|
||||
@ -31,6 +32,7 @@ export const ViewAssigneeSelect: React.FC<Props> = ({
|
||||
position = "left",
|
||||
selfPositioned = false,
|
||||
tooltipPosition = "right",
|
||||
user,
|
||||
isNotAllowed,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
@ -83,7 +85,8 @@ export const ViewAssigneeSelect: React.FC<Props> = ({
|
||||
projectName: issue.project_detail.name,
|
||||
issueId: issue.id,
|
||||
},
|
||||
"ISSUE_PROPERTY_UPDATE_ASSIGNEE"
|
||||
"ISSUE_PROPERTY_UPDATE_ASSIGNEE",
|
||||
user
|
||||
);
|
||||
}}
|
||||
options={options}
|
||||
|
@ -7,15 +7,21 @@ import { findHowManyDaysLeft } from "helpers/date-time.helper";
|
||||
// services
|
||||
import trackEventServices from "services/track-event.service";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
import { ICurrentUserResponse, IIssue } from "types";
|
||||
|
||||
type Props = {
|
||||
issue: IIssue;
|
||||
partialUpdateIssue: (formData: Partial<IIssue>, issueId: string) => void;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
isNotAllowed: boolean;
|
||||
};
|
||||
|
||||
export const ViewDueDateSelect: React.FC<Props> = ({ issue, partialUpdateIssue, isNotAllowed }) => {
|
||||
export const ViewDueDateSelect: React.FC<Props> = ({
|
||||
issue,
|
||||
partialUpdateIssue,
|
||||
user,
|
||||
isNotAllowed,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
@ -51,7 +57,8 @@ export const ViewDueDateSelect: React.FC<Props> = ({ issue, partialUpdateIssue,
|
||||
projectName: issue.project_detail.name,
|
||||
issueId: issue.id,
|
||||
},
|
||||
"ISSUE_PROPERTY_UPDATE_DUE_DATE"
|
||||
"ISSUE_PROPERTY_UPDATE_DUE_DATE",
|
||||
user
|
||||
);
|
||||
}}
|
||||
className={issue?.target_date ? "w-[6.5rem]" : "w-[5rem] text-center"}
|
||||
|
@ -11,13 +11,14 @@ import { CustomSelect, Tooltip } from "components/ui";
|
||||
// icons
|
||||
import { PlayIcon } from "@heroicons/react/24/outline";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
import { ICurrentUserResponse, IIssue } from "types";
|
||||
|
||||
type Props = {
|
||||
issue: IIssue;
|
||||
partialUpdateIssue: (formData: Partial<IIssue>, issueId: string) => void;
|
||||
position?: "left" | "right";
|
||||
selfPositioned?: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
isNotAllowed: boolean;
|
||||
};
|
||||
|
||||
@ -26,6 +27,7 @@ export const ViewEstimateSelect: React.FC<Props> = ({
|
||||
partialUpdateIssue,
|
||||
position = "left",
|
||||
selfPositioned = false,
|
||||
user,
|
||||
isNotAllowed,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
@ -51,7 +53,8 @@ export const ViewEstimateSelect: React.FC<Props> = ({
|
||||
projectName: issue.project_detail.name,
|
||||
issueId: issue.id,
|
||||
},
|
||||
"ISSUE_PROPERTY_UPDATE_ESTIMATE"
|
||||
"ISSUE_PROPERTY_UPDATE_ESTIMATE",
|
||||
user
|
||||
);
|
||||
}}
|
||||
label={
|
||||
|
@ -7,7 +7,7 @@ import { CustomSelect, Tooltip } from "components/ui";
|
||||
// icons
|
||||
import { getPriorityIcon } from "components/icons/priority-icon";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
import { ICurrentUserResponse, IIssue } from "types";
|
||||
// constants
|
||||
import { PRIORITIES } from "constants/project";
|
||||
// services
|
||||
@ -18,6 +18,7 @@ type Props = {
|
||||
partialUpdateIssue: (formData: Partial<IIssue>, issueId: string) => void;
|
||||
position?: "left" | "right";
|
||||
selfPositioned?: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
isNotAllowed: boolean;
|
||||
};
|
||||
|
||||
@ -26,6 +27,7 @@ export const ViewPrioritySelect: React.FC<Props> = ({
|
||||
partialUpdateIssue,
|
||||
position = "left",
|
||||
selfPositioned = false,
|
||||
user,
|
||||
isNotAllowed,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
@ -45,7 +47,8 @@ export const ViewPrioritySelect: React.FC<Props> = ({
|
||||
projectName: issue.project_detail.name,
|
||||
issueId: issue.id,
|
||||
},
|
||||
"ISSUE_PROPERTY_UPDATE_PRIORITY"
|
||||
"ISSUE_PROPERTY_UPDATE_PRIORITY",
|
||||
user
|
||||
);
|
||||
}}
|
||||
maxHeight="md"
|
||||
|
@ -13,7 +13,7 @@ import { getStateGroupIcon } from "components/icons";
|
||||
import { addSpaceIfCamelCase } from "helpers/string.helper";
|
||||
import { getStatesList } from "helpers/state.helper";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
import { ICurrentUserResponse, IIssue } from "types";
|
||||
// fetch-keys
|
||||
import { STATES_LIST } from "constants/fetch-keys";
|
||||
|
||||
@ -22,6 +22,7 @@ type Props = {
|
||||
partialUpdateIssue: (formData: Partial<IIssue>, issueId: string) => void;
|
||||
position?: "left" | "right";
|
||||
selfPositioned?: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
isNotAllowed: boolean;
|
||||
};
|
||||
|
||||
@ -30,6 +31,7 @@ export const ViewStateSelect: React.FC<Props> = ({
|
||||
partialUpdateIssue,
|
||||
position = "left",
|
||||
selfPositioned = false,
|
||||
user,
|
||||
isNotAllowed,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
@ -77,21 +79,25 @@ export const ViewStateSelect: React.FC<Props> = ({
|
||||
projectName: issue.project_detail.name,
|
||||
issueId: issue.id,
|
||||
},
|
||||
"ISSUE_PROPERTY_UPDATE_STATE"
|
||||
"ISSUE_PROPERTY_UPDATE_STATE",
|
||||
user
|
||||
);
|
||||
|
||||
const oldState = states.find((s) => s.id === issue.state);
|
||||
const newState = states.find((s) => s.id === data);
|
||||
|
||||
if (oldState?.group !== "completed" && newState?.group !== "completed") {
|
||||
trackEventServices.trackIssueMarkedAsDoneEvent({
|
||||
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,
|
||||
});
|
||||
trackEventServices.trackIssueMarkedAsDoneEvent(
|
||||
{
|
||||
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,
|
||||
},
|
||||
user
|
||||
);
|
||||
}
|
||||
}}
|
||||
options={options}
|
||||
|
@ -17,7 +17,7 @@ import { Input, PrimaryButton, SecondaryButton } from "components/ui";
|
||||
// icons
|
||||
import { ChevronDownIcon } from "@heroicons/react/24/outline";
|
||||
// types
|
||||
import type { IIssueLabels, IState } from "types";
|
||||
import type { ICurrentUserResponse, IIssueLabels, IState } from "types";
|
||||
// constants
|
||||
import { PROJECT_ISSUE_LABELS } from "constants/fetch-keys";
|
||||
|
||||
@ -26,6 +26,7 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
projectId: string;
|
||||
handleClose: () => void;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
const defaultValues: Partial<IState> = {
|
||||
@ -33,7 +34,7 @@ const defaultValues: Partial<IState> = {
|
||||
color: "#858E96",
|
||||
};
|
||||
|
||||
export const CreateLabelModal: React.FC<Props> = ({ isOpen, projectId, handleClose }) => {
|
||||
export const CreateLabelModal: React.FC<Props> = ({ isOpen, projectId, handleClose, user }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
@ -57,7 +58,7 @@ export const CreateLabelModal: React.FC<Props> = ({ isOpen, projectId, handleClo
|
||||
if (!workspaceSlug) return;
|
||||
|
||||
await issuesService
|
||||
.createIssueLabel(workspaceSlug as string, projectId as string, formData)
|
||||
.createIssueLabel(workspaceSlug as string, projectId as string, formData, user)
|
||||
.then((res) => {
|
||||
mutate<IIssueLabels[]>(
|
||||
PROJECT_ISSUE_LABELS(projectId),
|
||||
|
@ -6,6 +6,8 @@ import { mutate } from "swr";
|
||||
|
||||
// react-hook-form
|
||||
import { Controller, SubmitHandler, useForm } from "react-hook-form";
|
||||
// hooks
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// react-color
|
||||
import { TwitterPicker } from "react-color";
|
||||
// headless ui
|
||||
@ -42,6 +44,8 @@ export const CreateUpdateLabelInline = forwardRef<Ref, Props>(function CreateUpd
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
@ -58,7 +62,7 @@ export const CreateUpdateLabelInline = forwardRef<Ref, Props>(function CreateUpd
|
||||
if (!workspaceSlug || !projectId || isSubmitting) return;
|
||||
|
||||
await issuesService
|
||||
.createIssueLabel(workspaceSlug as string, projectId as string, formData)
|
||||
.createIssueLabel(workspaceSlug as string, projectId as string, formData, user)
|
||||
.then((res) => {
|
||||
mutate<IIssueLabels[]>(
|
||||
PROJECT_ISSUE_LABELS(projectId as string),
|
||||
@ -78,7 +82,8 @@ export const CreateUpdateLabelInline = forwardRef<Ref, Props>(function CreateUpd
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
labelToUpdate?.id ?? "",
|
||||
formData
|
||||
formData,
|
||||
user
|
||||
)
|
||||
.then(() => {
|
||||
reset(defaultValues);
|
||||
|
@ -15,7 +15,7 @@ import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { DangerButton, SecondaryButton } from "components/ui";
|
||||
// types
|
||||
import type { IIssueLabels } from "types";
|
||||
import type { ICurrentUserResponse, IIssueLabels } from "types";
|
||||
// fetch-keys
|
||||
import { PROJECT_ISSUE_LABELS } from "constants/fetch-keys";
|
||||
|
||||
@ -23,9 +23,10 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
data: IIssueLabels | null;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const DeleteLabelModal: React.FC<Props> = ({ isOpen, onClose, data }) => {
|
||||
export const DeleteLabelModal: React.FC<Props> = ({ isOpen, onClose, data, user }) => {
|
||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
@ -50,7 +51,7 @@ export const DeleteLabelModal: React.FC<Props> = ({ isOpen, onClose, data }) =>
|
||||
);
|
||||
|
||||
await issuesService
|
||||
.deleteIssueLabel(workspaceSlug.toString(), projectId.toString(), data.id)
|
||||
.deleteIssueLabel(workspaceSlug.toString(), projectId.toString(), data.id, user)
|
||||
.then(() => handleClose())
|
||||
.catch(() => {
|
||||
setIsDeleteLoading(false);
|
||||
|
@ -11,7 +11,7 @@ import { RectangleStackIcon, MagnifyingGlassIcon } from "@heroicons/react/24/out
|
||||
// services
|
||||
import issuesService from "services/issues.service";
|
||||
// types
|
||||
import { IIssueLabels } from "types";
|
||||
import { ICurrentUserResponse, IIssueLabels } from "types";
|
||||
// constants
|
||||
import { PROJECT_ISSUE_LABELS } from "constants/fetch-keys";
|
||||
|
||||
@ -19,9 +19,10 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
handleClose: () => void;
|
||||
parent: IIssueLabels | undefined;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const LabelsListModal: React.FC<Props> = ({ isOpen, handleClose, parent }) => {
|
||||
export const LabelsListModal: React.FC<Props> = ({ isOpen, handleClose, parent, user }) => {
|
||||
const [query, setQuery] = useState("");
|
||||
|
||||
const router = useRouter();
|
||||
@ -58,9 +59,15 @@ export const LabelsListModal: React.FC<Props> = ({ isOpen, handleClose, parent }
|
||||
);
|
||||
|
||||
await issuesService
|
||||
.patchIssueLabel(workspaceSlug as string, projectId as string, label.id, {
|
||||
parent: parent?.id ?? "",
|
||||
})
|
||||
.patchIssueLabel(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
label.id,
|
||||
{
|
||||
parent: parent?.id ?? "",
|
||||
},
|
||||
user
|
||||
)
|
||||
.then(() => mutate());
|
||||
};
|
||||
|
||||
|
@ -20,7 +20,7 @@ import {
|
||||
TrashIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
// types
|
||||
import { IIssueLabels } from "types";
|
||||
import { ICurrentUserResponse, IIssueLabels } from "types";
|
||||
// fetch-keys
|
||||
import { PROJECT_ISSUE_LABELS } from "constants/fetch-keys";
|
||||
|
||||
@ -30,6 +30,7 @@ type Props = {
|
||||
addLabelToGroup: (parentLabel: IIssueLabels) => void;
|
||||
editLabel: (label: IIssueLabels) => void;
|
||||
handleLabelDelete: () => void;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const SingleLabelGroup: React.FC<Props> = ({
|
||||
@ -38,6 +39,7 @@ export const SingleLabelGroup: React.FC<Props> = ({
|
||||
addLabelToGroup,
|
||||
editLabel,
|
||||
handleLabelDelete,
|
||||
user,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
@ -57,9 +59,15 @@ export const SingleLabelGroup: React.FC<Props> = ({
|
||||
);
|
||||
|
||||
issuesService
|
||||
.patchIssueLabel(workspaceSlug as string, projectId as string, label.id, {
|
||||
parent: null,
|
||||
})
|
||||
.patchIssueLabel(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
label.id,
|
||||
{
|
||||
parent: null,
|
||||
},
|
||||
user
|
||||
)
|
||||
.then(() => {
|
||||
mutate(PROJECT_ISSUE_LABELS(projectId as string));
|
||||
});
|
||||
|
@ -15,7 +15,7 @@ import { SecondaryButton, DangerButton } from "components/ui";
|
||||
// icons
|
||||
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
||||
// types
|
||||
import type { IModule } from "types";
|
||||
import type { ICurrentUserResponse, IModule } from "types";
|
||||
// fetch-keys
|
||||
import { MODULE_LIST } from "constants/fetch-keys";
|
||||
|
||||
@ -23,9 +23,10 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
data?: IModule;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const DeleteModuleModal: React.FC<Props> = ({ isOpen, setIsOpen, data }) => {
|
||||
export const DeleteModuleModal: React.FC<Props> = ({ isOpen, setIsOpen, data, user }) => {
|
||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
@ -50,7 +51,7 @@ export const DeleteModuleModal: React.FC<Props> = ({ isOpen, setIsOpen, data })
|
||||
);
|
||||
|
||||
await modulesService
|
||||
.deleteModule(workspaceSlug as string, projectId as string, data.id)
|
||||
.deleteModule(workspaceSlug as string, projectId as string, data.id, user)
|
||||
.then(() => {
|
||||
if (moduleId) router.push(`/${workspaceSlug}/projects/${data.project}/modules`);
|
||||
handleClose();
|
||||
|
@ -15,7 +15,7 @@ import modulesService from "services/modules.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// types
|
||||
import type { IModule } from "types";
|
||||
import type { ICurrentUserResponse, IModule } from "types";
|
||||
// fetch-keys
|
||||
import { MODULE_LIST } from "constants/fetch-keys";
|
||||
|
||||
@ -23,6 +23,7 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
data?: IModule;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
const defaultValues: Partial<IModule> = {
|
||||
@ -33,7 +34,7 @@ const defaultValues: Partial<IModule> = {
|
||||
members_list: [],
|
||||
};
|
||||
|
||||
export const CreateUpdateModuleModal: React.FC<Props> = ({ isOpen, setIsOpen, data }) => {
|
||||
export const CreateUpdateModuleModal: React.FC<Props> = ({ isOpen, setIsOpen, data, user }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
@ -50,7 +51,7 @@ export const CreateUpdateModuleModal: React.FC<Props> = ({ isOpen, setIsOpen, da
|
||||
|
||||
const createModule = async (payload: Partial<IModule>) => {
|
||||
await modulesService
|
||||
.createModule(workspaceSlug as string, projectId as string, payload)
|
||||
.createModule(workspaceSlug as string, projectId as string, payload, user)
|
||||
.then(() => {
|
||||
mutate(MODULE_LIST(projectId as string));
|
||||
handleClose();
|
||||
@ -72,7 +73,7 @@ export const CreateUpdateModuleModal: React.FC<Props> = ({ isOpen, setIsOpen, da
|
||||
|
||||
const updateModule = async (payload: Partial<IModule>) => {
|
||||
await modulesService
|
||||
.updateModule(workspaceSlug as string, projectId as string, data?.id ?? "", payload)
|
||||
.updateModule(workspaceSlug as string, projectId as string, data?.id ?? "", payload, user)
|
||||
.then((res) => {
|
||||
mutate<IModule[]>(
|
||||
MODULE_LIST(projectId as string),
|
||||
|
@ -37,7 +37,7 @@ import { LinkIcon } from "@heroicons/react/20/solid";
|
||||
import { renderDateFormat, renderShortDate } from "helpers/date-time.helper";
|
||||
import { capitalizeFirstLetter, copyTextToClipboard } from "helpers/string.helper";
|
||||
// types
|
||||
import { IIssue, IModule, ModuleLink } from "types";
|
||||
import { ICurrentUserResponse, IIssue, IModule, ModuleLink } from "types";
|
||||
// fetch-keys
|
||||
import { MODULE_DETAILS } from "constants/fetch-keys";
|
||||
// constant
|
||||
@ -56,9 +56,16 @@ type Props = {
|
||||
module?: IModule;
|
||||
isOpen: boolean;
|
||||
moduleIssues?: IIssue[];
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const ModuleDetailsSidebar: React.FC<Props> = ({ issues, module, isOpen, moduleIssues }) => {
|
||||
export const ModuleDetailsSidebar: React.FC<Props> = ({
|
||||
issues,
|
||||
module,
|
||||
isOpen,
|
||||
moduleIssues,
|
||||
user,
|
||||
}) => {
|
||||
const [moduleDeleteModal, setModuleDeleteModal] = useState(false);
|
||||
const [moduleLinkModal, setModuleLinkModal] = useState(false);
|
||||
|
||||
@ -86,7 +93,7 @@ export const ModuleDetailsSidebar: React.FC<Props> = ({ issues, module, isOpen,
|
||||
);
|
||||
|
||||
modulesService
|
||||
.patchModule(workspaceSlug as string, projectId as string, moduleId as string, data)
|
||||
.patchModule(workspaceSlug as string, projectId as string, moduleId as string, data, user)
|
||||
.then(() => mutate(MODULE_DETAILS(moduleId as string)))
|
||||
.catch((e) => console.log(e));
|
||||
};
|
||||
@ -181,6 +188,7 @@ export const ModuleDetailsSidebar: React.FC<Props> = ({ issues, module, isOpen,
|
||||
isOpen={moduleDeleteModal}
|
||||
setIsOpen={setModuleDeleteModal}
|
||||
data={module}
|
||||
user={user}
|
||||
/>
|
||||
<div
|
||||
className={`fixed top-[66px] ${
|
||||
|
@ -27,16 +27,17 @@ import { CalendarMonthIcon, TargetIcon } from "components/icons";
|
||||
import { copyTextToClipboard, truncateText } from "helpers/string.helper";
|
||||
import { renderShortDateWithYearFormat } from "helpers/date-time.helper";
|
||||
// types
|
||||
import { IModule } from "types";
|
||||
import { ICurrentUserResponse, IModule } from "types";
|
||||
// fetch-key
|
||||
import { MODULE_LIST } from "constants/fetch-keys";
|
||||
|
||||
type Props = {
|
||||
module: IModule;
|
||||
handleEditModule: () => void;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const SingleModuleCard: React.FC<Props> = ({ module, handleEditModule }) => {
|
||||
export const SingleModuleCard: React.FC<Props> = ({ module, handleEditModule, user }) => {
|
||||
const [moduleDeleteModal, setModuleDeleteModal] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
@ -128,6 +129,7 @@ export const SingleModuleCard: React.FC<Props> = ({ module, handleEditModule })
|
||||
isOpen={moduleDeleteModal}
|
||||
setIsOpen={setModuleDeleteModal}
|
||||
data={module}
|
||||
user={user}
|
||||
/>
|
||||
<div className="flex flex-col divide-y divide-brand-base overflow-hidden rounded-[10px] border border-brand-base bg-brand-base text-xs">
|
||||
<div className="p-4">
|
||||
|
@ -2,16 +2,17 @@
|
||||
import { useForm } from "react-hook-form";
|
||||
import useToast from "hooks/use-toast";
|
||||
import workspaceService from "services/workspace.service";
|
||||
import { IUser } from "types";
|
||||
import { ICurrentUserResponse, IUser } from "types";
|
||||
// ui components
|
||||
import { MultiInput, PrimaryButton, SecondaryButton } from "components/ui";
|
||||
|
||||
type Props = {
|
||||
setStep: React.Dispatch<React.SetStateAction<number>>;
|
||||
workspace: any;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const InviteMembers: React.FC<Props> = ({ setStep, workspace }) => {
|
||||
export const InviteMembers: React.FC<Props> = ({ setStep, workspace, user }) => {
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const {
|
||||
@ -23,7 +24,7 @@ export const InviteMembers: React.FC<Props> = ({ setStep, workspace }) => {
|
||||
|
||||
const onSubmit = async (formData: IUser) => {
|
||||
await workspaceService
|
||||
.inviteWorkspace(workspace.slug, formData)
|
||||
.inviteWorkspace(workspace.slug, formData, user)
|
||||
.then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
|
@ -9,7 +9,7 @@ import { Tab } from "@headlessui/react";
|
||||
// services
|
||||
import workspaceService from "services/workspace.service";
|
||||
// types
|
||||
import { IWorkspaceMemberInvitation } from "types";
|
||||
import { ICurrentUserResponse, IWorkspaceMemberInvitation } from "types";
|
||||
// fetch-keys
|
||||
import { USER_WORKSPACE_INVITATIONS } from "constants/fetch-keys";
|
||||
// constants
|
||||
@ -21,9 +21,10 @@ import { getFirstCharacters, truncateText } from "helpers/string.helper";
|
||||
type Props = {
|
||||
setStep: React.Dispatch<React.SetStateAction<number>>;
|
||||
setWorkspace: React.Dispatch<React.SetStateAction<any>>;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const Workspace: React.FC<Props> = ({ setStep, setWorkspace }) => {
|
||||
export const Workspace: React.FC<Props> = ({ setStep, setWorkspace, user }) => {
|
||||
const [isJoiningWorkspaces, setIsJoiningWorkspaces] = useState(false);
|
||||
const [invitationsRespond, setInvitationsRespond] = useState<string[]>([]);
|
||||
const [defaultValues, setDefaultValues] = useState({
|
||||
@ -98,7 +99,7 @@ export const Workspace: React.FC<Props> = ({ setStep, setWorkspace }) => {
|
||||
>
|
||||
<Tab.List as="div" className="flex flex-col gap-3 px-7 pt-7 pb-3.5">
|
||||
<div className="flex flex-col gap-2 justify-center">
|
||||
<h3 className="text-base font-semibold text-brand-base">Workspaces</h3>
|
||||
<h3 className="text-base font-semibold text-brand-base">Workspace</h3>
|
||||
<p className="text-sm text-brand-secondary">
|
||||
Create or join the workspace to get started with Plane.
|
||||
</p>
|
||||
@ -161,7 +162,10 @@ export const Workspace: React.FC<Props> = ({ setStep, setWorkspace }) => {
|
||||
{truncateText(invitation.workspace.name, 30)}
|
||||
</div>
|
||||
<p className="text-sm text-brand-secondary">
|
||||
Invited by {invitation.workspace.owner.first_name}
|
||||
Invited by{" "}
|
||||
{invitation.created_by_detail
|
||||
? invitation.created_by_detail.first_name
|
||||
: invitation.workspace.owner.first_name}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex-shrink-0 self-center">
|
||||
@ -237,6 +241,7 @@ export const Workspace: React.FC<Props> = ({ setStep, setWorkspace }) => {
|
||||
}}
|
||||
defaultValues={defaultValues}
|
||||
setDefaultValues={setDefaultValues}
|
||||
user={user}
|
||||
/>
|
||||
</Tab.Panel>
|
||||
</Tab.Panels>
|
||||
|
@ -16,7 +16,7 @@ import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { TextArea } from "components/ui";
|
||||
// types
|
||||
import { IPageBlock } from "types";
|
||||
import { ICurrentUserResponse, IPageBlock } from "types";
|
||||
// fetch-keys
|
||||
import { PAGE_BLOCKS_LIST } from "constants/fetch-keys";
|
||||
|
||||
@ -24,7 +24,11 @@ const defaultValues = {
|
||||
name: "",
|
||||
};
|
||||
|
||||
export const CreateBlock = () => {
|
||||
type Props = {
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const CreateBlock: React.FC<Props> = ({ user }) => {
|
||||
const [blockTitle, setBlockTitle] = useState("");
|
||||
|
||||
const router = useRouter();
|
||||
@ -49,9 +53,15 @@ export const CreateBlock = () => {
|
||||
if (!workspaceSlug || !projectId || !pageId) return;
|
||||
|
||||
await pagesService
|
||||
.createPageBlock(workspaceSlug as string, projectId as string, pageId as string, {
|
||||
name: watch("name"),
|
||||
})
|
||||
.createPageBlock(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
pageId as string,
|
||||
{
|
||||
name: watch("name"),
|
||||
},
|
||||
user
|
||||
)
|
||||
.then((res) => {
|
||||
mutate<IPageBlock[]>(
|
||||
PAGE_BLOCKS_LIST(pageId as string),
|
||||
|
@ -20,7 +20,7 @@ import { GptAssistantModal } from "components/core";
|
||||
// ui
|
||||
import { Loader, PrimaryButton, SecondaryButton, TextArea } from "components/ui";
|
||||
// types
|
||||
import { IPageBlock } from "types";
|
||||
import { ICurrentUserResponse, IPageBlock } from "types";
|
||||
// fetch-keys
|
||||
import { PAGE_BLOCKS_LIST } from "constants/fetch-keys";
|
||||
|
||||
@ -30,6 +30,7 @@ type Props = {
|
||||
handleAiAssistance?: (response: string) => void;
|
||||
setIsSyncing?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
focus?: keyof IPageBlock;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
const defaultValues = {
|
||||
@ -61,6 +62,7 @@ export const CreateUpdateBlockInline: React.FC<Props> = ({
|
||||
handleAiAssistance,
|
||||
setIsSyncing,
|
||||
focus,
|
||||
user,
|
||||
}) => {
|
||||
const [iAmFeelingLucky, setIAmFeelingLucky] = useState(false);
|
||||
const [gptAssistantModal, setGptAssistantModal] = useState(false);
|
||||
@ -96,11 +98,17 @@ export const CreateUpdateBlockInline: React.FC<Props> = ({
|
||||
if (!workspaceSlug || !projectId || !pageId) return;
|
||||
|
||||
await pagesService
|
||||
.createPageBlock(workspaceSlug as string, projectId as string, pageId as string, {
|
||||
name: formData.name,
|
||||
description: formData.description ?? "",
|
||||
description_html: formData.description_html ?? "<p></p>",
|
||||
})
|
||||
.createPageBlock(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
pageId as string,
|
||||
{
|
||||
name: formData.name,
|
||||
description: formData.description ?? "",
|
||||
description_html: formData.description_html ?? "<p></p>",
|
||||
},
|
||||
user
|
||||
)
|
||||
.then((res) => {
|
||||
mutate<IPageBlock[]>(
|
||||
PAGE_BLOCKS_LIST(pageId as string),
|
||||
@ -139,21 +147,34 @@ export const CreateUpdateBlockInline: React.FC<Props> = ({
|
||||
);
|
||||
|
||||
await pagesService
|
||||
.patchPageBlock(workspaceSlug as string, projectId as string, pageId as string, data.id, {
|
||||
name: formData.name,
|
||||
description: formData.description,
|
||||
description_html: formData.description_html,
|
||||
})
|
||||
.patchPageBlock(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
pageId as string,
|
||||
data.id,
|
||||
{
|
||||
name: formData.name,
|
||||
description: formData.description,
|
||||
description_html: formData.description_html,
|
||||
},
|
||||
user
|
||||
)
|
||||
.then((res) => {
|
||||
mutate(PAGE_BLOCKS_LIST(pageId as string));
|
||||
editorRef.current?.setEditorValue(res.description_html);
|
||||
if (data.issue && data.sync)
|
||||
issuesService
|
||||
.patchIssue(workspaceSlug as string, projectId as string, data.issue, {
|
||||
name: res.name,
|
||||
description: res.description,
|
||||
description_html: res.description_html,
|
||||
})
|
||||
.patchIssue(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
data.issue,
|
||||
{
|
||||
name: res.name,
|
||||
description: res.description,
|
||||
description_html: res.description_html,
|
||||
},
|
||||
user
|
||||
)
|
||||
.finally(() => {
|
||||
if (setIsSyncing) setIsSyncing(false);
|
||||
});
|
||||
@ -169,10 +190,15 @@ export const CreateUpdateBlockInline: React.FC<Props> = ({
|
||||
setIAmFeelingLucky(true);
|
||||
|
||||
aiService
|
||||
.createGptTask(workspaceSlug as string, projectId as string, {
|
||||
prompt: watch("name"),
|
||||
task: "Generate a proper description for this issue in context of a project management software.",
|
||||
})
|
||||
.createGptTask(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
{
|
||||
prompt: watch("name"),
|
||||
task: "Generate a proper description for this issue in context of a project management software.",
|
||||
},
|
||||
user
|
||||
)
|
||||
.then((res) => {
|
||||
if (res.response === "")
|
||||
setToastAlert({
|
||||
|
@ -13,7 +13,7 @@ import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { PageForm } from "./page-form";
|
||||
// types
|
||||
import { IPage } from "types";
|
||||
import { ICurrentUserResponse, IPage } from "types";
|
||||
// fetch-keys
|
||||
import {
|
||||
ALL_PAGES_LIST,
|
||||
@ -26,9 +26,10 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
handleClose: () => void;
|
||||
data?: IPage | null;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const CreateUpdatePageModal: React.FC<Props> = ({ isOpen, handleClose, data }) => {
|
||||
export const CreateUpdatePageModal: React.FC<Props> = ({ isOpen, handleClose, data, user }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
@ -40,7 +41,7 @@ export const CreateUpdatePageModal: React.FC<Props> = ({ isOpen, handleClose, da
|
||||
|
||||
const createPage = async (payload: IPage) => {
|
||||
await pagesService
|
||||
.createPage(workspaceSlug as string, projectId as string, payload)
|
||||
.createPage(workspaceSlug as string, projectId as string, payload, user)
|
||||
.then((res) => {
|
||||
mutate(RECENT_PAGES_LIST(projectId as string));
|
||||
mutate<IPage[]>(
|
||||
@ -82,7 +83,7 @@ export const CreateUpdatePageModal: React.FC<Props> = ({ isOpen, handleClose, da
|
||||
|
||||
const updatePage = async (payload: IPage) => {
|
||||
await pagesService
|
||||
.patchPage(workspaceSlug as string, projectId as string, data?.id ?? "", payload)
|
||||
.patchPage(workspaceSlug as string, projectId as string, data?.id ?? "", payload, user)
|
||||
.then((res) => {
|
||||
mutate(RECENT_PAGES_LIST(projectId as string));
|
||||
mutate<IPage[]>(
|
||||
|
@ -15,7 +15,7 @@ import { DangerButton, SecondaryButton } from "components/ui";
|
||||
// icons
|
||||
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
||||
// types
|
||||
import type { IPage } from "types";
|
||||
import type { ICurrentUserResponse, IPage } from "types";
|
||||
// fetch-keys
|
||||
import {
|
||||
ALL_PAGES_LIST,
|
||||
@ -28,12 +28,14 @@ type TConfirmPageDeletionProps = {
|
||||
isOpen: boolean;
|
||||
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
data?: IPage | null;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const DeletePageModal: React.FC<TConfirmPageDeletionProps> = ({
|
||||
isOpen,
|
||||
setIsOpen,
|
||||
data,
|
||||
user,
|
||||
}) => {
|
||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||
|
||||
@ -52,7 +54,7 @@ export const DeletePageModal: React.FC<TConfirmPageDeletionProps> = ({
|
||||
if (!data || !workspaceSlug || !projectId) return;
|
||||
|
||||
await pagesService
|
||||
.deletePage(workspaceSlug as string, data.project, data.id)
|
||||
.deletePage(workspaceSlug as string, data.project, data.id, user)
|
||||
.then(() => {
|
||||
mutate(RECENT_PAGES_LIST(projectId as string));
|
||||
mutate<IPage[]>(
|
||||
|
@ -8,6 +8,7 @@ import pagesService from "services/pages.service";
|
||||
import projectService from "services/project.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// components
|
||||
import {
|
||||
CreateUpdatePageModal,
|
||||
@ -44,6 +45,8 @@ export const PagesView: React.FC<Props> = ({ pages, viewType }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const { data: people } = useSWR(
|
||||
@ -181,7 +184,7 @@ export const PagesView: React.FC<Props> = ({ pages, viewType }) => {
|
||||
);
|
||||
|
||||
pagesService
|
||||
.patchPage(workspaceSlug.toString(), projectId.toString(), page.id, formData)
|
||||
.patchPage(workspaceSlug.toString(), projectId.toString(), page.id, formData, user)
|
||||
.then(() => {
|
||||
mutate(RECENT_PAGES_LIST(projectId.toString()));
|
||||
});
|
||||
@ -193,11 +196,13 @@ export const PagesView: React.FC<Props> = ({ pages, viewType }) => {
|
||||
isOpen={createUpdatePageModal}
|
||||
handleClose={() => setCreateUpdatePageModal(false)}
|
||||
data={selectedPageToUpdate}
|
||||
user={user}
|
||||
/>
|
||||
<DeletePageModal
|
||||
isOpen={deletePageModal}
|
||||
setIsOpen={setDeletePageModal}
|
||||
data={selectedPageToDelete}
|
||||
user={user}
|
||||
/>
|
||||
{pages ? (
|
||||
<div className="space-y-4 h-full overflow-y-auto">
|
||||
|
@ -35,7 +35,7 @@ import {
|
||||
// helpers
|
||||
import { copyTextToClipboard } from "helpers/string.helper";
|
||||
// types
|
||||
import { IIssue, IPageBlock, IProject } from "types";
|
||||
import { ICurrentUserResponse, IIssue, IPageBlock, IProject } from "types";
|
||||
// fetch-keys
|
||||
import { PAGE_BLOCKS_LIST } from "constants/fetch-keys";
|
||||
|
||||
@ -43,9 +43,10 @@ type Props = {
|
||||
block: IPageBlock;
|
||||
projectDetails: IProject | undefined;
|
||||
index: number;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const SinglePageBlock: React.FC<Props> = ({ block, projectDetails, index }) => {
|
||||
export const SinglePageBlock: React.FC<Props> = ({ block, projectDetails, index, user }) => {
|
||||
const [isSyncing, setIsSyncing] = useState(false);
|
||||
const [createBlockForm, setCreateBlockForm] = useState(false);
|
||||
const [iAmFeelingLucky, setIAmFeelingLucky] = useState(false);
|
||||
@ -87,20 +88,33 @@ export const SinglePageBlock: React.FC<Props> = ({ block, projectDetails, index
|
||||
);
|
||||
|
||||
await pagesService
|
||||
.patchPageBlock(workspaceSlug as string, projectId as string, pageId as string, block.id, {
|
||||
name: formData.name,
|
||||
description: formData.description,
|
||||
description_html: formData.description_html,
|
||||
})
|
||||
.patchPageBlock(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
pageId as string,
|
||||
block.id,
|
||||
{
|
||||
name: formData.name,
|
||||
description: formData.description,
|
||||
description_html: formData.description_html,
|
||||
},
|
||||
user
|
||||
)
|
||||
.then((res) => {
|
||||
mutate(PAGE_BLOCKS_LIST(pageId as string));
|
||||
if (block.issue && block.sync)
|
||||
issuesService
|
||||
.patchIssue(workspaceSlug as string, projectId as string, block.issue, {
|
||||
name: res.name,
|
||||
description: res.description,
|
||||
description_html: res.description_html,
|
||||
})
|
||||
.patchIssue(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
block.issue,
|
||||
{
|
||||
name: res.name,
|
||||
description: res.description,
|
||||
description_html: res.description_html,
|
||||
},
|
||||
user
|
||||
)
|
||||
.finally(() => setIsSyncing(false));
|
||||
});
|
||||
};
|
||||
@ -113,7 +127,8 @@ export const SinglePageBlock: React.FC<Props> = ({ block, projectDetails, index
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
pageId as string,
|
||||
block.id
|
||||
block.id,
|
||||
user
|
||||
)
|
||||
.then((res: IIssue) => {
|
||||
mutate<IPageBlock[]>(
|
||||
@ -152,7 +167,13 @@ export const SinglePageBlock: React.FC<Props> = ({ block, projectDetails, index
|
||||
);
|
||||
|
||||
await pagesService
|
||||
.deletePageBlock(workspaceSlug as string, projectId as string, pageId as string, block.id)
|
||||
.deletePageBlock(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
pageId as string,
|
||||
block.id,
|
||||
user
|
||||
)
|
||||
.catch(() => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
@ -168,10 +189,15 @@ export const SinglePageBlock: React.FC<Props> = ({ block, projectDetails, index
|
||||
setIAmFeelingLucky(true);
|
||||
|
||||
aiService
|
||||
.createGptTask(workspaceSlug as string, projectId as string, {
|
||||
prompt: block.name,
|
||||
task: "Generate a proper description for this issue in context of a project management software.",
|
||||
})
|
||||
.createGptTask(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
{
|
||||
prompt: block.name,
|
||||
task: "Generate a proper description for this issue in context of a project management software.",
|
||||
},
|
||||
user
|
||||
)
|
||||
.then((res) => {
|
||||
if (res.response === "")
|
||||
setToastAlert({
|
||||
@ -243,7 +269,8 @@ export const SinglePageBlock: React.FC<Props> = ({ block, projectDetails, index
|
||||
block.id,
|
||||
{
|
||||
sync: !block.sync,
|
||||
}
|
||||
},
|
||||
user
|
||||
);
|
||||
};
|
||||
|
||||
@ -281,6 +308,7 @@ export const SinglePageBlock: React.FC<Props> = ({ block, projectDetails, index
|
||||
data={block}
|
||||
setIsSyncing={setIsSyncing}
|
||||
focus="name"
|
||||
user={user}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
|
@ -24,7 +24,7 @@ import EmojiIconPicker from "components/emoji-icon-picker";
|
||||
// helpers
|
||||
import { getRandomEmoji } from "helpers/common.helper";
|
||||
// types
|
||||
import { IProject } from "types";
|
||||
import { ICurrentUserResponse, IProject } from "types";
|
||||
// fetch-keys
|
||||
import { PROJECTS_LIST, WORKSPACE_MEMBERS_ME } from "constants/fetch-keys";
|
||||
// constants
|
||||
@ -33,6 +33,7 @@ import { NETWORK_CHOICES } from "constants/project";
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
const defaultValues: Partial<IProject> = {
|
||||
@ -63,7 +64,7 @@ const IsGuestCondition: React.FC<{
|
||||
};
|
||||
|
||||
export const CreateProjectModal: React.FC<Props> = (props) => {
|
||||
const { isOpen, setIsOpen } = props;
|
||||
const { isOpen, setIsOpen, user } = props;
|
||||
|
||||
const [isChangeIdentifierRequired, setIsChangeIdentifierRequired] = useState(true);
|
||||
|
||||
@ -120,7 +121,7 @@ export const CreateProjectModal: React.FC<Props> = (props) => {
|
||||
else payload.emoji = formData.emoji_and_icon;
|
||||
|
||||
await projectServices
|
||||
.createProject(workspaceSlug as string, payload)
|
||||
.createProject(workspaceSlug as string, payload, user)
|
||||
.then((res) => {
|
||||
mutate<IProject[]>(
|
||||
PROJECTS_LIST(workspaceSlug as string),
|
||||
|
@ -13,7 +13,7 @@ import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
||||
// ui
|
||||
import { DangerButton, Input, SecondaryButton } from "components/ui";
|
||||
// types
|
||||
import type { IProject, IWorkspace } from "types";
|
||||
import type { ICurrentUserResponse, IProject, IWorkspace } from "types";
|
||||
// fetch-keys
|
||||
import { PROJECTS_LIST } from "constants/fetch-keys";
|
||||
|
||||
@ -22,6 +22,7 @@ type TConfirmProjectDeletionProps = {
|
||||
onClose: () => void;
|
||||
onSuccess?: () => void;
|
||||
data: IProject | null;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const DeleteProjectModal: React.FC<TConfirmProjectDeletionProps> = ({
|
||||
@ -29,6 +30,7 @@ export const DeleteProjectModal: React.FC<TConfirmProjectDeletionProps> = ({
|
||||
data,
|
||||
onClose,
|
||||
onSuccess,
|
||||
user,
|
||||
}) => {
|
||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||
const [confirmProjectName, setConfirmProjectName] = useState("");
|
||||
@ -65,7 +67,7 @@ export const DeleteProjectModal: React.FC<TConfirmProjectDeletionProps> = ({
|
||||
setIsDeleteLoading(true);
|
||||
if (!data || !workspaceSlug || !canDelete) return;
|
||||
await projectService
|
||||
.deleteProject(workspaceSlug, data.id)
|
||||
.deleteProject(workspaceSlug, data.id, user)
|
||||
.then(() => {
|
||||
handleClose();
|
||||
mutate<IProject[]>(PROJECTS_LIST(workspaceSlug), (prevData) =>
|
||||
|
@ -15,7 +15,7 @@ import useToast from "hooks/use-toast";
|
||||
import projectService from "services/project.service";
|
||||
import workspaceService from "services/workspace.service";
|
||||
// types
|
||||
import { IProjectMemberInvitation } from "types";
|
||||
import { ICurrentUserResponse, IProjectMemberInvitation } from "types";
|
||||
// fetch-keys
|
||||
import { PROJECT_INVITATIONS, WORKSPACE_MEMBERS } from "constants/fetch-keys";
|
||||
// constants
|
||||
@ -25,6 +25,7 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
members: any[];
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
type ProjectMember = IProjectMemberInvitation & {
|
||||
@ -40,7 +41,7 @@ const defaultValues: Partial<ProjectMember> = {
|
||||
user_id: "",
|
||||
};
|
||||
|
||||
const SendProjectInvitationModal: React.FC<Props> = ({ isOpen, setIsOpen, members }) => {
|
||||
const SendProjectInvitationModal: React.FC<Props> = ({ isOpen, setIsOpen, members, user }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
@ -70,7 +71,7 @@ const SendProjectInvitationModal: React.FC<Props> = ({ isOpen, setIsOpen, member
|
||||
const onSubmit = async (formData: ProjectMember) => {
|
||||
if (!workspaceSlug || !projectId || isSubmitting) return;
|
||||
await projectService
|
||||
.inviteProject(workspaceSlug as string, projectId as string, formData)
|
||||
.inviteProject(workspaceSlug as string, projectId as string, formData, user)
|
||||
.then((response) => {
|
||||
setIsOpen(false);
|
||||
mutate<any[]>(
|
||||
|
@ -9,6 +9,7 @@ import { PlusIcon } from "@heroicons/react/24/outline";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useTheme from "hooks/use-theme";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// services
|
||||
import projectService from "services/project.service";
|
||||
// components
|
||||
@ -29,6 +30,9 @@ export const ProjectSidebarList: FC = () => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
// states
|
||||
const [isCreateProjectModal, setCreateProjectModal] = useState(false);
|
||||
// theme
|
||||
@ -136,11 +140,16 @@ export const ProjectSidebarList: FC = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<CreateProjectModal isOpen={isCreateProjectModal} setIsOpen={setCreateProjectModal} />
|
||||
<CreateProjectModal
|
||||
isOpen={isCreateProjectModal}
|
||||
setIsOpen={setCreateProjectModal}
|
||||
user={user}
|
||||
/>
|
||||
<DeleteProjectModal
|
||||
isOpen={deleteProjectModal}
|
||||
onClose={() => setDeleteProjectModal(false)}
|
||||
data={projectToDelete}
|
||||
user={user}
|
||||
/>
|
||||
<div className="mt-2.5 h-full overflow-y-auto border-t border-brand-base bg-brand-sidebar pt-2.5">
|
||||
{favoriteProjects && favoriteProjects.length > 0 && (
|
||||
|
@ -19,7 +19,7 @@ import { CustomSelect, Input, PrimaryButton, SecondaryButton, TextArea } from "c
|
||||
// icons
|
||||
import { ChevronDownIcon } from "@heroicons/react/24/outline";
|
||||
// types
|
||||
import type { IState, IStateResponse } from "types";
|
||||
import type { ICurrentUserResponse, IState, IStateResponse } from "types";
|
||||
// fetch keys
|
||||
import { STATES_LIST } from "constants/fetch-keys";
|
||||
// constants
|
||||
@ -30,6 +30,7 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
projectId: string;
|
||||
handleClose: () => void;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
const defaultValues: Partial<IState> = {
|
||||
@ -39,7 +40,7 @@ const defaultValues: Partial<IState> = {
|
||||
group: "backlog",
|
||||
};
|
||||
|
||||
export const CreateStateModal: React.FC<Props> = ({ isOpen, projectId, handleClose }) => {
|
||||
export const CreateStateModal: React.FC<Props> = ({ isOpen, projectId, handleClose, user }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
@ -69,7 +70,7 @@ export const CreateStateModal: React.FC<Props> = ({ isOpen, projectId, handleClo
|
||||
};
|
||||
|
||||
await stateService
|
||||
.createState(workspaceSlug as string, projectId, payload)
|
||||
.createState(workspaceSlug as string, projectId, payload, user)
|
||||
.then((res) => {
|
||||
mutate<IStateResponse>(
|
||||
STATES_LIST(projectId.toString()),
|
||||
|
@ -17,7 +17,7 @@ import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { CustomSelect, Input, PrimaryButton, SecondaryButton } from "components/ui";
|
||||
// types
|
||||
import type { IState, IStateResponse } from "types";
|
||||
import type { ICurrentUserResponse, IState, IStateResponse } from "types";
|
||||
// fetch-keys
|
||||
import { STATES_LIST } from "constants/fetch-keys";
|
||||
// constants
|
||||
@ -27,6 +27,7 @@ type Props = {
|
||||
data: IState | null;
|
||||
onClose: () => void;
|
||||
selectedGroup: StateGroup | null;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export type StateGroup = "backlog" | "unstarted" | "started" | "completed" | "cancelled" | null;
|
||||
@ -37,7 +38,12 @@ const defaultValues: Partial<IState> = {
|
||||
group: "backlog",
|
||||
};
|
||||
|
||||
export const CreateUpdateStateInline: React.FC<Props> = ({ data, onClose, selectedGroup }) => {
|
||||
export const CreateUpdateStateInline: React.FC<Props> = ({
|
||||
data,
|
||||
onClose,
|
||||
selectedGroup,
|
||||
user,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
@ -83,7 +89,7 @@ export const CreateUpdateStateInline: React.FC<Props> = ({ data, onClose, select
|
||||
|
||||
if (!data) {
|
||||
await stateService
|
||||
.createState(workspaceSlug.toString(), projectId.toString(), { ...payload })
|
||||
.createState(workspaceSlug.toString(), projectId.toString(), { ...payload }, user)
|
||||
.then((res) => {
|
||||
mutate<IStateResponse>(
|
||||
STATES_LIST(projectId.toString()),
|
||||
@ -121,9 +127,15 @@ export const CreateUpdateStateInline: React.FC<Props> = ({ data, onClose, select
|
||||
});
|
||||
} else {
|
||||
await stateService
|
||||
.updateState(workspaceSlug.toString(), projectId.toString(), data.id, {
|
||||
...payload,
|
||||
})
|
||||
.updateState(
|
||||
workspaceSlug.toString(),
|
||||
projectId.toString(),
|
||||
data.id,
|
||||
{
|
||||
...payload,
|
||||
},
|
||||
user
|
||||
)
|
||||
.then(() => {
|
||||
mutate(STATES_LIST(projectId.toString()));
|
||||
handleClose();
|
||||
|
@ -15,7 +15,7 @@ import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { DangerButton, SecondaryButton } from "components/ui";
|
||||
// types
|
||||
import type { IState, IStateResponse } from "types";
|
||||
import type { ICurrentUserResponse, IState, IStateResponse } from "types";
|
||||
// fetch-keys
|
||||
import { STATES_LIST } from "constants/fetch-keys";
|
||||
|
||||
@ -23,9 +23,10 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
data: IState | null;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const DeleteStateModal: React.FC<Props> = ({ isOpen, onClose, data }) => {
|
||||
export const DeleteStateModal: React.FC<Props> = ({ isOpen, onClose, data, user }) => {
|
||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
@ -44,7 +45,7 @@ export const DeleteStateModal: React.FC<Props> = ({ isOpen, onClose, data }) =>
|
||||
setIsDeleteLoading(true);
|
||||
|
||||
await stateServices
|
||||
.deleteState(workspaceSlug as string, data.project, data.id)
|
||||
.deleteState(workspaceSlug as string, data.project, data.id, user)
|
||||
.then(() => {
|
||||
mutate<IStateResponse>(
|
||||
STATES_LIST(data.project),
|
||||
|
@ -21,7 +21,7 @@ import { addSpaceIfCamelCase } from "helpers/string.helper";
|
||||
import { groupBy, orderArrayBy } from "helpers/array.helper";
|
||||
import { orderStateGroups } from "helpers/state.helper";
|
||||
// types
|
||||
import { IState } from "types";
|
||||
import { ICurrentUserResponse, IState } from "types";
|
||||
// fetch-keys
|
||||
import { STATES_LIST } from "constants/fetch-keys";
|
||||
|
||||
@ -31,6 +31,7 @@ type Props = {
|
||||
statesList: IState[];
|
||||
handleEditState: () => void;
|
||||
handleDeleteState: () => void;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const SingleState: React.FC<Props> = ({
|
||||
@ -39,6 +40,7 @@ export const SingleState: React.FC<Props> = ({
|
||||
statesList,
|
||||
handleEditState,
|
||||
handleDeleteState,
|
||||
user,
|
||||
}) => {
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
@ -67,14 +69,26 @@ export const SingleState: React.FC<Props> = ({
|
||||
|
||||
if (currentDefaultState)
|
||||
stateService
|
||||
.patchState(workspaceSlug as string, projectId as string, currentDefaultState?.id ?? "", {
|
||||
default: false,
|
||||
})
|
||||
.patchState(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
currentDefaultState?.id ?? "",
|
||||
{
|
||||
default: false,
|
||||
},
|
||||
user
|
||||
)
|
||||
.then(() => {
|
||||
stateService
|
||||
.patchState(workspaceSlug as string, projectId as string, state.id, {
|
||||
default: true,
|
||||
})
|
||||
.patchState(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
state.id,
|
||||
{
|
||||
default: true,
|
||||
},
|
||||
user
|
||||
)
|
||||
.then(() => {
|
||||
mutate(STATES_LIST(projectId as string));
|
||||
setIsSubmitting(false);
|
||||
@ -85,9 +99,15 @@ export const SingleState: React.FC<Props> = ({
|
||||
});
|
||||
else
|
||||
stateService
|
||||
.patchState(workspaceSlug as string, projectId as string, state.id, {
|
||||
default: true,
|
||||
})
|
||||
.patchState(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
state.id,
|
||||
{
|
||||
default: true,
|
||||
},
|
||||
user
|
||||
)
|
||||
.then(() => {
|
||||
mutate(STATES_LIST(projectId as string));
|
||||
setIsSubmitting(false);
|
||||
@ -121,9 +141,15 @@ export const SingleState: React.FC<Props> = ({
|
||||
);
|
||||
|
||||
stateService
|
||||
.patchState(workspaceSlug as string, projectId as string, state.id, {
|
||||
sequence: newSequence,
|
||||
})
|
||||
.patchState(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
state.id,
|
||||
{
|
||||
sequence: newSequence,
|
||||
},
|
||||
user
|
||||
)
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
mutate(STATES_LIST(projectId as string));
|
||||
|
@ -15,7 +15,7 @@ import { DangerButton, SecondaryButton } from "components/ui";
|
||||
// icons
|
||||
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
||||
// types
|
||||
import type { IView } from "types";
|
||||
import type { ICurrentUserResponse, IView } from "types";
|
||||
// fetch-keys
|
||||
import { VIEWS_LIST } from "constants/fetch-keys";
|
||||
|
||||
@ -23,9 +23,10 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
data: IView | null;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const DeleteViewModal: React.FC<Props> = ({ isOpen, data, setIsOpen }) => {
|
||||
export const DeleteViewModal: React.FC<Props> = ({ isOpen, data, setIsOpen, user }) => {
|
||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
@ -43,7 +44,7 @@ export const DeleteViewModal: React.FC<Props> = ({ isOpen, data, setIsOpen }) =>
|
||||
if (!workspaceSlug || !data || !projectId) return;
|
||||
|
||||
await viewsService
|
||||
.deleteView(workspaceSlug as string, projectId as string, data.id)
|
||||
.deleteView(workspaceSlug as string, projectId as string, data.id, user)
|
||||
.then(() => {
|
||||
mutate<IView[]>(VIEWS_LIST(projectId as string), (views) =>
|
||||
views?.filter((view) => view.id !== data.id)
|
||||
|
@ -13,7 +13,7 @@ import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { ViewForm } from "components/views";
|
||||
// types
|
||||
import { IView } from "types";
|
||||
import { ICurrentUserResponse, IView } from "types";
|
||||
// fetch-keys
|
||||
import { VIEWS_LIST } from "constants/fetch-keys";
|
||||
|
||||
@ -22,6 +22,7 @@ type Props = {
|
||||
handleClose: () => void;
|
||||
data?: IView | null;
|
||||
preLoadedData?: Partial<IView> | null;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const CreateUpdateViewModal: React.FC<Props> = ({
|
||||
@ -29,6 +30,7 @@ export const CreateUpdateViewModal: React.FC<Props> = ({
|
||||
handleClose,
|
||||
data,
|
||||
preLoadedData,
|
||||
user,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
@ -45,7 +47,7 @@ export const CreateUpdateViewModal: React.FC<Props> = ({
|
||||
query_data: payload.query,
|
||||
};
|
||||
await viewsService
|
||||
.createView(workspaceSlug as string, projectId as string, payload)
|
||||
.createView(workspaceSlug as string, projectId as string, payload, user)
|
||||
.then(() => {
|
||||
mutate(VIEWS_LIST(projectId as string));
|
||||
handleClose();
|
||||
@ -71,7 +73,7 @@ export const CreateUpdateViewModal: React.FC<Props> = ({
|
||||
query_data: payload.query,
|
||||
};
|
||||
await viewsService
|
||||
.updateView(workspaceSlug as string, projectId as string, data?.id ?? "", payloadData)
|
||||
.updateView(workspaceSlug as string, projectId as string, data?.id ?? "", payloadData, user)
|
||||
.then((res) => {
|
||||
mutate<IView[]>(
|
||||
VIEWS_LIST(projectId as string),
|
||||
|
@ -11,7 +11,7 @@ import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { CustomSelect, Input, PrimaryButton } from "components/ui";
|
||||
// types
|
||||
import { IWorkspace } from "types";
|
||||
import { ICurrentUserResponse, IWorkspace } from "types";
|
||||
// fetch-keys
|
||||
import { USER_WORKSPACES } from "constants/fetch-keys";
|
||||
// constants
|
||||
@ -25,6 +25,7 @@ type Props = {
|
||||
company_size: number | null;
|
||||
};
|
||||
setDefaultValues: Dispatch<SetStateAction<any>>;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
const restrictedUrls = [
|
||||
@ -44,6 +45,7 @@ export const CreateWorkspaceForm: React.FC<Props> = ({
|
||||
onSubmit,
|
||||
defaultValues,
|
||||
setDefaultValues,
|
||||
user,
|
||||
}) => {
|
||||
const [slugError, setSlugError] = useState(false);
|
||||
const [invalidSlug, setInvalidSlug] = useState(false);
|
||||
@ -66,7 +68,7 @@ export const CreateWorkspaceForm: React.FC<Props> = ({
|
||||
if (res.status === true && !restrictedUrls.includes(formData.slug)) {
|
||||
setSlugError(false);
|
||||
await workspaceService
|
||||
.createWorkspace(formData)
|
||||
.createWorkspace(formData, user)
|
||||
.then((res) => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
|
@ -15,7 +15,7 @@ import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
||||
// ui
|
||||
import { DangerButton, Input, SecondaryButton } from "components/ui";
|
||||
// types
|
||||
import type { IWorkspace } from "types";
|
||||
import type { ICurrentUserResponse, IWorkspace } from "types";
|
||||
// fetch-keys
|
||||
import { USER_WORKSPACES } from "constants/fetch-keys";
|
||||
|
||||
@ -23,9 +23,10 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
data: IWorkspace | null;
|
||||
onClose: () => void;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
export const DeleteWorkspaceModal: React.FC<Props> = ({ isOpen, data, onClose }) => {
|
||||
export const DeleteWorkspaceModal: React.FC<Props> = ({ isOpen, data, onClose, user }) => {
|
||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||
|
||||
const [confirmWorkspaceName, setConfirmWorkspaceName] = useState("");
|
||||
@ -57,7 +58,7 @@ export const DeleteWorkspaceModal: React.FC<Props> = ({ isOpen, data, onClose })
|
||||
setIsDeleteLoading(true);
|
||||
if (!data || !canDelete) return;
|
||||
await workspaceService
|
||||
.deleteWorkspace(data.slug)
|
||||
.deleteWorkspace(data.slug, user)
|
||||
.then(() => {
|
||||
handleClose();
|
||||
router.push("/");
|
||||
|
@ -10,7 +10,7 @@ import { CustomSelect, Input, PrimaryButton, SecondaryButton } from "components/
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// types
|
||||
import { IWorkspaceMemberInvitation } from "types";
|
||||
import { ICurrentUserResponse, IWorkspaceMemberInvitation } from "types";
|
||||
// fetch keys
|
||||
import { WORKSPACE_INVITATIONS } from "constants/fetch-keys";
|
||||
// constants
|
||||
@ -21,6 +21,7 @@ type Props = {
|
||||
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
workspace_slug: string;
|
||||
members: any[];
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
const defaultValues: Partial<IWorkspaceMemberInvitation> = {
|
||||
@ -33,6 +34,7 @@ const SendWorkspaceInvitationModal: React.FC<Props> = ({
|
||||
setIsOpen,
|
||||
workspace_slug,
|
||||
members,
|
||||
user,
|
||||
}) => {
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
@ -54,7 +56,7 @@ const SendWorkspaceInvitationModal: React.FC<Props> = ({
|
||||
|
||||
const onSubmit = async (formData: IWorkspaceMemberInvitation) => {
|
||||
await workspaceService
|
||||
.inviteWorkspace(workspace_slug, { emails: [formData] })
|
||||
.inviteWorkspace(workspace_slug, { emails: [formData] }, user)
|
||||
.then((res) => {
|
||||
setIsOpen(false);
|
||||
handleClose();
|
||||
@ -101,7 +103,10 @@ const SendWorkspaceInvitationModal: React.FC<Props> = ({
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className="space-y-5">
|
||||
<div>
|
||||
<Dialog.Title as="h3" className="text-lg font-medium leading-6 text-brand-base">
|
||||
<Dialog.Title
|
||||
as="h3"
|
||||
className="text-lg font-medium leading-6 text-brand-base"
|
||||
>
|
||||
Members
|
||||
</Dialog.Title>
|
||||
<p className="text-sm text-brand-secondary">
|
||||
|
@ -46,7 +46,10 @@ const SingleInvitation: React.FC<Props> = ({
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="text-sm font-medium">{truncateText(invitation.workspace.name, 30)}</div>
|
||||
<p className="text-sm text-brand-secondary">
|
||||
Invited by {invitation.workspace.owner.first_name}
|
||||
Invited by{" "}
|
||||
{invitation.created_by_detail
|
||||
? invitation.created_by_detail.first_name
|
||||
: invitation.workspace.owner.first_name}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex-shrink-0 self-center">
|
||||
|
@ -18,6 +18,7 @@ import {
|
||||
IProjectMember,
|
||||
TIssueGroupByOptions,
|
||||
TIssueOrderByOptions,
|
||||
ICurrentUserResponse,
|
||||
} from "types";
|
||||
// fetch-keys
|
||||
import {
|
||||
@ -26,6 +27,7 @@ import {
|
||||
USER_PROJECT_VIEW,
|
||||
VIEW_DETAILS,
|
||||
} from "constants/fetch-keys";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
|
||||
export const issueViewContext = createContext<ContextType>({} as ContextType);
|
||||
|
||||
@ -212,33 +214,54 @@ const saveCycleFilters = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
cycleId: string,
|
||||
state: any
|
||||
state: any,
|
||||
user: ICurrentUserResponse | undefined
|
||||
) => {
|
||||
await cyclesService.patchCycle(workspaceSlug, projectId, cycleId, {
|
||||
...state,
|
||||
});
|
||||
await cyclesService.patchCycle(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
cycleId,
|
||||
{
|
||||
...state,
|
||||
},
|
||||
user
|
||||
);
|
||||
};
|
||||
|
||||
const saveModuleFilters = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
moduleId: string,
|
||||
state: any
|
||||
state: any,
|
||||
user: ICurrentUserResponse | undefined
|
||||
) => {
|
||||
await modulesService.patchModule(workspaceSlug, projectId, moduleId, {
|
||||
...state,
|
||||
});
|
||||
await modulesService.patchModule(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
moduleId,
|
||||
{
|
||||
...state,
|
||||
},
|
||||
user
|
||||
);
|
||||
};
|
||||
|
||||
const saveViewFilters = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
viewId: string,
|
||||
state: any
|
||||
state: any,
|
||||
user: ICurrentUserResponse | undefined
|
||||
) => {
|
||||
await viewsService.patchView(workspaceSlug, projectId, viewId, {
|
||||
...state,
|
||||
});
|
||||
await viewsService.patchView(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
viewId,
|
||||
{
|
||||
...state,
|
||||
},
|
||||
user
|
||||
);
|
||||
};
|
||||
|
||||
const setNewDefault = async (workspaceSlug: string, projectId: string, state: any) => {
|
||||
@ -267,6 +290,8 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { data: myViewProps, mutate: mutateMyViewProps } = useSWR(
|
||||
workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId as string) : null,
|
||||
workspaceSlug && projectId
|
||||
@ -505,14 +530,20 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
|
||||
};
|
||||
}, false);
|
||||
|
||||
saveCycleFilters(workspaceSlug.toString(), projectId.toString(), cycleId.toString(), {
|
||||
view_props: {
|
||||
filters: {
|
||||
...state.filters,
|
||||
...property,
|
||||
saveCycleFilters(
|
||||
workspaceSlug.toString(),
|
||||
projectId.toString(),
|
||||
cycleId.toString(),
|
||||
{
|
||||
view_props: {
|
||||
filters: {
|
||||
...state.filters,
|
||||
...property,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
user
|
||||
);
|
||||
} else if (moduleId) {
|
||||
mutateModuleDetails((prevData: any) => {
|
||||
if (!prevData) return prevData;
|
||||
@ -528,14 +559,20 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
|
||||
};
|
||||
}, false);
|
||||
|
||||
saveModuleFilters(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), {
|
||||
view_props: {
|
||||
filters: {
|
||||
...state.filters,
|
||||
...property,
|
||||
saveModuleFilters(
|
||||
workspaceSlug.toString(),
|
||||
projectId.toString(),
|
||||
moduleId.toString(),
|
||||
{
|
||||
view_props: {
|
||||
filters: {
|
||||
...state.filters,
|
||||
...property,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
user
|
||||
);
|
||||
} else if (viewId) {
|
||||
mutateViewDetails((prevData: any) => {
|
||||
if (!prevData) return prevData;
|
||||
@ -548,12 +585,18 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
|
||||
};
|
||||
}, false);
|
||||
if (saveToServer)
|
||||
saveViewFilters(workspaceSlug as string, projectId as string, viewId as string, {
|
||||
query_data: {
|
||||
...state.filters,
|
||||
...property,
|
||||
saveViewFilters(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
viewId as string,
|
||||
{
|
||||
query_data: {
|
||||
...state.filters,
|
||||
...property,
|
||||
},
|
||||
},
|
||||
});
|
||||
user
|
||||
);
|
||||
} else {
|
||||
mutateMyViewProps((prevData) => {
|
||||
if (!prevData) return prevData;
|
||||
|
@ -6,6 +6,8 @@ import useSWR from "swr";
|
||||
|
||||
// react-hook-form
|
||||
import { useForm } from "react-hook-form";
|
||||
// hooks
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// headless ui
|
||||
import { Tab } from "@headlessui/react";
|
||||
// services
|
||||
@ -35,6 +37,8 @@ const Analytics = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { control, watch, setValue } = useForm<IAnalyticsParams>({ defaultValues });
|
||||
|
||||
const params: IAnalyticsParams = {
|
||||
@ -59,7 +63,7 @@ const Analytics = () => {
|
||||
? "WORKSPACE_SCOPE_AND_DEMAND_ANALYTICS"
|
||||
: "WORKSPACE_CUSTOM_ANALYTICS";
|
||||
|
||||
trackEventServices.trackAnalyticsEvent(eventPayload, eventType);
|
||||
trackEventServices.trackAnalyticsEvent(eventPayload, eventType, user);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@ -67,7 +71,8 @@ const Analytics = () => {
|
||||
|
||||
trackEventServices.trackAnalyticsEvent(
|
||||
{ workspaceSlug: workspaceSlug?.toString() },
|
||||
"WORKSPACE_SCOPE_AND_DEMAND_ANALYTICS"
|
||||
"WORKSPACE_SCOPE_AND_DEMAND_ANALYTICS",
|
||||
user
|
||||
);
|
||||
}, [workspaceSlug]);
|
||||
|
||||
@ -119,6 +124,7 @@ const Analytics = () => {
|
||||
params={params}
|
||||
control={control}
|
||||
setValue={setValue}
|
||||
user={user}
|
||||
fullScreen
|
||||
/>
|
||||
</Tab.Panel>
|
||||
|
@ -19,6 +19,7 @@ import cycleServices from "services/cycles.service";
|
||||
import projectService from "services/project.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// components
|
||||
import { AnalyticsProjectModal } from "components/analytics";
|
||||
// ui
|
||||
@ -44,6 +45,8 @@ const SingleCycle: React.FC = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, cycleId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const { data: activeProject } = useSWR(
|
||||
@ -94,7 +97,7 @@ const SingleCycle: React.FC = () => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
await issuesService
|
||||
.addIssueToCycle(workspaceSlug as string, projectId as string, cycleId as string, data)
|
||||
.addIssueToCycle(workspaceSlug as string, projectId as string, cycleId as string, data, user)
|
||||
.then(() => {
|
||||
mutate(CYCLE_ISSUES(cycleId as string));
|
||||
})
|
||||
@ -185,6 +188,7 @@ const SingleCycle: React.FC = () => {
|
||||
cycle={cycleDetails}
|
||||
isOpen={cycleSidebar}
|
||||
isCompleted={cycleStatus === "completed" ?? false}
|
||||
user={user}
|
||||
/>
|
||||
</ProjectAuthorizationWrapper>
|
||||
</IssueViewContextProvider>
|
||||
|
@ -8,6 +8,7 @@ import useSWR from "swr";
|
||||
import { Tab } from "@headlessui/react";
|
||||
// hooks
|
||||
import useLocalStorage from "hooks/use-local-storage";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// services
|
||||
import cycleService from "services/cycles.service";
|
||||
import projectService from "services/project.service";
|
||||
@ -62,6 +63,8 @@ const ProjectCycles: NextPage = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { data: activeProject } = useSWR(
|
||||
workspaceSlug && projectId ? PROJECT_DETAILS(projectId as string) : null,
|
||||
workspaceSlug && projectId
|
||||
@ -110,6 +113,7 @@ const ProjectCycles: NextPage = () => {
|
||||
isOpen={createUpdateCycleModal}
|
||||
handleClose={() => setCreateUpdateCycleModal(false)}
|
||||
data={selectedCycle}
|
||||
user={user}
|
||||
/>
|
||||
<div className="space-y-5 p-8 h-full flex flex-col overflow-hidden">
|
||||
<div className="flex gap-4 justify-between">
|
||||
|
@ -7,6 +7,8 @@ import useSWR, { mutate } from "swr";
|
||||
|
||||
// react-hook-form
|
||||
import { useForm } from "react-hook-form";
|
||||
// hooks
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// services
|
||||
import issuesService from "services/issues.service";
|
||||
// layouts
|
||||
@ -50,6 +52,8 @@ const IssueDetailsPage: NextPage = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, issueId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { data: issueDetails, mutate: mutateIssueDetails } = useSWR<IIssue | undefined>(
|
||||
workspaceSlug && projectId && issueId ? ISSUE_DETAILS(issueId as string) : null,
|
||||
workspaceSlug && projectId && issueId
|
||||
@ -92,7 +96,7 @@ const IssueDetailsPage: NextPage = () => {
|
||||
|
||||
const payload = { ...formData };
|
||||
await issuesService
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload)
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
|
||||
.then((res) => {
|
||||
mutateIssueDetails();
|
||||
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
||||
@ -192,7 +196,7 @@ const IssueDetailsPage: NextPage = () => {
|
||||
) : null}
|
||||
<IssueDescriptionForm issue={issueDetails} handleFormSubmit={submitChanges} />
|
||||
<div className="mt-2 space-y-2">
|
||||
<SubIssuesList parentIssue={issueDetails} />
|
||||
<SubIssuesList parentIssue={issueDetails} user={user} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-3 py-3">
|
||||
@ -204,8 +208,8 @@ const IssueDetailsPage: NextPage = () => {
|
||||
</div>
|
||||
<div className="space-y-5 pt-3">
|
||||
<h3 className="text-lg text-brand-base">Comments/Activity</h3>
|
||||
<IssueActivitySection />
|
||||
<AddComment />
|
||||
<IssueActivitySection user={user} />
|
||||
<AddComment user={user} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="basis-1/3 space-y-5 border-l border-brand-base p-5">
|
||||
|
@ -17,6 +17,7 @@ import modulesService from "services/modules.service";
|
||||
import issuesService from "services/issues.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// layouts
|
||||
import { ProjectAuthorizationWrapper } from "layouts/auth-layout";
|
||||
// contexts
|
||||
@ -49,6 +50,8 @@ const SingleModule: React.FC = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, moduleId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const { data: issues } = useSWR(
|
||||
@ -95,7 +98,13 @@ const SingleModule: React.FC = () => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
await modulesService
|
||||
.addIssuesToModule(workspaceSlug as string, projectId as string, moduleId as string, data)
|
||||
.addIssuesToModule(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
moduleId as string,
|
||||
data,
|
||||
user
|
||||
)
|
||||
.then(() => mutate(MODULE_ISSUES(moduleId as string)))
|
||||
.catch(() =>
|
||||
setToastAlert({
|
||||
@ -186,6 +195,7 @@ const SingleModule: React.FC = () => {
|
||||
module={moduleDetails}
|
||||
isOpen={moduleSidebar}
|
||||
moduleIssues={moduleIssues}
|
||||
user={user}
|
||||
/>
|
||||
</ProjectAuthorizationWrapper>
|
||||
</IssueViewContextProvider>
|
||||
|
@ -6,6 +6,8 @@ import useSWR from "swr";
|
||||
|
||||
// layouts
|
||||
import { ProjectAuthorizationWrapper } from "layouts/auth-layout";
|
||||
// hooks
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// services
|
||||
import projectService from "services/project.service";
|
||||
import modulesService from "services/modules.service";
|
||||
@ -37,6 +39,8 @@ const ProjectModules: NextPage = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { data: activeProject } = useSWR(
|
||||
workspaceSlug && projectId ? PROJECT_DETAILS(projectId as string) : null,
|
||||
workspaceSlug && projectId
|
||||
@ -89,6 +93,7 @@ const ProjectModules: NextPage = () => {
|
||||
isOpen={createUpdateModule}
|
||||
setIsOpen={setCreateUpdateModule}
|
||||
data={selectedModule}
|
||||
user={user}
|
||||
/>
|
||||
{modules ? (
|
||||
modules.length > 0 ? (
|
||||
@ -126,6 +131,7 @@ const ProjectModules: NextPage = () => {
|
||||
key={module.id}
|
||||
module={module}
|
||||
handleEditModule={() => handleEditModule(module)}
|
||||
user={user}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
@ -116,7 +116,7 @@ const SinglePage: NextPage = () => {
|
||||
if (!formData.name || formData.name.length === 0 || formData.name === "") return;
|
||||
|
||||
await pagesService
|
||||
.patchPage(workspaceSlug as string, projectId as string, pageId as string, formData)
|
||||
.patchPage(workspaceSlug as string, projectId as string, pageId as string, formData, user)
|
||||
.then(() => {
|
||||
mutate<IPage>(
|
||||
PAGE_DETAILS(pageId as string),
|
||||
@ -143,7 +143,7 @@ const SinglePage: NextPage = () => {
|
||||
);
|
||||
|
||||
await pagesService
|
||||
.patchPage(workspaceSlug as string, projectId as string, pageId as string, formData)
|
||||
.patchPage(workspaceSlug as string, projectId as string, pageId as string, formData, user)
|
||||
.then(() => {
|
||||
mutate(PAGE_DETAILS(pageId as string));
|
||||
});
|
||||
@ -237,7 +237,8 @@ const SinglePage: NextPage = () => {
|
||||
result.draggableId,
|
||||
{
|
||||
sort_order: newSortOrder,
|
||||
}
|
||||
},
|
||||
user
|
||||
);
|
||||
};
|
||||
|
||||
@ -529,6 +530,7 @@ const SinglePage: NextPage = () => {
|
||||
block={block}
|
||||
projectDetails={projectDetails}
|
||||
index={index}
|
||||
user={user}
|
||||
/>
|
||||
))}
|
||||
{provided.placeholder}
|
||||
@ -542,6 +544,7 @@ const SinglePage: NextPage = () => {
|
||||
<CreateUpdateBlockInline
|
||||
handleClose={() => setCreateBlockForm(false)}
|
||||
focus="name"
|
||||
user={user}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -550,6 +553,7 @@ const SinglePage: NextPage = () => {
|
||||
isOpen={labelModal}
|
||||
handleClose={() => setLabelModal(false)}
|
||||
projectId={projectId}
|
||||
user={user}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
@ -562,7 +566,7 @@ const SinglePage: NextPage = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<CreateBlock />
|
||||
<CreateBlock user={user} />
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
|
@ -27,6 +27,7 @@ import { TPageViewProps } from "types";
|
||||
import type { NextPage } from "next";
|
||||
// fetch-keys
|
||||
import { PROJECT_DETAILS } from "constants/fetch-keys";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
|
||||
const AllPagesList = dynamic<TPagesListProps>(
|
||||
() => import("components/pages").then((a) => a.AllPagesList),
|
||||
@ -66,6 +67,8 @@ const ProjectPages: NextPage = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { storedValue: pageTab, setValue: setPageTab } = useLocalStorage("pageTab", "Recent");
|
||||
|
||||
const { data: projectDetails } = useSWR(
|
||||
@ -98,6 +101,7 @@ const ProjectPages: NextPage = () => {
|
||||
<CreateUpdatePageModal
|
||||
isOpen={createUpdatePageModal}
|
||||
handleClose={() => setCreateUpdatePageModal(false)}
|
||||
user={user}
|
||||
/>
|
||||
<ProjectAuthorizationWrapper
|
||||
breadcrumbs={
|
||||
|
@ -13,6 +13,7 @@ import { ProjectAuthorizationWrapper } from "layouts/auth-layout";
|
||||
import projectService from "services/project.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// components
|
||||
import { SettingsHeader } from "components/project";
|
||||
// ui
|
||||
@ -35,6 +36,8 @@ const ControlSettings: NextPage = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { data: projectDetails } = useSWR<IProject>(
|
||||
workspaceSlug && projectId ? PROJECT_DETAILS(projectId as string) : null,
|
||||
workspaceSlug && projectId
|
||||
@ -65,7 +68,7 @@ const ControlSettings: NextPage = () => {
|
||||
};
|
||||
|
||||
await projectService
|
||||
.updateProject(workspaceSlug as string, projectId as string, payload)
|
||||
.updateProject(workspaceSlug as string, projectId as string, payload, user)
|
||||
.then((res) => {
|
||||
mutate(PROJECT_DETAILS(projectId as string));
|
||||
mutate(PROJECTS_LIST(workspaceSlug as string));
|
||||
|
@ -16,6 +16,7 @@ import { CreateUpdateEstimateModal, SingleEstimate } from "components/estimates"
|
||||
import { SettingsHeader } from "components/project";
|
||||
//hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// ui
|
||||
import { EmptyState, Loader, SecondaryButton } from "components/ui";
|
||||
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
|
||||
@ -37,6 +38,8 @@ const EstimatesSettings: NextPage = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const { projectDetails } = useProjectDetails();
|
||||
@ -63,7 +66,7 @@ const EstimatesSettings: NextPage = () => {
|
||||
);
|
||||
|
||||
estimatesService
|
||||
.deleteEstimate(workspaceSlug as string, projectId as string, estimateId)
|
||||
.deleteEstimate(workspaceSlug as string, projectId as string, estimateId, user)
|
||||
.catch(() => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
@ -87,7 +90,7 @@ const EstimatesSettings: NextPage = () => {
|
||||
);
|
||||
|
||||
projectService
|
||||
.updateProject(workspaceSlug as string, projectId as string, { estimate: null })
|
||||
.updateProject(workspaceSlug as string, projectId as string, { estimate: null }, user)
|
||||
.catch(() =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
@ -106,6 +109,7 @@ const EstimatesSettings: NextPage = () => {
|
||||
setEstimateFormOpen(false);
|
||||
setEstimateToUpdate(undefined);
|
||||
}}
|
||||
user={user}
|
||||
/>
|
||||
<ProjectAuthorizationWrapper
|
||||
breadcrumbs={
|
||||
@ -149,6 +153,7 @@ const EstimatesSettings: NextPage = () => {
|
||||
estimate={estimate}
|
||||
editEstimate={(estimate) => editEstimate(estimate)}
|
||||
handleEstimateDelete={(estimateId) => removeEstimate(estimateId)}
|
||||
user={user}
|
||||
/>
|
||||
))}
|
||||
</section>
|
||||
|
@ -11,6 +11,7 @@ import trackEventServices, { MiscellaneousEventType } from "services/track-event
|
||||
import { ProjectAuthorizationWrapper } from "layouts/auth-layout";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// components
|
||||
import { SettingsHeader } from "components/project";
|
||||
// ui
|
||||
@ -75,6 +76,8 @@ const FeaturesSettings: NextPage = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const { data: projectDetails } = useSWR(
|
||||
@ -134,7 +137,7 @@ const FeaturesSettings: NextPage = () => {
|
||||
});
|
||||
|
||||
await projectService
|
||||
.updateProject(workspaceSlug as string, projectId as string, formData)
|
||||
.updateProject(workspaceSlug as string, projectId as string, formData, user)
|
||||
.then(() => {
|
||||
mutate(
|
||||
projectDetails.is_favorite
|
||||
@ -194,7 +197,8 @@ const FeaturesSettings: NextPage = () => {
|
||||
},
|
||||
!projectDetails?.[feature.property as keyof IProject]
|
||||
? getEventType(feature.title, true)
|
||||
: getEventType(feature.title, false)
|
||||
: getEventType(feature.title, false),
|
||||
user
|
||||
);
|
||||
handleSubmit({
|
||||
[feature.property]: !projectDetails?.[feature.property as keyof IProject],
|
||||
|
@ -17,6 +17,7 @@ import { ImagePickerPopover } from "components/core";
|
||||
import EmojiIconPicker from "components/emoji-icon-picker";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// ui
|
||||
import {
|
||||
Input,
|
||||
@ -45,6 +46,8 @@ const defaultValues: Partial<IProject> = {
|
||||
const GeneralSettings: NextPage = () => {
|
||||
const [selectProject, setSelectedProject] = useState<string | null>(null);
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const router = useRouter();
|
||||
@ -83,7 +86,7 @@ const GeneralSettings: NextPage = () => {
|
||||
if (!workspaceSlug || !projectDetails) return;
|
||||
|
||||
await projectService
|
||||
.updateProject(workspaceSlug as string, projectDetails.id, payload)
|
||||
.updateProject(workspaceSlug as string, projectDetails.id, payload, user)
|
||||
.then((res) => {
|
||||
mutate<IProject>(
|
||||
PROJECT_DETAILS(projectDetails.id),
|
||||
@ -154,6 +157,7 @@ const GeneralSettings: NextPage = () => {
|
||||
onSuccess={() => {
|
||||
router.push(`/${workspaceSlug}/projects`);
|
||||
}}
|
||||
user={user}
|
||||
/>
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="p-8">
|
||||
<SettingsHeader />
|
||||
|
@ -4,6 +4,8 @@ import { useRouter } from "next/router";
|
||||
|
||||
import useSWR from "swr";
|
||||
|
||||
// hooks
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// services
|
||||
import projectService from "services/project.service";
|
||||
import issuesService from "services/issues.service";
|
||||
@ -47,6 +49,8 @@ const LabelsSettings: NextPage = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const scrollToRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const { data: projectDetails } = useSWR(
|
||||
@ -85,11 +89,13 @@ const LabelsSettings: NextPage = () => {
|
||||
isOpen={labelsListModal}
|
||||
handleClose={() => setLabelsListModal(false)}
|
||||
parent={parentLabel}
|
||||
user={user}
|
||||
/>
|
||||
<DeleteLabelModal
|
||||
isOpen={!!selectDeleteLabel}
|
||||
data={selectDeleteLabel ?? null}
|
||||
onClose={() => setSelectDeleteLabel(null)}
|
||||
user={user}
|
||||
/>
|
||||
<ProjectAuthorizationWrapper
|
||||
breadcrumbs={
|
||||
@ -160,6 +166,7 @@ const LabelsSettings: NextPage = () => {
|
||||
});
|
||||
}}
|
||||
handleLabelDelete={() => setSelectDeleteLabel(label)}
|
||||
user={user}
|
||||
/>
|
||||
);
|
||||
})
|
||||
|
@ -135,6 +135,7 @@ const MembersSettings: NextPage = () => {
|
||||
isOpen={inviteModal}
|
||||
setIsOpen={setInviteModal}
|
||||
members={members}
|
||||
user={user}
|
||||
/>
|
||||
<ProjectAuthorizationWrapper
|
||||
breadcrumbs={
|
||||
|
@ -8,6 +8,7 @@ import useSWR from "swr";
|
||||
import stateService from "services/state.service";
|
||||
// hooks
|
||||
import useProjectDetails from "hooks/use-project-details";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// layouts
|
||||
import { ProjectAuthorizationWrapper } from "layouts/auth-layout";
|
||||
// components
|
||||
@ -38,6 +39,8 @@ const StatesSettings: NextPage = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { projectDetails } = useProjectDetails();
|
||||
|
||||
const { data: states } = useSWR(
|
||||
@ -55,6 +58,7 @@ const StatesSettings: NextPage = () => {
|
||||
isOpen={!!selectDeleteState}
|
||||
data={statesList?.find((s) => s.id === selectDeleteState) ?? null}
|
||||
onClose={() => setSelectDeleteState(null)}
|
||||
user={user}
|
||||
/>
|
||||
<ProjectAuthorizationWrapper
|
||||
breadcrumbs={
|
||||
@ -100,6 +104,7 @@ const StatesSettings: NextPage = () => {
|
||||
}}
|
||||
data={null}
|
||||
selectedGroup={key as keyof StateGroup}
|
||||
user={user}
|
||||
/>
|
||||
)}
|
||||
{orderedStateGroups[key].map((state, index) =>
|
||||
@ -111,6 +116,7 @@ const StatesSettings: NextPage = () => {
|
||||
statesList={statesList}
|
||||
handleEditState={() => setSelectedState(state.id)}
|
||||
handleDeleteState={() => setSelectDeleteState(state.id)}
|
||||
user={user}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
@ -126,6 +132,7 @@ const StatesSettings: NextPage = () => {
|
||||
statesList?.find((state) => state.id === selectedState) ?? null
|
||||
}
|
||||
selectedGroup={key as keyof StateGroup}
|
||||
user={user}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
@ -4,6 +4,8 @@ import { useRouter } from "next/router";
|
||||
|
||||
import useSWR from "swr";
|
||||
|
||||
// hooks
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// services
|
||||
import viewsService from "services/views.service";
|
||||
import projectService from "services/project.service";
|
||||
@ -34,6 +36,8 @@ const ProjectViews: NextPage = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { data: activeProject } = useSWR(
|
||||
workspaceSlug && projectId ? PROJECT_DETAILS(projectId as string) : null,
|
||||
workspaceSlug && projectId
|
||||
@ -86,11 +90,13 @@ const ProjectViews: NextPage = () => {
|
||||
isOpen={createUpdateViewModal}
|
||||
handleClose={() => setCreateUpdateViewModal(false)}
|
||||
data={selectedViewToUpdate}
|
||||
user={user}
|
||||
/>
|
||||
<DeleteViewModal
|
||||
isOpen={deleteViewModal}
|
||||
data={selectedViewToDelete}
|
||||
setIsOpen={setDeleteViewModal}
|
||||
user={user}
|
||||
/>
|
||||
{views ? (
|
||||
views.length > 0 ? (
|
||||
|
@ -9,6 +9,7 @@ import projectService from "services/project.service";
|
||||
// hooks
|
||||
import useProjects from "hooks/use-projects";
|
||||
import useWorkspaces from "hooks/use-workspaces";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// layouts
|
||||
import { WorkspaceAuthorizationLayout } from "layouts/auth-layout";
|
||||
// components
|
||||
@ -30,6 +31,8 @@ const ProjectsPage: NextPage = () => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
// context data
|
||||
const { activeWorkspace } = useWorkspaces();
|
||||
const { projects } = useProjects();
|
||||
@ -81,6 +84,7 @@ const ProjectsPage: NextPage = () => {
|
||||
isOpen={!!deleteProject}
|
||||
onClose={() => setDeleteProject(null)}
|
||||
data={projects?.find((item) => item.id === deleteProject) ?? null}
|
||||
user={user}
|
||||
/>
|
||||
{projects ? (
|
||||
<div className="p-8">
|
||||
|
@ -12,6 +12,7 @@ import workspaceService from "services/workspace.service";
|
||||
import fileService from "services/file.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// layouts
|
||||
import { WorkspaceAuthorizationLayout } from "layouts/auth-layout";
|
||||
import SettingsNavbar from "layouts/settings-navbar";
|
||||
@ -49,6 +50,8 @@ const WorkspaceSettings: NextPage = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const { data: activeWorkspace } = useSWR(
|
||||
@ -82,7 +85,7 @@ const WorkspaceSettings: NextPage = () => {
|
||||
};
|
||||
|
||||
await workspaceService
|
||||
.updateWorkspace(activeWorkspace.slug, payload)
|
||||
.updateWorkspace(activeWorkspace.slug, payload, user)
|
||||
.then((res) => {
|
||||
mutate<IWorkspace[]>(USER_WORKSPACES, (prevData) =>
|
||||
prevData?.map((workspace) => (workspace.id === res.id ? res : workspace))
|
||||
@ -114,7 +117,7 @@ const WorkspaceSettings: NextPage = () => {
|
||||
|
||||
fileService.deleteFile(asset).then(() => {
|
||||
workspaceService
|
||||
.updateWorkspace(activeWorkspace.slug, { logo: "" })
|
||||
.updateWorkspace(activeWorkspace.slug, { logo: "" }, user)
|
||||
.then((res) => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
@ -169,6 +172,7 @@ const WorkspaceSettings: NextPage = () => {
|
||||
setIsOpen(false);
|
||||
}}
|
||||
data={activeWorkspace ?? null}
|
||||
user={user}
|
||||
/>
|
||||
<div className="p-8">
|
||||
<SettingsHeader />
|
||||
|
@ -135,6 +135,7 @@ const MembersSettings: NextPage = () => {
|
||||
setIsOpen={setInviteModal}
|
||||
workspace_slug={workspaceSlug as string}
|
||||
members={members}
|
||||
user={user}
|
||||
/>
|
||||
<WorkspaceAuthorizationLayout
|
||||
breadcrumbs={
|
||||
|
@ -10,28 +10,12 @@ const jitsu = createClient({
|
||||
});
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { eventName, extra } = req.body;
|
||||
const { eventName, user, extra } = req.body;
|
||||
|
||||
if (!eventName) {
|
||||
return res.status(400).json({ message: "Bad request" });
|
||||
}
|
||||
|
||||
const cookie = convertCookieStringToObject(req.headers.cookie);
|
||||
const accessToken = cookie?.accessToken;
|
||||
|
||||
if (!accessToken) return res.status(401).json({ message: "Unauthorized" });
|
||||
|
||||
const user = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/users/me/`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((data) => data.user)
|
||||
.catch(() => res.status(401).json({ message: "Unauthorized" }));
|
||||
|
||||
if (!user) return res.status(401).json({ message: "Unauthorized" });
|
||||
|
||||
// TODO: cache user info
|
||||
|
@ -47,6 +47,7 @@ const CreateWorkspace: NextPage = () => {
|
||||
defaultValues={defaultValues}
|
||||
setDefaultValues={() => {}}
|
||||
onSubmit={(res) => router.push(`/${res.slug}`)}
|
||||
user={user}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -95,21 +95,21 @@ const HomePage: NextPage = () => {
|
||||
<Spinner />
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex h-screen w-full items-center justify-center overflow-auto bg-gray-50">
|
||||
<div className="flex h-screen w-full items-center justify-center overflow-auto">
|
||||
<div className="flex min-h-full w-full flex-col justify-center py-12 px-6 lg:px-8">
|
||||
<div className="flex flex-col gap-10 sm:mx-auto sm:w-full sm:max-w-md">
|
||||
<div className="flex flex-col items-center justify-center gap-10">
|
||||
<Image src={Logo} height={80} width={80} alt="Plane Web Logo" />
|
||||
<div className="text-center text-xl font-medium text-black">
|
||||
<div className="text-center text-xl font-medium text-brand-base">
|
||||
Sign In to your Plane Account
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col rounded-[10px] bg-white shadow-md">
|
||||
<div className="flex flex-col rounded-[10px] bg-brand-base shadow-md">
|
||||
{parseInt(process.env.NEXT_PUBLIC_ENABLE_OAUTH || "0") ? (
|
||||
<>
|
||||
<EmailCodeForm />
|
||||
<div className="flex flex-col gap-3 py-5 px-5 border-t items-center justify-center border-gray-300 ">
|
||||
<div className="flex flex-col items-center justify-center gap-3 border-t border-brand-base py-5 px-5">
|
||||
<GoogleLoginButton handleSignIn={handleGoogleSignIn} />
|
||||
<GithubLoginButton handleSignIn={handleGithubSignIn} />
|
||||
</div>
|
||||
|
@ -124,7 +124,7 @@ const OnBoard: NextPage = () => {
|
||||
</div>
|
||||
</div>
|
||||
) : workspaces && workspaces.length > 0 ? (
|
||||
<div className="flex flex-col gap-y-3">
|
||||
<div className="flex flex-col w-full overflow-auto gap-y-3">
|
||||
<h2 className="mb-4 text-xl font-medium">Your workspaces</h2>
|
||||
{workspaces.map((workspace) => (
|
||||
<Link key={workspace.id} href={workspace.slug}>
|
||||
|
@ -49,18 +49,18 @@ const MagicSignIn: NextPage = () => {
|
||||
|
||||
return (
|
||||
<DefaultLayout>
|
||||
<div className="flex h-screen w-full items-center justify-center overflow-auto bg-gray-50">
|
||||
<div className="h-screen w-full overflow-auto bg-brand-surface-1">
|
||||
{isSigningIn ? (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center gap-y-2">
|
||||
<h2 className="text-4xl">Signing you in...</h2>
|
||||
<p className="text-sm text-gray-600">
|
||||
<p className="text-sm text-brand-secondary">
|
||||
Please wait while we are preparing your take off.
|
||||
</p>
|
||||
</div>
|
||||
) : errorSigningIn ? (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center gap-y-2">
|
||||
<h2 className="text-4xl">Error</h2>
|
||||
<p className="text-sm text-gray-600">
|
||||
<p className="text-sm text-brand-secondary">
|
||||
{errorSigningIn}.
|
||||
<span
|
||||
className="cursor-pointer underline"
|
||||
@ -90,7 +90,7 @@ const MagicSignIn: NextPage = () => {
|
||||
) : (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center gap-y-2">
|
||||
<h2 className="text-4xl">Success</h2>
|
||||
<p className="text-sm text-gray-600">Redirecting you to the app...</p>
|
||||
<p className="text-sm text-brand-secondary">Redirecting you to the app...</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@ -53,9 +53,9 @@ const Onboarding: NextPage = () => {
|
||||
{step === 1 ? (
|
||||
<UserDetails user={user} setStep={setStep} setUserRole={setUserRole} />
|
||||
) : step === 2 ? (
|
||||
<Workspace setStep={setStep} setWorkspace={setWorkspace} />
|
||||
<Workspace setStep={setStep} setWorkspace={setWorkspace} user={user} />
|
||||
) : (
|
||||
<InviteMembers setStep={setStep} workspace={workspace} />
|
||||
<InviteMembers setStep={setStep} workspace={workspace} user={user} />
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
@ -80,7 +80,7 @@ const Onboarding: NextPage = () => {
|
||||
onClick={() => {
|
||||
if (step === 8) {
|
||||
userService
|
||||
.updateUserOnBoard({ userRole })
|
||||
.updateUserOnBoard({ userRole }, user)
|
||||
.then(async () => {
|
||||
mutate<ICurrentUserResponse>(
|
||||
CURRENT_USER,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user