mirror of
https://github.com/makeplane/plane.git
synced 2026-07-13 14:01:45 +02:00
* chore: add template * chore: add page template and project template migrations * chore: add migration file for project and page templates * chore: page templates * chore: update template * feat: page templates * chore: update model * chore: asset copy * chore: update page templates * feat: add project template create/update endpoint * improvement: update all templates endpoint * chore: project template basic types and services * feat: project template instance and store * feat: project template store hooks * chore: feature flags and minor improvements * feat: project templates list settings * feat: project templates * chore: common constants across templates * improvement: work item template util types * improvement: moved all project related types to packages and re-exported them to avoid changes in files. * feat: create project template form with all basic fields and attributes * chore: add project creation bgtask from template * chore: update project template configuration * chore: update project template migrations * chore: added migration for workspace connection disconnect_meta * chore: update migration files * chore: model changes * chore: add project template validation * chore: update template task * chore: project templates endpoints * fix: base serializers * chore: add comment edit migrations * chore: minor improvements and base template store fixes * chore: minor improvements * improvement: common template related components * feat: project template features * chore: minor formatting * chore: minor translation updates * feat: update project template form data * chore: work item template util improvements * feat: use project templates in create project modal * chore: use template endpoint * chore: update imports * feat: project creation using templates * fix: build error * feat: work item type creation form * chore: convert project work item types form data to required schema * feat: update work item type form data extraction and sanitization * chore: add project template default settings * chore: update formatting * improvement: sync all project level features * revert: utils package build related changes * feat: project epics in templates * chore: update background task to handle member and intake creation * improvement: epic name while creating template * fix: api server * revert: utils build * feat: added work item labels while creating project templates * chore: update project template task * refactor: project state list components * improvement: additional classNames for the group list item and state item * fix: options * fix: epic creations * feat: add project states while creating project templates * improvements: add empty state for labels * chore: remove unused exports * fix: build error * chore: add intake setting schema * feat: intake feature settings for project templates * feat: intake settings and deploy board when creating project from template * fix: feature children layout * fix: form keydown events * fix: template description * fix: delete state button type * improvement: UI enhancements related to background, border and shadow * improvement: project templates dropdown * improvement: remove empty templates list sections * improvement: remove empty templates list sections * improvement: enhance project level template list modularity * improvement: minor component improvements * chore: minor type changes * improvement: template list loader * improvement: project template form background color * improvement: work item template form background color * chore: add asset url validation and resolve pr comments --------- Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com> Co-authored-by: Henit Chobisa <chobisa.henit@gmail.com>
130 lines
4.3 KiB
TypeScript
130 lines
4.3 KiB
TypeScript
import { useCallback, useMemo } from "react";
|
|
import { observer } from "mobx-react";
|
|
import { ChevronDown } from "lucide-react";
|
|
// plane imports
|
|
import {
|
|
ETemplateLevel,
|
|
ETemplateType,
|
|
EUserPermissionsLevel,
|
|
EUserProjectRoles,
|
|
EUserWorkspaceRoles,
|
|
} from "@plane/constants";
|
|
import { useTranslation } from "@plane/i18n";
|
|
import { CustomMenu, Button, TButtonSizes } from "@plane/ui";
|
|
import {
|
|
getCreateUpdateTemplateSettingsPath,
|
|
getTemplateI18nLabel,
|
|
TCreateTemplateSettingsPathProps,
|
|
} from "@plane/utils";
|
|
// hooks
|
|
import { useUserPermissions } from "@/hooks/store";
|
|
import { useAppRouter } from "@/hooks/use-app-router";
|
|
|
|
type TCreateTemplatesButtonProps = {
|
|
workspaceSlug: string;
|
|
buttonI18nLabel?: string;
|
|
buttonSize?: TButtonSizes;
|
|
} & (
|
|
| {
|
|
projectId: string;
|
|
currentLevel: ETemplateLevel.PROJECT;
|
|
}
|
|
| {
|
|
currentLevel: ETemplateLevel.WORKSPACE;
|
|
}
|
|
);
|
|
|
|
type TCreateTemplateOption = {
|
|
i18n_label: string;
|
|
onClick: () => void;
|
|
availableForLevels: ETemplateLevel[];
|
|
};
|
|
|
|
export const CreateTemplatesButton = observer((props: TCreateTemplatesButtonProps) => {
|
|
// router
|
|
const router = useAppRouter();
|
|
// plane hooks
|
|
const { t } = useTranslation();
|
|
// store hooks
|
|
const { allowPermissions } = useUserPermissions();
|
|
// derived values
|
|
const hasAdminPermission =
|
|
props.currentLevel === ETemplateLevel.PROJECT
|
|
? allowPermissions([EUserProjectRoles.ADMIN], EUserPermissionsLevel.PROJECT, props.workspaceSlug, props.projectId)
|
|
: allowPermissions([EUserWorkspaceRoles.ADMIN], EUserPermissionsLevel.WORKSPACE, props.workspaceSlug);
|
|
|
|
const CREATE_TEMPLATE_OPTIONS: TCreateTemplateOption[] = useMemo(() => {
|
|
const getCreateTemplateSettingsPathProps = (type: ETemplateType) => {
|
|
const createTemplatePathProps: TCreateTemplateSettingsPathProps = {
|
|
type,
|
|
workspaceSlug: props.workspaceSlug,
|
|
...("projectId" in props
|
|
? { level: ETemplateLevel.PROJECT, projectId: props.projectId }
|
|
: { level: ETemplateLevel.WORKSPACE }),
|
|
};
|
|
return createTemplatePathProps;
|
|
};
|
|
|
|
return [
|
|
{
|
|
i18n_label: getTemplateI18nLabel(ETemplateType.PROJECT),
|
|
onClick: () =>
|
|
router.push(getCreateUpdateTemplateSettingsPath(getCreateTemplateSettingsPathProps(ETemplateType.PROJECT))),
|
|
availableForLevels: [ETemplateLevel.WORKSPACE],
|
|
},
|
|
{
|
|
i18n_label: getTemplateI18nLabel(ETemplateType.WORK_ITEM),
|
|
onClick: () =>
|
|
router.push(getCreateUpdateTemplateSettingsPath(getCreateTemplateSettingsPathProps(ETemplateType.WORK_ITEM))),
|
|
availableForLevels: [ETemplateLevel.WORKSPACE, ETemplateLevel.PROJECT],
|
|
},
|
|
{
|
|
i18n_label: getTemplateI18nLabel(ETemplateType.PAGE),
|
|
onClick: () =>
|
|
router.push(getCreateUpdateTemplateSettingsPath(getCreateTemplateSettingsPathProps(ETemplateType.PAGE))),
|
|
availableForLevels: [],
|
|
},
|
|
];
|
|
}, [router, props]);
|
|
|
|
const getButtonLabel = useCallback(() => {
|
|
if (!hasAdminPermission)
|
|
return props.currentLevel === ETemplateLevel.PROJECT
|
|
? t("templates.settings.create_template.no_permission.project")
|
|
: t("templates.settings.create_template.no_permission.workspace");
|
|
|
|
return t(props.buttonI18nLabel || "templates.settings.create_template.label");
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [hasAdminPermission, props.buttonI18nLabel, props.currentLevel]);
|
|
|
|
if (!hasAdminPermission) return null;
|
|
return (
|
|
<CustomMenu
|
|
customButton={
|
|
<Button
|
|
variant="primary"
|
|
size={props.buttonSize}
|
|
className="flex items-center justify-center gap-1.5"
|
|
disabled={!hasAdminPermission}
|
|
>
|
|
{getButtonLabel()}
|
|
{hasAdminPermission && <ChevronDown className="size-3.5" />}
|
|
</Button>
|
|
}
|
|
placement="bottom-end"
|
|
disabled={!hasAdminPermission}
|
|
closeOnSelect
|
|
>
|
|
{CREATE_TEMPLATE_OPTIONS.map((option) => {
|
|
const isAvailable = option.availableForLevels.includes(props.currentLevel);
|
|
if (!isAvailable) return null;
|
|
return (
|
|
<CustomMenu.MenuItem key={option.i18n_label} onClick={option.onClick} disabled={!isAvailable}>
|
|
{t(option.i18n_label)}
|
|
</CustomMenu.MenuItem>
|
|
);
|
|
})}
|
|
</CustomMenu>
|
|
);
|
|
});
|