snapshot of https://github.com/makeplane/plane.git @ d868349a55de79979eb8b98701bf1702c67ad634 (2026-09-15)
Some checks failed
CodeQL / Analyze (javascript) (push) Failing after 16s
CodeQL / Analyze (python) (push) Failing after 3s
i18n sync check / check:sync (push) Failing after 3s
React Doctor / react-doctor (push) Failing after 16s
Branch Build CE / Build-Push Admin Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Admin Manifest (push) Has been cancelled
Branch Build CE / Build-Push Web Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Web Manifest (push) Has been cancelled
Branch Build CE / Build-Push Space Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Proxy Manifest (push) Has been cancelled
Branch Build CE / Merge Space Manifest (push) Has been cancelled
Branch Build CE / Prepare AIO Assets (push) Has been cancelled
Branch Build CE / Build Setup (push) Has been cancelled
Branch Build CE / Build-Push Live Collaboration Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Live Collaboration Manifest (push) Has been cancelled
Branch Build CE / Build-Push API Server Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge API Server Manifest (push) Has been cancelled
Branch Build CE / Build-Push Proxy Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Build-Push AIO Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge AIO Manifest (push) Has been cancelled
Branch Build CE / Upload Build Assets (push) Has been cancelled
Branch Build CE / Build Release (push) Has been cancelled
Some checks failed
CodeQL / Analyze (javascript) (push) Failing after 16s
CodeQL / Analyze (python) (push) Failing after 3s
i18n sync check / check:sync (push) Failing after 3s
React Doctor / react-doctor (push) Failing after 16s
Branch Build CE / Build-Push Admin Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Admin Manifest (push) Has been cancelled
Branch Build CE / Build-Push Web Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Web Manifest (push) Has been cancelled
Branch Build CE / Build-Push Space Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Proxy Manifest (push) Has been cancelled
Branch Build CE / Merge Space Manifest (push) Has been cancelled
Branch Build CE / Prepare AIO Assets (push) Has been cancelled
Branch Build CE / Build Setup (push) Has been cancelled
Branch Build CE / Build-Push Live Collaboration Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Live Collaboration Manifest (push) Has been cancelled
Branch Build CE / Build-Push API Server Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge API Server Manifest (push) Has been cancelled
Branch Build CE / Build-Push Proxy Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Build-Push AIO Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge AIO Manifest (push) Has been cancelled
Branch Build CE / Upload Build Assets (push) Has been cancelled
Branch Build CE / Build Release (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import { observer } from "mobx-react";
|
||||
// plane imports
|
||||
import { setPromiseToast } from "@plane/propel/toast";
|
||||
import type { IProject } from "@plane/types";
|
||||
import { Switch } from "@makeplane/propel/components/switch";
|
||||
// components
|
||||
import { SettingsBoxedControlItem } from "@/components/settings/boxed-control-item";
|
||||
// hooks
|
||||
import { useProject } from "@/hooks/store/use-project";
|
||||
|
||||
type Props = {
|
||||
description?: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
projectId: string;
|
||||
featureProperty: keyof IProject;
|
||||
title: React.ReactNode;
|
||||
value: boolean;
|
||||
workspaceSlug: string;
|
||||
};
|
||||
|
||||
export const ProjectSettingsFeatureControlItem = observer(function ProjectSettingsFeatureControlItem(props: Props) {
|
||||
const { description, disabled, featureProperty, projectId, title, value, workspaceSlug } = props;
|
||||
// store hooks
|
||||
const { getProjectById, updateProject } = useProject();
|
||||
// derived values
|
||||
const currentProjectDetails = getProjectById(projectId);
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!workspaceSlug || !projectId || !currentProjectDetails) return;
|
||||
|
||||
// making the request to update the project feature
|
||||
const settingsPayload = {
|
||||
[featureProperty]: !currentProjectDetails?.[featureProperty],
|
||||
};
|
||||
const updateProjectPromise = updateProject(workspaceSlug, projectId, settingsPayload);
|
||||
|
||||
setPromiseToast(updateProjectPromise, {
|
||||
loading: "Updating project feature...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Project feature updated successfully.",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: () => "Something went wrong while updating project feature. Please try again.",
|
||||
},
|
||||
});
|
||||
void updateProjectPromise.then(() => {
|
||||
return undefined;
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<SettingsBoxedControlItem
|
||||
title={title}
|
||||
description={description}
|
||||
control={
|
||||
<Switch
|
||||
size="sm"
|
||||
checked={value}
|
||||
onCheckedChange={handleSubmit}
|
||||
disabled={disabled}
|
||||
aria-label={typeof title === "string" ? title : "Toggle project feature"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
});
|
||||
64
apps/web/core/components/settings/project/sidebar/header.tsx
Normal file
64
apps/web/core/components/settings/project/sidebar/header.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import { ArrowNarrowLeftOutline } from "@makeplane/propel/icons";
|
||||
import { observer } from "mobx-react";
|
||||
// plane imports
|
||||
import { ROLE_DETAILS } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { Logo } from "@plane/propel/emoji-icon-picker";
|
||||
import { IconButton } from "@plane/propel/icon-button";
|
||||
// hooks
|
||||
import { useUserPermissions } from "@/hooks/store/user";
|
||||
import { useAppRouter } from "@/hooks/use-app-router";
|
||||
import { useProject } from "@/hooks/store/use-project";
|
||||
import { useWorkspace } from "@/hooks/store/use-workspace";
|
||||
|
||||
type Props = {
|
||||
projectId: string;
|
||||
};
|
||||
|
||||
export const ProjectSettingsSidebarHeader = observer(function ProjectSettingsSidebarHeader(props: Props) {
|
||||
const { projectId } = props;
|
||||
// router
|
||||
const router = useAppRouter();
|
||||
// store hooks
|
||||
const { getProjectRoleByWorkspaceSlugAndProjectId } = useUserPermissions();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { getPartialProjectById } = useProject();
|
||||
// derived values
|
||||
const projectDetails = getPartialProjectById(projectId);
|
||||
const currentProjectRole = currentWorkspace?.slug
|
||||
? getProjectRoleByWorkspaceSlugAndProjectId(currentWorkspace.slug, projectId)
|
||||
: undefined;
|
||||
// translation
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (!currentProjectRole) return null;
|
||||
|
||||
return (
|
||||
<div className="shrink-0">
|
||||
<div className="flex items-center gap-1 py-3 pr-5 pl-4 text-body-md-medium">
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
size="base"
|
||||
icon={ArrowNarrowLeftOutline}
|
||||
onClick={() => router.push(`/${currentWorkspace?.slug}/projects/${projectId}/issues/`)}
|
||||
/>
|
||||
<p>Project settings</p>
|
||||
</div>
|
||||
<div className="mt-1.5 flex items-center gap-2 truncate px-5 py-0.5">
|
||||
<div className="grid size-8 shrink-0 place-items-center rounded bg-layer-2">
|
||||
<Logo logo={projectDetails?.logo_props} size={20} />
|
||||
</div>
|
||||
<div className="truncate">
|
||||
<p className="truncate text-body-sm-medium">{projectDetails?.name}</p>
|
||||
<p className="truncate text-caption-md-regular">{t(ROLE_DETAILS[currentProjectRole].i18n_title)}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
export * from "./root";
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import { observer } from "mobx-react";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useParams } from "react-router";
|
||||
// plane imports
|
||||
import {
|
||||
EUserPermissionsLevel,
|
||||
GROUPED_PROJECT_SETTINGS,
|
||||
PROJECT_SETTINGS_CATEGORIES,
|
||||
PROJECT_SETTINGS_CATEGORY_LABELS,
|
||||
} from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
// components
|
||||
import { SettingsSidebarItem } from "@/components/settings/sidebar/item";
|
||||
// hooks
|
||||
import { useUserPermissions } from "@/hooks/store/user";
|
||||
// local imports
|
||||
import { PROJECT_SETTINGS_ICONS } from "./item-icon";
|
||||
|
||||
type Props = {
|
||||
projectId: string;
|
||||
};
|
||||
|
||||
export const ProjectSettingsSidebarItemCategories = observer(function ProjectSettingsSidebarItemCategories(
|
||||
props: Props
|
||||
) {
|
||||
const { projectId } = props;
|
||||
// params
|
||||
const { workspaceSlug } = useParams();
|
||||
const pathname = usePathname();
|
||||
// store hooks
|
||||
const { allowPermissions } = useUserPermissions();
|
||||
// translation
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className="mt-3 flex flex-col divide-y divide-subtle px-3">
|
||||
{PROJECT_SETTINGS_CATEGORIES.map((category) => {
|
||||
const categoryItems = GROUPED_PROJECT_SETTINGS[category];
|
||||
const accessibleItems = categoryItems.filter((item) =>
|
||||
allowPermissions(item.access, EUserPermissionsLevel.PROJECT, workspaceSlug, projectId)
|
||||
);
|
||||
|
||||
if (accessibleItems.length === 0) return null;
|
||||
|
||||
return (
|
||||
<div key={category} className="shrink-0 py-3 first:pt-0 last:pb-0">
|
||||
<div className="p-2 text-caption-md-medium text-tertiary capitalize">
|
||||
{t(PROJECT_SETTINGS_CATEGORY_LABELS[category])}
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
{accessibleItems.map((item) => {
|
||||
const isItemActive =
|
||||
item.href === ""
|
||||
? pathname === `/${workspaceSlug}/settings/projects/${projectId}${item.href}/`
|
||||
: new RegExp(`^/${workspaceSlug}/settings/projects/${projectId}${item.href}/`).test(pathname);
|
||||
|
||||
return (
|
||||
<SettingsSidebarItem
|
||||
key={item.key}
|
||||
as="link"
|
||||
href={`/${workspaceSlug}/settings/projects/${projectId}${item.href}/`}
|
||||
isActive={isItemActive}
|
||||
icon={PROJECT_SETTINGS_ICONS[item.key]}
|
||||
label={t(item.i18n_label)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
import {
|
||||
CyclesOutline,
|
||||
EstimateOutline,
|
||||
IntakeOutline,
|
||||
LabelsOutline,
|
||||
MembersOutline,
|
||||
ModuleOutline,
|
||||
PagesOutline,
|
||||
StateOutline,
|
||||
TriggerOutline,
|
||||
ViewsOutline,
|
||||
} from "@makeplane/propel/icons";
|
||||
// plane imports
|
||||
import type { ISvgIcons } from "@plane/propel/icons";
|
||||
import type { TProjectSettingsTabs } from "@plane/types";
|
||||
// components
|
||||
import { SettingIcon } from "@/components/icons/attachment";
|
||||
|
||||
export const PROJECT_SETTINGS_ICONS: Record<TProjectSettingsTabs, LucideIcon | React.FC<ISvgIcons>> = {
|
||||
general: SettingIcon,
|
||||
members: MembersOutline,
|
||||
features_cycles: CyclesOutline,
|
||||
features_modules: ModuleOutline,
|
||||
features_views: ViewsOutline,
|
||||
features_pages: PagesOutline,
|
||||
features_intake: IntakeOutline,
|
||||
states: StateOutline,
|
||||
labels: LabelsOutline,
|
||||
estimates: EstimateOutline,
|
||||
automations: TriggerOutline,
|
||||
};
|
||||
32
apps/web/core/components/settings/project/sidebar/root.tsx
Normal file
32
apps/web/core/components/settings/project/sidebar/root.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
// plane imports
|
||||
import { ScrollArea } from "@plane/propel/scrollarea";
|
||||
// local imports
|
||||
import { ProjectSettingsSidebarHeader } from "./header";
|
||||
import { ProjectSettingsSidebarItemCategories } from "./item-categories";
|
||||
|
||||
type Props = {
|
||||
projectId: string;
|
||||
};
|
||||
|
||||
export function ProjectSettingsSidebarRoot(props: Props) {
|
||||
const { projectId } = props;
|
||||
|
||||
return (
|
||||
<ScrollArea
|
||||
scrollType="hover"
|
||||
orientation="vertical"
|
||||
size="sm"
|
||||
rootClassName="shrink-0 animate-fade-in h-full w-[250px] bg-surface-1 border-r border-r-subtle overflow-y-scroll"
|
||||
viewportClassName="pb-5"
|
||||
>
|
||||
<ProjectSettingsSidebarHeader projectId={projectId} />
|
||||
<ProjectSettingsSidebarItemCategories projectId={projectId} />
|
||||
</ScrollArea>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user