chore: workspace roles (#3024)

* chore: workspace project roles for the current user

* dev: workspace and project member

* chore: store implementation for workspace user projects role

* view changes for the project roles

* connect workspace member's project roles to assigned

---------

Co-authored-by: gurusainath <gurusainath007@gmail.com>
Co-authored-by: rahulramesha <rahulramesham@gmail.com>
Co-authored-by: rahulramesha <71900764+rahulramesha@users.noreply.github.com>
This commit is contained in:
Nikhil 2023-12-07 19:46:57 +05:30 committed by sriram veeraghanta
parent 2a5ff3397f
commit 74ca187659
27 changed files with 348 additions and 173 deletions

View File

@ -13,6 +13,7 @@ from plane.app.views import (
UserProjectInvitationsViewset, UserProjectInvitationsViewset,
ProjectPublicCoverImagesEndpoint, ProjectPublicCoverImagesEndpoint,
ProjectDeployBoardViewSet, ProjectDeployBoardViewSet,
UserProjectRolesEndpoint,
) )
@ -74,6 +75,11 @@ urlpatterns = [
), ),
name="user-project-invitations", name="user-project-invitations",
), ),
path(
"users/me/workspaces/<str:slug>/project-roles/",
UserProjectRolesEndpoint.as_view(),
name="user-project-roles",
),
path( path(
"workspaces/<str:slug>/projects/<uuid:project_id>/join/<uuid:pk>/", "workspaces/<str:slug>/projects/<uuid:project_id>/join/<uuid:pk>/",
ProjectJoinEndpoint.as_view(), ProjectJoinEndpoint.as_view(),

View File

@ -11,6 +11,7 @@ from .project import (
ProjectFavoritesViewSet, ProjectFavoritesViewSet,
ProjectPublicCoverImagesEndpoint, ProjectPublicCoverImagesEndpoint,
ProjectDeployBoardViewSet, ProjectDeployBoardViewSet,
UserProjectRolesEndpoint,
) )
from .user import ( from .user import (
UserEndpoint, UserEndpoint,

View File

@ -39,6 +39,7 @@ from plane.app.serializers import (
) )
from plane.app.permissions import ( from plane.app.permissions import (
WorkspaceUserPermission,
ProjectBasePermission, ProjectBasePermission,
ProjectMemberPermission, ProjectMemberPermission,
) )
@ -165,7 +166,7 @@ class ProjectViewSet(WebhookMixin, BaseViewSet):
workspace__slug=slug, workspace__slug=slug,
is_active=True, is_active=True,
).select_related("member"), ).select_related("member"),
to_attr='members_list' to_attr="members_list",
) )
) )
.order_by("sort_order", "name") .order_by("sort_order", "name")
@ -1049,3 +1050,20 @@ class ProjectDeployBoardViewSet(BaseViewSet):
serializer = ProjectDeployBoardSerializer(project_deploy_board) serializer = ProjectDeployBoardSerializer(project_deploy_board)
return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.data, status=status.HTTP_200_OK)
class UserProjectRolesEndpoint(BaseAPIView):
permission_classes = [
WorkspaceUserPermission,
]
def get(self, request, slug):
project_members = ProjectMember.objects.filter(
workspace__slug=slug,
member_id=request.user.id,
).values("project_id", "role")
project_members = {
str(member["project_id"]): member["role"] for member in project_members
}
return Response(project_members, status=status.HTTP_200_OK)

View File

@ -30,7 +30,7 @@ from plane.license.api.serializers import (
from plane.license.api.permissions import ( from plane.license.api.permissions import (
InstanceAdminPermission, InstanceAdminPermission,
) )
from plane.db.models import User from plane.db.models import User, WorkspaceMember, ProjectMember
from plane.license.utils.encryption import encrypt_data from plane.license.utils.encryption import encrypt_data
@ -221,6 +221,37 @@ class InstanceAdminSignInEndpoint(BaseAPIView):
is_password_autoset=False, is_password_autoset=False,
) )
# if the current user is not using captain then add the current all users to workspace and projects
if user.email != "captain@plane.so":
# Add the current user also as a workspace member and project memeber to all the workspaces and projects
captain = User.objects.filter(email="captain@plane.so")
# Workspace members
workspace_members = WorkspaceMember.objects.filter(member=captain)
WorkspaceMember.objects.bulk_create(
[
WorkspaceMember(
workspace=member.workspace_id,
member=user,
role=member.role,
)
for member in workspace_members
],
batch_size=100,
)
# project members
project_members = ProjectMember.objects.filter(member=captain)
ProjectMember.objects.bulk_create(
[
ProjectMember(
workspace=member.workspace_id,
member=user,
role=member.role,
)
for member in project_members
],
batch_size=100,
)
# settings last active for the user # settings last active for the user
user.is_active = True user.is_active = True
user.last_active = timezone.now() user.last_active = timezone.now()

View File

