Skip to content

Commit

Permalink
fix: corrected rendering of workspace-level labels, members, and stat…
Browse files Browse the repository at this point in the history
…es in project view (#2966)

* fix: dynamic issue properties filters in project, workspace and profile level

* clean-up: removed logs from the project store
  • Loading branch information
gurusainath authored and sriramveeraghanta committed Dec 7, 2023
1 parent 1296b6a commit f969ed0
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 28 deletions.
3 changes: 3 additions & 0 deletions web/components/issues/issue-layouts/kanban/properties.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ export const KanBanProperties: React.FC<IKanBanProperties> = observer((props) =>
<IssuePropertyState
projectId={issue?.project_detail?.id || null}
value={issue?.state || null}
defaultOptions={issue?.state_detail ? [issue.state_detail] : []}
onChange={handleState}
disabled={isReadOnly}
hideDropdownArrow
Expand All @@ -110,6 +111,7 @@ export const KanBanProperties: React.FC<IKanBanProperties> = observer((props) =>
<IssuePropertyLabels
projectId={issue?.project_detail?.id || null}
value={issue?.labels || null}
defaultOptions={issue?.label_details ? issue.label_details : []}
onChange={handleLabel}
disabled={isReadOnly}
hideDropdownArrow
Expand Down Expand Up @@ -141,6 +143,7 @@ export const KanBanProperties: React.FC<IKanBanProperties> = observer((props) =>
<IssuePropertyAssignee
projectId={issue?.project_detail?.id || null}
value={issue?.assignees || null}
defaultOptions={issue?.assignee_details ? issue.assignee_details : []}
hideDropdownArrow
onChange={handleAssignee}
disabled={isReadOnly}
Expand Down
3 changes: 3 additions & 0 deletions web/components/issues/issue-layouts/list/properties.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export const ListProperties: FC<IListProperties> = observer((props) => {
<IssuePropertyState
projectId={issue?.project_detail?.id || null}
value={issue?.state || null}
defaultOptions={issue?.state_detail ? [issue.state_detail] : []}
hideDropdownArrow
onChange={handleState}
disabled={isReadonly}
Expand All @@ -81,6 +82,7 @@ export const ListProperties: FC<IListProperties> = observer((props) => {
<IssuePropertyLabels
projectId={issue?.project_detail?.id || null}
value={issue?.labels || null}
defaultOptions={issue?.label_details ? issue.label_details : []}
onChange={handleLabel}
disabled={isReadonly}
hideDropdownArrow
Expand All @@ -92,6 +94,7 @@ export const ListProperties: FC<IListProperties> = observer((props) => {
<IssuePropertyAssignee
projectId={issue?.project_detail?.id || null}
value={issue?.assignees || null}
defaultOptions={issue?.assignee_details ? issue.assignee_details : []}
hideDropdownArrow
onChange={handleAssignee}
disabled={isReadonly}
Expand Down
30 changes: 14 additions & 16 deletions web/components/issues/issue-layouts/properties/assignee.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import { Check, ChevronDown, Search, User2 } from "lucide-react";
import { Avatar, AvatarGroup, Tooltip } from "@plane/ui";
// types
import { Placement } from "@popperjs/core";
import { IProjectMember } from "types";

export interface IIssuePropertyAssignee {
projectId: string | null;
value: string[] | string;
defaultOptions?: any;
onChange: (data: string[]) => void;
disabled?: boolean;
hideDropdownArrow?: boolean;
Expand All @@ -27,6 +29,7 @@ export const IssuePropertyAssignee: React.FC<IIssuePropertyAssignee> = observer(
const {
projectId,
value,
defaultOptions = [],
onChange,
disabled = false,
hideDropdownArrow = false,
Expand All @@ -40,8 +43,7 @@ export const IssuePropertyAssignee: React.FC<IIssuePropertyAssignee> = observer(
// store
const {
workspace: workspaceStore,
project: projectStore,
workspaceMember: { workspaceMembers, fetchWorkspaceMembers },
projectMember: { projectMembers: _projectMembers, fetchProjectMembers },
} = useMobxStore();
const workspaceSlug = workspaceStore?.workspaceSlug;
// states
Expand All @@ -50,20 +52,16 @@ export const IssuePropertyAssignee: React.FC<IIssuePropertyAssignee> = observer(
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
const [isLoading, setIsLoading] = useState<Boolean>(false);

// const fetchProjectMembers = () => {
// setIsLoading(true);
// if (workspaceSlug && projectId)
// workspaceSlug &&
// projectId &&
// projectStore.fetchProjectMembers(workspaceSlug, projectId).then(() => setIsLoading(false));
// };

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

const options = (workspaceMembers ?? [])?.map((member) => ({
const updatedDefaultOptions: IProjectMember[] =
defaultOptions.map((member: any) => ({ member: { ...member } })) ?? [];
const projectMembers = _projectMembers ?? updatedDefaultOptions;

const options = projectMembers?.map((member) => ({
value: member.member.id,
query: member.member.display_name,
content: (
Expand All @@ -82,7 +80,7 @@ export const IssuePropertyAssignee: React.FC<IIssuePropertyAssignee> = observer(

// if multiple assignees
if (Array.isArray(value)) {
const assignees = workspaceMembers?.filter((m) => value.includes(m.member.id));
const assignees = projectMembers?.filter((m) => value.includes(m.member.id));

if (!assignees || assignees.length === 0) return "No Assignee";

Expand All @@ -93,7 +91,7 @@ export const IssuePropertyAssignee: React.FC<IIssuePropertyAssignee> = observer(
}

// if single assignee
const assignee = workspaceMembers?.find((m) => m.member.id === value)?.member;
const assignee = projectMembers?.find((m) => m.member.id === value)?.member;

if (!assignee) return "No Assignee";

Expand All @@ -107,7 +105,7 @@ export const IssuePropertyAssignee: React.FC<IIssuePropertyAssignee> = observer(
{value && value.length > 0 && Array.isArray(value) ? (
<AvatarGroup showTooltip={false}>
{value.map((assigneeId) => {
const member = workspaceMembers?.find((m) => m.member.id === assigneeId)?.member;
const member = projectMembers?.find((m) => m.member.id === assigneeId)?.member;
if (!member) return null;
return <Avatar key={member.id} name={member.display_name} src={member.avatar} />;
})}
Expand Down Expand Up @@ -149,7 +147,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 && getWorkspaceMembers()}
onClick={() => !projectMembers && getWorkspaceMembers()}
>
{label}
{!hideDropdownArrow && !disabled && <ChevronDown className="h-3 w-3" aria-hidden="true" />}
Expand Down
22 changes: 15 additions & 7 deletions web/components/issues/issue-layouts/properties/labels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import { Check, ChevronDown, Search } from "lucide-react";
// types
import { Placement } from "@popperjs/core";
import { RootStore } from "store/root";
import { IIssueLabel } from "types";

export interface IIssuePropertyLabels {
projectId: string | null;
value: string[];
defaultOptions?: any;
onChange: (data: string[]) => void;
disabled?: boolean;
hideDropdownArrow?: boolean;
Expand All @@ -29,6 +31,7 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro
const {
projectId,
value,
defaultOptions = [],
onChange,
disabled,
hideDropdownArrow = false,
Expand All @@ -42,7 +45,7 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro

const {
workspace: workspaceStore,
projectLabel: { fetchProjectLabels, projectLabels },
projectLabel: { fetchProjectLabels, labels },
}: RootStore = useMobxStore();
const workspaceSlug = workspaceStore?.workspaceSlug;

Expand All @@ -59,7 +62,11 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro

if (!value) return null;

const options = (projectLabels ? projectLabels : []).map((label) => ({
let projectLabels: IIssueLabel[] = defaultOptions;
const storeLabels = projectId && labels ? labels[projectId] : [];
if (storeLabels && storeLabels.length > 0) projectLabels = storeLabels;

const options = projectLabels.map((label) => ({
value: label.id,
query: label.name,
content: (
Expand Down Expand Up @@ -95,7 +102,7 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro
{value.length > 0 ? (
value.length <= maxRender ? (
<>
{(projectLabels ? projectLabels : [])
{projectLabels
?.filter((l) => value.includes(l.id))
.map((label) => (
<Tooltip position="top" tooltipHeading="Labels" tooltipContent={label.name ?? ""}>
Expand Down Expand Up @@ -123,7 +130,7 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro
<Tooltip
position="top"
tooltipHeading="Labels"
tooltipContent={(projectLabels ? projectLabels : [])
tooltipContent={projectLabels
?.filter((l) => value.includes(l.id))
.map((l) => l.name)
.join(", ")}
Expand Down Expand Up @@ -167,7 +174,7 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro
? "cursor-pointer"
: "cursor-pointer hover:bg-custom-background-80"
} ${buttonClassName}`}
onClick={() => !projectLabels && fetchLabels()}
onClick={() => !storeLabels && fetchLabels()}
>
{label}
{!hideDropdownArrow && !disabled && <ChevronDown className="h-3 w-3" aria-hidden="true" />}
Expand Down Expand Up @@ -200,8 +207,9 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro
key={option.value}
value={option.value}
className={({ selected }) =>
`flex items-center justify-between gap-2 cursor-pointer select-none truncate rounded px-1 py-1.5 hover:bg-custom-background-80
${selected ? "text-custom-text-100" : "text-custom-text-200"}`
`flex items-center justify-between gap-2 cursor-pointer select-none truncate rounded px-1 py-1.5 hover:bg-custom-background-80 ${
selected ? "text-custom-text-100" : "text-custom-text-200"
}`
}
>
{({ selected }) => (
Expand Down
11 changes: 6 additions & 5 deletions web/components/issues/issue-layouts/properties/state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { RootStore } from "store/root";
export interface IIssuePropertyState {
projectId: string | null;
value: any | string | null;
defaultOptions?: any;
onChange: (state: IState) => void;
disabled?: boolean;
hideDropdownArrow?: boolean;
Expand All @@ -30,6 +31,7 @@ export const IssuePropertyState: React.FC<IIssuePropertyState> = observer((props
const {
projectId,
value,
defaultOptions = [],
onChange,
disabled,
hideDropdownArrow = false,
Expand All @@ -47,10 +49,9 @@ export const IssuePropertyState: React.FC<IIssuePropertyState> = observer((props
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
const [isLoading, setIsLoading] = useState<Boolean>(false);

const projectStates: IState[] = [];
const projectStatesByGroup = projectStateStore.groupedProjectStates;
if (projectStatesByGroup)
for (const group in projectStatesByGroup) projectStates.push(...projectStatesByGroup[group]);
let projectStates: IState[] = defaultOptions;
const storeStates = projectId ? projectStateStore.states[projectId] : [];
if (storeStates && storeStates.length > 0) projectStates = storeStates;

const fetchProjectStates = () => {
setIsLoading(true);
Expand Down Expand Up @@ -120,7 +121,7 @@ export const IssuePropertyState: React.FC<IIssuePropertyState> = observer((props
className={`flex items-center justify-between h-5 gap-1 w-full text-xs px-2.5 py-1 rounded border-[0.5px] border-custom-border-300 ${
disabled ? "cursor-not-allowed text-custom-text-200" : "cursor-pointer hover:bg-custom-background-80"
} ${buttonClassName}`}
onClick={() => !projectStatesByGroup && fetchProjectStates()}
onClick={() => !storeStates && fetchProjectStates()}
>
{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 @@ -25,6 +25,7 @@ export const SpreadsheetAssigneeColumn: React.FC<Props> = ({ issue, members, onC
<IssuePropertyAssignee
projectId={issue.project_detail?.id ?? null}
value={issue.assignees}
defaultOptions={issue?.assignee_details ? issue.assignee_details : []}
onChange={(data) => onChange({ assignees: data })}
className="h-full w-full"
buttonClassName="!shadow-none !border-0 h-full w-full px-2.5 py-1 "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const SpreadsheetLabelColumn: React.FC<Props> = (props) => {
<IssuePropertyLabels
projectId={issue.project_detail?.id ?? null}
value={issue.labels}
defaultOptions={issue?.label_details ? issue.label_details : []}
onChange={(data) => onChange({ labels: data })}
className="h-full w-full"
buttonClassName="px-2.5 h-full"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const SpreadsheetStateColumn: React.FC<Props> = (props) => {
<IssuePropertyState
projectId={issue.project_detail?.id ?? null}
value={issue.state_detail.id}
defaultOptions={issue?.state_detail ? [issue.state_detail] : []}
onChange={(data) => onChange({ state: data.id, state_detail: data })}
className="h-full w-full"
buttonClassName="!shadow-none !border-0 h-full w-full"
Expand Down

0 comments on commit f969ed0

Please sign in to comment.