Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7719d6f39 | ||
|
|
36e81f4851 | ||
|
|
0bbfe95cc7 | ||
|
|
9a30a07cf5 | ||
|
|
b6e47ccdae | ||
|
|
4280c4d1b1 |
+2
-2
@@ -115,5 +115,5 @@ scripts/
|
||||
# i18n auto-generated types (regenerated on every build)
|
||||
packages/i18n/src/types/keys.generated.ts
|
||||
|
||||
# Local security advisory notes (not for version control)
|
||||
/advisories.md
|
||||
# Local security notes (not for version control)
|
||||
/security/
|
||||
|
||||
@@ -19,6 +19,7 @@ from plane.bgtasks.storage_metadata_task import get_asset_object_metadata
|
||||
from plane.settings.storage import S3Storage
|
||||
from plane.utils.path_validator import sanitize_filename
|
||||
from plane.db.models import FileAsset, User, Workspace
|
||||
from plane.app.permissions import WorkspaceUserPermission
|
||||
from plane.api.views.base import BaseAPIView
|
||||
from plane.api.serializers import (
|
||||
UserAssetUploadSerializer,
|
||||
@@ -404,6 +405,12 @@ class UserServerAssetEndpoint(BaseAPIView):
|
||||
class GenericAssetEndpoint(BaseAPIView):
|
||||
"""This endpoint is used to upload generic assets that can be later bound to entities."""
|
||||
|
||||
# The workspace is taken straight from the URL slug, so every method must
|
||||
# verify the caller is an active member of that workspace. Without this the
|
||||
# endpoint is a cross-workspace IDOR (the public-API sibling of the
|
||||
# CVE-2026-46558 dashboard fix).
|
||||
permission_classes = [WorkspaceUserPermission]
|
||||
|
||||
use_read_replica = True
|
||||
|
||||
@asset_docs(
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
# Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
# See the LICENSE file for details.
|
||||
|
||||
"""Contract tests for the public REST API ``GenericAssetEndpoint``.
|
||||
|
||||
Regression coverage for the cross-workspace asset IDOR (the unfixed
|
||||
external-API sibling of CVE-2026-46558 / GHSA-qw87-v5w3-6vxx). The endpoint
|
||||
must reject any caller that is not an active member of the workspace named in
|
||||
the URL slug, regardless of the workspace their Personal Access Token came
|
||||
from.
|
||||
"""
|
||||
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from rest_framework import status
|
||||
|
||||
from plane.db.models import FileAsset, User, Workspace, WorkspaceMember
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def victim_user(db):
|
||||
"""A user that owns a separate workspace the attacker is not part of."""
|
||||
unique_id = uuid4().hex[:8]
|
||||
user = User.objects.create(
|
||||
email=f"victim-{unique_id}@plane.so",
|
||||
username=f"victim_{unique_id}",
|
||||
first_name="Victim",
|
||||
last_name="User",
|
||||
)
|
||||
user.set_password("test-password")
|
||||
user.save()
|
||||
return user
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def victim_workspace(db, victim_user):
|
||||
"""A workspace whose only active member is ``victim_user``.
|
||||
|
||||
The attacker (``create_user``, who authenticates ``api_key_client``) is
|
||||
deliberately NOT a member here.
|
||||
"""
|
||||
workspace = Workspace.objects.create(
|
||||
name="Victim Workspace",
|
||||
owner=victim_user,
|
||||
slug="victim-workspace",
|
||||
)
|
||||
WorkspaceMember.objects.create(workspace=workspace, member=victim_user, role=20)
|
||||
return workspace
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def victim_asset(db, victim_workspace, victim_user):
|
||||
"""An uploaded attachment that lives inside the victim workspace.
|
||||
|
||||
``storage_metadata`` is pre-populated so the PATCH handler does not enqueue
|
||||
the metadata Celery task during the test.
|
||||
"""
|
||||
return FileAsset.objects.create(
|
||||
attributes={"name": "secret.pdf", "type": "application/pdf", "size": 1024},
|
||||
asset=f"{victim_workspace.id}/secret.pdf",
|
||||
size=1024,
|
||||
workspace=victim_workspace,
|
||||
created_by=victim_user,
|
||||
entity_type=FileAsset.EntityTypeContext.ISSUE_ATTACHMENT,
|
||||
is_uploaded=True,
|
||||
storage_metadata={"size": 1024},
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.contract
|
||||
class TestGenericAssetCrossWorkspaceIDOR:
|
||||
"""A PAT holder must not reach assets in a workspace they don't belong to."""
|
||||
|
||||
def detail_url(self, slug, asset_id):
|
||||
return f"/api/v1/workspaces/{slug}/assets/{asset_id}/"
|
||||
|
||||
def list_url(self, slug):
|
||||
return f"/api/v1/workspaces/{slug}/assets/"
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_get_cross_workspace_asset_returns_403(self, api_key_client, victim_workspace, victim_asset):
|
||||
"""GET on another workspace's asset must be forbidden, not return a
|
||||
presigned download URL."""
|
||||
url = self.detail_url(victim_workspace.slug, victim_asset.id)
|
||||
|
||||
with mock.patch("plane.api.views.asset.S3Storage") as mock_storage:
|
||||
mock_storage.return_value.generate_presigned_url.return_value = "https://signed.example/download"
|
||||
response = api_key_client.get(url)
|
||||
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN, f"Got {response.status_code}: {response.data!r}"
|
||||
# The S3 download URL must never be minted for a non-member.
|
||||
mock_storage.return_value.generate_presigned_url.assert_not_called()
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_post_cross_workspace_asset_returns_403(self, api_key_client, victim_workspace):
|
||||
"""POST (upload) into another workspace must be forbidden and must not
|
||||
plant an asset row in the victim workspace."""
|
||||
url = self.list_url(victim_workspace.slug)
|
||||
payload = {"name": "evil.pdf", "type": "application/pdf", "size": 1024}
|
||||
|
||||
with mock.patch("plane.api.views.asset.S3Storage") as mock_storage:
|
||||
mock_storage.return_value.generate_presigned_post.return_value = {"url": "x", "fields": {}}
|
||||
response = api_key_client.post(url, payload, format="json")
|
||||
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN, f"Got {response.status_code}: {response.data!r}"
|
||||
assert FileAsset.objects.filter(workspace=victim_workspace).count() == 0
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_patch_cross_workspace_asset_returns_403(self, api_key_client, victim_workspace, victim_asset):
|
||||
"""PATCH on another workspace's asset must be forbidden and must leave
|
||||
the asset untouched."""
|
||||
url = self.detail_url(victim_workspace.slug, victim_asset.id)
|
||||
|
||||
response = api_key_client.patch(url, {"is_uploaded": False}, format="json")
|
||||
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN, f"Got {response.status_code}: {response.data!r}"
|
||||
victim_asset.refresh_from_db()
|
||||
assert victim_asset.is_uploaded is True
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_member_can_patch_own_workspace_asset(self, api_key_client, workspace, create_user):
|
||||
"""Positive control: an active member of the workspace can still update
|
||||
their own asset, so the fix does not over-block legitimate callers."""
|
||||
asset = FileAsset.objects.create(
|
||||
attributes={"name": "mine.pdf", "type": "application/pdf", "size": 10},
|
||||
asset=f"{workspace.id}/mine.pdf",
|
||||
size=10,
|
||||
workspace=workspace,
|
||||
created_by=create_user,
|
||||
entity_type=FileAsset.EntityTypeContext.ISSUE_ATTACHMENT,
|
||||
is_uploaded=False,
|
||||
storage_metadata={"size": 10},
|
||||
)
|
||||
url = self.detail_url(workspace.slug, asset.id)
|
||||
|
||||
response = api_key_client.patch(url, {"is_uploaded": True}, format="json")
|
||||
|
||||
assert response.status_code == status.HTTP_204_NO_CONTENT, f"Got {response.status_code}: {response.data!r}"
|
||||
asset.refresh_from_db()
|
||||
assert asset.is_uploaded is True
|
||||
@@ -22,7 +22,7 @@ import { SidebarProjectsListItem } from "@/components/workspace/sidebar/projects
|
||||
import { useAppTheme } from "@/hooks/store/use-app-theme";
|
||||
import { useProject } from "@/hooks/store/use-project";
|
||||
import { useUserPermissions } from "@/hooks/store/user";
|
||||
import type { TProject } from "@plane/types";
|
||||
import type { TProject } from "@/plane-web/types";
|
||||
import { ExtendedSidebarWrapper } from "./extended-sidebar-wrapper";
|
||||
|
||||
export const ExtendedProjectSidebar = observer(function ExtendedProjectSidebar() {
|
||||
|
||||
@@ -15,7 +15,7 @@ import { AppHeader } from "@/components/core/app-header";
|
||||
import { ContentWrapper } from "@/components/core/content-wrapper";
|
||||
import { ProfileSidebar } from "@/components/profile/sidebar";
|
||||
// constants
|
||||
import { USER_PROFILE_PROJECT_SEGREGATION } from "@plane/constants";
|
||||
import { USER_PROFILE_PROJECT_SEGREGATION } from "@/constants/fetch-keys";
|
||||
// hooks
|
||||
import { useUserPermissions } from "@/hooks/store/user";
|
||||
import useSize from "@/hooks/use-window-size";
|
||||
|
||||
@@ -18,7 +18,7 @@ import { ProfileStateDistribution } from "@/components/profile/overview/state-di
|
||||
import { ProfileStats } from "@/components/profile/overview/stats";
|
||||
import { ProfileWorkload } from "@/components/profile/overview/workload";
|
||||
// constants
|
||||
import { USER_PROFILE_DATA } from "@plane/constants";
|
||||
import { USER_PROFILE_DATA } from "@/constants/fetch-keys";
|
||||
// services
|
||||
import { UserService } from "@/services/user.service";
|
||||
import type { Route } from "./+types/page";
|
||||
|
||||
+2
-2
@@ -14,13 +14,13 @@ import { Breadcrumbs, Header } from "@plane/ui";
|
||||
import { BreadcrumbLink } from "@/components/common/breadcrumb-link";
|
||||
import { IssueDetailQuickActions } from "@/components/issues/issue-detail/issue-detail-quick-actions";
|
||||
// constants
|
||||
import { ISSUE_DETAILS } from "@plane/constants";
|
||||
import { ISSUE_DETAILS } from "@/constants/fetch-keys";
|
||||
// hooks
|
||||
import { useProject } from "@/hooks/store/use-project";
|
||||
// plane web
|
||||
import { ProjectBreadcrumb } from "@/plane-web/components/breadcrumbs/project";
|
||||
// services
|
||||
import { IssueService } from "@plane/services";
|
||||
import { IssueService } from "@/services/issue";
|
||||
|
||||
const issueService = new IssueService();
|
||||
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import { LogoSpinner } from "@/components/common/logo-spinner";
|
||||
// hooks
|
||||
import { useAppRouter } from "@/hooks/use-app-router";
|
||||
// services
|
||||
import { IssueService } from "@plane/services";
|
||||
import { IssueService } from "@/services/issue/issue.service";
|
||||
// types
|
||||
import type { Route } from "./+types/page";
|
||||
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ import { EPageStoreType, usePage, usePageStore } from "@/plane-web/hooks/store";
|
||||
// plane web services
|
||||
import { WorkspaceService } from "@/services/workspace.service";
|
||||
// services
|
||||
import { ProjectPageService, ProjectPageVersionService } from "@plane/services";
|
||||
import { ProjectPageService, ProjectPageVersionService } from "@/services/page";
|
||||
import type { Route } from "./+types/page";
|
||||
const workspaceService = new WorkspaceService();
|
||||
const projectPageService = new ProjectPageService();
|
||||
|
||||
+2
-2
@@ -14,12 +14,12 @@ import { SingleIntegrationCard } from "@/components/integration/single-integrati
|
||||
import { IntegrationAndImportExportBanner } from "@/components/ui/integration-and-import-export-banner";
|
||||
import { IntegrationsSettingsLoader } from "@/components/ui/loader/settings/integration";
|
||||
// constants
|
||||
import { APP_INTEGRATIONS } from "@plane/constants";
|
||||
import { APP_INTEGRATIONS } from "@/constants/fetch-keys";
|
||||
// hooks
|
||||
import { useWorkspace } from "@/hooks/store/use-workspace";
|
||||
import { useUserPermissions } from "@/hooks/store/user";
|
||||
// services
|
||||
import { IntegrationService } from "@plane/services";
|
||||
import { IntegrationService } from "@/services/integrations";
|
||||
|
||||
const integrationService = new IntegrationService();
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import emptyInvitation from "@/app/assets/empty-state/invitation.svg?url";
|
||||
// components
|
||||
import { EmptyState } from "@/components/common/empty-state";
|
||||
import { WorkspaceLogo } from "@/components/workspace/logo";
|
||||
import { USER_WORKSPACES_LIST } from "@plane/constants";
|
||||
import { USER_WORKSPACES_LIST } from "@/constants/fetch-keys";
|
||||
// hooks
|
||||
import { useWorkspace } from "@/hooks/store/use-workspace";
|
||||
import { useUser, useUserProfile } from "@/hooks/store/user";
|
||||
|
||||
@@ -11,7 +11,7 @@ import useSWR from "swr";
|
||||
import { LogoSpinner } from "@/components/common/logo-spinner";
|
||||
import { OnboardingRoot } from "@/components/onboarding";
|
||||
// constants
|
||||
import { USER_WORKSPACES_LIST } from "@plane/constants";
|
||||
import { USER_WORKSPACES_LIST } from "@/constants/fetch-keys";
|
||||
// helpers
|
||||
import { EPageTypes } from "@/helpers/authentication.helper";
|
||||
// hooks
|
||||
|
||||
@@ -13,7 +13,7 @@ import { CheckIcon, CloseIcon } from "@plane/propel/icons";
|
||||
import { LogoSpinner } from "@/components/common/logo-spinner";
|
||||
import { EmptySpace, EmptySpaceItem } from "@/components/ui/empty-space";
|
||||
// constants
|
||||
import { WORKSPACE_INVITATION } from "@plane/constants";
|
||||
import { WORKSPACE_INVITATION } from "@/constants/fetch-keys";
|
||||
// helpers
|
||||
import { EPageTypes } from "@/helpers/authentication.helper";
|
||||
// hooks
|
||||
|
||||
@@ -14,7 +14,7 @@ import { SwitcherLabel } from "@/components/common/switcher-label";
|
||||
// hooks
|
||||
import { useProject } from "@/hooks/store/use-project";
|
||||
import { useAppRouter } from "@/hooks/use-app-router";
|
||||
import type { TProject } from "@plane/types";
|
||||
import type { TProject } from "@/plane-web/types";
|
||||
|
||||
type TProjectBreadcrumbProps = {
|
||||
workspaceSlug: string;
|
||||
|
||||
@@ -16,10 +16,10 @@ import { Tooltip } from "@plane/propel/tooltip";
|
||||
import { cn } from "@plane/utils";
|
||||
import { RichTextEditor } from "@/components/editor/rich-text";
|
||||
// plane web constants
|
||||
import { AI_EDITOR_TASKS, LOADING_TEXTS } from "@plane/constants";
|
||||
import { AI_EDITOR_TASKS, LOADING_TEXTS } from "@/constants/ai";
|
||||
// plane web services
|
||||
import type { TTaskPayload } from "@plane/services";
|
||||
import { AIService } from "@plane/services";
|
||||
import type { TTaskPayload } from "@/services/ai.service";
|
||||
import { AIService } from "@/services/ai.service";
|
||||
import { AskPiMenu } from "./ask-pi-menu";
|
||||
const aiService = new AIService();
|
||||
|
||||
@@ -75,7 +75,7 @@ export function EditorAIMenu(props: Props) {
|
||||
// params
|
||||
const handleGenerateResponse = async (payload: TTaskPayload) => {
|
||||
if (!workspaceSlug) return;
|
||||
await aiService.rephraseGrammar(workspaceSlug.toString(), payload).then((res) => setResponse(res.response));
|
||||
await aiService.performEditorTask(workspaceSlug.toString(), payload).then((res) => setResponse(res.response));
|
||||
};
|
||||
// handle task click
|
||||
const handleClick = async (key: AI_EDITOR_TASKS) => {
|
||||
|
||||
@@ -20,7 +20,7 @@ import { getCoverImageType, uploadCoverImage } from "@/helpers/cover-image.helpe
|
||||
import { useProject } from "@/hooks/store/use-project";
|
||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
// plane web types
|
||||
import type { TProject } from "@plane/types";
|
||||
import type { TProject } from "@/plane-web/types/projects";
|
||||
import { ProjectAttributes } from "./attributes";
|
||||
import { getProjectFormValues } from "./utils";
|
||||
|
||||
@@ -110,7 +110,7 @@ export const CreateProjectForm = observer(function CreateProjectForm(props: TCre
|
||||
if (setToFavorite) {
|
||||
handleAddToFavorites(res.id);
|
||||
}
|
||||
handleNextStep(res.id);
|
||||
return handleNextStep(res.id);
|
||||
})
|
||||
.catch((err) => {
|
||||
try {
|
||||
@@ -119,8 +119,9 @@ export const CreateProjectForm = observer(function CreateProjectForm(props: TCre
|
||||
|
||||
const nameError = errorData.name?.includes("PROJECT_NAME_ALREADY_EXIST");
|
||||
const identifierError = errorData?.identifier?.includes("PROJECT_IDENTIFIER_ALREADY_EXIST");
|
||||
const nameSpecialCharError = errorData?.name?.includes("PROJECT_NAME_CANNOT_CONTAIN_SPECIAL_CHARACTERS");
|
||||
|
||||
if (nameError || identifierError) {
|
||||
if (nameError || identifierError || nameSpecialCharError) {
|
||||
if (nameError) {
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
@@ -136,6 +137,14 @@ export const CreateProjectForm = observer(function CreateProjectForm(props: TCre
|
||||
message: t("project_identifier_already_taken"),
|
||||
});
|
||||
}
|
||||
|
||||
if (nameSpecialCharError) {
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: t("toast.error"),
|
||||
message: t("project_name_cannot_contain_special_characters"),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { CircleDot, XCircle } from "lucide-react";
|
||||
import { RelatedIcon, DuplicatePropertyIcon } from "@plane/propel/icons";
|
||||
import type { TRelationObject } from "@/components/issues/issue-detail-widgets/relations";
|
||||
import type { TIssueRelationTypes } from "@plane/types";
|
||||
import type { TIssueRelationTypes } from "../../types";
|
||||
|
||||
export * from "./activity";
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import { EProductSubscriptionEnum } from "@plane/types";
|
||||
import { getSubscriptionName } from "@plane/utils";
|
||||
// components
|
||||
import { DiscountInfo } from "@/components/license/modal/card/discount-info";
|
||||
import type { TPlanDetail } from "@/components/workspace/billing/comparison/plans";
|
||||
import type { TPlanDetail } from "@/constants/plans";
|
||||
// local imports
|
||||
import { PlanFrequencyToggle } from "./frequency-toggle";
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import { observer } from "mobx-react";
|
||||
import type { EProductSubscriptionEnum, TBillingFrequency } from "@plane/types";
|
||||
// components
|
||||
import { PlansComparisonBase, shouldRenderPlanDetail } from "@/components/workspace/billing/comparison/base";
|
||||
import type { TPlanePlans } from "@/components/workspace/billing/comparison/plans";
|
||||
import { PLANE_PLANS } from "@/components/workspace/billing/comparison/plans";
|
||||
import type { TPlanePlans } from "@/constants/plans";
|
||||
import { PLANE_PLANS } from "@/constants/plans";
|
||||
// plane web imports
|
||||
import { PlanDetail } from "./plan-detail";
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
import { useAppRouter } from "@/hooks/use-app-router";
|
||||
import { useQueryParams } from "@/hooks/use-query-params";
|
||||
import type { TPageNavigationPaneTab } from "@/plane-web/components/pages/navigation-pane";
|
||||
import type { INavigationPaneExtension } from "@/components/pages/navigation-pane";
|
||||
import type { INavigationPaneExtension } from "@/plane-web/types/pages/pane-extensions";
|
||||
import type { TPageInstance } from "@/store/pages/base-page";
|
||||
|
||||
export type TPageExtensionHookParams = {
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@
|
||||
// plane imports
|
||||
import type { IFavorite } from "@plane/types";
|
||||
// components
|
||||
import { FavoriteItemIcon } from "@/components/workspace/sidebar/favorites/favorite-items/common";
|
||||
import { getFavoriteItemIcon } from "@/components/workspace/sidebar/favorites/favorite-items/common";
|
||||
|
||||
export const useAdditionalFavoriteItemDetails = () => {
|
||||
const getAdditionalFavoriteItemDetails = (_workspaceSlug: string, favorite: IFavorite) => {
|
||||
@@ -20,7 +20,7 @@ export const useAdditionalFavoriteItemDetails = () => {
|
||||
switch (favoriteItemEntityType) {
|
||||
default:
|
||||
itemTitle = favoriteItemName;
|
||||
itemIcon = <FavoriteItemIcon type={favoriteItemEntityType} />;
|
||||
itemIcon = getFavoriteItemIcon(favoriteItemEntityType);
|
||||
break;
|
||||
}
|
||||
return { itemIcon, itemTitle };
|
||||
@@ -14,7 +14,7 @@ import type {
|
||||
TEstimateSystemKeys,
|
||||
} from "@plane/types";
|
||||
// plane web services
|
||||
import { EstimateService } from "@plane/services";
|
||||
import estimateService from "@/services/estimate.service";
|
||||
// store
|
||||
import type { IEstimatePoint } from "@/store/estimates/estimate-point";
|
||||
import { EstimatePoint } from "@/store/estimates/estimate-point";
|
||||
@@ -41,8 +41,6 @@ export interface IEstimate extends Omit<IEstimateType, "points"> {
|
||||
) => Promise<IEstimatePointType | undefined>;
|
||||
}
|
||||
|
||||
const estimateService = new EstimateService();
|
||||
|
||||
export class Estimate implements IEstimate {
|
||||
// data model observables
|
||||
id: string | undefined = undefined;
|
||||
|
||||
@@ -20,7 +20,7 @@ import type {
|
||||
import { EIssueServiceType } from "@plane/types";
|
||||
// plane web constants
|
||||
// services
|
||||
import { IssueActivityService } from "@plane/services";
|
||||
import { IssueActivityService } from "@/services/issue";
|
||||
// store
|
||||
import type { CoreRootStore } from "@/store/root.store";
|
||||
|
||||
|
||||
+1
-2
@@ -4,5 +4,4 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
export type TIssuePropertyValues = object;
|
||||
export type TIssuePropertyValueErrors = object;
|
||||
export type TIssueRelationTypes = "blocking" | "blocked_by" | "duplicate" | "relates_to";
|
||||
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
export * from "./projects";
|
||||
export * from "./issue-types";
|
||||
export * from "./gantt-chart";
|
||||
@@ -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 "./issue-property-values.d";
|
||||
@@ -0,0 +1,2 @@
|
||||
export type TIssuePropertyValues = object;
|
||||
export type TIssuePropertyValueErrors = object;
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
// CE re-exports the core navigation pane extension types directly
|
||||
// EE overrides this with specific extension data types
|
||||
export type {
|
||||
INavigationPaneExtension,
|
||||
INavigationPaneExtensionComponent,
|
||||
INavigationPaneExtensionProps,
|
||||
} from "@/components/pages/navigation-pane";
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
export * from "./projects";
|
||||
export * from "./project-activity";
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import type { TProjectBaseActivity } from "../activity";
|
||||
import type { TProjectBaseActivity } from "@plane/types";
|
||||
|
||||
export type TProjectActivity = TProjectBaseActivity & {
|
||||
content: string;
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import type { IPartialProject, IProject } from "@plane/types";
|
||||
|
||||
export type TPartialProject = IPartialProject;
|
||||
|
||||
export type TProject = TPartialProject & IProject;
|
||||
@@ -19,7 +19,7 @@ import { cn, checkEmailValidity } from "@plane/utils";
|
||||
// hooks
|
||||
import useTimer from "@/hooks/use-timer";
|
||||
// services
|
||||
import { AuthService } from "@plane/services";
|
||||
import { AuthService } from "@/services/auth.service";
|
||||
// local components
|
||||
import { FormContainer } from "./common/container";
|
||||
import { AuthFormHeader } from "./common/header";
|
||||
|
||||
@@ -16,7 +16,7 @@ import { authErrorHandler } from "@/helpers/authentication.helper";
|
||||
import { useInstance } from "@/hooks/store/use-instance";
|
||||
import { useAppRouter } from "@/hooks/use-app-router";
|
||||
// services
|
||||
import { AuthService } from "@plane/services";
|
||||
import { AuthService } from "@/services/auth.service";
|
||||
// local components
|
||||
import { AuthEmailForm } from "./email";
|
||||
import { AuthPasswordForm } from "./password";
|
||||
|
||||
@@ -22,7 +22,7 @@ import { ForgotPasswordPopover } from "@/components/account/auth-forms/forgot-pa
|
||||
// helpers
|
||||
import { EAuthModes, EAuthSteps } from "@/helpers/authentication.helper";
|
||||
// services
|
||||
import { AuthService } from "@plane/services";
|
||||
import { AuthService } from "@/services/auth.service";
|
||||
|
||||
type Props = {
|
||||
email: string;
|
||||
|
||||
@@ -20,7 +20,7 @@ import { getPasswordStrength } from "@plane/utils";
|
||||
import type { EAuthenticationErrorCodes, TAuthErrorInfo } from "@/helpers/authentication.helper";
|
||||
import { EErrorAlertType, authErrorHandler } from "@/helpers/authentication.helper";
|
||||
// services
|
||||
import { AuthService } from "@plane/services";
|
||||
import { AuthService } from "@/services/auth.service";
|
||||
// local imports
|
||||
import { AuthBanner } from "./auth-banner";
|
||||
import { FormContainer } from "./common/container";
|
||||
|
||||
@@ -22,7 +22,7 @@ import { getPasswordStrength } from "@plane/utils";
|
||||
import { useUser } from "@/hooks/store/user";
|
||||
import { useAppRouter } from "@/hooks/use-app-router";
|
||||
// services
|
||||
import { AuthService } from "@plane/services";
|
||||
import { AuthService } from "@/services/auth.service";
|
||||
// local components
|
||||
import { FormContainer } from "./common/container";
|
||||
import { AuthFormHeader } from "./common/header";
|
||||
|
||||
@@ -16,7 +16,7 @@ import { EAuthModes } from "@/helpers/authentication.helper";
|
||||
// hooks
|
||||
import useTimer from "@/hooks/use-timer";
|
||||
// services
|
||||
import { AuthService } from "@plane/services";
|
||||
import { AuthService } from "@/services/auth.service";
|
||||
|
||||
// services
|
||||
const authService = new AuthService();
|
||||
|
||||
@@ -15,7 +15,7 @@ import type { TChartData } from "@plane/types";
|
||||
// hooks
|
||||
import { useAnalytics } from "@/hooks/store/use-analytics";
|
||||
// services
|
||||
import { AnalyticsService } from "@plane/services";
|
||||
import { AnalyticsService } from "@/services/analytics.service";
|
||||
// plane web components
|
||||
import AnalyticsSectionWrapper from "../analytics-section-wrapper";
|
||||
import { ProjectInsightsLoader } from "../loaders";
|
||||
|
||||
@@ -16,7 +16,7 @@ import { cn } from "@plane/utils";
|
||||
// hooks
|
||||
import { useAnalytics } from "@/hooks/store/use-analytics";
|
||||
// services
|
||||
import { AnalyticsService } from "@plane/services";
|
||||
import { AnalyticsService } from "@/services/analytics.service";
|
||||
// local imports
|
||||
import InsightCard from "./insight-card";
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import { renderFormattedDate } from "@plane/utils";
|
||||
// hooks
|
||||
import { useAnalytics } from "@/hooks/store/use-analytics";
|
||||
// services
|
||||
import { AnalyticsService } from "@plane/services";
|
||||
import { AnalyticsService } from "@/services/analytics.service";
|
||||
// plane web components
|
||||
import AnalyticsSectionWrapper from "../analytics-section-wrapper";
|
||||
import { ChartLoader } from "../loaders";
|
||||
|
||||
@@ -24,7 +24,7 @@ import { generateExtendedColors, parseChartData } from "@/components/chart/utils
|
||||
// hooks
|
||||
import { useAnalytics } from "@/hooks/store/use-analytics";
|
||||
import { useProjectState } from "@/hooks/store/use-project-state";
|
||||
import { AnalyticsService } from "@plane/services";
|
||||
import { AnalyticsService } from "@/services/analytics.service";
|
||||
import { exportCSV } from "../export";
|
||||
import { DataTable } from "../insight-table/data-table";
|
||||
import { ChartLoader } from "../loaders";
|
||||
|
||||
@@ -21,7 +21,7 @@ import { getFileURL } from "@plane/utils";
|
||||
// hooks
|
||||
import { useAnalytics } from "@/hooks/store/use-analytics";
|
||||
import { useProject } from "@/hooks/store/use-project";
|
||||
import { AnalyticsService } from "@plane/services";
|
||||
import { AnalyticsService } from "@/services/analytics.service";
|
||||
// plane web components
|
||||
import { exportCSV } from "../export";
|
||||
import { InsightTable } from "../insight-table";
|
||||
|
||||
@@ -14,7 +14,7 @@ import type { IApiToken } from "@plane/types";
|
||||
// ui
|
||||
import { AlertModalCore } from "@plane/ui";
|
||||
// fetch-keys
|
||||
import { API_TOKENS_LIST } from "@plane/constants";
|
||||
import { API_TOKENS_LIST } from "@/constants/fetch-keys";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
|
||||
@@ -13,7 +13,7 @@ import type { IApiToken } from "@plane/types";
|
||||
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
|
||||
import { renderFormattedDate, csvDownload } from "@plane/utils";
|
||||
// constants
|
||||
import { API_TOKENS_LIST } from "@plane/constants";
|
||||
import { API_TOKENS_LIST } from "@/constants/fetch-keys";
|
||||
// local imports
|
||||
import { CreateApiTokenForm } from "./form";
|
||||
import { GeneratedTokenDetails } from "./generated-token-details";
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
import type { TProjectActivity } from "@plane/types";
|
||||
import type { TProjectActivity } from "@/plane-web/types";
|
||||
import { ActivityBlockComponent } from "./activity-block";
|
||||
import { iconsMap, messages } from "./helper";
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ import {
|
||||
StatePropertyIcon,
|
||||
} from "@plane/propel/icons";
|
||||
import { store } from "@/lib/store-context";
|
||||
import type { TProjectActivity } from "@plane/types";
|
||||
import type { TProjectActivity } from "@/plane-web/types";
|
||||
|
||||
type ActivityIconMap = {
|
||||
[key: string]: FC<{ className?: string }>;
|
||||
|
||||
@@ -30,7 +30,7 @@ import { SimpleEmptyState } from "@/components/empty-state/simple-empty-state-ro
|
||||
import { useIssues } from "@/hooks/store/use-issues";
|
||||
import useDebounce from "@/hooks/use-debounce";
|
||||
// services
|
||||
import { ProjectService } from "@plane/services";
|
||||
import { ProjectService } from "@/services/project";
|
||||
// local components
|
||||
import { BulkDeleteIssuesModalItem } from "./bulk-delete-issues-modal-item";
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import type { EAuthenticationErrorCodes } from "@/helpers/authentication.helper"
|
||||
// hooks
|
||||
import { useUser } from "@/hooks/store/user";
|
||||
// services
|
||||
import { AuthService } from "@plane/services";
|
||||
import { AuthService } from "@/services/auth.service";
|
||||
import userService from "@/services/user.service";
|
||||
|
||||
type Props = { isOpen: boolean; onClose: () => void };
|
||||
|
||||
@@ -25,7 +25,7 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
// plane web components
|
||||
import { IssueIdentifier } from "@/plane-web/components/issues/issue-details/issue-identifier";
|
||||
// services
|
||||
import { ProjectService } from "@plane/services";
|
||||
import { ProjectService } from "@/services/project";
|
||||
// components
|
||||
import { IssueSearchModalEmptyState } from "./issue-search-modal-empty-state";
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import { Input } from "@plane/ui";
|
||||
// components
|
||||
import { RichTextEditor } from "@/components/editor/rich-text";
|
||||
// services
|
||||
import { AIService } from "@plane/services";
|
||||
import { AIService } from "@/services/ai.service";
|
||||
const aiService = new AIService();
|
||||
|
||||
type Props = {
|
||||
@@ -106,7 +106,7 @@ export function GptAssistantPopover(props: Props) {
|
||||
|
||||
const callAIService = async (formData: FormData) => {
|
||||
try {
|
||||
const res = await aiService.prompt(workspaceSlug.toString(), {
|
||||
const res = await aiService.createGptTask(workspaceSlug.toString(), {
|
||||
prompt: prompt || "",
|
||||
task: formData.task,
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ import useSWR from "swr";
|
||||
import type { TWorkItemFilterCondition } from "@plane/shared-state";
|
||||
import { EIssuesStoreType } from "@plane/types";
|
||||
// constants
|
||||
import { CYCLE_ISSUES_WITH_PARAMS } from "@plane/constants";
|
||||
import { CYCLE_ISSUES_WITH_PARAMS } from "@/constants/fetch-keys";
|
||||
// hooks
|
||||
import { useCycle } from "@/hooks/store/use-cycle";
|
||||
import { useIssues } from "@/hooks/store/use-issues";
|
||||
|
||||
@@ -22,7 +22,7 @@ import { useCycle } from "@/hooks/store/use-cycle";
|
||||
import { useUserPermissions } from "@/hooks/store/user";
|
||||
import { useTimeZoneConverter } from "@/hooks/use-timezone-converter";
|
||||
// services
|
||||
import { CycleService } from "@plane/services";
|
||||
import { CycleService } from "@/services/cycle.service";
|
||||
|
||||
type Props = {
|
||||
workspaceSlug: string;
|
||||
@@ -74,7 +74,7 @@ export const CycleSidebarHeader = observer(function CycleSidebarHeader(props: Pr
|
||||
|
||||
const dateChecker = async (payload: any) => {
|
||||
try {
|
||||
const res = await cycleService.validateDates(workspaceSlug, projectId, payload);
|
||||
const res = await cycleService.cycleDateCheck(workspaceSlug, projectId, payload);
|
||||
return res.status;
|
||||
} catch (_err) {
|
||||
return false;
|
||||
|
||||
@@ -19,7 +19,7 @@ import useKeypress from "@/hooks/use-keypress";
|
||||
import useLocalStorage from "@/hooks/use-local-storage";
|
||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
// services
|
||||
import { CycleService } from "@plane/services";
|
||||
import { CycleService } from "@/services/cycle.service";
|
||||
// local imports
|
||||
import { CycleForm } from "./form";
|
||||
|
||||
@@ -100,7 +100,7 @@ export function CycleCreateUpdateModal(props: CycleModalProps) {
|
||||
const dateChecker = async (projectId: string, payload: CycleDateCheckData) => {
|
||||
let status = false;
|
||||
|
||||
await cycleService.validateDates(workspaceSlug, projectId, payload).then((res) => {
|
||||
await cycleService.cycleDateCheck(workspaceSlug, projectId, payload).then((res) => {
|
||||
status = res.status;
|
||||
});
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import { cn, sortBySelectedFirst } from "@plane/utils";
|
||||
// hooks
|
||||
import { useDropdown } from "@/hooks/use-dropdown";
|
||||
// plane web imports
|
||||
import type { TProject } from "@plane/types";
|
||||
import type { TProject } from "@/plane-web/types";
|
||||
// local imports
|
||||
import { DropdownButton } from "../buttons";
|
||||
import { BUTTON_VARIANTS_WITH_TEXT } from "../constants";
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
import React from "react";
|
||||
import { ArrowUp, Paperclip } from "lucide-react";
|
||||
// constants
|
||||
import type { ToolbarMenuItem } from "@plane/editor";
|
||||
import { IMAGE_ITEM } from "@plane/editor";
|
||||
import type { ToolbarMenuItem } from "@/constants/editor";
|
||||
import { IMAGE_ITEM } from "@/constants/editor";
|
||||
|
||||
type LiteToolbarProps = {
|
||||
onSubmit: (e: React.KeyboardEvent<HTMLDivElement> | React.MouseEvent<HTMLButtonElement>) => void;
|
||||
|
||||
@@ -19,8 +19,8 @@ import type { ISvgIcons } from "@plane/propel/icons";
|
||||
import { Tooltip } from "@plane/propel/tooltip";
|
||||
// constants
|
||||
import { cn } from "@plane/utils";
|
||||
import type { ToolbarMenuItem } from "@plane/editor";
|
||||
import { TOOLBAR_ITEMS } from "@plane/editor";
|
||||
import type { ToolbarMenuItem } from "@/constants/editor";
|
||||
import { TOOLBAR_ITEMS } from "@/constants/editor";
|
||||
// helpers
|
||||
|
||||
type Props = {
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import type { PageProps, Styles } from "@react-pdf/renderer";
|
||||
import { Document, Font, Page, StyleSheet } from "@react-pdf/renderer";
|
||||
import type { PageProps } from "@react-pdf/renderer";
|
||||
import { Document, Font, Page } from "@react-pdf/renderer";
|
||||
import { Html } from "react-pdf-html";
|
||||
// assets
|
||||
import interBold from "@/app/assets/fonts/inter/bold.ttf?url";
|
||||
@@ -17,177 +17,8 @@ import interSemibold from "@/app/assets/fonts/inter/semibold.ttf?url";
|
||||
import interThin from "@/app/assets/fonts/inter/thin.ttf?url";
|
||||
import interUltraBold from "@/app/assets/fonts/inter/ultrabold.ttf?url";
|
||||
import interUltraLight from "@/app/assets/fonts/inter/ultralight.ttf?url";
|
||||
// plane imports
|
||||
import { convertRemToPixel } from "@plane/utils";
|
||||
|
||||
const EDITOR_PDF_FONT_FAMILY_STYLES: Styles = {
|
||||
"*:not(.courier, .courier-bold)": { fontFamily: "Inter" },
|
||||
".courier": { fontFamily: "Courier" },
|
||||
".courier-bold": { fontFamily: "Courier-Bold" },
|
||||
};
|
||||
|
||||
const EDITOR_PDF_TYPOGRAPHY_STYLES: Styles = {
|
||||
// page title
|
||||
"h1.page-title": {
|
||||
fontSize: convertRemToPixel(1.6),
|
||||
fontWeight: "bold",
|
||||
marginTop: 0,
|
||||
marginBottom: convertRemToPixel(2),
|
||||
},
|
||||
// headings
|
||||
"h1:not(.page-title)": {
|
||||
fontSize: convertRemToPixel(1.4),
|
||||
fontWeight: "semibold",
|
||||
marginTop: convertRemToPixel(2),
|
||||
marginBottom: convertRemToPixel(0.25),
|
||||
},
|
||||
h2: {
|
||||
fontSize: convertRemToPixel(1.2),
|
||||
fontWeight: "semibold",
|
||||
marginTop: convertRemToPixel(1.4),
|
||||
marginBottom: convertRemToPixel(0.0625),
|
||||
},
|
||||
h3: {
|
||||
fontSize: convertRemToPixel(1.1),
|
||||
fontWeight: "semibold",
|
||||
marginTop: convertRemToPixel(1),
|
||||
marginBottom: convertRemToPixel(0.0625),
|
||||
},
|
||||
h4: {
|
||||
fontSize: convertRemToPixel(1),
|
||||
fontWeight: "semibold",
|
||||
marginTop: convertRemToPixel(1),
|
||||
marginBottom: convertRemToPixel(0.0625),
|
||||
},
|
||||
h5: {
|
||||
fontSize: convertRemToPixel(0.9),
|
||||
fontWeight: "semibold",
|
||||
marginTop: convertRemToPixel(1),
|
||||
marginBottom: convertRemToPixel(0.0625),
|
||||
},
|
||||
h6: {
|
||||
fontSize: convertRemToPixel(0.8),
|
||||
fontWeight: "semibold",
|
||||
marginTop: convertRemToPixel(1),
|
||||
marginBottom: convertRemToPixel(0.0625),
|
||||
},
|
||||
// paragraph
|
||||
"p:not(table p)": {
|
||||
fontSize: convertRemToPixel(0.8),
|
||||
},
|
||||
"p:not(ol p, ul p)": {
|
||||
marginTop: convertRemToPixel(0.25),
|
||||
marginBottom: convertRemToPixel(0.0625),
|
||||
},
|
||||
};
|
||||
|
||||
const EDITOR_PDF_LIST_STYLES: Styles = {
|
||||
"ul, ol": {
|
||||
fontSize: convertRemToPixel(0.8),
|
||||
marginHorizontal: -20,
|
||||
},
|
||||
"ol p, ul p": {
|
||||
marginVertical: 0,
|
||||
},
|
||||
"ol li, ul li": {
|
||||
marginTop: convertRemToPixel(0.45),
|
||||
},
|
||||
"ul ul, ul ol, ol ol, ol ul": {
|
||||
marginVertical: 0,
|
||||
},
|
||||
"ul[data-type='taskList']": {
|
||||
position: "relative",
|
||||
},
|
||||
"div.input-checkbox": {
|
||||
position: "absolute",
|
||||
top: convertRemToPixel(0.15),
|
||||
left: -convertRemToPixel(1.2),
|
||||
height: convertRemToPixel(0.75),
|
||||
width: convertRemToPixel(0.75),
|
||||
borderWidth: "1.5px",
|
||||
borderStyle: "solid",
|
||||
borderRadius: convertRemToPixel(0.125),
|
||||
},
|
||||
"div.input-checkbox:not(.checked)": {
|
||||
backgroundColor: "#ffffff",
|
||||
borderColor: "#171717",
|
||||
},
|
||||
"div.input-checkbox.checked": {
|
||||
backgroundColor: "#3f76ff",
|
||||
borderColor: "#3f76ff",
|
||||
},
|
||||
"ul li[data-checked='true'] p": {
|
||||
color: "#a3a3a3",
|
||||
},
|
||||
};
|
||||
|
||||
const EDITOR_PDF_CODE_STYLES: Styles = {
|
||||
// code block
|
||||
"[data-node-type='code-block']": {
|
||||
marginVertical: convertRemToPixel(0.5),
|
||||
padding: convertRemToPixel(1),
|
||||
borderRadius: convertRemToPixel(0.5),
|
||||
backgroundColor: "#f7f7f7",
|
||||
fontSize: convertRemToPixel(0.7),
|
||||
},
|
||||
// inline code block
|
||||
"[data-node-type='inline-code-block']": {
|
||||
margin: 0,
|
||||
paddingVertical: convertRemToPixel(0.25 / 4 + 0.25 / 8),
|
||||
paddingHorizontal: convertRemToPixel(0.375),
|
||||
border: "0.5px solid #e5e5e5",
|
||||
borderRadius: convertRemToPixel(0.25),
|
||||
backgroundColor: "#e8e8e8",
|
||||
color: "#f97316",
|
||||
fontSize: convertRemToPixel(0.7),
|
||||
},
|
||||
};
|
||||
|
||||
const EDITOR_PDF_DOCUMENT_STYLESHEET = StyleSheet.create({
|
||||
...EDITOR_PDF_FONT_FAMILY_STYLES,
|
||||
...EDITOR_PDF_TYPOGRAPHY_STYLES,
|
||||
...EDITOR_PDF_LIST_STYLES,
|
||||
...EDITOR_PDF_CODE_STYLES,
|
||||
// quote block
|
||||
blockquote: {
|
||||
borderLeft: "3px solid gray",
|
||||
paddingLeft: convertRemToPixel(1),
|
||||
marginTop: convertRemToPixel(0.625),
|
||||
marginBottom: 0,
|
||||
marginHorizontal: 0,
|
||||
},
|
||||
img: {
|
||||
marginVertical: 0,
|
||||
borderRadius: convertRemToPixel(0.375),
|
||||
},
|
||||
// divider
|
||||
"div[data-type='horizontalRule']": {
|
||||
marginVertical: convertRemToPixel(1),
|
||||
height: 1,
|
||||
width: "100%",
|
||||
backgroundColor: "gray",
|
||||
},
|
||||
// mention block
|
||||
"[data-node-type='mention-block']": {
|
||||
margin: 0,
|
||||
color: "#3f76ff",
|
||||
backgroundColor: "#3f76ff33",
|
||||
paddingHorizontal: convertRemToPixel(0.375),
|
||||
},
|
||||
// table
|
||||
table: {
|
||||
marginTop: convertRemToPixel(0.5),
|
||||
marginBottom: convertRemToPixel(1),
|
||||
marginHorizontal: 0,
|
||||
},
|
||||
"table td": {
|
||||
padding: convertRemToPixel(0.625),
|
||||
border: "1px solid #e5e5e5",
|
||||
},
|
||||
"table p": {
|
||||
fontSize: convertRemToPixel(0.7),
|
||||
},
|
||||
});
|
||||
// constants
|
||||
import { EDITOR_PDF_DOCUMENT_STYLESHEET } from "@/constants/editor";
|
||||
|
||||
Font.register({
|
||||
family: "Inter",
|
||||
|
||||
@@ -15,8 +15,8 @@ import { Tooltip } from "@plane/propel/tooltip";
|
||||
import type { TSticky } from "@plane/types";
|
||||
// constants
|
||||
import { cn } from "@plane/utils";
|
||||
import type { ToolbarMenuItem } from "@plane/editor";
|
||||
import { TOOLBAR_ITEMS } from "@plane/editor";
|
||||
import type { ToolbarMenuItem } from "@/constants/editor";
|
||||
import { TOOLBAR_ITEMS } from "@/constants/editor";
|
||||
// helpers
|
||||
import { ColorPalette } from "./color-palette";
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import { CustomSearchSelect, CustomSelect } from "@plane/ui";
|
||||
// import { WorkItemFiltersRow } from "@/components/work-item-filters/filters-row";
|
||||
import { useProject } from "@/hooks/store/use-project";
|
||||
import { useUser, useUserPermissions } from "@/hooks/store/user";
|
||||
import { ProjectExportService } from "@plane/services";
|
||||
import { ProjectExportService } from "@/services/project/project-export.service";
|
||||
// local imports
|
||||
import { SettingsBoxedControlItem } from "../settings/boxed-control-item";
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import { useProject } from "@/hooks/store/use-project";
|
||||
import { useUser } from "@/hooks/store/user";
|
||||
import { useAppRouter } from "@/hooks/use-app-router";
|
||||
// services
|
||||
import { ProjectExportService } from "@plane/services";
|
||||
import { ProjectExportService } from "@/services/project";
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
handleClose: () => void;
|
||||
|
||||
@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
|
||||
import { useParams, useSearchParams } from "next/navigation";
|
||||
import { mutate } from "swr";
|
||||
// constants
|
||||
import { EXPORT_SERVICES_LIST } from "@plane/constants";
|
||||
import { EXPORT_SERVICES_LIST } from "@/constants/fetch-keys";
|
||||
// local imports
|
||||
import { ExportForm } from "./export-form";
|
||||
import { PrevExports } from "./prev-exports";
|
||||
|
||||
@@ -17,9 +17,9 @@ import { Table } from "@plane/ui";
|
||||
// components
|
||||
import { ImportExportSettingsLoader } from "@/components/ui/loader/settings/import-and-export";
|
||||
// constants
|
||||
import { EXPORT_SERVICES_LIST } from "@plane/constants";
|
||||
import { EXPORT_SERVICES_LIST } from "@/constants/fetch-keys";
|
||||
// services
|
||||
import { IntegrationService } from "@plane/services";
|
||||
import { IntegrationService } from "@/services/integrations";
|
||||
// local imports
|
||||
import { useExportColumns } from "./column";
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ import useReloadConfirmations from "@/hooks/use-reload-confirmation";
|
||||
import { DeDupeIssuePopoverRoot } from "@/plane-web/components/de-dupe/duplicate-popover";
|
||||
import { useDebouncedDuplicateIssues } from "@/plane-web/hooks/use-debounced-duplicate-issues";
|
||||
// services
|
||||
import { IntakeWorkItemVersionService } from "@plane/services";
|
||||
import { IntakeWorkItemVersionService } from "@/services/inbox";
|
||||
// stores
|
||||
import type { IInboxIssueStore } from "@/store/inbox/inbox-issue.store";
|
||||
// local imports
|
||||
|
||||
@@ -25,7 +25,7 @@ import { SimpleEmptyState } from "@/components/empty-state/simple-empty-state-ro
|
||||
import { useProject } from "@/hooks/store/use-project";
|
||||
import useDebounce from "@/hooks/use-debounce";
|
||||
// services
|
||||
import { ProjectService } from "@plane/services";
|
||||
import { ProjectService } from "@/services/project";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
|
||||
@@ -13,7 +13,7 @@ import type { IWorkspaceIntegration } from "@plane/types";
|
||||
import { CustomSearchSelect } from "@plane/ui";
|
||||
// helpers
|
||||
import { truncateText } from "@plane/utils";
|
||||
import { ProjectService } from "@plane/services";
|
||||
import { ProjectService } from "@/services/project";
|
||||
// types
|
||||
|
||||
type Props = {
|
||||
|
||||
@@ -20,14 +20,14 @@ import { Loader } from "@plane/ui";
|
||||
import GithubLogo from "@/app/assets/services/github.png?url";
|
||||
import SlackLogo from "@/app/assets/services/slack.png?url";
|
||||
// constants
|
||||
import { WORKSPACE_INTEGRATIONS } from "@plane/constants";
|
||||
import { WORKSPACE_INTEGRATIONS } from "@/constants/fetch-keys";
|
||||
// hooks
|
||||
import { useInstance } from "@/hooks/store/use-instance";
|
||||
import { useUserPermissions } from "@/hooks/store/user";
|
||||
import useIntegrationPopup from "@/hooks/use-integration-popup";
|
||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
// services
|
||||
import { IntegrationService } from "@plane/services";
|
||||
import { IntegrationService } from "@/services/integrations";
|
||||
|
||||
type Props = {
|
||||
integration: IAppIntegration;
|
||||
|
||||
@@ -13,12 +13,12 @@ import type { IWorkspaceIntegration, ISlackIntegration } from "@plane/types";
|
||||
// ui
|
||||
import { Loader } from "@plane/ui";
|
||||
// fetch-keys
|
||||
import { SLACK_CHANNEL_INFO } from "@plane/constants";
|
||||
import { SLACK_CHANNEL_INFO } from "@/constants/fetch-keys";
|
||||
// hooks
|
||||
import { useInstance } from "@/hooks/store/use-instance";
|
||||
import useIntegrationPopup from "@/hooks/use-integration-popup";
|
||||
// services
|
||||
import { AppInstallationService } from "@plane/services";
|
||||
import { AppInstallationService } from "@/services/app_installation.service";
|
||||
|
||||
type Props = {
|
||||
integration: IWorkspaceIntegration;
|
||||
|
||||
@@ -16,7 +16,7 @@ import { EIssueLayoutTypes, EIssuesStoreType } from "@plane/types";
|
||||
// hooks
|
||||
import { useIssues } from "@/hooks/store/use-issues";
|
||||
// plane web imports
|
||||
import type { TProject } from "@plane/types";
|
||||
import type { TProject } from "@/plane-web/types";
|
||||
// local imports
|
||||
import { WorkItemsModal } from "../analytics/work-items/modal";
|
||||
import { WorkItemFiltersToggle } from "../work-item-filters/filters-toggle";
|
||||
|
||||
@@ -18,7 +18,7 @@ import { useIssueDetail } from "@/hooks/store/use-issue-detail";
|
||||
// Plane-web
|
||||
import { CreateUpdateEpicModal } from "@/plane-web/components/epics/epic-modal";
|
||||
import { useTimeLineRelationOptions } from "@/plane-web/components/relations";
|
||||
import type { TIssueRelationTypes } from "@plane/types";
|
||||
import type { TIssueRelationTypes } from "@/plane-web/types";
|
||||
// helper
|
||||
import { DeleteIssueModal } from "../../delete-issue-modal";
|
||||
import { RelationIssueList } from "../../relations/issue-list";
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import { CustomMenu } from "@plane/ui";
|
||||
import { useIssueDetail } from "@/hooks/store/use-issue-detail";
|
||||
// Plane-web
|
||||
import { useTimeLineRelationOptions } from "@/plane-web/components/relations";
|
||||
import type { TIssueRelationTypes } from "@plane/types";
|
||||
import type { TIssueRelationTypes } from "@/plane-web/types";
|
||||
|
||||
type Props = {
|
||||
issueId: string;
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
|
||||
import { useIssueDetail } from "@/hooks/store/use-issue-detail";
|
||||
// Plane-web
|
||||
import { getRelationActivityContent, useTimeLineRelationOptions } from "@/plane-web/components/relations";
|
||||
import type { TIssueRelationTypes } from "@plane/types";
|
||||
import type { TIssueRelationTypes } from "@/plane-web/types";
|
||||
//
|
||||
import { IssueActivityBlockComponent } from "./";
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import { DeDupeIssuePopoverRoot } from "@/plane-web/components/de-dupe/duplicate
|
||||
import { IssueTypeSwitcher } from "@/plane-web/components/issues/issue-details/issue-type-switcher";
|
||||
import { useDebouncedDuplicateIssues } from "@/plane-web/hooks/use-debounced-duplicate-issues";
|
||||
// services
|
||||
import { WorkItemVersionService } from "@plane/services";
|
||||
import { WorkItemVersionService } from "@/services/issue";
|
||||
// local imports
|
||||
import { IssueDetailWidgets } from "../issue-detail-widgets";
|
||||
import { NameDescriptionUpdateStatus } from "../issue-update-status";
|
||||
|
||||
@@ -23,7 +23,7 @@ import { useProject } from "@/hooks/store/use-project";
|
||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
// Plane web imports
|
||||
import { useTimeLineRelationOptions } from "@/plane-web/components/relations";
|
||||
import type { TIssueRelationTypes } from "@plane/types";
|
||||
import type { TIssueRelationTypes } from "@/plane-web/types";
|
||||
import type { TRelationObject } from "../issue-detail-widgets/relations";
|
||||
|
||||
type TIssueRelationSelect = {
|
||||
|
||||
@@ -24,7 +24,7 @@ import { EIssuesStoreType, EIssueLayoutTypes } from "@plane/types";
|
||||
import { Spinner } from "@plane/ui";
|
||||
import { renderFormattedPayloadDate, cn } from "@plane/utils";
|
||||
// constants
|
||||
import { MONTHS_LIST } from "@plane/constants";
|
||||
import { MONTHS_LIST } from "@/constants/calendar";
|
||||
// helpers
|
||||
// hooks
|
||||
import { useIssues } from "@/hooks/store/use-issues";
|
||||
|
||||
@@ -17,7 +17,7 @@ import type { TGroupedIssues, TIssue, TIssueMap, TPaginationData, ICalendarDate
|
||||
import { cn, renderFormattedPayloadDate } from "@plane/utils";
|
||||
import { highlightIssueOnDrop } from "@/components/issues/issue-layouts/utils";
|
||||
// helpers
|
||||
import { MONTHS_LIST } from "@plane/constants";
|
||||
import { MONTHS_LIST } from "@/constants/calendar";
|
||||
// helpers
|
||||
// types
|
||||
import type { ICycleIssuesFilter } from "@/store/issue/cycle";
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import { ChevronLeftIcon, ChevronRightIcon } from "@plane/propel/icons";
|
||||
// icons
|
||||
// constants
|
||||
import { getDate } from "@plane/utils";
|
||||
import { MONTHS_LIST } from "@plane/constants";
|
||||
import { MONTHS_LIST } from "@/constants/calendar";
|
||||
import { useCalendarView } from "@/hooks/store/use-calendar-view";
|
||||
import type { ICycleIssuesFilter } from "@/store/issue/cycle";
|
||||
import type { IModuleIssuesFilter } from "@/store/issue/module";
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ import type { TCalendarLayouts, TSupportedFilterForUpdate } from "@plane/types";
|
||||
import { ToggleSwitch } from "@plane/ui";
|
||||
// types
|
||||
// constants
|
||||
import { CALENDAR_LAYOUTS } from "@plane/constants";
|
||||
import { CALENDAR_LAYOUTS } from "@/constants/calendar";
|
||||
import { useCalendarView } from "@/hooks/store/use-calendar-view";
|
||||
import useSize from "@/hooks/use-window-size";
|
||||
import type { ICycleIssuesFilter } from "@/store/issue/cycle";
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { observer } from "mobx-react";
|
||||
import { EStartOfTheWeek } from "@plane/types";
|
||||
import { getOrderedDays } from "@plane/utils";
|
||||
import { DAYS_LIST } from "@plane/constants";
|
||||
import { DAYS_LIST } from "@/constants/calendar";
|
||||
// helpers
|
||||
// hooks
|
||||
import { useUserProfile } from "@/hooks/store/user";
|
||||
|
||||
@@ -31,7 +31,7 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
// plane web services
|
||||
import { WorkspaceService } from "@/services/workspace.service";
|
||||
// services
|
||||
import { AIService } from "@plane/services";
|
||||
import { AIService } from "@/services/ai.service";
|
||||
const workspaceService = new WorkspaceService();
|
||||
const aiService = new AIService();
|
||||
|
||||
@@ -120,7 +120,7 @@ export const IssueDescriptionEditor = observer(function IssueDescriptionEditor(p
|
||||
setIAmFeelingLucky(true);
|
||||
|
||||
aiService
|
||||
.prompt(workspaceSlug.toString(), {
|
||||
.createGptTask(workspaceSlug.toString(), {
|
||||
prompt: issueName,
|
||||
task: "Generate a proper description for this work item.",
|
||||
})
|
||||
|
||||
@@ -9,7 +9,9 @@ import { createContext } from "react";
|
||||
import type { UseFormReset, UseFormWatch } from "react-hook-form";
|
||||
// plane imports
|
||||
import type { EditorRefApi } from "@plane/editor";
|
||||
import type { ISearchIssueResponse, TIssue, TIssuePropertyValues, TIssuePropertyValueErrors } from "@plane/types";
|
||||
import type { ISearchIssueResponse, TIssue } from "@plane/types";
|
||||
// plane web imports
|
||||
import type { TIssuePropertyValues, TIssuePropertyValueErrors } from "@/plane-web/types/issue-types";
|
||||
import type { TIssueFields } from "@/plane-web/components/issues/issue-modal";
|
||||
|
||||
export type TPropertyValuesValidationProps = {
|
||||
|
||||
@@ -27,7 +27,7 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
// plane web components
|
||||
import { IssueIdentifier } from "@/plane-web/components/issues/issue-details/issue-identifier";
|
||||
// services
|
||||
import { ProjectService } from "@plane/services";
|
||||
import { ProjectService } from "@/services/project";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
|
||||
@@ -27,7 +27,7 @@ import { IssueTypeSwitcher } from "@/plane-web/components/issues/issue-details/i
|
||||
// plane web hooks
|
||||
import { useDebouncedDuplicateIssues } from "@/plane-web/hooks/use-debounced-duplicate-issues";
|
||||
// services
|
||||
import { WorkItemVersionService } from "@plane/services";
|
||||
import { WorkItemVersionService } from "@/services/issue";
|
||||
// local components
|
||||
import type { TIssueOperations } from "../issue-detail";
|
||||
import { IssueParentDetail } from "../issue-detail/parent";
|
||||
|
||||
@@ -21,7 +21,7 @@ import useIssuePeekOverviewRedirection from "@/hooks/use-issue-peek-overview-red
|
||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
// plane web imports
|
||||
import { IssueIdentifier } from "@/plane-web/components/issues/issue-details/issue-identifier";
|
||||
import type { TIssueRelationTypes } from "@plane/types";
|
||||
import type { TIssueRelationTypes } from "@/plane-web/types";
|
||||
// local imports
|
||||
import { useRelationOperations } from "../issue-detail-widgets/relations/helper";
|
||||
import { RelationIssueProperty } from "./properties";
|
||||
|
||||
@@ -10,7 +10,7 @@ import { observer } from "mobx-react";
|
||||
import type { TIssue, TIssueServiceType } from "@plane/types";
|
||||
import { EIssueServiceType } from "@plane/types";
|
||||
// Plane-web imports
|
||||
import type { TIssueRelationTypes } from "@plane/types";
|
||||
import type { TIssueRelationTypes } from "@/plane-web/types";
|
||||
// local imports
|
||||
import { RelationIssueListItem } from "./issue-list-item";
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
// helpers
|
||||
import { getSidebarNavigationItemIcon } from "@/plane-web/components/workspace/sidebar/helper";
|
||||
// types
|
||||
import type { TPersonalNavigationItemKey } from "@plane/types";
|
||||
import type { TPersonalNavigationItemKey } from "@/types/navigation-preferences";
|
||||
|
||||
type TCustomizeNavigationDialogProps = {
|
||||
isOpen: boolean;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import type { TPartialProject } from "@plane/types";
|
||||
import type { TPartialProject } from "@/plane-web/types";
|
||||
// plane propel imports
|
||||
import { Logo } from "@plane/propel/emoji-icon-picker";
|
||||
import { ChevronDownIcon } from "@plane/propel/icons";
|
||||
|
||||
@@ -22,7 +22,7 @@ import { UserImageUploadModal } from "@/components/core/modals/user-image-upload
|
||||
// hooks
|
||||
import { useUser, useUserProfile } from "@/hooks/store/user";
|
||||
// services
|
||||
import { AuthService } from "@plane/services";
|
||||
import { AuthService } from "@/services/auth.service";
|
||||
|
||||
type TProfileSetupFormValues = {
|
||||
first_name: string;
|
||||
|
||||
@@ -21,7 +21,7 @@ import { UserImageUploadModal } from "@/components/core/modals/user-image-upload
|
||||
import { useInstance } from "@/hooks/store/use-instance";
|
||||
import { useUser, useUserProfile } from "@/hooks/store/user";
|
||||
// services
|
||||
import { AuthService } from "@plane/services";
|
||||
import { AuthService } from "@/services/auth.service";
|
||||
// local components
|
||||
import { CommonOnboardingHeader } from "../common";
|
||||
import { MarketingConsent } from "./consent";
|
||||
|
||||
@@ -12,8 +12,8 @@ import { Tooltip } from "@plane/propel/tooltip";
|
||||
import { CustomMenu } from "@plane/ui";
|
||||
import { cn } from "@plane/utils";
|
||||
// constants
|
||||
import type { ToolbarMenuItem } from "@plane/editor";
|
||||
import { TOOLBAR_ITEMS, TYPOGRAPHY_ITEMS } from "@plane/editor";
|
||||
import type { ToolbarMenuItem } from "@/constants/editor";
|
||||
import { TOOLBAR_ITEMS, TYPOGRAPHY_ITEMS } from "@/constants/editor";
|
||||
// local imports
|
||||
import { ColorDropdown } from "./color-dropdown";
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import React from "react";
|
||||
// components
|
||||
import { Logo } from "@plane/propel/emoji-icon-picker";
|
||||
// plane imports
|
||||
import type { TPartialProject } from "@plane/types";
|
||||
import type { TPartialProject } from "@/plane-web/types";
|
||||
// local imports
|
||||
import { PowerKMenuBuilder } from "./builder";
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useEffect } from "react";
|
||||
import { useParams } from "next/navigation";
|
||||
import useSWR from "swr";
|
||||
// services
|
||||
import { USER_PROFILE_ACTIVITY } from "@plane/constants";
|
||||
import { USER_PROFILE_ACTIVITY } from "@/constants/fetch-keys";
|
||||
import { UserService } from "@/services/user.service";
|
||||
// components
|
||||
import { ActivityList } from "./activity-list";
|
||||
|
||||
@@ -16,7 +16,7 @@ import { calculateTimeAgo, getFileURL } from "@plane/utils";
|
||||
// components
|
||||
import { ActivityMessage, IssueLink } from "@/components/core/activity";
|
||||
// constants
|
||||
import { USER_PROFILE_ACTIVITY } from "@plane/constants";
|
||||
import { USER_PROFILE_ACTIVITY } from "@/constants/fetch-keys";
|
||||
// helpers
|
||||
// hooks
|
||||
import { useUser } from "@/hooks/store/user";
|
||||
|
||||
@@ -14,7 +14,7 @@ import useKeypress from "@/hooks/use-keypress";
|
||||
// plane web components
|
||||
import { CreateProjectForm } from "@/plane-web/components/projects/create/root";
|
||||
// plane web types
|
||||
import type { TProject } from "@plane/types";
|
||||
import type { TProject } from "@/plane-web/types/projects";
|
||||
// services
|
||||
import { FileService } from "@/services/file.service";
|
||||
const fileService = new FileService();
|
||||
|
||||
@@ -18,7 +18,7 @@ import { cn, projectIdentifierSanitizer, getTabIndex } from "@plane/utils";
|
||||
// plane utils
|
||||
// helpers
|
||||
// plane-web types
|
||||
import type { TProject } from "@plane/types";
|
||||
import type { TProject } from "@/plane-web/types/projects";
|
||||
|
||||
type Props = {
|
||||
setValue: UseFormSetValue<TProject>;
|
||||
|
||||
@@ -28,7 +28,7 @@ import { handleCoverImageChange } from "@/helpers/cover-image.helper";
|
||||
import { useProject } from "@/hooks/store/use-project";
|
||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
// services
|
||||
import { ProjectService } from "@plane/services";
|
||||
import { ProjectService } from "@/services/project";
|
||||
// local imports
|
||||
import { ProjectNetworkIcon } from "./project-network-icon";
|
||||
|
||||
@@ -105,8 +105,9 @@ export function ProjectDetailsForm(props: IProjectDetailsForm) {
|
||||
|
||||
const nameError = errorData.name?.includes("PROJECT_NAME_ALREADY_EXIST");
|
||||
const identifierError = errorData?.identifier?.includes("PROJECT_IDENTIFIER_ALREADY_EXIST");
|
||||
const nameSpecialCharError = errorData?.name?.includes("PROJECT_NAME_CANNOT_CONTAIN_SPECIAL_CHARACTERS");
|
||||
|
||||
if (nameError || identifierError) {
|
||||
if (nameError || identifierError || nameSpecialCharError) {
|
||||
if (nameError) {
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
@@ -122,6 +123,14 @@ export function ProjectDetailsForm(props: IProjectDetailsForm) {
|
||||
message: t("project_identifier_already_taken"),
|
||||
});
|
||||
}
|
||||
|
||||
if (nameSpecialCharError) {
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: t("toast.error"),
|
||||
message: t("project_name_cannot_contain_special_characters"),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
|
||||
@@ -15,9 +15,9 @@ import SlackLogo from "@/app/assets/services/slack.png?url";
|
||||
import { SelectChannel } from "@/components/integration/slack/select-channel";
|
||||
import { SelectRepository } from "@/components/integration/github/select-repository";
|
||||
// constants
|
||||
import { PROJECT_GITHUB_REPOSITORY } from "@plane/constants";
|
||||
import { PROJECT_GITHUB_REPOSITORY } from "@/constants/fetch-keys";
|
||||
// services
|
||||
import { ProjectService } from "@plane/services";
|
||||
import { ProjectService } from "@/services/project";
|
||||
|
||||
type Props = {
|
||||
integration: IWorkspaceIntegration;
|
||||
|
||||
@@ -16,7 +16,7 @@ import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
||||
import type { IProject, IUserLite, IWorkspace } from "@plane/types";
|
||||
import { Loader, ToggleSwitch } from "@plane/ui";
|
||||
// constants
|
||||
import { PROJECT_DETAILS } from "@plane/constants";
|
||||
import { PROJECT_DETAILS } from "@/constants/fetch-keys";
|
||||
// hooks
|
||||
import { useProject } from "@/hooks/store/use-project";
|
||||
import { useUserPermissions } from "@/hooks/store/user";
|
||||
|
||||
@@ -18,7 +18,7 @@ import { ApiTokenListItem } from "@/components/api-token/token-list-item";
|
||||
import { ProfileSettingsHeading } from "@/components/settings/profile/heading";
|
||||
import { APITokenSettingsLoader } from "@/components/ui/loader/settings/api-token";
|
||||
// constants
|
||||
import { API_TOKENS_LIST } from "@plane/constants";
|
||||
import { API_TOKENS_LIST } from "@/constants/fetch-keys";
|
||||
|
||||
const apiTokenService = new APITokenService();
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import { authErrorHandler, EAuthenticationErrorCodes, passwordErrors } from "@/h
|
||||
// hooks
|
||||
import { useUser } from "@/hooks/store/user";
|
||||
// services
|
||||
import { AuthService } from "@plane/services";
|
||||
import { AuthService } from "@/services/auth.service";
|
||||
|
||||
export interface FormValues {
|
||||
old_password: string;
|
||||
|
||||
@@ -10,8 +10,8 @@ import { ArrowDown, ArrowUp } from "lucide-react";
|
||||
import { Button } from "@plane/propel/button";
|
||||
import { cn } from "@plane/utils";
|
||||
// constants
|
||||
import type { TPlanePlans } from "@/components/workspace/billing/comparison/plans";
|
||||
import { ComingSoonBadge, PLANE_PLANS, PLANS_LIST } from "@/components/workspace/billing/comparison/plans";
|
||||
import type { TPlanePlans } from "@/constants/plans";
|
||||
import { ComingSoonBadge, PLANE_PLANS, PLANS_LIST } from "@/constants/plans";
|
||||
// local imports
|
||||
import { PlanFeatureDetail } from "./feature-detail";
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user