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

chore: global issues ui improvement and bug fixes #2300

Merged
merged 1 commit into from
Sep 29, 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
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export const IssueColumn: React.FC<Props> = ({
const isNotAllowed = userAuth.isGuest || userAuth.isViewer;

return (
<div className="group flex items-center w-[28rem] text-sm h-11 sticky top-0 bg-custom-background-100 truncate border-b border-r border-custom-border-200">
<div className="group flex items-center w-[28rem] text-sm h-11 sticky top-0 bg-custom-background-100 truncate border-b border-r border-custom-border-100">
<div
className="flex gap-1.5 px-4 pr-0 py-2.5 items-center w-24"
style={issue.parent && nestingLevel !== 0 ? { paddingLeft } : {}}
Expand All @@ -101,7 +101,7 @@ export const IssueColumn: React.FC<Props> = ({
onInteraction={(nextOpenState) => setIsOpen(nextOpenState)}
content={
<div
className={`flex flex-col gap-1.5 overflow-y-scroll whitespace-nowrap rounded-md border p-1 text-xs shadow-lg focus:outline-none max-h-44 min-w-full border-custom-border-200 bg-custom-background-90`}
className={`flex flex-col gap-1.5 overflow-y-scroll whitespace-nowrap rounded-md border p-1 text-xs shadow-lg focus:outline-none max-h-44 min-w-full border-custom-border-100 bg-custom-background-90`}
>
<button
type="button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ export const SpreadsheetView: React.FC<Props> = ({
descendingOrder: TIssueOrderByOptions
) => (
<div className="relative flex flex-col h-max w-full bg-custom-background-100">
<div className="flex items-center min-w-[9rem] px-4 py-2.5 text-sm font-medium z-[1] h-11 w-full sticky top-0 bg-custom-background-90 border border-l-0 border-custom-border-200">
<div className="flex items-center min-w-[9rem] px-4 py-2.5 text-sm font-medium z-[1] h-11 w-full sticky top-0 bg-custom-background-90 border border-l-0 border-custom-border-100">
<CustomMenu
customButtonClassName="!w-full"
className="!w-full"
Expand Down Expand Up @@ -491,7 +491,7 @@ export const SpreadsheetView: React.FC<Props> = ({
isScrolled ? "shadow-r shadow-custom-shadow-xs" : ""
}`}
>
<div className="flex items-center text-sm font-medium z-[2] h-11 w-full sticky top-0 bg-custom-background-90 border border-l-0 border-custom-border-200">
<div className="flex items-center text-sm font-medium z-[2] h-11 w-full sticky top-0 bg-custom-background-90 border border-l-0 border-custom-border-100">
<span className="flex items-center px-4 py-2.5 h-full w-24 flex-shrink-0">
ID
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { IIssue, IWorkspaceIssueFilterOptions } from "types";

export const WorkspaceViewIssues = () => {
const router = useRouter();
const { workspaceSlug, workspaceViewId } = router.query;
const { workspaceSlug, viewId } = router.query;

const { memberRole } = useProjectMyMembership();
const { user } = useUser();
Expand Down Expand Up @@ -189,16 +189,16 @@ export const WorkspaceViewIssues = () => {
/>
<PrimaryButton
onClick={() => {
if (workspaceViewId) handleFilters("filters", filters.filters, true);
if (viewId) handleFilters("filters", filters.filters, true);
else
setCreateViewModal({
query: filters.filters,
});
}}
className="flex items-center gap-2 text-sm"
>
{!workspaceViewId && <PlusIcon className="h-4 w-4" />}
{workspaceViewId ? "Update" : "Save"} view
{!viewId && <PlusIcon className="h-4 w-4" />}
{viewId ? "Update" : "Save"} view
</PrimaryButton>
</div>
{<div className="mt-3 border-t border-custom-border-200" />}
Expand Down
8 changes: 4 additions & 4 deletions web/components/issues/workspace-views/workspace-all-issue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { IIssue, IWorkspaceIssueFilterOptions } from "types";

export const WorkspaceAllIssue = () => {
const router = useRouter();
const { workspaceSlug, workspaceViewId } = router.query;
const { workspaceSlug, viewId } = router.query;

const [createViewModal, setCreateViewModal] = useState<any>(null);

Expand Down Expand Up @@ -203,16 +203,16 @@ export const WorkspaceAllIssue = () => {
/>
<PrimaryButton
onClick={() => {
if (workspaceViewId) handleFilters("filters", filters.filters, true);
if (viewId) handleFilters("filters", filters.filters, true);
else
setCreateViewModal({
query: filters.filters,
});
}}
className="flex items-center gap-2 text-sm"
>
{!workspaceViewId && <PlusIcon className="h-4 w-4" />}
{workspaceViewId ? "Update" : "Save"} view
{!viewId && <PlusIcon className="h-4 w-4" />}
{viewId ? "Update" : "Save"} view
</PrimaryButton>
</div>
{<div className="mt-3 border-t border-custom-border-200" />}
Expand Down
2 changes: 1 addition & 1 deletion web/components/views/single-view-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export const SingleViewItem: React.FC<Props> = ({
const viewRedirectionUrl =
viewType === "project"
? `/${workspaceSlug}/projects/${projectId}/views/${view.id}`
: `/${workspaceSlug}/workspace-views/${view.id}`;
: `/${workspaceSlug}/workspace-views/issues?viewId=${view.id}`;

return (
<div className="group hover:bg-custom-background-90 border-b border-custom-border-200">
Expand Down
2 changes: 1 addition & 1 deletion web/components/workspace/sidebar-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const workspaceLinks = (workspaceSlug: string) => [
},
{
Icon: TaskAltOutlined,
name: "Issues",
name: "All Issues",
href: `/${workspaceSlug}/workspace-views/all-issues`,
},
];
Expand Down
4 changes: 3 additions & 1 deletion web/components/workspace/views/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = ({
};
await workspaceService
.createView(workspaceSlug as string, payloadData)
.then(() => {
.then((res) => {
mutate(WORKSPACE_VIEWS_LIST(workspaceSlug as string));
handleClose();

router.replace(`/${workspaceSlug}/workspace-views/issues?viewId=${res.id}`);

setToastAlert({
type: "success",
title: "Success!",
Expand Down
41 changes: 27 additions & 14 deletions web/components/workspace/views/workpace-view-navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,75 +17,88 @@ type Props = {

export const WorkspaceViewsNavigation: React.FC<Props> = ({ handleAddView }) => {
const router = useRouter();
const { workspaceSlug, workspaceViewId } = router.query;
const { workspaceSlug, viewId } = router.query;

const { data: workspaceViews } = useSWR(
workspaceSlug ? WORKSPACE_VIEWS_LIST(workspaceSlug.toString()) : null,
workspaceSlug ? () => workspaceService.getAllViews(workspaceSlug.toString()) : null
);

const isSelected = (pathName: string) => router.pathname.includes(pathName);
React.useEffect(() => {
const activeTabElement = document.getElementById("active-tab-global-view");
if (activeTabElement) activeTabElement.scrollIntoView({ behavior: "smooth", inline: "center" });
}, [viewId, workspaceViews]);

const tabsList = [
{
key: "all",
label: "All Issues",
selected: isSelected("workspace-views/all-issues"),
onClick: () => router.push(`/${workspaceSlug}/workspace-views/all-issues`),
onClick: () => router.replace(`/${workspaceSlug}/workspace-views/all-issues`),
},
{
key: "assigned",
label: "Assigned",
selected: isSelected("workspace-views/assigned"),
onClick: () => router.push(`/${workspaceSlug}/workspace-views/assigned`),
onClick: () => router.replace(`/${workspaceSlug}/workspace-views/assigned`),
},
{
key: "created",
label: "Created",
selected: isSelected("workspace-views/created"),
onClick: () => router.push(`/${workspaceSlug}/workspace-views/created`),
onClick: () => router.replace(`/${workspaceSlug}/workspace-views/created`),
},
{
key: "subscribed",
label: "Subscribed",
selected: isSelected("workspace-views/subscribed"),
onClick: () => router.push(`/${workspaceSlug}/workspace-views/subscribed`),
onClick: () => router.replace(`/${workspaceSlug}/workspace-views/subscribed`),
},
];

return (
<div className="group flex items-center overflow-x-scroll">
<div className="group flex items-center gap-x-1 overflow-x-scroll relative">
{tabsList.map((tab) => (
<button
key={tab.key}
type="button"
onClick={tab.onClick}
className={`border-b-2 min-w-[96px] p-4 text-sm font-medium outline-none whitespace-nowrap ${
className={`border-b-2 min-w-min p-3 text-sm font-medium outline-none whitespace-nowrap flex-shrink-0 ${
tab.selected
? "border-custom-primary-100 text-custom-primary-100"
: "border-transparent hover:border-custom-primary-100 hover:text-custom-primary-100"
: "border-transparent hover:border-custom-border-200 hover:text-custom-text-400"
}`}
id={tab.selected ? `active-tab-global-view` : ``}
>
{tab.label}
</button>
))}

{workspaceViews &&
workspaceViews.length > 0 &&
workspaceViews?.map((view) => (
<button
className={`border-b-2 min-w-[96px] p-4 text-sm font-medium outline-none whitespace-nowrap ${
view.id === workspaceViewId
className={`border-b-2 min-w-min p-3 text-sm font-medium outline-none whitespace-nowrap flex-shrink-0 ${
view.id === viewId
? "border-custom-primary-100 text-custom-primary-100"
: "border-transparent hover:border-custom-primary-100 hover:text-custom-primary-100"
: "border-transparent hover:border-custom-border-200 hover:text-custom-text-400"
}`}
onClick={() => router.push(`/${workspaceSlug}/workspace-views/${view.id}`)}
id={view.id === viewId ? `active-tab-global-view` : ``}
onClick={() =>
router.replace(`/${workspaceSlug}/workspace-views/issues?viewId=${view.id}`)
}
>
{view.name}
</button>
))}

<button type="button" className="min-w-[96px] " onClick={handleAddView}>
<PlusIcon className="h-4 w-4 text-custom-primary-200 hover:text-current" />
<button
type="button"
className="flex items-center justify-center flex-shrink-0 sticky right-0 w-12 py-3 border-transparent bg-custom-background-100 hover:border-custom-border-200 hover:text-custom-text-400"
onClick={handleAddView}
>
<PlusIcon className="h-4 w-4 text-custom-primary-200" />
</button>
</div>
);
Expand Down
22 changes: 11 additions & 11 deletions web/contexts/workspace-view-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,19 @@ export const initialState: IWorkspaceGlobalViewProps = {

const saveViewFilters = async (
workspaceSlug: string,
workspaceViewId: string,
viewId: string,
state: IWorkspaceGlobalViewProps
) => {
await workspaceService.updateView(workspaceSlug, workspaceViewId, {
await workspaceService.updateView(workspaceSlug, viewId, {
query_data: state,
});
};

export const WorkspaceViewProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const router = useRouter();
const { workspaceSlug, workspaceViewId } = router.query as {
const { workspaceSlug, viewId } = router.query as {
workspaceSlug: string;
workspaceViewId: string;
viewId: string;
};

const [filters, setFilters] = useState<IWorkspaceGlobalViewProps>(initialState);
Expand All @@ -98,7 +98,7 @@ export const WorkspaceViewProvider: React.FC<{ children: React.ReactNode }> = ({
};
setFilters(() => updatedFilterPayload);

if (saveFiltersToServer) saveViewFilters(workspaceSlug, workspaceViewId, updatedFilterPayload);
if (saveFiltersToServer) saveViewFilters(workspaceSlug, viewId, updatedFilterPayload);
};

const computedFilter = (filters: any) => {
Expand Down Expand Up @@ -151,9 +151,9 @@ export const WorkspaceViewProvider: React.FC<{ children: React.ReactNode }> = ({
};

const { data: view, isLoading: viewLoading } = useSWR(
workspaceSlug && workspaceViewId ? WORKSPACE_VIEW_DETAILS(workspaceViewId.toString()) : null,
workspaceSlug && workspaceViewId
? () => workspaceService.getViewDetails(workspaceSlug.toString(), workspaceViewId.toString())
workspaceSlug && viewId ? WORKSPACE_VIEW_DETAILS(viewId.toString()) : null,
workspaceSlug && viewId
? () => workspaceService.getViewDetails(workspaceSlug.toString(), viewId.toString())
: null
);

Expand All @@ -162,10 +162,10 @@ export const WorkspaceViewProvider: React.FC<{ children: React.ReactNode }> = ({
mutate: mutateViewIssues,
isLoading: viewIssueLoading,
} = useSWR(
workspaceSlug && view && workspaceViewId && filters
? WORKSPACE_VIEW_ISSUES(workspaceViewId.toString(), params)
workspaceSlug && view && viewId && filters
? WORKSPACE_VIEW_ISSUES(viewId.toString(), params)
: null,
workspaceSlug && view && workspaceViewId
workspaceSlug && view && viewId
? () =>
workspaceService.getViewIssues(
workspaceSlug.toString(),
Expand Down
87 changes: 44 additions & 43 deletions web/pages/[workspaceSlug]/settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -312,51 +312,52 @@ const WorkspaceSettings: NextPage = () => {
</PrimaryButton>
</div>
</div>
{isAdmin && (
<Disclosure as="div" className="border-t border-custom-border-400">
{({ open }) => (
<div className="w-full">
<Disclosure.Button
as="button"
type="button"
className="flex items-center justify-between w-full py-4"
>
<span className="text-xl tracking-tight">Delete Workspace</span>
<Icon iconName={open ? "expand_less" : "expand_more"} className="!text-2xl" />
</Disclosure.Button>

<Disclosure as="div" className="border-t border-custom-border-400">
{({ open }) => (
<div className="w-full">
<Disclosure.Button
as="button"
type="button"
className="flex items-center justify-between w-full py-4"
>
<span className="text-xl tracking-tight">Delete Workspace</span>
<Icon iconName={open ? "expand_less" : "expand_more"} className="!text-2xl" />
</Disclosure.Button>

<Transition
show={open}
enter="transition duration-100 ease-out"
enterFrom="transform opacity-0"
enterTo="transform opacity-100"
leave="transition duration-75 ease-out"
leaveFrom="transform opacity-100"
leaveTo="transform opacity-0"
>
<Disclosure.Panel>
<div className="flex flex-col gap-8">
<span className="text-sm tracking-tight">
The danger zone of the workspace delete page is a critical area that
requires careful consideration and attention. When deleting a workspace,
all of the data and resources within that workspace will be permanently
removed and cannot be recovered.
</span>
<div>
<DangerButton
onClick={() => setIsOpen(true)}
className="!text-sm"
outline
>
Delete my workspace
</DangerButton>
<Transition
show={open}
enter="transition duration-100 ease-out"
enterFrom="transform opacity-0"
enterTo="transform opacity-100"
leave="transition duration-75 ease-out"
leaveFrom="transform opacity-100"
leaveTo="transform opacity-0"
>
<Disclosure.Panel>
<div className="flex flex-col gap-8">
<span className="text-sm tracking-tight">
The danger zone of the workspace delete page is a critical area that
requires careful consideration and attention. When deleting a workspace,
all of the data and resources within that workspace will be permanently
removed and cannot be recovered.
</span>
<div>
<DangerButton
onClick={() => setIsOpen(true)}
className="!text-sm"
outline
>
Delete my workspace
</DangerButton>
</div>
</div>
</div>
</Disclosure.Panel>
</Transition>
</div>
)}
</Disclosure>
</Disclosure.Panel>
</Transition>
</div>
)}
</Disclosure>
)}
</div>
) : (
<div className="flex items-center justify-center h-full w-full px-4 sm:px-0">
Expand Down
Loading