@ -68,6 +68,7 @@ export interface IBaseKanBanLayout {
issueWithIds: any issueWithIds: any
) => Promise<IIssue | undefined>; ) => Promise<IIssue | undefined>;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>; addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
canEditPropertiesBasedOnProject?: (projectId: string) => boolean;
} }
type KanbanDragState = { type KanbanDragState = {
@ -88,6 +89,7 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
currentStore, currentStore,
handleDragDrop, handleDragDrop,
addIssuesToView, addIssuesToView,
canEditPropertiesBasedOnProject,
} = props; } = props;
// router // router
const router = useRouter(); const router = useRouter();
@ -105,7 +107,6 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
const { currentProjectRole } = userStore; const { currentProjectRole } = userStore;
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
const issues = issueStore?.getIssues || {}; const issues = issueStore?.getIssues || {};
const issueIds = issueStore?.getIssuesIds || []; const issueIds = issueStore?.getIssuesIds || [];
@ -130,6 +131,15 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
const [dragState, setDragState] = useState<KanbanDragState>({}); const [dragState, setDragState] = useState<KanbanDragState>({});
const [deleteIssueModal, setDeleteIssueModal] = useState(false); const [deleteIssueModal, setDeleteIssueModal] = useState(false);
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
const canEditProperties = (projectId: string | undefined) => {
const isEditingAllowedBasedOnProject =
canEditPropertiesBasedOnProject && projectId ? canEditPropertiesBasedOnProject(projectId) : isEditingAllowed;
return enableInlineEditing && isEditingAllowedBasedOnProject;
};
const onDragStart = (dragStart: DragStart) => { const onDragStart = (dragStart: DragStart) => {
setDragState({ setDragState({
draggedIssueId: dragStart.draggableId.split("__")[0], draggedIssueId: dragStart.draggableId.split("__")[0],
@ -285,7 +295,7 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
quickAddCallback={issueStore?.quickAddIssue} quickAddCallback={issueStore?.quickAddIssue}
viewId={viewId} viewId={viewId}
disableIssueCreation={!enableIssueCreation || !isEditingAllowed} disableIssueCreation={!enableIssueCreation || !isEditingAllowed}
isReadOnly={!enableInlineEditing || !isEditingAllowed} canEditProperties={canEditProperties}
currentStore={currentStore} currentStore={currentStore}
addIssuesToView={addIssuesToView} addIssuesToView={addIssuesToView}
/> />
@ -327,14 +337,10 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
isDragStarted={isDragStarted} isDragStarted={isDragStarted}
disableIssueCreation={true} disableIssueCreation={true}
enableQuickIssueCreate={enableQuickAdd} enableQuickIssueCreate={enableQuickAdd}
isReadOnly={!enableInlineEditing || !isEditingAllowed}
currentStore={currentStore} currentStore={currentStore}
quickAddCallback={issueStore?.quickAddIssue} quickAddCallback={issueStore?.quickAddIssue}
addIssuesToView={(issues) => { addIssuesToView={addIssuesToView}
console.log("kanban existingIds", issues); canEditProperties={canEditProperties}
return Promise.resolve({} as IIssue);
}}
/> />
)} )}
</DragDropContext> </DragDropContext>

View File

@ -20,7 +20,7 @@ interface IssueBlockProps {
handleIssues: (sub_group_by: string | null, group_by: string | null, issue: IIssue, action: EIssueActions) => void; handleIssues: (sub_group_by: string | null, group_by: string | null, issue: IIssue, action: EIssueActions) => void;
quickActions: (sub_group_by: string | null, group_by: string | null, issue: IIssue) => React.ReactNode; quickActions: (sub_group_by: string | null, group_by: string | null, issue: IIssue) => React.ReactNode;
displayProperties: IIssueDisplayProperties | null; displayProperties: IIssueDisplayProperties | null;
isReadOnly: boolean; canEditProperties: (projectId: string | undefined) => boolean;
} }
interface IssueDetailsBlockProps { interface IssueDetailsBlockProps {
@ -110,13 +110,15 @@ export const KanbanIssueBlock: React.FC<IssueBlockProps> = (props) => {
handleIssues, handleIssues,
quickActions, quickActions,
displayProperties, displayProperties,
isReadOnly, canEditProperties,
} = props; } = props;
let draggableId = issue.id; let draggableId = issue.id;
if (columnId) draggableId = `${draggableId}__${columnId}`; if (columnId) draggableId = `${draggableId}__${columnId}`;
if (sub_group_id) draggableId = `${draggableId}__${sub_group_id}`; if (sub_group_id) draggableId = `${draggableId}__${sub_group_id}`;
const canEditIssueProperties = canEditProperties(issue.project);
return ( return (
<> <>
<Draggable draggableId={draggableId} index={index}> <Draggable draggableId={draggableId} index={index}>
@ -143,7 +145,7 @@ export const KanbanIssueBlock: React.FC<IssueBlockProps> = (props) => {
handleIssues={handleIssues} handleIssues={handleIssues}
quickActions={quickActions} quickActions={quickActions}
displayProperties={displayProperties} displayProperties={displayProperties}
isReadOnly={isReadOnly} isReadOnly={!canEditIssueProperties}
/> />
</div> </div>
</div> </div>

View File

@ -19,7 +19,7 @@ interface IssueBlocksListProps {
customActionButton?: React.ReactElement customActionButton?: React.ReactElement
) => React.ReactNode; ) => React.ReactNode;
displayProperties: IIssueDisplayProperties | null; displayProperties: IIssueDisplayProperties | null;
isReadOnly: boolean; canEditProperties: (projectId: string | undefined) => boolean;
} }
export const KanbanIssueBlocksList: React.FC<IssueBlocksListProps> = (props) => { export const KanbanIssueBlocksList: React.FC<IssueBlocksListProps> = (props) => {
@ -33,7 +33,7 @@ export const KanbanIssueBlocksList: React.FC<IssueBlocksListProps> = (props) =>
handleIssues, handleIssues,
quickActions, quickActions,
displayProperties, displayProperties,
isReadOnly, canEditProperties,
} = props; } = props;
return ( return (
@ -57,7 +57,7 @@ export const KanbanIssueBlocksList: React.FC<IssueBlocksListProps> = (props) =>
columnId={columnId} columnId={columnId}
sub_group_id={sub_group_id} sub_group_id={sub_group_id}
isDragDisabled={isDragDisabled} isDragDisabled={isDragDisabled}
isReadOnly={isReadOnly} canEditProperties={canEditProperties}
/> />
); );
})} })}

View File

@ -48,7 +48,7 @@ export interface IGroupByKanBan {
disableIssueCreation?: boolean; disableIssueCreation?: boolean;
currentStore?: EProjectStore; currentStore?: EProjectStore;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>; addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
isReadOnly: boolean; canEditProperties: (projectId: string | undefined) => boolean;
} }
const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => { const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
@ -75,9 +75,9 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
quickAddCallback, quickAddCallback,
viewId, viewId,
disableIssueCreation, disableIssueCreation,
isReadOnly,
currentStore, currentStore,
addIssuesToView, addIssuesToView,
canEditProperties,
} = props; } = props;
const verticalAlignPosition = (_list: any) => const verticalAlignPosition = (_list: any) =>
@ -133,7 +133,7 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
handleIssues={handleIssues} handleIssues={handleIssues}
quickActions={quickActions} quickActions={quickActions}
displayProperties={displayProperties} displayProperties={displayProperties}
isReadOnly={isReadOnly} canEditProperties={canEditProperties}
/> />
) : ( ) : (
isDragDisabled && ( isDragDisabled && (
@ -216,7 +216,7 @@ export interface IKanBan {
disableIssueCreation?: boolean; disableIssueCreation?: boolean;
currentStore?: EProjectStore; currentStore?: EProjectStore;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>; addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
isReadOnly: boolean; canEditProperties: (projectId: string | undefined) => boolean;
} }
export const KanBan: React.FC<IKanBan> = observer((props) => { export const KanBan: React.FC<IKanBan> = observer((props) => {
@ -244,9 +244,9 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
quickAddCallback, quickAddCallback,
viewId, viewId,
disableIssueCreation, disableIssueCreation,
isReadOnly,
currentStore, currentStore,
addIssuesToView, addIssuesToView,
canEditProperties,
} = props; } = props;
const { issueKanBanView: issueKanBanViewStore } = useMobxStore(); const { issueKanBanView: issueKanBanViewStore } = useMobxStore();
@ -276,9 +276,9 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
isReadOnly={isReadOnly}
currentStore={currentStore} currentStore={currentStore}
addIssuesToView={addIssuesToView} addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
/> />
)} )}
@ -305,9 +305,9 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
isReadOnly={isReadOnly}
currentStore={currentStore} currentStore={currentStore}
addIssuesToView={addIssuesToView} addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
/> />
)} )}
@ -334,9 +334,9 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
isReadOnly={isReadOnly}
currentStore={currentStore} currentStore={currentStore}
addIssuesToView={addIssuesToView} addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
/> />
)} )}
@ -363,9 +363,9 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
isReadOnly={isReadOnly}
currentStore={currentStore} currentStore={currentStore}
addIssuesToView={addIssuesToView} addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
/> />
)} )}
@ -392,9 +392,9 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
isReadOnly={isReadOnly}
currentStore={currentStore} currentStore={currentStore}
addIssuesToView={addIssuesToView} addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
/> />
)} )}
@ -421,9 +421,9 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
isReadOnly={isReadOnly}
currentStore={currentStore} currentStore={currentStore}
addIssuesToView={addIssuesToView} addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
/> />
)} )}
@ -450,9 +450,9 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
isReadOnly={isReadOnly}
currentStore={currentStore} currentStore={currentStore}
addIssuesToView={addIssuesToView} addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
/> />
)} )}
</div> </div>

View File

