Merge pull request #2669 from makeplane/sync/ce-ee
Sync: Community Changes
This commit is contained in:
@@ -116,25 +116,23 @@ class IssueCreateSerializer(BaseSerializer):
|
||||
data["label_ids"] = label_ids if label_ids else []
|
||||
return data
|
||||
|
||||
def validate(self, data):
|
||||
def validate(self, attrs):
|
||||
if (
|
||||
data.get("start_date", None) is not None
|
||||
and data.get("target_date", None) is not None
|
||||
and data.get("start_date", None) > data.get("target_date", None)
|
||||
attrs.get("start_date", None) is not None
|
||||
and attrs.get("target_date", None) is not None
|
||||
and attrs.get("start_date", None) > attrs.get("target_date", None)
|
||||
):
|
||||
raise serializers.ValidationError("Start date cannot exceed target date")
|
||||
return data
|
||||
|
||||
def get_valid_assignees(self, assignees, project_id):
|
||||
if not assignees:
|
||||
return []
|
||||
if attrs.get("assignee_ids", []):
|
||||
attrs["assignee_ids"] = ProjectMember.objects.filter(
|
||||
project_id=self.context["project_id"],
|
||||
role__gte=15,
|
||||
is_active=True,
|
||||
member_id__in=attrs["assignee_ids"],
|
||||
).values_list("member_id", flat=True)
|
||||
|
||||
return ProjectMember.objects.filter(
|
||||
project_id=project_id,
|
||||
role__gte=15,
|
||||
is_active=True,
|
||||
member_id__in=assignees
|
||||
).values_list('member_id', flat=True)
|
||||
return attrs
|
||||
|
||||
def create(self, validated_data):
|
||||
assignees = validated_data.pop("assignee_ids", None)
|
||||
@@ -164,20 +162,19 @@ class IssueCreateSerializer(BaseSerializer):
|
||||
created_by_id = issue.created_by_id
|
||||
updated_by_id = issue.updated_by_id
|
||||
|
||||
valid_assignee_ids = self.get_valid_assignees(assignees, project_id)
|
||||
if valid_assignee_ids is not None and len(valid_assignee_ids):
|
||||
if assignees is not None and len(assignees):
|
||||
try:
|
||||
IssueAssignee.objects.bulk_create(
|
||||
[
|
||||
IssueAssignee(
|
||||
assignee_id=user_id,
|
||||
assignee_id=assignee_id,
|
||||
issue=issue,
|
||||
project_id=project_id,
|
||||
workspace_id=workspace_id,
|
||||
created_by_id=created_by_id,
|
||||
updated_by_id=updated_by_id,
|
||||
)
|
||||
for user_id in valid_assignee_ids
|
||||
for assignee_id in assignees
|
||||
],
|
||||
batch_size=10,
|
||||
)
|
||||
@@ -185,12 +182,15 @@ class IssueCreateSerializer(BaseSerializer):
|
||||
pass
|
||||
else:
|
||||
# Then assign it to default assignee, if it is a valid assignee
|
||||
if default_assignee_id is not None and ProjectMember.objects.filter(
|
||||
member_id=default_assignee_id,
|
||||
project_id=project_id,
|
||||
role__gte=15,
|
||||
is_active=True
|
||||
).exists():
|
||||
if (
|
||||
default_assignee_id is not None
|
||||
and ProjectMember.objects.filter(
|
||||
member_id=default_assignee_id,
|
||||
project_id=project_id,
|
||||
role__gte=15,
|
||||
is_active=True,
|
||||
).exists()
|
||||
):
|
||||
try:
|
||||
IssueAssignee.objects.create(
|
||||
assignee_id=default_assignee_id,
|
||||
@@ -234,21 +234,20 @@ class IssueCreateSerializer(BaseSerializer):
|
||||
created_by_id = instance.created_by_id
|
||||
updated_by_id = instance.updated_by_id
|
||||
|
||||
valid_assignee_ids = self.get_valid_assignees(assignees, project_id)
|
||||
if valid_assignee_ids is not None:
|
||||
if assignees is not None:
|
||||
IssueAssignee.objects.filter(issue=instance).delete()
|
||||
try:
|
||||
IssueAssignee.objects.bulk_create(
|
||||
[
|
||||
IssueAssignee(
|
||||
assignee_id=user_id,
|
||||
assignee_id=assignee_id,
|
||||
issue=instance,
|
||||
project_id=project_id,
|
||||
workspace_id=workspace_id,
|
||||
created_by_id=created_by_id,
|
||||
updated_by_id=updated_by_id,
|
||||
)
|
||||
for user_id in valid_assignee_ids
|
||||
for assignee_id in assignees
|
||||
],
|
||||
batch_size=10,
|
||||
ignore_conflicts=True,
|
||||
|
||||
@@ -431,7 +431,7 @@ class IntakeIssueViewSet(BaseViewSet):
|
||||
}
|
||||
|
||||
issue_serializer = IssueCreateSerializer(
|
||||
issue, data=issue_data, partial=True
|
||||
issue, data=issue_data, partial=True, context={"project_id": project_id}
|
||||
)
|
||||
|
||||
if issue_serializer.is_valid():
|
||||
|
||||
@@ -706,7 +706,7 @@ class IssueViewSet(BaseViewSet):
|
||||
|
||||
requested_data = json.dumps(self.request.data, cls=DjangoJSONEncoder)
|
||||
serializer = IssueCreateSerializer(
|
||||
issue, data=request.data, partial=True
|
||||
issue, data=request.data, partial=True, context={"project_id": project_id}
|
||||
)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
@@ -1223,7 +1223,6 @@ class IssueBulkUpdateDateEndpoint(BaseAPIView):
|
||||
|
||||
|
||||
class IssueMetaEndpoint(BaseAPIView):
|
||||
|
||||
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="PROJECT")
|
||||
def get(self, request, slug, project_id, issue_id):
|
||||
issue = Issue.issue_objects.only("sequence_id", "project__identifier").get(
|
||||
@@ -1239,14 +1238,12 @@ class IssueMetaEndpoint(BaseAPIView):
|
||||
|
||||
|
||||
class IssueDetailIdentifierEndpoint(BaseAPIView):
|
||||
|
||||
def strict_str_to_int(self, s):
|
||||
if not s.isdigit() and not (s.startswith('-') and s[1:].isdigit()):
|
||||
if not s.isdigit() and not (s.startswith("-") and s[1:].isdigit()):
|
||||
raise ValueError("Invalid integer string")
|
||||
return int(s)
|
||||
|
||||
def get(self, request, slug, project_identifier, issue_identifier):
|
||||
|
||||
# Check if the issue identifier is a valid integer
|
||||
try:
|
||||
issue_identifier = self.strict_str_to_int(issue_identifier)
|
||||
@@ -1258,8 +1255,7 @@ class IssueDetailIdentifierEndpoint(BaseAPIView):
|
||||
|
||||
# Fetch the project
|
||||
project = Project.objects.get(
|
||||
identifier__iexact=project_identifier,
|
||||
workspace__slug=slug,
|
||||
identifier__iexact=project_identifier, workspace__slug=slug
|
||||
)
|
||||
|
||||
|
||||
@@ -1353,8 +1349,8 @@ class IssueDetailIdentifierEndpoint(BaseAPIView):
|
||||
.annotate(
|
||||
is_subscribed=Exists(
|
||||
IssueSubscriber.objects.filter(
|
||||
workspace__slug=slug,
|
||||
project_id=project.id,
|
||||
workspace__slug=slug,
|
||||
project_id=project.id,
|
||||
issue__sequence_id=issue_identifier,
|
||||
subscriber=request.user,
|
||||
)
|
||||
|
||||
@@ -12,15 +12,7 @@ from rest_framework.response import Response
|
||||
|
||||
# Module imports
|
||||
from .base import BaseViewSet
|
||||
from plane.db.models import (
|
||||
IntakeIssue,
|
||||
Issue,
|
||||
State,
|
||||
IssueLink,
|
||||
FileAsset,
|
||||
DeployBoard,
|
||||
IssueType,
|
||||
)
|
||||
from plane.db.models import IntakeIssue, Issue, IssueLink, FileAsset, DeployBoard
|
||||
from plane.app.serializers import (
|
||||
IssueSerializer,
|
||||
IntakeIssueSerializer,
|
||||
@@ -216,7 +208,12 @@ class IntakeIssuePublicViewSet(BaseViewSet):
|
||||
"description": issue_data.get("description", issue.description),
|
||||
}
|
||||
|
||||
issue_serializer = IssueCreateSerializer(issue, data=issue_data, partial=True)
|
||||
issue_serializer = IssueCreateSerializer(
|
||||
issue,
|
||||
data=issue_data,
|
||||
partial=True,
|
||||
context={"project_id": project_deploy_board.project_id},
|
||||
)
|
||||
|
||||
if issue_serializer.is_valid():
|
||||
current_instance = issue
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# base requirements
|
||||
|
||||
# django
|
||||
Django==4.2.18
|
||||
Django==4.2.20
|
||||
# rest framework
|
||||
djangorestframework==3.15.2
|
||||
# postgres
|
||||
|
||||
@@ -695,7 +695,7 @@
|
||||
"you": "You",
|
||||
"upgrade_cta": {
|
||||
"higher_subscription": "Upgrade to higher subscription",
|
||||
"talk_to_sales": "Talk to sales"
|
||||
"talk_to_sales": "Talk to Sales"
|
||||
},
|
||||
"category": "Category",
|
||||
"categories": "Categories",
|
||||
@@ -704,7 +704,8 @@
|
||||
"delete": "Delete",
|
||||
"deleting": "Deleting",
|
||||
"pending": "Pending",
|
||||
"invite": "Invite"
|
||||
"invite": "Invite",
|
||||
"view": "View"
|
||||
},
|
||||
|
||||
"chart": {
|
||||
|
||||
@@ -867,7 +867,8 @@
|
||||
"delete": "Eliminar",
|
||||
"deleting": "Eliminando",
|
||||
"pending": "Pendiente",
|
||||
"invite": "Invitar"
|
||||
"invite": "Invitar",
|
||||
"view": "Ver"
|
||||
},
|
||||
|
||||
"chart": {
|
||||
|
||||
@@ -856,7 +856,7 @@
|
||||
"you": "Vous",
|
||||
"upgrade_cta": {
|
||||
"higher_subscription": "Passer à une abonnement plus élevé",
|
||||
"talk_to_sales": "Parler à la vente"
|
||||
"talk_to_sales": "Parler aux ventes"
|
||||
},
|
||||
"category": "Catégorie",
|
||||
"categories": "Catégories",
|
||||
@@ -865,7 +865,8 @@
|
||||
"delete": "Supprimer",
|
||||
"deleting": "Suppression",
|
||||
"pending": "En attente",
|
||||
"invite": "Inviter"
|
||||
"invite": "Inviter",
|
||||
"view": "Afficher"
|
||||
},
|
||||
|
||||
"chart": {
|
||||
|
||||
@@ -862,7 +862,8 @@
|
||||
"delete": "Elimina",
|
||||
"deleting": "Eliminazione in corso",
|
||||
"pending": "In sospeso",
|
||||
"invite": "Invita"
|
||||
"invite": "Invita",
|
||||
"view": "Visualizza"
|
||||
},
|
||||
|
||||
"chart": {
|
||||
@@ -982,7 +983,7 @@
|
||||
"created_on": "Creato il",
|
||||
"sub_issue": "Sotto-elemento di lavoro",
|
||||
"work_item_count": "Conteggio degli elementi di lavoro"
|
||||
},
|
||||
},
|
||||
"extra": {
|
||||
"show_sub_issues": "Mostra sotto-elementi di lavoro",
|
||||
"show_empty_groups": "Mostra gruppi vuoti"
|
||||
|
||||
@@ -856,7 +856,7 @@
|
||||
"you": "あなた",
|
||||
"upgrade_cta": {
|
||||
"higher_subscription": "高いサブスクリプションにアップグレード",
|
||||
"talk_to_sales": "セールスに連絡"
|
||||
"talk_to_sales": "トーク トゥ セールス"
|
||||
},
|
||||
"category": "カテゴリー",
|
||||
"categories": "カテゴリーズ",
|
||||
@@ -865,7 +865,8 @@
|
||||
"delete": "デリート",
|
||||
"deleting": "デリーティング",
|
||||
"pending": "保留中",
|
||||
"invite": "招待"
|
||||
"invite": "招待",
|
||||
"view": "ビュー"
|
||||
},
|
||||
|
||||
"chart": {
|
||||
@@ -985,7 +986,7 @@
|
||||
"created_on": "作成日",
|
||||
"sub_issue": "サブ作業項目",
|
||||
"work_item_count": "作業項目数"
|
||||
},
|
||||
},
|
||||
"extra": {
|
||||
"show_sub_issues": "サブ作業項目を表示",
|
||||
"show_empty_groups": "空のグループを表示"
|
||||
|
||||
@@ -864,7 +864,8 @@
|
||||
"delete": "Удалить",
|
||||
"deleting": "Удаление",
|
||||
"pending": "Ожидание",
|
||||
"invite": "Пригласить"
|
||||
"invite": "Пригласить",
|
||||
"view": "Просмотр"
|
||||
},
|
||||
|
||||
"chart": {
|
||||
@@ -1867,7 +1868,7 @@
|
||||
}
|
||||
},
|
||||
"completed_no_issues": {
|
||||
"title": "Нет рабочих элементов в цикле",
|
||||
"title": "Нет рабочих элементов в цикле",
|
||||
"description": "Нет рабочих элементов. Рабочие элементы были перенесены или скрыты. Для просмотра измените настройки отображения."
|
||||
},
|
||||
"active": {
|
||||
@@ -2286,7 +2287,7 @@
|
||||
"short_description": "Экспорт в csv"
|
||||
},
|
||||
"excel": {
|
||||
"title": "Excel",
|
||||
"title": "Excel",
|
||||
"description": "Экспорт рабочих элементов в файл Excel.",
|
||||
"short_description": "Экспорт в excel"
|
||||
},
|
||||
@@ -2304,7 +2305,7 @@
|
||||
"default_global_view": {
|
||||
"all_issues": "Все рабочие элементы",
|
||||
"assigned": "Назначенные",
|
||||
"created": "Созданные",
|
||||
"created": "Созданные",
|
||||
"subscribed": "Подписанные"
|
||||
},
|
||||
|
||||
@@ -2333,7 +2334,7 @@
|
||||
"project_modules": {
|
||||
"status": {
|
||||
"backlog": "Бэклог",
|
||||
"planned": "Запланировано",
|
||||
"planned": "Запланировано",
|
||||
"in_progress": "В процессе",
|
||||
"paused": "Приостановлено",
|
||||
"completed": "Завершено",
|
||||
|
||||
@@ -865,7 +865,8 @@
|
||||
"delete": "删除",
|
||||
"deleting": "删除中",
|
||||
"pending": "待处理",
|
||||
"invite": "邀请"
|
||||
"invite": "邀请",
|
||||
"view": "查看"
|
||||
},
|
||||
|
||||
"chart": {
|
||||
|
||||
@@ -2,3 +2,4 @@ export * from "./ai";
|
||||
export * from "./estimates";
|
||||
export * from "./gantt-chart";
|
||||
export * from "./project";
|
||||
export * from "./sidebar-favorites";
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { Briefcase, ContrastIcon, FileText, Layers, LucideIcon } from "lucide-react";
|
||||
// plane imports
|
||||
import { IFavorite } from "@plane/types";
|
||||
import { DiceIcon, FavoriteFolderIcon, ISvgIcons } from "@plane/ui";
|
||||
|
||||
export const FAVORITE_ITEM_ICONS: Record<string, React.FC<ISvgIcons> | LucideIcon> = {
|
||||
page: FileText,
|
||||
project: Briefcase,
|
||||
view: Layers,
|
||||
module: DiceIcon,
|
||||
cycle: ContrastIcon,
|
||||
folder: FavoriteFolderIcon,
|
||||
};
|
||||
|
||||
export const FAVORITE_ITEM_LINKS: {
|
||||
[key: string]: {
|
||||
itemLevel: "project" | "workspace";
|
||||
getLink: (favorite: IFavorite) => string;
|
||||
};
|
||||
} = {
|
||||
project: {
|
||||
itemLevel: "project",
|
||||
getLink: () => `issues`,
|
||||
},
|
||||
cycle: {
|
||||
itemLevel: "project",
|
||||
getLink: (favorite) => `cycles/${favorite.entity_identifier}`,
|
||||
},
|
||||
module: {
|
||||
itemLevel: "project",
|
||||
getLink: (favorite) => `modules/${favorite.entity_identifier}`,
|
||||
},
|
||||
view: {
|
||||
itemLevel: "project",
|
||||
getLink: (favorite) => `views/${favorite.entity_identifier}`,
|
||||
},
|
||||
page: {
|
||||
itemLevel: "project",
|
||||
getLink: (favorite) => `pages/${favorite.entity_identifier}`,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
// plane imports
|
||||
import { IFavorite } from "@plane/types";
|
||||
// components
|
||||
import { getFavoriteItemIcon } from "@/components/workspace/sidebar/favorites/favorite-items/common";
|
||||
|
||||
export const useAdditionalFavoriteItemDetails = () => {
|
||||
const getAdditionalFavoriteItemDetails = (_workspaceSlug: string, favorite: IFavorite) => {
|
||||
const { entity_type: favoriteItemEntityType } = favorite;
|
||||
const favoriteItemName = favorite?.entity_data?.name || favorite?.name;
|
||||
|
||||
let itemIcon;
|
||||
let itemTitle;
|
||||
|
||||
switch (favoriteItemEntityType) {
|
||||
default:
|
||||
itemTitle = favoriteItemName;
|
||||
itemIcon = getFavoriteItemIcon(favoriteItemEntityType);
|
||||
break;
|
||||
}
|
||||
return { itemIcon, itemTitle };
|
||||
};
|
||||
|
||||
return {
|
||||
getAdditionalFavoriteItemDetails,
|
||||
};
|
||||
};
|
||||
@@ -1,49 +1,45 @@
|
||||
"use client";
|
||||
// lucide
|
||||
import { Briefcase, FileText, Layers } from "lucide-react";
|
||||
// types
|
||||
|
||||
import { FileText } from "lucide-react";
|
||||
// plane imports
|
||||
import { IFavorite, TLogoProps } from "@plane/types";
|
||||
// ui
|
||||
import { ContrastIcon, DiceIcon, FavoriteFolderIcon } from "@plane/ui";
|
||||
// components
|
||||
import { Logo } from "@/components/common";
|
||||
// plane web constants
|
||||
import { FAVORITE_ITEM_ICONS, FAVORITE_ITEM_LINKS } from "@/plane-web/constants";
|
||||
|
||||
const iconClassName = `flex-shrink-0 size-4 stroke-[1.5] m-auto`;
|
||||
export const getFavoriteItemIcon = (type: string, logo?: TLogoProps | undefined) => {
|
||||
const Icon = FAVORITE_ITEM_ICONS[type] || FileText;
|
||||
|
||||
export const FAVORITE_ITEM_ICON: Record<string, JSX.Element> = {
|
||||
page: <FileText className={iconClassName} />,
|
||||
project: <Briefcase className={iconClassName} />,
|
||||
view: <Layers className={iconClassName} />,
|
||||
module: <DiceIcon className={iconClassName} />,
|
||||
cycle: <ContrastIcon className={iconClassName} />,
|
||||
folder: <FavoriteFolderIcon className={iconClassName} />,
|
||||
};
|
||||
|
||||
export const getFavoriteItemIcon = (type: string, logo?: TLogoProps | undefined) => (
|
||||
<>
|
||||
<div className="hidden group-hover:flex items-center justify-center size-5">
|
||||
{FAVORITE_ITEM_ICON[type] || <FileText className={iconClassName} />}
|
||||
</div>
|
||||
<div className="flex items-center justify-center size-5 group-hover:hidden">
|
||||
{logo?.in_use ? (
|
||||
<Logo logo={logo} size={16} type={type === "project" ? "material" : "lucide"} />
|
||||
) : (
|
||||
FAVORITE_ITEM_ICON[type] || <FileText className={iconClassName} />
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
const entityPaths: Record<string, string> = {
|
||||
project: "issues",
|
||||
cycle: "cycles",
|
||||
module: "modules",
|
||||
view: "views",
|
||||
page: "pages",
|
||||
return (
|
||||
<>
|
||||
<div className="hidden group-hover:flex items-center justify-center size-5">
|
||||
<Icon className="flex-shrink-0 size-4 stroke-[1.5] m-auto" />
|
||||
</div>
|
||||
<div className="flex items-center justify-center size-5 group-hover:hidden">
|
||||
{logo?.in_use ? (
|
||||
<Logo logo={logo} size={16} type={type === "project" ? "material" : "lucide"} />
|
||||
) : (
|
||||
<Icon className="flex-shrink-0 size-4 stroke-[1.5] m-auto" />
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const generateFavoriteItemLink = (workspaceSlug: string, favorite: IFavorite) => {
|
||||
const entityPath = entityPaths[favorite.entity_type];
|
||||
return entityPath
|
||||
? `/${workspaceSlug}/projects/${favorite.project_id}/${entityPath}/${entityPath === "issues" ? "" : favorite.entity_identifier || ""}`
|
||||
: `/${workspaceSlug}`;
|
||||
const entityLinkDetails = FAVORITE_ITEM_LINKS[favorite.entity_type];
|
||||
|
||||
if (!entityLinkDetails) {
|
||||
console.error(`Unrecognized favorite entity type: ${favorite.entity_type}`);
|
||||
return `/${workspaceSlug}`;
|
||||
}
|
||||
|
||||
if (entityLinkDetails.itemLevel === "workspace") {
|
||||
return `/${workspaceSlug}/${entityLinkDetails.getLink(favorite)}`;
|
||||
} else if (entityLinkDetails.itemLevel === "project") {
|
||||
return `/${workspaceSlug}/projects/${favorite.project_id}/${entityLinkDetails.getLink(favorite)}`;
|
||||
} else {
|
||||
return `/${workspaceSlug}`;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// plane types
|
||||
// plane imports
|
||||
import { IFavorite } from "@plane/types";
|
||||
// components
|
||||
import {
|
||||
@@ -11,19 +11,22 @@ import { getPageName } from "@/helpers/page.helper";
|
||||
import { useProject, useProjectView, useCycle, useModule } from "@/hooks/store";
|
||||
// plane web hooks
|
||||
import { EPageStoreType, usePage } from "@/plane-web/hooks/store";
|
||||
import { useAdditionalFavoriteItemDetails } from "@/plane-web/hooks/use-additional-favorite-item-details";
|
||||
|
||||
export const useFavoriteItemDetails = (workspaceSlug: string, favorite: IFavorite) => {
|
||||
const favoriteItemId = favorite?.entity_identifier;
|
||||
const favoriteItemLogoProps = favorite?.entity_data?.logo_props;
|
||||
const {
|
||||
entity_identifier: favoriteItemId,
|
||||
entity_data: { logo_props: favoriteItemLogoProps },
|
||||
entity_type: favoriteItemEntityType,
|
||||
} = favorite;
|
||||
const favoriteItemName = favorite?.entity_data?.name || favorite?.name;
|
||||
const favoriteItemEntityType = favorite?.entity_type;
|
||||
|
||||
// store hooks
|
||||
const { getViewById } = useProjectView();
|
||||
const { getProjectById } = useProject();
|
||||
const { getCycleById } = useCycle();
|
||||
const { getModuleById } = useModule();
|
||||
|
||||
// additional details
|
||||
const { getAdditionalFavoriteItemDetails } = useAdditionalFavoriteItemDetails();
|
||||
// derived values
|
||||
const pageDetail = usePage({
|
||||
pageId: favoriteItemId ?? "",
|
||||
@@ -32,7 +35,6 @@ export const useFavoriteItemDetails = (workspaceSlug: string, favorite: IFavorit
|
||||
const viewDetails = getViewById(favoriteItemId ?? "");
|
||||
const cycleDetail = getCycleById(favoriteItemId ?? "");
|
||||
const moduleDetail = getModuleById(favoriteItemId ?? "");
|
||||
|
||||
const currentProjectDetails = getProjectById(favorite.project_id ?? "");
|
||||
|
||||
let itemIcon;
|
||||
@@ -60,10 +62,12 @@ export const useFavoriteItemDetails = (workspaceSlug: string, favorite: IFavorit
|
||||
itemTitle = moduleDetail?.name || favoriteItemName;
|
||||
itemIcon = getFavoriteItemIcon("module");
|
||||
break;
|
||||
default:
|
||||
itemTitle = favoriteItemName;
|
||||
itemIcon = getFavoriteItemIcon(favoriteItemEntityType);
|
||||
default: {
|
||||
const additionalDetails = getAdditionalFavoriteItemDetails(workspaceSlug, favorite);
|
||||
itemTitle = additionalDetails.itemTitle;
|
||||
itemIcon = additionalDetails.itemIcon;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return { itemIcon, itemTitle, itemLink };
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./sidebar-favorites";
|
||||
export * from "./ai";
|
||||
export * from "./estimates";
|
||||
export * from "./gantt-chart";
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from "ce/constants/sidebar-favorites";
|
||||
@@ -0,0 +1 @@
|
||||
export * from "ce/hooks/use-additional-favorite-item-details";
|
||||
@@ -38,12 +38,14 @@
|
||||
background-color: rgba(var(--color-background-80));
|
||||
}
|
||||
|
||||
[cmdk-item][aria-disabled="true"], [cmdk-item][data-disabled="true"] {
|
||||
[cmdk-item][aria-disabled="true"],
|
||||
[cmdk-item][data-disabled="true"] {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
[cmdk-item][aria-disabled="true"]:hover, [cmdk-item][data-disabled="true"]:hover {
|
||||
[cmdk-item][aria-disabled="true"]:hover,
|
||||
[cmdk-item][data-disabled="true"]:hover {
|
||||
background-color: rgba(var(--color-background-80), 0.7);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user