Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion web/components/headers/global-issues.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
globalViewFilters: globalViewFiltersStore,
workspaceFilter: workspaceFilterStore,
workspace: workspaceStore,
workspaceMember: { workspaceMembers },
project: projectStore,
} = useMobxStore();

Expand Down Expand Up @@ -145,7 +146,7 @@ export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
handleFiltersUpdate={handleFiltersUpdate}
layoutDisplayFiltersOptions={ISSUE_DISPLAY_FILTERS_BY_LAYOUT.my_issues.spreadsheet}
labels={workspaceStore.workspaceLabels ?? undefined}
members={workspaceStore.workspaceMembers?.map((m) => m.member) ?? undefined}
members={workspaceMembers?.map((m) => m.member) ?? undefined}
projects={workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : undefined}
/>
</FiltersDropdown>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const GlobalViewsAppliedFiltersRoot = observer(() => {
globalViewFilters: globalViewFiltersStore,
project: projectStore,
workspace: workspaceStore,
workspaceMember: { workspaceMembers },
} = useMobxStore();

const viewDetails = globalViewId ? globalViewsStore.globalViewDetails[globalViewId.toString()] : undefined;
Expand Down Expand Up @@ -101,7 +102,7 @@ export const GlobalViewsAppliedFiltersRoot = observer(() => {
handleClearAllFilters={handleClearAllFilters}
handleRemoveFilter={handleRemoveFilter}
labels={workspaceStore.workspaceLabels ?? undefined}
members={workspaceStore.workspaceMembers?.map((m) => m.member)}
members={workspaceMembers?.map((m) => m.member)}
projects={workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : undefined}
/>
{storedFilters && viewDetails && areFiltersDifferent(storedFilters, viewDetails.query_data.filters ?? {}) && (
Expand Down
20 changes: 10 additions & 10 deletions web/components/issues/issue-layouts/properties/assignee.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,19 @@ export const IssuePropertyAssignee: React.FC<IIssuePropertyAssignee> = observer(
multiple = false,
noLabelBorder = false,
} = props;

const { workspace: workspaceStore, project: projectStore } = useMobxStore();
// store
const {
workspace: workspaceStore,
project: projectStore,
workspaceMember: { workspaceMembers, fetchWorkspaceMembers },
} = useMobxStore();
const workspaceSlug = workspaceStore?.workspaceSlug;

// states
const [query, setQuery] = useState("");

const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
const [isLoading, setIsLoading] = useState<Boolean>(false);

const workspaceMembers = workspaceSlug ? workspaceStore?.workspaceMembers : undefined;

const fetchProjectMembers = () => {
setIsLoading(true);
if (workspaceSlug && projectId)
Expand All @@ -59,10 +60,9 @@ export const IssuePropertyAssignee: React.FC<IIssuePropertyAssignee> = observer(
projectStore.fetchProjectMembers(workspaceSlug, projectId).then(() => setIsLoading(false));
};

const fetchWorkspaceMembers = () => {
const getWorkspaceMembers = () => {
setIsLoading(true);
if (workspaceSlug)
workspaceSlug && workspaceStore.fetchWorkspaceMembers(workspaceSlug).then(() => setIsLoading(false));
if (workspaceSlug) workspaceSlug && fetchWorkspaceMembers(workspaceSlug).then(() => setIsLoading(false));
};

const options = (workspaceMembers ?? [])?.map((member) => ({
Expand Down Expand Up @@ -138,7 +138,7 @@ export const IssuePropertyAssignee: React.FC<IIssuePropertyAssignee> = observer(
className={`flex items-center justify-between gap-1 w-full text-xs ${
disabled ? "cursor-not-allowed text-custom-text-200" : "cursor-pointer hover:bg-custom-background-80"
} ${buttonClassName}`}
onClick={() => !workspaceMembers && fetchWorkspaceMembers()}
onClick={() => !workspaceMembers && getWorkspaceMembers()}
>
{label}
{!hideDropdownArrow && !disabled && <ChevronDown className="h-3 w-3" aria-hidden="true" />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const GlobalViewLayoutRoot: React.FC<Props> = observer((props) => {
globalViewFilters: globalViewFiltersStore,
workspaceFilter: workspaceFilterStore,
workspace: workspaceStore,
workspaceMember: { workspaceMembers },
issueDetail: issueDetailStore,
project: projectStore,
} = useMobxStore();
Expand Down Expand Up @@ -106,7 +107,7 @@ export const GlobalViewLayoutRoot: React.FC<Props> = observer((props) => {
displayFilters={workspaceFilterStore.workspaceDisplayFilters}
handleDisplayFilterUpdate={handleDisplayFiltersUpdate}
issues={issues}
members={workspaceStore.workspaceMembers ? workspaceStore.workspaceMembers.map((m) => m.member) : undefined}
members={workspaceMembers?.map((m) => m.member)}
labels={workspaceStore.workspaceLabels ? workspaceStore.workspaceLabels : undefined}
handleIssueAction={() => {}}
handleUpdateIssue={handleUpdateIssue}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,12 @@ export const ProjectLayoutRoot: React.FC = observer(() => {

const { issue: issueStore, issueFilter: issueFilterStore } = useMobxStore();

const { isLoading } = useSWR(
workspaceSlug && projectId ? `PROJECT_FILTERS_AND_ISSUES_${projectId.toString()}` : null,
async () => {
if (workspaceSlug && projectId) {
await issueFilterStore.fetchUserProjectFilters(workspaceSlug.toString(), projectId.toString());
await issueStore.fetchIssues(workspaceSlug.toString(), projectId.toString());
}
useSWR(workspaceSlug && projectId ? `PROJECT_FILTERS_AND_ISSUES_${projectId.toString()}` : null, async () => {
if (workspaceSlug && projectId) {
await issueFilterStore.fetchUserProjectFilters(workspaceSlug.toString(), projectId.toString());
await issueStore.fetchIssues(workspaceSlug.toString(), projectId.toString());
}
);
});

const activeLayout = issueFilterStore.userDisplayFilters.layout;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { FC } from "react";
import Link from "next/link";
import { History } from "lucide-react";
// packages
import { Loader, Tooltip } from "@plane/ui";
import { Tooltip } from "@plane/ui";
// components
import { ActivityIcon, ActivityMessage } from "components/core";
import { IssueCommentCard } from "./comment-card";
Expand Down
8 changes: 5 additions & 3 deletions web/components/project/create-project-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,10 @@ export interface ICreateProjectForm {
export const CreateProjectModal: FC<Props> = observer((props) => {
const { isOpen, onClose, setToFavorite = false, workspaceSlug } = props;
// store
const { project: projectStore, workspace: workspaceStore } = useMobxStore();
const workspaceMembers = workspaceStore.members[workspaceSlug] || [];
const {
project: projectStore,
workspaceMember: { workspaceMembers },
} = useMobxStore();
// states
const [isChangeInIdentifierRequired, setIsChangeInIdentifierRequired] = useState(true);
// toast
Expand Down Expand Up @@ -370,7 +372,7 @@ export const CreateProjectModal: FC<Props> = observer((props) => {
<WorkspaceMemberSelect
value={value}
onChange={onChange}
options={workspaceMembers}
options={workspaceMembers || []}
placeholder="Select Lead"
/>
)}
Expand Down
9 changes: 5 additions & 4 deletions web/components/project/settings/features-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,10 @@ export const ProjectFeaturesList: FC<Props> = observer(() => {
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
// store
const { project: projectStore, user: userStore } = useMobxStore();
const { currentUser, currentProjectRole } = userStore;
const { currentProjectDetails } = projectStore;
const {
project: { currentProjectDetails, updateProject },
user: { currentUser, currentProjectRole },
} = useMobxStore();
const isAdmin = currentProjectRole === 20;
// hooks
const { setToastAlert } = useToast();
Expand All @@ -86,7 +87,7 @@ export const ProjectFeaturesList: FC<Props> = observer(() => {
title: "Success!",
message: "Project feature updated successfully.",
});
projectStore.updateProject(workspaceSlug.toString(), projectId.toString(), formData);
updateProject(workspaceSlug.toString(), projectId.toString(), formData);
};

if (!currentUser) return <></>;
Expand Down
9 changes: 5 additions & 4 deletions web/components/workspace/confirm-workspace-member-remove.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ export const ConfirmWorkspaceMemberRemove: React.FC<Props> = observer((props) =>

const [isRemoving, setIsRemoving] = useState(false);

const { user: userStore } = useMobxStore();
const user = userStore.currentUser;
const {
user: { currentUser },
} = useMobxStore();

const handleClose = () => {
onClose();
Expand Down Expand Up @@ -69,10 +70,10 @@ export const ConfirmWorkspaceMemberRemove: React.FC<Props> = observer((props) =>
</div>
<div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<Dialog.Title as="h3" className="text-lg font-medium leading-6 text-custom-text-100">
{user?.id === data?.memberId ? "Leave workspace?" : `Remove ${data?.display_name}?`}
{currentUser?.id === data?.memberId ? "Leave workspace?" : `Remove ${data?.display_name}?`}
</Dialog.Title>
<div className="mt-2">
{user?.id === data?.memberId ? (
{currentUser?.id === data?.memberId ? (
<p className="text-sm text-custom-text-200">
Are you sure you want to leave the workspace? You will no longer have access to this
workspace. This action cannot be undone.
Expand Down
68 changes: 27 additions & 41 deletions web/components/workspace/send-workspace-invitation-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,19 @@
import React, { useEffect } from "react";
import { mutate } from "swr";
import { Controller, useFieldArray, useForm } from "react-hook-form";
import { Dialog, Transition } from "@headlessui/react";
// services
import { WorkspaceService } from "services/workspace.service";
// hooks
import useToast from "hooks/use-toast";
// ui
import { Button, CustomSelect, Input } from "@plane/ui";
// icons
import { Plus, X } from "lucide-react";
// types
import { IUser, TUserWorkspaceRole } from "types";
import { IWorkspaceBulkInviteFormData, TUserWorkspaceRole } from "types";
// constants
import { ROLE } from "constants/workspace";
// fetch-keys
import { WORKSPACE_INVITATIONS } from "constants/fetch-keys";

type Props = {
isOpen: boolean;
onClose: () => void;
workspaceSlug: string;
user: IUser | undefined;
onSuccess?: () => Promise<void>;
onSubmit: (data: IWorkspaceBulkInviteFormData) => Promise<void> | undefined;
};

type EmailRole = {
Expand All @@ -43,11 +34,10 @@ const defaultValues: FormValues = {
],
};

const workspaceService = new WorkspaceService();

export const SendWorkspaceInvitationModal: React.FC<Props> = (props) => {
const { isOpen, onClose, workspaceSlug, user, onSuccess } = props;
const { isOpen, onClose, onSubmit } = props;

// form info
const {
control,
reset,
Expand All @@ -60,8 +50,6 @@ export const SendWorkspaceInvitationModal: React.FC<Props> = (props) => {
name: "emails",
});

const { setToastAlert } = useToast();

const handleClose = () => {
onClose();

Expand All @@ -71,31 +59,29 @@ export const SendWorkspaceInvitationModal: React.FC<Props> = (props) => {
}, 350);
};

const onSubmit = async (formData: FormValues) => {
if (!workspaceSlug) return;

await workspaceService
.inviteWorkspace(workspaceSlug, formData, user)
.then(async () => {
if (onSuccess) await onSuccess();

handleClose();

setToastAlert({
type: "success",
title: "Success!",
message: "Invitations sent successfully.",
});
})
.catch((err) =>
setToastAlert({
type: "error",
title: "Error!",
message: `${err.error ?? "Something went wrong. Please try again."}`,
})
)
.finally(() => mutate(WORKSPACE_INVITATIONS));
};
// const onSubmit = async (formData: FormValues) => {
// if (!workspaceSlug) return;

// return workspaceService
// .inviteWorkspace(workspaceSlug, formData, user)

// .then(async () => {
// if (onSuccess) await onSuccess();
// handleClose();
// setToastAlert({
// type: "success",
// title: "Success!",
// message: "Invitations sent successfully.",
// });
// })
// .catch((err) =>
// setToastAlert({
// type: "error",
// title: "Error!",
// message: `${err.error ?? "Something went wrong. Please try again."}`,
// })
// );
// };

const appendField = () => {
append({ email: "", role: 15 });
Expand Down
34 changes: 14 additions & 20 deletions web/components/workspace/settings/members-list-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import Link from "next/link";
import { useRouter } from "next/router";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// services
import { WorkspaceService } from "services/workspace.service";
// hooks
import useToast from "hooks/use-toast";
// components
Expand Down Expand Up @@ -33,17 +31,16 @@ type Props = {
};
};

// services
const workspaceService = new WorkspaceService();

export const WorkspaceMembersListItem: FC<Props> = (props) => {
const { member } = props;
// router
const router = useRouter();
const { workspaceSlug } = router.query;
// store
const { workspace: workspaceStore, user: userStore } = useMobxStore();
const { currentWorkspaceMemberInfo, currentWorkspaceRole } = userStore;
const {
workspaceMember: { removeMember, updateMember, deleteWorkspaceInvitation },
user: { currentWorkspaceMemberInfo, currentWorkspaceRole },
} = useMobxStore();
const isAdmin = currentWorkspaceRole === 20;
// states
const [removeMemberModal, setRemoveMemberModal] = useState(false);
Expand All @@ -54,7 +51,7 @@ export const WorkspaceMembersListItem: FC<Props> = (props) => {
if (!workspaceSlug) return;

if (member.member)
await workspaceStore.removeMember(workspaceSlug.toString(), member.id).catch((err) => {
await removeMember(workspaceSlug.toString(), member.id).catch((err) => {
const error = err?.error;
setToastAlert({
type: "error",
Expand All @@ -63,8 +60,7 @@ export const WorkspaceMembersListItem: FC<Props> = (props) => {
});
});
else
await workspaceService
.deleteWorkspaceInvitations(workspaceSlug.toString(), member.id)
await deleteWorkspaceInvitation(workspaceSlug.toString(), member.id)
.then(() => {
setToastAlert({
type: "success",
Expand Down Expand Up @@ -157,17 +153,15 @@ export const WorkspaceMembersListItem: FC<Props> = (props) => {
onChange={(value: TUserWorkspaceRole | undefined) => {
if (!workspaceSlug || !value) return;

workspaceStore
.updateMember(workspaceSlug.toString(), member.id, {
role: value,
})
.catch(() => {
setToastAlert({
type: "error",
title: "Error!",
message: "An error occurred while updating member role. Please try again.",
});
updateMember(workspaceSlug.toString(), member.id, {
role: value,
}).catch(() => {
setToastAlert({
type: "error",
title: "Error!",
message: "An error occurred while updating member role. Please try again.",
});
});
}}
disabled={
member.memberId === currentWorkspaceMemberInfo.member ||
Expand Down
Loading