@ -10,6 +10,7 @@ import { IIssue } from "types";
import { EIssueActions } from "../../types"; import { EIssueActions } from "../../types";
import { BaseKanBanRoot } from "../base-kanban-root"; import { BaseKanBanRoot } from "../base-kanban-root";
import { EProjectStore } from "store/command-palette.store"; import { EProjectStore } from "store/command-palette.store";
import { EUserWorkspaceRoles } from "constants/workspace";
export const ProfileIssuesKanBanLayout: React.FC = observer(() => { export const ProfileIssuesKanBanLayout: React.FC = observer(() => {
const router = useRouter(); const router = useRouter();
@ -18,6 +19,7 @@ export const ProfileIssuesKanBanLayout: React.FC = observer(() => {
const { const {
workspaceProfileIssues: profileIssuesStore, workspaceProfileIssues: profileIssuesStore,
workspaceProfileIssuesFilter: profileIssueFiltersStore, workspaceProfileIssuesFilter: profileIssueFiltersStore,
workspaceMember: { currentWorkspaceUserProjectsRole },
issueKanBanView: issueKanBanViewStore, issueKanBanView: issueKanBanViewStore,
} = useMobxStore(); } = useMobxStore();
@ -34,6 +36,12 @@ export const ProfileIssuesKanBanLayout: React.FC = observer(() => {
}, },
}; };
const canEditPropertiesBasedOnProject = (projectId: string) => {
const currentProjectRole = currentWorkspaceUserProjectsRole && currentWorkspaceUserProjectsRole[projectId];
return !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
};
return ( return (
<BaseKanBanRoot <BaseKanBanRoot
issueActions={issueActions} issueActions={issueActions}
@ -43,6 +51,7 @@ export const ProfileIssuesKanBanLayout: React.FC = observer(() => {
showLoader={true} showLoader={true}
QuickActions={ProjectIssueQuickActions} QuickActions={ProjectIssueQuickActions}
currentStore={EProjectStore.PROFILE} currentStore={EProjectStore.PROFILE}
canEditPropertiesBasedOnProject={canEditPropertiesBasedOnProject}
/> />
); );
}); });

View File

@ -95,7 +95,7 @@ interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader {
disableIssueCreation?: boolean; disableIssueCreation?: boolean;
currentStore?: EProjectStore; currentStore?: EProjectStore;
enableQuickIssueCreate: boolean; enableQuickIssueCreate: boolean;
isReadOnly: boolean; canEditProperties: (projectId: string | undefined) => boolean;
quickAddCallback?: ( quickAddCallback?: (
workspaceSlug: string, workspaceSlug: string,
projectId: string, projectId: string,
@ -127,7 +127,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
isDragStarted, isDragStarted,
disableIssueCreation, disableIssueCreation,
enableQuickIssueCreate, enableQuickIssueCreate,
isReadOnly, canEditProperties,
addIssuesToView, addIssuesToView,
quickAddCallback, quickAddCallback,
} = props; } = props;
@ -186,7 +186,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
projects={projects} projects={projects}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted} isDragStarted={isDragStarted}
isReadOnly={isReadOnly} canEditProperties={canEditProperties}
addIssuesToView={addIssuesToView} addIssuesToView={addIssuesToView}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
/> />
@ -232,7 +232,7 @@ export interface IKanBanSwimLanes {
data: IIssue, data: IIssue,
viewId?: string viewId?: string
) => Promise<IIssue | undefined>; ) => Promise<IIssue | undefined>;
isReadOnly: boolean; canEditProperties: (projectId: string | undefined) => boolean;
} }
export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => { export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
@ -257,7 +257,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
isDragStarted, isDragStarted,
disableIssueCreation, disableIssueCreation,
enableQuickIssueCreate, enableQuickIssueCreate,
isReadOnly, canEditProperties,
currentStore, currentStore,
addIssuesToView, addIssuesToView,
quickAddCallback, quickAddCallback,
@ -402,7 +402,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
isDragStarted={isDragStarted} isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isReadOnly={isReadOnly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
/> />
)} )}
@ -431,7 +431,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
isDragStarted={isDragStarted} isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isReadOnly={isReadOnly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
/> />
)} )}
@ -460,7 +460,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
isDragStarted={isDragStarted} isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isReadOnly={isReadOnly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
/> />
)} )}
@ -489,7 +489,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
isDragStarted={isDragStarted} isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isReadOnly={isReadOnly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
/> />
)} )}
@ -518,7 +518,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
isDragStarted={isDragStarted} isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isReadOnly={isReadOnly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
/> />
)} )}
@ -547,7 +547,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
isDragStarted={isDragStarted} isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isReadOnly={isReadOnly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
/> />
)} )}
@ -576,7 +576,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
isDragStarted={isDragStarted} isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isReadOnly={isReadOnly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
/> />
)} )}
@ -605,7 +605,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
isDragStarted={isDragStarted} isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isReadOnly={isReadOnly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
/> />
)} )}

View File

