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

This commit is contained in:
upstream-mirror
2026-09-15 15:14:58 +05:00
commit 23059a1de3
5252 changed files with 573834 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import React from "react";
import { Command } from "cmdk";
// local imports
import { PowerKModalCommandItem } from "../ui/modal/command-item";
import { PowerKMenuEmptyState } from "./empty-state";
type Props<T> = {
heading?: string;
items: T[];
onSelect: (item: T) => void;
getIcon?: (item: T) => React.ComponentType<{ className?: string }>;
getIconNode?: (item: T) => React.ReactNode;
getKey: (item: T) => string;
getLabel: (item: T) => React.ReactNode;
getValue: (item: T) => string;
isSelected?: (item: T) => boolean;
emptyText?: string;
};
export function PowerKMenuBuilder<T>({
heading,
items,
onSelect,
getIcon,
getIconNode,
getKey,
getLabel,
getValue,
isSelected,
emptyText,
}: Props<T>) {
if (items.length === 0) return <PowerKMenuEmptyState emptyText={emptyText} />;
return (
<Command.Group heading={heading}>
{items.map((item) => (
<PowerKModalCommandItem
key={getKey(item)}
icon={getIcon?.(item)}
iconNode={getIconNode?.(item)}
value={getValue(item)}
label={getLabel(item)}
isSelected={isSelected?.(item)}
onSelect={() => onSelect(item)}
/>
))}
</Command.Group>
);
}

View File

@@ -0,0 +1,34 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import React from "react";
import { observer } from "mobx-react";
// plane imports
import { CyclesOutline } from "@makeplane/propel/icons";
import type { ICycle } from "@plane/types";
// local imports
import { PowerKMenuBuilder } from "./builder";
type Props = {
cycles: ICycle[];
onSelect: (cycle: ICycle) => void;
value?: string | null;
};
export const PowerKCyclesMenu = observer(function PowerKCyclesMenu({ cycles, onSelect, value }: Props) {
return (
<PowerKMenuBuilder
items={cycles}
getIcon={() => CyclesOutline}
getKey={(cycle) => cycle.id}
getValue={(cycle) => cycle.name}
getLabel={(cycle) => cycle.name}
isSelected={(cycle) => value === cycle.id}
onSelect={onSelect}
emptyText="No cycles found"
/>
);
});

View File

@@ -0,0 +1,15 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import React from "react";
type Props = {
emptyText?: string;
};
export function PowerKMenuEmptyState({ emptyText = "No results found" }: Props) {
return <div className="px-3 py-8 text-center text-13 text-tertiary">{emptyText}</div>;
}

View File

@@ -0,0 +1,37 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import React from "react";
import { observer } from "mobx-react";
// plane imports
import type { IIssueLabel } from "@plane/types";
// local imports
import { PowerKMenuBuilder } from "./builder";
type Props = {
labels: IIssueLabel[];
onSelect: (label: IIssueLabel) => void;
value?: string[];
};
export const PowerKLabelsMenu = observer(function PowerKLabelsMenu({ labels, onSelect, value }: Props) {
return (
<PowerKMenuBuilder
items={labels}
getIconNode={(label) => (
<span className="grid size-3.5 shrink-0 place-items-center">
<span className="size-2.5 rounded-full" style={{ backgroundColor: label.color }} />
</span>
)}
getKey={(label) => label.id}
getValue={(label) => label.name}
getLabel={(label) => label.name}
isSelected={(label) => !!value?.includes(label.id)}
onSelect={onSelect}
emptyText="No labels found"
/>
);
});

View File

@@ -0,0 +1,55 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import { Command } from "cmdk";
import { observer } from "mobx-react";
// plane imports
import { Avatar } from "@makeplane/propel/components/avatar";
import { getFileURL } from "@plane/utils";
// hooks
import { useMember } from "@/hooks/store/use-member";
// local imports
import { PowerKModalCommandItem } from "../ui/modal/command-item";
type Props = {
handleSelect: (assigneeId: string) => void;
heading?: string;
userIds: string[] | undefined;
value: string[];
};
export const PowerKMembersMenu = observer(function PowerKMembersMenu(props: Props) {
const { handleSelect, heading, userIds, value } = props;
// store hooks
const { getUserDetails } = useMember();
return (
<Command.Group heading={heading}>
{userIds?.map((memberId) => {
const memberDetails = getUserDetails(memberId);
if (!memberDetails) return;
return (
<PowerKModalCommandItem
key={memberId}
iconNode={
<Avatar
alt={memberDetails?.display_name}
fallback={memberDetails?.display_name?.[0]?.toUpperCase()}
src={getFileURL(memberDetails?.avatar_url ?? "")}
size="xs"
/>
}
isSelected={value.includes(memberId)}
label={memberDetails?.display_name}
onSelect={() => handleSelect(memberId)}
/>
);
})}
</Command.Group>
);
});

