Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: project issues topbar #2256

Merged
merged 7 commits into from
Sep 25, 2023
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
6 changes: 3 additions & 3 deletions web/components/core/filters/issues-view-filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ import {
import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
import { checkIfArraysHaveSameElements } from "helpers/array.helper";
// types
import { Properties, TIssueViewOptions } from "types";
import { Properties, TIssueLayouts } from "types";
// constants
import { ISSUE_GROUP_BY_OPTIONS, ISSUE_ORDER_BY_OPTIONS, ISSUE_FILTER_OPTIONS } from "constants/issue";

const issueViewOptions: { type: TIssueViewOptions; Icon: any }[] = [
const issueViewOptions: { type: TIssueLayouts; Icon: any }[] = [
{
type: "list",
Icon: FormatListBulletedOutlined,
Expand All @@ -52,7 +52,7 @@ const issueViewOptions: { type: TIssueViewOptions; Icon: any }[] = [
},
];

const issueViewForDraftIssues: { type: TIssueViewOptions; Icon: any }[] = [
const issueViewForDraftIssues: { type: TIssueLayouts; Icon: any }[] = [
{
type: "list",
Icon: FormatListBulletedOutlined,
Expand Down
21 changes: 6 additions & 15 deletions web/components/core/views/board-view/all-boards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,28 +65,21 @@ export const AllBoards: React.FC<Props> = ({

const { displayFilters, groupedIssues } = viewProps;

console.log("viewProps", viewProps);

return (
<>
<IssuePeekOverview
handleMutation={() =>
isMyIssue ? mutateMyIssues() : isProfileIssue ? mutateProfileIssues() : mutateIssues()
}
handleMutation={() => (isMyIssue ? mutateMyIssues() : isProfileIssue ? mutateProfileIssues() : mutateIssues())}
projectId={myIssueProjectId ? myIssueProjectId : projectId?.toString() ?? ""}
workspaceSlug={workspaceSlug?.toString() ?? ""}
readOnly={disableUserActions}
/>
{groupedIssues ? (
<div className="horizontal-scroll-enable flex h-full gap-x-4 p-8 bg-custom-background-90">
<div className="horizontal-scroll-enable flex h-full gap-x-4 p-5 bg-custom-background-90">
{Object.keys(groupedIssues).map((singleGroup, index) => {
const currentState =
displayFilters?.group_by === "state"
? states?.find((s) => s.id === singleGroup)
: null;
displayFilters?.group_by === "state" ? states?.find((s) => s.id === singleGroup) : null;

if (!displayFilters?.show_empty_groups && groupedIssues[singleGroup].length === 0)
return null;
if (!displayFilters?.show_empty_groups && groupedIssues[singleGroup].length === 0) return null;

return (
<SingleBoard
Expand Down Expand Up @@ -115,15 +108,13 @@ export const AllBoards: React.FC<Props> = ({
<div className="space-y-3">
{Object.keys(groupedIssues).map((singleGroup, index) => {
const currentState =
displayFilters?.group_by === "state"
? states?.find((s) => s.id === singleGroup)
: null;
displayFilters?.group_by === "state" ? states?.find((s) => s.id === singleGroup) : null;

if (groupedIssues[singleGroup].length === 0)
return (
<div
key={index}
className="flex items-center justify-between gap-2 rounded bg-custom-background-90 p-2 shadow"
className="flex items-center justify-between gap-2 rounded bg-custom-background-100 p-2 shadow-custom-shadow-2xs"
>
<div className="flex items-center gap-2">
{currentState && (
Expand Down
1 change: 1 addition & 0 deletions web/components/core/views/issues-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ export const IssuesView: React.FC<Props> = ({ openIssuesListModal, disableUserAc
labels: null,
priority: null,
state: null,
state_group: null,
start_date: null,
target_date: null,
})
Expand Down
2 changes: 0 additions & 2 deletions web/components/core/views/list-view/single-issue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,6 @@ export const SingleListIssue: React.FC<Props> = ({

const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disableUserActions || isArchivedIssues;

console.log("properties", properties);

return (
<>
<ContextMenu
Expand Down
1 change: 1 addition & 0 deletions web/components/headers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./project-issues";
42 changes: 42 additions & 0 deletions web/components/headers/project-issues.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useRouter } from "next/router";

// mobx
import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider";
// components
import { DisplayFiltersSelection, FilterSelection, IssueDropdown, LayoutSelection } from "components/issue-layouts";
// types
import { TIssueLayouts } from "types";

export const ProjectIssuesHeader = observer(() => {
const router = useRouter();
const { workspaceSlug, projectId } = router.query;

const { issueFilter: issueFilterStore } = useMobxStore();

const handleLayoutChange = (layout: TIssueLayouts) => {
if (!workspaceSlug || !projectId) return;

issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), {
display_filters: {
layout,
},
});
};

return (
<div className="flex items-center gap-2">
<LayoutSelection
layouts={["calendar", "gantt_chart", "kanban", "list", "spreadsheet"]}
onChange={(layout) => handleLayoutChange(layout)}
selectedLayout={issueFilterStore.userDisplayFilters.layout ?? "list"}
/>
<IssueDropdown title="Filters">
<FilterSelection workspaceSlug={workspaceSlug?.toString() ?? ""} projectId={projectId?.toString() ?? ""} />
</IssueDropdown>
<IssueDropdown title="View">
<DisplayFiltersSelection />
</IssueDropdown>
</div>
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React from "react";

// mobx
import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider";
// components
import {
FilterDisplayProperties,
FilterExtraOptions,
FilterGroupBy,
FilterIssueType,
FilterOrderBy,
} from "components/issue-layouts";
// helpers
import { issueFilterVisibilityData } from "helpers/issue.helper";

export const DisplayFiltersSelection = observer(() => {
const { issueFilter: issueFilterStore } = useMobxStore();

const isDisplayFilterEnabled = (displayFilter: string) =>
issueFilterVisibilityData.issues.display_filters[issueFilterStore.userDisplayFilters.layout ?? "list"].includes(
displayFilter
);

return (
<div className="w-full h-full overflow-hidden select-none relative flex flex-col divide-y divide-custom-border-200 px-0.5">
{/* <div className="flex-shrink-0 p-2 text-sm">Search container</div> */}
<div className="w-full h-full overflow-hidden overflow-y-auto relative pb-2 divide-y divide-custom-border-200">
{/* display properties */}
{issueFilterVisibilityData.issues.display_properties[issueFilterStore.userDisplayFilters.layout ?? "list"] && (
<div className="pb-2 px-2">
<FilterDisplayProperties />
</div>
)}

{/* group by */}
{isDisplayFilterEnabled("group_by") && (
<div className="py-1 px-2">
<FilterGroupBy />
</div>
)}

{/* order by */}
{isDisplayFilterEnabled("order_by") && (
<div className="py-1 px-2">
<FilterOrderBy />
</div>
)}

{/* issue type */}
{isDisplayFilterEnabled("issue_type") && (
<div className="py-1 px-2">
<FilterIssueType />
</div>
)}

{/* Options */}
{issueFilterVisibilityData.issues.extra_options[issueFilterStore.userDisplayFilters.layout ?? "list"]
.access && (
<div className="pt-1 px-2">
<FilterExtraOptions />
</div>
)}
</div>
</div>
);
});
57 changes: 33 additions & 24 deletions web/components/issue-layouts/display-filters/display-properties.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,58 @@
import React from "react";
// components
import { FilterHeader } from "../helpers/filter-header";
// mobx react lite

import { useRouter } from "next/router";

// mobx
import { observer } from "mobx-react-lite";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
// components
import { FilterHeader } from "../helpers/filter-header";
// types
import { IIssueDisplayProperties } from "types";
// constants
import { ISSUE_DISPLAY_PROPERTIES } from "constants/issue";

export const FilterDisplayProperties = observer(() => {
const store: RootStore = useMobxStore();
const router = useRouter();
const { workspaceSlug, projectId } = router.query;

const store = useMobxStore();
const { issueFilter: issueFilterStore } = store;

const [previewEnabled, setPreviewEnabled] = React.useState(true);

const handleDisplayProperties = (key: string, value: boolean) => {
// issueFilterStore.handleUserFilter("display_properties", key, !value);
const handleDisplayProperties = (property: Partial<IIssueDisplayProperties>) => {
if (!workspaceSlug || !projectId) return;

issueFilterStore.updateDisplayProperties(workspaceSlug.toString(), projectId.toString(), property);
};

return (
<div>
<FilterHeader
title={"Display Properties"}
title="Display Properties"
isPreviewEnabled={previewEnabled}
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
/>
{previewEnabled && (
<div className="space-y-[2px] pt-1 px-1 flex items-center whitespace-nowrap gap-2 flex-wrap">
<div className="flex items-center gap-2 flex-wrap mx-1 mt-1">
{ISSUE_DISPLAY_PROPERTIES.map((displayProperty) => (
<div
key={displayProperty?.key}
className={`cursor-pointer rounded-sm transition-all text-xs border p-0.5 px-1.5 ${
issueFilterStore?.userDisplayProperties?.[displayProperty?.key]
? `bg-custom-primary-200 border-custom-primary-200 text-white`
: `hover:bg-custom-border-100 border-custom-border-100`
<button
key={displayProperty.key}
type="button"
className={`rounded transition-all text-xs border px-2 py-0.5 ${
issueFilterStore?.userDisplayProperties?.[displayProperty.key]
? "bg-custom-primary-100 border-custom-primary-100 text-white"
: "border-custom-border-200 hover:bg-custom-background-80"
}`}
onClick={() => {
handleDisplayProperties(
displayProperty?.key,
issueFilterStore?.userDisplayProperties?.[displayProperty?.key]
);
}}
onClick={() =>
handleDisplayProperties({
[displayProperty.key]: !issueFilterStore?.userDisplayProperties?.[displayProperty.key],
})
}
>
{displayProperty?.title}
</div>
{displayProperty.title}
</button>
))}
</div>
)}
Expand Down
64 changes: 29 additions & 35 deletions web/components/issue-layouts/display-filters/extra-options.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,47 @@
import React from "react";
// components
import { FilterHeader } from "../helpers/filter-header";
import { FilterOption } from "../helpers/filter-option";
// mobx react lite
import React, { useState } from "react";

// mobx
import { observer } from "mobx-react-lite";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
import { ISSUE_EXTRA_PROPERTIES } from "constants/issue";
// default data
// import { issueFilterVisibilityData } from "helpers/issue.helper";

export const FilterExtraOptions = observer(() => {
const store: RootStore = useMobxStore();
const { issueFilter: issueFilterStore } = store;
// components
import { FilterHeader, FilterOption } from "components/issue-layouts";
// helpers
import { issueFilterVisibilityData } from "helpers/issue.helper";
// constants
import { ISSUE_EXTRA_OPTIONS } from "constants/issue";

const [previewEnabled, setPreviewEnabled] = React.useState(true);
export const FilterExtraOptions = observer(() => {
const [previewEnabled, setPreviewEnabled] = useState(true);

const handleExtraOptions = (key: string, value: boolean) => {
// issueFilterStore.handleUserFilter("display_filters", key, !value);
};
const store = useMobxStore();
const { issueFilter: issueFilterStore } = store;

const handleExtraOptionsSectionVisibility = (key: string) => {
// issueFilterStore?.issueView &&
// issueFilterStore?.issueLayout &&
// issueFilterVisibilityData[issueFilterStore?.issueView === "my_issues" ? "my_issues" : "issues"]?.extra_options?.[
// issueFilterStore?.issueLayout
// ].values?.includes(key);
};
const isExtraOptionEnabled = (option: string) =>
issueFilterVisibilityData.issues.extra_options[
issueFilterStore.userDisplayFilters.layout ?? "list"
].values.includes(option);

return (
<div>
<FilterHeader
title={"Extra Options"}
title="Extra Options"
isPreviewEnabled={previewEnabled}
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
/>
{previewEnabled && (
<div className="space-y-[2px] pt-1">
{ISSUE_EXTRA_PROPERTIES.map((_extraProperties) => (
<FilterOption
key={_extraProperties?.key}
isChecked={issueFilterStore?.userDisplayFilters?.[_extraProperties?.key] ? true : false}
onClick={() =>
handleExtraOptions(_extraProperties?.key, issueFilterStore?.userDisplayFilters?.[_extraProperties?.key])
}
title={_extraProperties.title}
/>
))}
{ISSUE_EXTRA_OPTIONS.map((option) => {
if (!isExtraOptionEnabled(option.key)) return null;

return (
<FilterOption
key={option.key}
isChecked={issueFilterStore?.userDisplayFilters?.[option.key] ? true : false}
title={option.title}
/>
);
})}
</div>
)}
</div>
Expand Down
Loading
Loading