@ -58,6 +58,7 @@ interface IBaseListRoot {
viewId?: string; viewId?: string;
currentStore: EProjectStore; currentStore: EProjectStore;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>; addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
canEditPropertiesBasedOnProject?: (projectId: string) => boolean;
} }
export const BaseListRoot = observer((props: IBaseListRoot) => { export const BaseListRoot = observer((props: IBaseListRoot) => {
@ -70,6 +71,7 @@ export const BaseListRoot = observer((props: IBaseListRoot) => {
viewId, viewId,
currentStore, currentStore,
addIssuesToView, addIssuesToView,
canEditPropertiesBasedOnProject,
} = props; } = props;
// router // router
const router = useRouter(); const router = useRouter();
@ -90,6 +92,12 @@ export const BaseListRoot = observer((props: IBaseListRoot) => {
const issues = issueStore?.getIssues; const issues = issueStore?.getIssues;
const { enableInlineEditing, enableQuickAdd, enableIssueCreation } = issueStore?.viewFlags || {}; const { enableInlineEditing, enableQuickAdd, enableIssueCreation } = issueStore?.viewFlags || {};
const canEditProperties = (projectId: string | undefined) => {
const isEditingAllowedBasedOnProject =
canEditPropertiesBasedOnProject && projectId ? canEditPropertiesBasedOnProject(projectId) : isEditingAllowed;
return enableInlineEditing && isEditingAllowedBasedOnProject;
};
const displayFilters = issueFilterStore?.issueFilters?.displayFilters; const displayFilters = issueFilterStore?.issueFilters?.displayFilters;
const group_by = displayFilters?.group_by || null; const group_by = displayFilters?.group_by || null;
@ -147,7 +155,7 @@ export const BaseListRoot = observer((props: IBaseListRoot) => {
viewId={viewId} viewId={viewId}
quickAddCallback={issueStore?.quickAddIssue} quickAddCallback={issueStore?.quickAddIssue}
enableIssueQuickAdd={!!enableQuickAdd} enableIssueQuickAdd={!!enableQuickAdd}
isReadonly={!enableInlineEditing || !isEditingAllowed} canEditProperties={canEditProperties}
disableIssueCreation={!enableIssueCreation || !isEditingAllowed} disableIssueCreation={!enableIssueCreation || !isEditingAllowed}
currentStore={currentStore} currentStore={currentStore}
addIssuesToView={addIssuesToView} addIssuesToView={addIssuesToView}

View File

@ -14,11 +14,11 @@ interface IssueBlockProps {
handleIssues: (issue: IIssue, action: EIssueActions) => void; handleIssues: (issue: IIssue, action: EIssueActions) => void;
quickActions: (group_by: string | null, issue: IIssue) => React.ReactNode; quickActions: (group_by: string | null, issue: IIssue) => React.ReactNode;
displayProperties: IIssueDisplayProperties | undefined; displayProperties: IIssueDisplayProperties | undefined;
isReadonly?: boolean; canEditProperties: (projectId: string | undefined) => boolean;
} }
export const IssueBlock: React.FC<IssueBlockProps> = (props) => { export const IssueBlock: React.FC<IssueBlockProps> = (props) => {
const { columnId, issue, handleIssues, quickActions, displayProperties, isReadonly } = props; const { columnId, issue, handleIssues, quickActions, displayProperties, canEditProperties } = props;
// router // router
const router = useRouter(); const router = useRouter();
const updateIssue = (group_by: string | null, issueToUpdate: IIssue) => { const updateIssue = (group_by: string | null, issueToUpdate: IIssue) => {
@ -34,6 +34,8 @@ export const IssueBlock: React.FC<IssueBlockProps> = (props) => {
}); });
}; };
const canEditIssueProperties = canEditProperties(issue.project);
return ( return (
<> <>
<div className="text-sm p-3 relative bg-custom-background-100 flex items-center gap-3"> <div className="text-sm p-3 relative bg-custom-background-100 flex items-center gap-3">
@ -61,7 +63,7 @@ export const IssueBlock: React.FC<IssueBlockProps> = (props) => {
<ListProperties <ListProperties
columnId={columnId} columnId={columnId}
issue={issue} issue={issue}
isReadonly={isReadonly} isReadonly={!canEditIssueProperties}
handleIssues={updateIssue} handleIssues={updateIssue}
displayProperties={displayProperties} displayProperties={displayProperties}
/> />

View File

@ -10,14 +10,14 @@ interface Props {
columnId: string; columnId: string;
issueIds: IGroupedIssues | TUnGroupedIssues | any; issueIds: IGroupedIssues | TUnGroupedIssues | any;
issues: IIssueResponse; issues: IIssueResponse;
isReadonly?: boolean; canEditProperties: (projectId: string | undefined) => boolean;
handleIssues: (issue: IIssue, action: EIssueActions) => void; handleIssues: (issue: IIssue, action: EIssueActions) => void;
quickActions: (group_by: string | null, issue: IIssue) => React.ReactNode; quickActions: (group_by: string | null, issue: IIssue) => React.ReactNode;
displayProperties: IIssueDisplayProperties | undefined; displayProperties: IIssueDisplayProperties | undefined;
} }
export const IssueBlocksList: FC<Props> = (props) => { export const IssueBlocksList: FC<Props> = (props) => {
const { columnId, issueIds, issues, handleIssues, quickActions, displayProperties, isReadonly } = props; const { columnId, issueIds, issues, handleIssues, quickActions, displayProperties, canEditProperties } = props;
return ( return (
<div className="w-full h-full relative divide-y-[0.5px] divide-custom-border-200"> <div className="w-full h-full relative divide-y-[0.5px] divide-custom-border-200">
@ -31,7 +31,7 @@ export const IssueBlocksList: FC<Props> = (props) => {
issue={issues[issueId]} issue={issues[issueId]}
handleIssues={handleIssues} handleIssues={handleIssues}
quickActions={quickActions} quickActions={quickActions}
isReadonly={isReadonly} canEditProperties={canEditProperties}
displayProperties={displayProperties} displayProperties={displayProperties}
/> />
) )

View File

@ -23,7 +23,7 @@ export interface IGroupByList {
displayProperties: IIssueDisplayProperties | undefined; displayProperties: IIssueDisplayProperties | undefined;
enableIssueQuickAdd: boolean; enableIssueQuickAdd: boolean;
showEmptyGroup?: boolean; showEmptyGroup?: boolean;
isReadonly: boolean; canEditProperties: (projectId: string | undefined) => boolean;
quickAddCallback?: ( quickAddCallback?: (
workspaceSlug: string, workspaceSlug: string,
projectId: string, projectId: string,
@ -50,7 +50,7 @@ const GroupByList: React.FC<IGroupByList> = (props) => {
displayProperties, displayProperties,
enableIssueQuickAdd, enableIssueQuickAdd,
showEmptyGroup, showEmptyGroup,
isReadonly, canEditProperties,
quickAddCallback, quickAddCallback,
viewId, viewId,
disableIssueCreation, disableIssueCreation,
@ -105,7 +105,7 @@ const GroupByList: React.FC<IGroupByList> = (props) => {
handleIssues={handleIssues} handleIssues={handleIssues}
quickActions={quickActions} quickActions={quickActions}
displayProperties={displayProperties} displayProperties={displayProperties}
isReadonly={isReadonly} canEditProperties={canEditProperties}
/> />
)} )}
@ -134,7 +134,7 @@ export interface IList {
displayProperties: IIssueDisplayProperties | undefined; displayProperties: IIssueDisplayProperties | undefined;
showEmptyGroup: boolean; showEmptyGroup: boolean;
enableIssueQuickAdd: boolean; enableIssueQuickAdd: boolean;
isReadonly: boolean; canEditProperties: (projectId: string | undefined) => boolean;
states: IState[] | null; states: IState[] | null;
labels: IIssueLabel[] | null; labels: IIssueLabel[] | null;
members: IUserLite[] | null; members: IUserLite[] | null;
@ -165,7 +165,7 @@ export const List: React.FC<IList> = (props) => {
displayProperties, displayProperties,
showEmptyGroup, showEmptyGroup,
enableIssueQuickAdd, enableIssueQuickAdd,
isReadonly, canEditProperties,
disableIssueCreation, disableIssueCreation,
states, states,
stateGroups, stateGroups,
@ -193,7 +193,7 @@ export const List: React.FC<IList> = (props) => {
displayProperties={displayProperties} displayProperties={displayProperties}
enableIssueQuickAdd={enableIssueQuickAdd} enableIssueQuickAdd={enableIssueQuickAdd}
showEmptyGroup={showEmptyGroup} showEmptyGroup={showEmptyGroup}
isReadonly={isReadonly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
@ -215,7 +215,7 @@ export const List: React.FC<IList> = (props) => {
displayProperties={displayProperties} displayProperties={displayProperties}
showEmptyGroup={showEmptyGroup} showEmptyGroup={showEmptyGroup}
enableIssueQuickAdd={enableIssueQuickAdd} enableIssueQuickAdd={enableIssueQuickAdd}
isReadonly={isReadonly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
@ -237,7 +237,7 @@ export const List: React.FC<IList> = (props) => {
displayProperties={displayProperties} displayProperties={displayProperties}
showEmptyGroup={showEmptyGroup} showEmptyGroup={showEmptyGroup}
enableIssueQuickAdd={enableIssueQuickAdd} enableIssueQuickAdd={enableIssueQuickAdd}
isReadonly={isReadonly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
@ -259,7 +259,7 @@ export const List: React.FC<IList> = (props) => {
displayProperties={displayProperties} displayProperties={displayProperties}
showEmptyGroup={showEmptyGroup} showEmptyGroup={showEmptyGroup}
enableIssueQuickAdd={enableIssueQuickAdd} enableIssueQuickAdd={enableIssueQuickAdd}
isReadonly={isReadonly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
@ -281,7 +281,7 @@ export const List: React.FC<IList> = (props) => {
displayProperties={displayProperties} displayProperties={displayProperties}
showEmptyGroup={showEmptyGroup} showEmptyGroup={showEmptyGroup}
enableIssueQuickAdd={enableIssueQuickAdd} enableIssueQuickAdd={enableIssueQuickAdd}
isReadonly={isReadonly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
@ -303,7 +303,7 @@ export const List: React.FC<IList> = (props) => {
displayProperties={displayProperties} displayProperties={displayProperties}
showEmptyGroup={showEmptyGroup} showEmptyGroup={showEmptyGroup}
enableIssueQuickAdd={enableIssueQuickAdd} enableIssueQuickAdd={enableIssueQuickAdd}
isReadonly={isReadonly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
@ -325,7 +325,7 @@ export const List: React.FC<IList> = (props) => {
displayProperties={displayProperties} displayProperties={displayProperties}
showEmptyGroup={showEmptyGroup} showEmptyGroup={showEmptyGroup}
enableIssueQuickAdd={enableIssueQuickAdd} enableIssueQuickAdd={enableIssueQuickAdd}
isReadonly={isReadonly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
@ -347,7 +347,7 @@ export const List: React.FC<IList> = (props) => {
displayProperties={displayProperties} displayProperties={displayProperties}
showEmptyGroup={showEmptyGroup} showEmptyGroup={showEmptyGroup}
enableIssueQuickAdd={enableIssueQuickAdd} enableIssueQuickAdd={enableIssueQuickAdd}
isReadonly={isReadonly} canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}

View File

@ -12,14 +12,18 @@ import { EIssueActions } from "../../types";
import { BaseListRoot } from "../base-list-root"; import { BaseListRoot } from "../base-list-root";
import { IProjectStore } from "store/project"; import { IProjectStore } from "store/project";
import { EProjectStore } from "store/command-palette.store"; import { EProjectStore } from "store/command-palette.store";
import { EUserWorkspaceRoles } from "constants/workspace";
export const ProfileIssuesListLayout: FC = observer(() => { export const ProfileIssuesListLayout: FC = observer(() => {
const router = useRouter(); const router = useRouter();
const { workspaceSlug, userId } = router.query as { workspaceSlug: string; userId: string }; const { workspaceSlug, userId } = router.query as { workspaceSlug: string; userId: string };
// store // store
const { workspaceProfileIssuesFilter: profileIssueFiltersStore, workspaceProfileIssues: profileIssuesStore } = const {
useMobxStore(); workspaceProfileIssuesFilter: profileIssueFiltersStore,
workspaceProfileIssues: profileIssuesStore,
workspaceMember: { currentWorkspaceUserProjectsRole },
} = useMobxStore();
const issueActions = { const issueActions = {
[EIssueActions.UPDATE]: async (group_by: string | null, issue: IIssue) => { [EIssueActions.UPDATE]: async (group_by: string | null, issue: IIssue) => {
@ -36,6 +40,17 @@ export const ProfileIssuesListLayout: FC = observer(() => {
const getProjects = (projectStore: IProjectStore) => projectStore.workspaceProjects; const getProjects = (projectStore: IProjectStore) => projectStore.workspaceProjects;
const canEditPropertiesBasedOnProject = (projectId: string) => {
const currentProjectRole = currentWorkspaceUserProjectsRole && currentWorkspaceUserProjectsRole[projectId];
console.log(
projectId,
currentWorkspaceUserProjectsRole,
!!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER
);
return !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
};
return ( return (
<BaseListRoot <BaseListRoot
issueFilterStore={profileIssueFiltersStore} issueFilterStore={profileIssueFiltersStore}
@ -44,6 +59,7 @@ export const ProfileIssuesListLayout: FC = observer(() => {
issueActions={issueActions} issueActions={issueActions}
getProjects={getProjects} getProjects={getProjects}
currentStore={EProjectStore.PROFILE} currentStore={EProjectStore.PROFILE}
canEditPropertiesBasedOnProject={canEditPropertiesBasedOnProject}
/> />
); );
}); });

View File

@ -16,6 +16,7 @@ import { IIssueUnGroupedStructure } from "store/issue";
import { EIssueActions } from "../types"; import { EIssueActions } from "../types";
import { EFilterType, TUnGroupedIssues } from "store/issues/types"; import { EFilterType, TUnGroupedIssues } from "store/issues/types";
import { EUserWorkspaceRoles } from "constants/workspace";
type Props = { type Props = {
type?: TStaticViewTypes | null; type?: TStaticViewTypes | null;
@ -35,6 +36,7 @@ export const AllIssueLayoutRoot: React.FC<Props> = observer((props) => {
globalViews: { fetchAllGlobalViews }, globalViews: { fetchAllGlobalViews },
workspaceGlobalIssues: { loader, getIssues, getIssuesIds, fetchIssues, updateIssue, removeIssue }, workspaceGlobalIssues: { loader, getIssues, getIssuesIds, fetchIssues, updateIssue, removeIssue },
workspaceGlobalIssuesFilter: { currentView, issueFilters, fetchFilters, updateFilters, setCurrentView }, workspaceGlobalIssuesFilter: { currentView, issueFilters, fetchFilters, updateFilters, setCurrentView },
workspaceMember: { currentWorkspaceUserProjectsRole },
} = useMobxStore(); } = useMobxStore();
useSWR(workspaceSlug ? `WORKSPACE_GLOBAL_VIEWS${workspaceSlug}` : null, async () => { useSWR(workspaceSlug ? `WORKSPACE_GLOBAL_VIEWS${workspaceSlug}` : null, async () => {
@ -55,7 +57,13 @@ export const AllIssueLayoutRoot: React.FC<Props> = observer((props) => {
} }
); );
const isEditingAllowed = false; const canEditProperties = (projectId: string | undefined) => {
if (!projectId) return false;
const currentProjectRole = currentWorkspaceUserProjectsRole && currentWorkspaceUserProjectsRole[projectId];
return !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
};
const issuesResponse = getIssues; const issuesResponse = getIssues;
const issueIds = (getIssuesIds ?? []) as TUnGroupedIssues; const issueIds = (getIssuesIds ?? []) as TUnGroupedIssues;
@ -123,7 +131,7 @@ export const AllIssueLayoutRoot: React.FC<Props> = observer((props) => {
members={workspaceMembers?.map((m) => m.member)} members={workspaceMembers?.map((m) => m.member)}
labels={workspaceLabels || undefined} labels={workspaceLabels || undefined}
handleIssues={handleIssues} handleIssues={handleIssues}
disableUserActions={isEditingAllowed} canEditProperties={canEditProperties}
viewId={currentIssueView} viewId={currentIssueView}
/> />
</div> </div>

View File

@ -34,10 +34,11 @@ interface IBaseSpreadsheetRoot {
[EIssueActions.UPDATE]?: (issue: IIssue) => void; [EIssueActions.UPDATE]?: (issue: IIssue) => void;
[EIssueActions.REMOVE]?: (issue: IIssue) => void; [EIssueActions.REMOVE]?: (issue: IIssue) => void;
}; };
canEditPropertiesBasedOnProject?: (projectId: string) => boolean;
} }
export const BaseSpreadsheetRoot = observer((props: IBaseSpreadsheetRoot) => { export const BaseSpreadsheetRoot = observer((props: IBaseSpreadsheetRoot) => {
const { issueFiltersStore, issueStore, viewId, QuickActions, issueActions } = props; const { issueFiltersStore, issueStore, viewId, QuickActions, issueActions, canEditPropertiesBasedOnProject } = props;
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string }; const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
@ -49,9 +50,18 @@ export const BaseSpreadsheetRoot = observer((props: IBaseSpreadsheetRoot) => {
user: userStore, user: userStore,
} = useMobxStore(); } = useMobxStore();
const { enableInlineEditing, enableQuickAdd } = issueStore?.viewFlags || {};
const { currentProjectRole } = userStore; const { currentProjectRole } = userStore;
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
const canEditProperties = (projectId: string | undefined) => {
const isEditingAllowedBasedOnProject =
canEditPropertiesBasedOnProject && projectId ? canEditPropertiesBasedOnProject(projectId) : isEditingAllowed;
return enableInlineEditing && isEditingAllowedBasedOnProject;
};
const issuesResponse = issueStore.getIssues; const issuesResponse = issueStore.getIssues;
const issueIds = (issueStore.getIssuesIds ?? []) as TUnGroupedIssues; const issueIds = (issueStore.getIssuesIds ?? []) as TUnGroupedIssues;
@ -106,10 +116,10 @@ export const BaseSpreadsheetRoot = observer((props: IBaseSpreadsheetRoot) => {
labels={projectLabels || undefined} labels={projectLabels || undefined}
states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined} states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined}
handleIssues={handleIssues} handleIssues={handleIssues}
disableUserActions={!isEditingAllowed} canEditProperties={canEditProperties}
quickAddCallback={issueStore.quickAddIssue} quickAddCallback={issueStore.quickAddIssue}
viewId={viewId} viewId={viewId}
enableQuickCreateIssue enableQuickCreateIssue={enableQuickAdd}
/> />
); );
}); });

View File

@ -8,7 +8,7 @@ import { IIssue, IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueLabe
type Props = { type Props = {
displayFilters: IIssueDisplayFilterOptions; displayFilters: IIssueDisplayFilterOptions;
displayProperties: IIssueDisplayProperties; displayProperties: IIssueDisplayProperties;
disableUserActions: boolean; canEditProperties: (projectId: string | undefined) => boolean;
expandedIssues: string[]; expandedIssues: string[];
handleDisplayFilterUpdate: (data: Partial<IIssueDisplayFilterOptions>) => void; handleDisplayFilterUpdate: (data: Partial<IIssueDisplayFilterOptions>) => void;
handleUpdateIssue: (issue: IIssue, data: Partial<IIssue>) => void; handleUpdateIssue: (issue: IIssue, data: Partial<IIssue>) => void;
@ -20,7 +20,7 @@ type Props = {
export const SpreadsheetColumnsList: React.FC<Props> = observer((props) => { export const SpreadsheetColumnsList: React.FC<Props> = observer((props) => {
const { const {
disableUserActions, canEditProperties,
displayFilters, displayFilters,
displayProperties, displayProperties,
expandedIssues, expandedIssues,
@ -43,7 +43,7 @@ export const SpreadsheetColumnsList: React.FC<Props> = observer((props) => {
{displayProperties.state && ( {displayProperties.state && (
<SpreadsheetColumn <SpreadsheetColumn
displayFilters={displayFilters} displayFilters={displayFilters}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
expandedIssues={expandedIssues} expandedIssues={expandedIssues}
handleDisplayFilterUpdate={handleDisplayFilterUpdate} handleDisplayFilterUpdate={handleDisplayFilterUpdate}
handleUpdateIssue={handleUpdateIssue} handleUpdateIssue={handleUpdateIssue}
@ -55,7 +55,7 @@ export const SpreadsheetColumnsList: React.FC<Props> = observer((props) => {
{displayProperties.priority && ( {displayProperties.priority && (
<SpreadsheetColumn <SpreadsheetColumn
displayFilters={displayFilters} displayFilters={displayFilters}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
expandedIssues={expandedIssues} expandedIssues={expandedIssues}
handleDisplayFilterUpdate={handleDisplayFilterUpdate} handleDisplayFilterUpdate={handleDisplayFilterUpdate}
handleUpdateIssue={handleUpdateIssue} handleUpdateIssue={handleUpdateIssue}
@ -66,7 +66,7 @@ export const SpreadsheetColumnsList: React.FC<Props> = observer((props) => {
{displayProperties.assignee && ( {displayProperties.assignee && (
<SpreadsheetColumn <SpreadsheetColumn
displayFilters={displayFilters} displayFilters={displayFilters}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
expandedIssues={expandedIssues} expandedIssues={expandedIssues}
handleDisplayFilterUpdate={handleDisplayFilterUpdate} handleDisplayFilterUpdate={handleDisplayFilterUpdate}
handleUpdateIssue={handleUpdateIssue} handleUpdateIssue={handleUpdateIssue}
@ -78,7 +78,7 @@ export const SpreadsheetColumnsList: React.FC<Props> = observer((props) => {
{displayProperties.labels && ( {displayProperties.labels && (
<SpreadsheetColumn <SpreadsheetColumn
displayFilters={displayFilters} displayFilters={displayFilters}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
expandedIssues={expandedIssues} expandedIssues={expandedIssues}
handleDisplayFilterUpdate={handleDisplayFilterUpdate} handleDisplayFilterUpdate={handleDisplayFilterUpdate}
handleUpdateIssue={handleUpdateIssue} handleUpdateIssue={handleUpdateIssue}
@ -90,7 +90,7 @@ export const SpreadsheetColumnsList: React.FC<Props> = observer((props) => {
{displayProperties.start_date && ( {displayProperties.start_date && (
<SpreadsheetColumn <SpreadsheetColumn
displayFilters={displayFilters} displayFilters={displayFilters}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
expandedIssues={expandedIssues} expandedIssues={expandedIssues}
handleDisplayFilterUpdate={handleDisplayFilterUpdate} handleDisplayFilterUpdate={handleDisplayFilterUpdate}
handleUpdateIssue={handleUpdateIssue} handleUpdateIssue={handleUpdateIssue}
@ -101,7 +101,7 @@ export const SpreadsheetColumnsList: React.FC<Props> = observer((props) => {
{displayProperties.due_date && ( {displayProperties.due_date && (
<SpreadsheetColumn <SpreadsheetColumn
displayFilters={displayFilters} displayFilters={displayFilters}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
expandedIssues={expandedIssues} expandedIssues={expandedIssues}
handleDisplayFilterUpdate={handleDisplayFilterUpdate} handleDisplayFilterUpdate={handleDisplayFilterUpdate}
handleUpdateIssue={handleUpdateIssue} handleUpdateIssue={handleUpdateIssue}
@ -112,7 +112,7 @@ export const SpreadsheetColumnsList: React.FC<Props> = observer((props) => {
{displayProperties.estimate && isEstimateEnabled && ( {displayProperties.estimate && isEstimateEnabled && (
<SpreadsheetColumn <SpreadsheetColumn
displayFilters={displayFilters} displayFilters={displayFilters}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
expandedIssues={expandedIssues} expandedIssues={expandedIssues}
handleDisplayFilterUpdate={handleDisplayFilterUpdate} handleDisplayFilterUpdate={handleDisplayFilterUpdate}
handleUpdateIssue={handleUpdateIssue} handleUpdateIssue={handleUpdateIssue}
@ -123,7 +123,7 @@ export const SpreadsheetColumnsList: React.FC<Props> = observer((props) => {
{displayProperties.created_on && ( {displayProperties.created_on && (
<SpreadsheetColumn <SpreadsheetColumn
displayFilters={displayFilters} displayFilters={displayFilters}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
expandedIssues={expandedIssues} expandedIssues={expandedIssues}
handleDisplayFilterUpdate={handleDisplayFilterUpdate} handleDisplayFilterUpdate={handleDisplayFilterUpdate}
handleUpdateIssue={handleUpdateIssue} handleUpdateIssue={handleUpdateIssue}
@ -134,7 +134,7 @@ export const SpreadsheetColumnsList: React.FC<Props> = observer((props) => {
{displayProperties.updated_on && ( {displayProperties.updated_on && (
<SpreadsheetColumn <SpreadsheetColumn
displayFilters={displayFilters} displayFilters={displayFilters}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
expandedIssues={expandedIssues} expandedIssues={expandedIssues}
handleDisplayFilterUpdate={handleDisplayFilterUpdate} handleDisplayFilterUpdate={handleDisplayFilterUpdate}
handleUpdateIssue={handleUpdateIssue} handleUpdateIssue={handleUpdateIssue}
@ -145,7 +145,7 @@ export const SpreadsheetColumnsList: React.FC<Props> = observer((props) => {
{displayProperties.link && ( {displayProperties.link && (
<SpreadsheetColumn <SpreadsheetColumn
displayFilters={displayFilters} displayFilters={displayFilters}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
expandedIssues={expandedIssues} expandedIssues={expandedIssues}
handleDisplayFilterUpdate={handleDisplayFilterUpdate} handleDisplayFilterUpdate={handleDisplayFilterUpdate}
handleUpdateIssue={handleUpdateIssue} handleUpdateIssue={handleUpdateIssue}
@ -156,7 +156,7 @@ export const SpreadsheetColumnsList: React.FC<Props> = observer((props) => {
{displayProperties.attachment_count && ( {displayProperties.attachment_count && (
<SpreadsheetColumn <SpreadsheetColumn
displayFilters={displayFilters} displayFilters={displayFilters}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
expandedIssues={expandedIssues} expandedIssues={expandedIssues}
handleDisplayFilterUpdate={handleDisplayFilterUpdate} handleDisplayFilterUpdate={handleDisplayFilterUpdate}
handleUpdateIssue={handleUpdateIssue} handleUpdateIssue={handleUpdateIssue}
@ -167,7 +167,7 @@ export const SpreadsheetColumnsList: React.FC<Props> = observer((props) => {
{displayProperties.sub_issue_count && ( {displayProperties.sub_issue_count && (
<SpreadsheetColumn <SpreadsheetColumn
displayFilters={displayFilters} displayFilters={displayFilters}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
expandedIssues={expandedIssues} expandedIssues={expandedIssues}
handleDisplayFilterUpdate={handleDisplayFilterUpdate} handleDisplayFilterUpdate={handleDisplayFilterUpdate}
handleUpdateIssue={handleUpdateIssue} handleUpdateIssue={handleUpdateIssue}

View File

@ -14,7 +14,7 @@ type Props = {
handleToggleExpand: (issueId: string) => void; handleToggleExpand: (issueId: string) => void;
properties: IIssueDisplayProperties; properties: IIssueDisplayProperties;
quickActions: (issue: IIssue, customActionButton?: React.ReactElement) => React.ReactNode; quickActions: (issue: IIssue, customActionButton?: React.ReactElement) => React.ReactNode;
disableUserActions: boolean; canEditProperties: (projectId: string | undefined) => boolean;
nestingLevel: number; nestingLevel: number;
}; };
@ -24,7 +24,7 @@ export const IssueColumn: React.FC<Props> = ({
handleToggleExpand, handleToggleExpand,
properties, properties,
quickActions, quickActions,
disableUserActions, canEditProperties,
nestingLevel, nestingLevel,
}) => { }) => {
// router // router
@ -76,7 +76,7 @@ export const IssueColumn: React.FC<Props> = ({
{issue.project_detail?.identifier}-{issue.sequence_id} {issue.project_detail?.identifier}-{issue.sequence_id}
</span> </span>
{!disableUserActions && ( {canEditProperties(issue.project) && (
<div className={`absolute top-0 left-2.5 hidden group-hover:block ${isMenuActive ? "!block" : ""}`}> <div className={`absolute top-0 left-2.5 hidden group-hover:block ${isMenuActive ? "!block" : ""}`}>
{quickActions(issue, customActionButton)} {quickActions(issue, customActionButton)}
</div> </div>

View File

@ -13,7 +13,7 @@ type Props = {
setExpandedIssues: React.Dispatch<React.SetStateAction<string[]>>; setExpandedIssues: React.Dispatch<React.SetStateAction<string[]>>;
properties: IIssueDisplayProperties; properties: IIssueDisplayProperties;
quickActions: (issue: IIssue, customActionButton?: React.ReactElement) => React.ReactNode; quickActions: (issue: IIssue, customActionButton?: React.ReactElement) => React.ReactNode;
disableUserActions: boolean; canEditProperties: (projectId: string | undefined) => boolean;
nestingLevel?: number; nestingLevel?: number;
}; };
@ -23,7 +23,7 @@ export const SpreadsheetIssuesColumn: React.FC<Props> = ({
setExpandedIssues, setExpandedIssues,
properties, properties,
quickActions, quickActions,
disableUserActions, canEditProperties,
nestingLevel = 0, nestingLevel = 0,
}) => { }) => {
const handleToggleExpand = (issueId: string) => { const handleToggleExpand = (issueId: string) => {
@ -49,7 +49,7 @@ export const SpreadsheetIssuesColumn: React.FC<Props> = ({
expanded={isExpanded} expanded={isExpanded}
handleToggleExpand={handleToggleExpand} handleToggleExpand={handleToggleExpand}
properties={properties} properties={properties}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
nestingLevel={nestingLevel} nestingLevel={nestingLevel}
quickActions={quickActions} quickActions={quickActions}
/> />
@ -66,7 +66,7 @@ export const SpreadsheetIssuesColumn: React.FC<Props> = ({
setExpandedIssues={setExpandedIssues} setExpandedIssues={setExpandedIssues}
properties={properties} properties={properties}
quickActions={quickActions} quickActions={quickActions}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
nestingLevel={nestingLevel + 1} nestingLevel={nestingLevel + 1}
/> />
))} ))}

View File

@ -32,7 +32,7 @@ import { IIssue, IIssueDisplayFilterOptions, IIssueLabel, IState, IUserLite, TIs
import { SPREADSHEET_PROPERTY_DETAILS } from "constants/spreadsheet"; import { SPREADSHEET_PROPERTY_DETAILS } from "constants/spreadsheet";
type Props = { type Props = {
disableUserActions: boolean; canEditProperties: (projectId: string | undefined) => boolean;
displayFilters: IIssueDisplayFilterOptions; displayFilters: IIssueDisplayFilterOptions;
expandedIssues: string[]; expandedIssues: string[];
handleDisplayFilterUpdate: (data: Partial<IIssueDisplayFilterOptions>) => void; handleDisplayFilterUpdate: (data: Partial<IIssueDisplayFilterOptions>) => void;
@ -46,7 +46,7 @@ type Props = {
export const SpreadsheetColumn: React.FC<Props> = (props) => { export const SpreadsheetColumn: React.FC<Props> = (props) => {
const { const {
disableUserActions, canEditProperties,
displayFilters, displayFilters,
expandedIssues, expandedIssues,
handleDisplayFilterUpdate, handleDisplayFilterUpdate,
@ -160,7 +160,9 @@ export const SpreadsheetColumn: React.FC<Props> = (props) => {
</div> </div>
<div className="h-full min-w-[8rem] w-full"> <div className="h-full min-w-[8rem] w-full">
{issues?.map((issue) => ( {issues?.map((issue) => {
const disableUserActions = !canEditProperties(issue.project);
return (
<div <div
key={`${property}-${issue.id}`} key={`${property}-${issue.id}`}
className={`h-11 border-b-[0.5px] border-custom-border-200 ${ className={`h-11 border-b-[0.5px] border-custom-border-200 ${
@ -231,7 +233,8 @@ export const SpreadsheetColumn: React.FC<Props> = (props) => {
<SpreadsheetSubIssueColumn expandedIssues={expandedIssues} issue={issue} /> <SpreadsheetSubIssueColumn expandedIssues={expandedIssues} issue={issue} />
) : null} ) : null}
</div> </div>
))} );
})}
</div> </div>
</div> </div>
); );

View File

@ -31,7 +31,7 @@ type Props = {
viewId?: string viewId?: string
) => Promise<IIssue | undefined>; ) => Promise<IIssue | undefined>;
viewId?: string; viewId?: string;
disableUserActions: boolean; canEditProperties: (projectId: string | undefined) => boolean;
enableQuickCreateIssue?: boolean; enableQuickCreateIssue?: boolean;
}; };
@ -48,7 +48,7 @@ export const SpreadsheetView: React.FC<Props> = observer((props) => {
handleIssues, handleIssues,
quickAddCallback, quickAddCallback,
viewId, viewId,
disableUserActions, canEditProperties,
enableQuickCreateIssue, enableQuickCreateIssue,
} = props; } = props;
// states // states
@ -114,7 +114,7 @@ export const SpreadsheetView: React.FC<Props> = observer((props) => {
setExpandedIssues={setExpandedIssues} setExpandedIssues={setExpandedIssues}
properties={displayProperties} properties={displayProperties}
quickActions={quickActions} quickActions={quickActions}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
/> />
) : null ) : null
)} )}
@ -124,7 +124,7 @@ export const SpreadsheetView: React.FC<Props> = observer((props) => {
<SpreadsheetColumnsList <SpreadsheetColumnsList
displayFilters={displayFilters} displayFilters={displayFilters}
displayProperties={displayProperties} displayProperties={displayProperties}
disableUserActions={disableUserActions} canEditProperties={canEditProperties}
expandedIssues={expandedIssues} expandedIssues={expandedIssues}
handleDisplayFilterUpdate={handleDisplayFilterUpdate} handleDisplayFilterUpdate={handleDisplayFilterUpdate}
handleUpdateIssue={(issue, data) => handleIssues({ ...issue, ...data }, EIssueActions.UPDATE)} handleUpdateIssue={(issue, data) => handleIssues({ ...issue, ...data }, EIssueActions.UPDATE)}

View File

@ -19,7 +19,7 @@ export const WorkspaceAuthWrapper: FC<IWorkspaceAuthWrapper> = observer((props)
user: { currentWorkspaceMemberInfo, hasPermissionToCurrentWorkspace, fetchUserWorkspaceInfo }, user: { currentWorkspaceMemberInfo, hasPermissionToCurrentWorkspace, fetchUserWorkspaceInfo },
project: { fetchProjects }, project: { fetchProjects },
workspace: { fetchWorkspaceLabels }, workspace: { fetchWorkspaceLabels },
workspaceMember: { fetchWorkspaceMembers }, workspaceMember: { fetchWorkspaceMembers, fetchWorkspaceUserProjectsRole },
} = useMobxStore(); } = useMobxStore();
// router // router
@ -45,6 +45,11 @@ export const WorkspaceAuthWrapper: FC<IWorkspaceAuthWrapper> = observer((props)
workspaceSlug ? `WORKSPACE_LABELS_${workspaceSlug}` : null, workspaceSlug ? `WORKSPACE_LABELS_${workspaceSlug}` : null,
workspaceSlug ? () => fetchWorkspaceLabels(workspaceSlug.toString()) : null workspaceSlug ? () => fetchWorkspaceLabels(workspaceSlug.toString()) : null
); );
// fetch workspace user projects role
useSWR(
workspaceSlug ? `WORKSPACE_PROJECTS_ROLE_${workspaceSlug}` : null,
workspaceSlug ? () => fetchWorkspaceUserProjectsRole(workspaceSlug.toString()) : null
);
// while data is being loaded // while data is being loaded
if (!currentWorkspaceMemberInfo && hasPermissionToCurrentWorkspace === undefined) { if (!currentWorkspaceMemberInfo && hasPermissionToCurrentWorkspace === undefined) {

View File

@ -13,6 +13,7 @@ import {
IProductUpdateResponse, IProductUpdateResponse,
IWorkspaceBulkInviteFormData, IWorkspaceBulkInviteFormData,
IWorkspaceViewProps, IWorkspaceViewProps,
IUserProjectsRole,
} from "types"; } from "types";
import { IWorkspaceView } from "types/workspace-views"; import { IWorkspaceView } from "types/workspace-views";
// store // store
@ -267,4 +268,12 @@ export class WorkspaceService extends APIService {
throw error?.response?.data; throw error?.response?.data;
}); });
} }
async getWorkspaceUserProjectsRole(workspaceSlug: string): Promise<IUserProjectsRole> {
return this.get(`/api/users/me/workspaces/${workspaceSlug}/project-roles/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
} }

View File

@ -136,7 +136,7 @@ export class ProfileIssuesStore extends IssueBaseStore implements IProfileIssues
return { return {
enableQuickAdd: false, enableQuickAdd: false,
enableIssueCreation: false, enableIssueCreation: false,
enableInlineEditing: false, enableInlineEditing: true,
}; };
} }
@ -233,8 +233,8 @@ export class ProfileIssuesStore extends IssueBaseStore implements IProfileIssues
let _issues = { ...this.issues }; let _issues = { ...this.issues };
if (!_issues) _issues = {}; if (!_issues) _issues = {};
if (!_issues[userId]) _issues[userId] = { assigned: {}, created: {}, subscribed: {} }; if (!_issues[userId]) _issues[userId] = { assigned: {}, created: {}, subscribed: {} };
_issues[userId][this.currentUserIssueTab][userId] = { _issues[userId][this.currentUserIssueTab][issueId] = {
..._issues[userId][this.currentUserIssueTab][userId], ..._issues[userId][this.currentUserIssueTab][issueId],
...data, ...data,
}; };

View File

@ -1,7 +1,7 @@
import { action, computed, observable, makeObservable, runInAction } from "mobx"; import { action, computed, observable, makeObservable, runInAction } from "mobx";
import { RootStore } from "../root"; import { RootStore } from "../root";
// types // types
import { IWorkspaceMember, IWorkspaceMemberInvitation, IWorkspaceBulkInviteFormData } from "types"; import { IWorkspaceMember, IWorkspaceMemberInvitation, IWorkspaceBulkInviteFormData, IUserProjectsRole } from "types";
// services // services
import { WorkspaceService } from "services/workspace.service"; import { WorkspaceService } from "services/workspace.service";
@ -13,7 +13,9 @@ export interface IWorkspaceMemberStore {
// observables // observables
members: { [workspaceSlug: string]: IWorkspaceMember[] }; // workspaceSlug: members[] members: { [workspaceSlug: string]: IWorkspaceMember[] }; // workspaceSlug: members[]
memberInvitations: { [workspaceSlug: string]: IWorkspaceMemberInvitation[] }; memberInvitations: { [workspaceSlug: string]: IWorkspaceMemberInvitation[] };
workspaceUserProjectsRole: { [workspaceSlug: string]: IUserProjectsRole } | undefined;
// actions // actions
fetchWorkspaceUserProjectsRole: (workspaceSlug: string) => Promise<IUserProjectsRole>;
fetchWorkspaceMembers: (workspaceSlug: string) => Promise<void>; fetchWorkspaceMembers: (workspaceSlug: string) => Promise<void>;
fetchWorkspaceMemberInvitations: (workspaceSlug: string) => Promise<IWorkspaceMemberInvitation[]>; fetchWorkspaceMemberInvitations: (workspaceSlug: string) => Promise<IWorkspaceMemberInvitation[]>;
updateMember: (workspaceSlug: string, memberId: string, data: Partial<IWorkspaceMember>) => Promise<void>; updateMember: (workspaceSlug: string, memberId: string, data: Partial<IWorkspaceMember>) => Promise<void>;
@ -29,6 +31,7 @@ export interface IWorkspaceMemberStore {
workspaceMembers: IWorkspaceMember[] | null; workspaceMembers: IWorkspaceMember[] | null;
workspaceMemberInvitations: IWorkspaceMemberInvitation[] | null; workspaceMemberInvitations: IWorkspaceMemberInvitation[] | null;
workspaceMembersWithInvitations: any[] | null; workspaceMembersWithInvitations: any[] | null;
currentWorkspaceUserProjectsRole: IUserProjectsRole | undefined;
} }
export class WorkspaceMemberStore implements IWorkspaceMemberStore { export class WorkspaceMemberStore implements IWorkspaceMemberStore {
@ -38,6 +41,7 @@ export class WorkspaceMemberStore implements IWorkspaceMemberStore {
// observables // observables
members: { [workspaceSlug: string]: IWorkspaceMember[] } = {}; members: { [workspaceSlug: string]: IWorkspaceMember[] } = {};
memberInvitations: { [workspaceSlug: string]: IWorkspaceMemberInvitation[] } = {}; memberInvitations: { [workspaceSlug: string]: IWorkspaceMemberInvitation[] } = {};
workspaceUserProjectsRole: { [workspaceSlug: string]: IUserProjectsRole } | undefined = undefined;
// services // services
workspaceService; workspaceService;
// root store // root store
@ -52,7 +56,9 @@ export class WorkspaceMemberStore implements IWorkspaceMemberStore {
// observables // observables
members: observable.ref, members: observable.ref,
memberInvitations: observable.ref, memberInvitations: observable.ref,
workspaceUserProjectsRole: observable.ref,
// actions // actions
fetchWorkspaceUserProjectsRole: action,
fetchWorkspaceMembers: action, fetchWorkspaceMembers: action,
fetchWorkspaceMemberInvitations: action, fetchWorkspaceMemberInvitations: action,
updateMember: action, updateMember: action,
@ -64,6 +70,7 @@ export class WorkspaceMemberStore implements IWorkspaceMemberStore {
workspaceMembers: computed, workspaceMembers: computed,
workspaceMemberInvitations: computed, workspaceMemberInvitations: computed,
workspaceMembersWithInvitations: computed, workspaceMembersWithInvitations: computed,
currentWorkspaceUserProjectsRole: computed,
}); });
this.rootStore = _rootStore; this.rootStore = _rootStore;
@ -126,6 +133,36 @@ export class WorkspaceMemberStore implements IWorkspaceMemberStore {
]; ];
} }
/**
* computed value provides the workspace user projects role
*/
get currentWorkspaceUserProjectsRole() {
if (!this.rootStore.workspace.workspaceSlug) return undefined;
return this.workspaceUserProjectsRole?.[this.rootStore.workspace.workspaceSlug];
}
/**
* fetch workspace user projects role using workspace slug
* @param workspaceSlug
*/
fetchWorkspaceUserProjectsRole = async (workspaceSlug: string) => {
try {
const _workspaceUserProjectsRole = { ...this.workspaceUserProjectsRole };
if (!_workspaceUserProjectsRole[workspaceSlug]) _workspaceUserProjectsRole[workspaceSlug] = {};
const response = await this.workspaceService.getWorkspaceUserProjectsRole(workspaceSlug);
_workspaceUserProjectsRole[workspaceSlug] = response;
runInAction(() => {
this.workspaceUserProjectsRole = _workspaceUserProjectsRole;
});
return response;
} catch (error) {
throw error;
}
};
/** /**
* fetch workspace members using workspace slug * fetch workspace members using workspace slug
* @param workspaceSlug * @param workspaceSlug

View File

@ -162,6 +162,10 @@ export interface IUserProfileProjectSegregation {
}; };
} }
export interface IUserProjectsRole {
[project_id: string]: number;
}
// export interface ICurrentUser { // export interface ICurrentUser {
// id: readonly string; // id: readonly string;
// avatar: string; // avatar: string;