View File

@@ -0,0 +1,34 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import React from "react";
import { observer } from "mobx-react";
// plane imports
import { ModuleStatusIcon } from "@plane/propel/icons";
import type { IModule } from "@plane/types";
// local imports
import { PowerKMenuBuilder } from "./builder";
type Props = {
modules: IModule[];
onSelect: (module: IModule) => void;
value?: string[];
};
export const PowerKModulesMenu = observer(function PowerKModulesMenu({ modules, onSelect, value }: Props) {
return (
<PowerKMenuBuilder
items={modules}
getKey={(module) => module.id}
getIconNode={(module) => <ModuleStatusIcon status={module.status ?? "backlog"} className="size-3.5 shrink-0" />}
getValue={(module) => module.name}
getLabel={(module) => module.name}
isSelected={(module) => !!value?.includes(module.id)}
onSelect={onSelect}
emptyText="No modules found"
/>
);
});

View File

@@ -0,0 +1,36 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import React from "react";
// components
import { Logo } from "@plane/propel/emoji-icon-picker";
// plane imports
import type { TPartialProject } from "@plane/types";
// local imports
import { PowerKMenuBuilder } from "./builder";
type Props = {
projects: TPartialProject[];
onSelect: (project: TPartialProject) => void;
};
export function PowerKProjectsMenu({ projects, onSelect }: Props) {
return (
<PowerKMenuBuilder
items={projects}
getKey={(project) => project.id}
getIconNode={(project) => (
<span className="shrink-0">
<Logo logo={project.logo_props} size={14} />
</span>
)}
getValue={(project) => project.name}
getLabel={(project) => project.name}
onSelect={onSelect}
emptyText="No projects found"
/>
);
}

View File

@@ -0,0 +1,36 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import React from "react";
import { observer } from "mobx-react";
// local imports
import { PowerKMenuBuilder } from "./builder";
type TSettingItem = {
key: string;
icon: React.ComponentType<{ className?: string }>;
label: string;
href: string;
};
type Props = {
settings: TSettingItem[];
onSelect: (setting: TSettingItem) => void;
};
export const PowerKSettingsMenu = observer(function PowerKSettingsMenu({ settings, onSelect }: Props) {
return (
<PowerKMenuBuilder
items={settings}
getKey={(setting) => setting.key}
getIcon={(setting) => setting.icon}
getValue={(setting) => setting.label}
getLabel={(setting) => setting.label}
onSelect={onSelect}
emptyText="No settings found"
/>
);
});

View 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.
*/
import React from "react";
import { observer } from "mobx-react";
import { WorkItemsOutline } from "@makeplane/propel/icons";
// plane imports
import type { IProjectView } from "@plane/types";
// local imports
import { PowerKMenuBuilder } from "./builder";
type Props = {
views: IProjectView[];
onSelect: (view: IProjectView) => void;
};
export const PowerKViewsMenu = observer(function PowerKViewsMenu({ views, onSelect }: Props) {
return (
<PowerKMenuBuilder
items={views}
getKey={(view) => view.id}
getIcon={() => WorkItemsOutline}
getValue={(view) => view.name}
getLabel={(view) => view.name}
onSelect={onSelect}
emptyText="No views found"
/>
);
});

View File

@@ -0,0 +1,34 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import React from "react";
// plane imports
import type { IWorkspace } from "@plane/types";
// components
import { WorkspaceLogo } from "@/components/workspace/logo";
// local imports
import { PowerKMenuBuilder } from "./builder";
type Props = {
workspaces: IWorkspace[];
onSelect: (workspace: IWorkspace) => void;
};
export function PowerKWorkspacesMenu({ workspaces, onSelect }: Props) {
return (
<PowerKMenuBuilder
items={workspaces}
getKey={(workspace) => workspace.id}
getIconNode={(workspace) => (
<WorkspaceLogo logo={workspace.logo_url} name={workspace.name} classNames="shrink-0" />
)}
getValue={(workspace) => workspace.name}
getLabel={(workspace) => workspace.name}
onSelect={onSelect}
emptyText="No workspaces found"
/>
);
}