mirror of
https://github.com/makeplane/plane.git
synced 2026-08-29 10:08:51 +02:00
chore: remove posthog integration and analytics scaffold (#9634)
* chore: remove posthog integration and analytics scaffold
Removes the PostHog integration end to end, plus the inert autocapture
scaffold left behind by an earlier partial removal (d61b157929,
"chore: remove posthog events (#8465)").
Backend:
- delete bgtasks/event_tracking_task.py and utils/analytics_events.py
- drop all 6 track_event.delay call sites
- drop POSTHOG_API_KEY / POSTHOG_HOST settings
- stop returning posthog_api_key / posthog_host from GET /api/instances/
- drop the posthog==3.5.0 dependency
Frontend:
- delete packages/constants/src/event-tracker (all 40 exports were unused)
- remove 42 data-ph-element attributes across 36 files
- remove the dead shouldTrackEvents and trackerElements prop chains
- remove the Microsoft Clarity session-recording tag
Note: GET /api/instances/ no longer returns posthog_api_key/posthog_host.
Nothing in this repo read them and neither do plane-ee or plane-commercial,
but the endpoint is AllowAny and cached for 2h.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HD7dTidmtWWRRiFv3nmW3s
* chore: apply oxfmt formatting
Collapse JSX elements and import statements that were left multi-line
after the tracker props and specifiers were removed. Whitespace only.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HD7dTidmtWWRRiFv3nmW3s
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
committed by
GitHub
parent
e056bbf9eb
commit
e093a22094
@@ -46,9 +46,7 @@ from plane.app.permissions import ROLE, allow_permission
|
||||
from plane.utils.constants import RESTRICTED_WORKSPACE_SLUGS
|
||||
from plane.license.utils.instance_value import get_configuration_value
|
||||
from plane.bgtasks.workspace_seed_task import workspace_seed
|
||||
from plane.bgtasks.event_tracking_task import track_event
|
||||
from plane.utils.url import contains_url
|
||||
from plane.utils.analytics_events import WORKSPACE_CREATED, WORKSPACE_DELETED
|
||||
from plane.utils.csv_utils import sanitize_csv_row
|
||||
|
||||
|
||||
@@ -138,20 +136,6 @@ class WorkSpaceViewSet(BaseViewSet):
|
||||
|
||||
workspace_seed.delay(serializer.data["id"])
|
||||
|
||||
track_event.delay(
|
||||
user_id=request.user.id,
|
||||
event_name=WORKSPACE_CREATED,
|
||||
slug=data["slug"],
|
||||
event_properties={
|
||||
"user_id": request.user.id,
|
||||
"workspace_id": data["id"],
|
||||
"workspace_slug": data["slug"],
|
||||
"role": "owner",
|
||||
"workspace_name": data["name"],
|
||||
"created_at": data["created_at"],
|
||||
},
|
||||
)
|
||||
|
||||
return Response(data, status=status.HTTP_201_CREATED)
|
||||
return Response(
|
||||
[serializer.errors[error][0] for error in serializer.errors],
|
||||
@@ -185,19 +169,6 @@ class WorkSpaceViewSet(BaseViewSet):
|
||||
# Get the workspace
|
||||
workspace = self.get_object()
|
||||
self.remove_last_workspace_ids_from_user_settings(workspace.id)
|
||||
track_event.delay(
|
||||
user_id=request.user.id,
|
||||
event_name=WORKSPACE_DELETED,
|
||||
slug=workspace.slug,
|
||||
event_properties={
|
||||
"user_id": request.user.id,
|
||||
"workspace_id": workspace.id,
|
||||
"workspace_slug": workspace.slug,
|
||||
"role": "owner",
|
||||
"workspace_name": workspace.name,
|
||||
"deleted_at": str(timezone.now().isoformat()),
|
||||
},
|
||||
)
|
||||
return super().destroy(request, *args, **kwargs)
|
||||
|
||||
|
||||
|
||||
@@ -26,12 +26,10 @@ from plane.app.serializers import (
|
||||
WorkSpaceMemberSerializer,
|
||||
)
|
||||
from plane.app.views.base import BaseAPIView
|
||||
from plane.bgtasks.event_tracking_task import track_event
|
||||
from plane.bgtasks.workspace_invitation_task import workspace_invitation
|
||||
from plane.db.models import User, Workspace, WorkspaceMember, WorkspaceMemberInvite
|
||||
from plane.utils.cache import invalidate_cache, invalidate_cache_directly
|
||||
from plane.utils.host import base_host
|
||||
from plane.utils.analytics_events import USER_JOINED_WORKSPACE, USER_INVITED_TO_WORKSPACE
|
||||
from .. import BaseViewSet
|
||||
|
||||
|
||||
@@ -126,19 +124,6 @@ class WorkspaceInvitationsViewset(BaseViewSet):
|
||||
current_site,
|
||||
request.user.email,
|
||||
)
|
||||
track_event.delay(
|
||||
user_id=request.user.id,
|
||||
event_name=USER_INVITED_TO_WORKSPACE,
|
||||
slug=slug,
|
||||
event_properties={
|
||||
"user_id": request.user.id,
|
||||
"workspace_id": workspace.id,
|
||||
"workspace_slug": workspace.slug,
|
||||
"invitee_role": invitation.role,
|
||||
"invited_at": str(timezone.now()),
|
||||
"invitee_email": invitation.email,
|
||||
},
|
||||
)
|
||||
|
||||
return Response({"message": "Emails sent successfully"}, status=status.HTTP_200_OK)
|
||||
|
||||
@@ -219,18 +204,6 @@ class WorkspaceJoinEndpoint(BaseAPIView):
|
||||
# Set the user last_workspace_id to the accepted workspace
|
||||
user.last_workspace_id = workspace_invite.workspace.id
|
||||
user.save()
|
||||
track_event.delay(
|
||||
user_id=user.id,
|
||||
event_name=USER_JOINED_WORKSPACE,
|
||||
slug=slug,
|
||||
event_properties={
|
||||
"user_id": user.id,
|
||||
"workspace_id": workspace_invite.workspace.id,
|
||||
"workspace_slug": workspace_invite.workspace.slug,
|
||||
"role": workspace_invite.role,
|
||||
"joined_at": str(timezone.now()),
|
||||
},
|
||||
)
|
||||
|
||||
# Delete the invitation
|
||||
workspace_invite.delete()
|
||||
@@ -290,20 +263,6 @@ class UserWorkspaceInvitationsViewSet(BaseViewSet):
|
||||
is_active=True, role=invitation.role
|
||||
)
|
||||
|
||||
# Track event
|
||||
track_event.delay(
|
||||
user_id=request.user.id,
|
||||
event_name=USER_JOINED_WORKSPACE,
|
||||
slug=invitation.workspace.slug,
|
||||
event_properties={
|
||||
"user_id": request.user.id,
|
||||
"workspace_id": invitation.workspace.id,
|
||||
"workspace_slug": invitation.workspace.slug,
|
||||
"role": invitation.role,
|
||||
"joined_at": str(timezone.now()),
|
||||
},
|
||||
)
|
||||
|
||||
# Bulk create the user for all the workspaces
|
||||
WorkspaceMember.objects.bulk_create(
|
||||
[
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
# See the LICENSE file for details.
|
||||
|
||||
# Django imports
|
||||
from django.utils import timezone
|
||||
|
||||
# Module imports
|
||||
from plane.db.models import (
|
||||
ProjectMember,
|
||||
@@ -13,8 +10,6 @@ from plane.db.models import (
|
||||
WorkspaceMemberInvite,
|
||||
)
|
||||
from plane.utils.cache import invalidate_cache_directly
|
||||
from plane.bgtasks.event_tracking_task import track_event
|
||||
from plane.utils.analytics_events import USER_JOINED_WORKSPACE
|
||||
|
||||
|
||||
def process_workspace_project_invitations(user):
|
||||
@@ -42,18 +37,6 @@ def process_workspace_project_invitations(user):
|
||||
user=False,
|
||||
multiple=True,
|
||||
)
|
||||
track_event.delay(
|
||||
user_id=user.id,
|
||||
event_name=USER_JOINED_WORKSPACE,
|
||||
slug=workspace_member_invite.workspace.slug,
|
||||
event_properties={
|
||||
"user_id": user.id,
|
||||
"workspace_id": workspace_member_invite.workspace.id,
|
||||
"workspace_slug": workspace_member_invite.workspace.slug,
|
||||
"role": workspace_member_invite.role,
|
||||
"joined_at": str(timezone.now().isoformat()),
|
||||
},
|
||||
)
|
||||
|
||||
# Check if user has any project invites
|
||||
project_member_invites = ProjectMemberInvite.objects.filter(email=user.email, accepted=True)
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
# Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
# See the LICENSE file for details.
|
||||
|
||||
import logging
|
||||
import os
|
||||
import uuid
|
||||
from typing import Dict, Any
|
||||
|
||||
# third party imports
|
||||
from celery import shared_task
|
||||
from posthog import Posthog
|
||||
|
||||
# module imports
|
||||
from plane.license.utils.instance_value import get_configuration_value
|
||||
from plane.utils.exception_logger import log_exception
|
||||
from plane.db.models import Workspace
|
||||
from plane.utils.analytics_events import USER_INVITED_TO_WORKSPACE, WORKSPACE_DELETED
|
||||
|
||||
|
||||
logger = logging.getLogger("plane.worker")
|
||||
|
||||
|
||||
def posthogConfiguration():
|
||||
POSTHOG_API_KEY, POSTHOG_HOST = get_configuration_value(
|
||||
[
|
||||
{
|
||||
"key": "POSTHOG_API_KEY",
|
||||
"default": os.environ.get("POSTHOG_API_KEY", None),
|
||||
},
|
||||
{
|
||||
"key": "POSTHOG_HOST",
|
||||
"default": os.environ.get("POSTHOG_HOST", None),
|
||||
},
|
||||
]
|
||||
)
|
||||
if POSTHOG_API_KEY and POSTHOG_HOST:
|
||||
return POSTHOG_API_KEY, POSTHOG_HOST
|
||||
else:
|
||||
return None, None
|
||||
|
||||
|
||||
def preprocess_data_properties(
|
||||
user_id: uuid.UUID, event_name: str, slug: str, data_properties: Dict[str, Any]
|
||||
) -> Dict[str, Any]:
|
||||
if event_name == USER_INVITED_TO_WORKSPACE or event_name == WORKSPACE_DELETED:
|
||||
try:
|
||||
# Check if the current user is the workspace owner
|
||||
workspace = Workspace.objects.get(slug=slug)
|
||||
if str(workspace.owner_id) == str(user_id):
|
||||
data_properties["role"] = "owner"
|
||||
else:
|
||||
data_properties["role"] = "admin"
|
||||
except Workspace.DoesNotExist:
|
||||
logger.warning(f"Workspace {slug} does not exist while sending event {event_name} for user {user_id}")
|
||||
data_properties["role"] = "unknown"
|
||||
|
||||
return data_properties
|
||||
|
||||
|
||||
@shared_task
|
||||
def track_event(user_id: uuid.UUID, event_name: str, slug: str, event_properties: Dict[str, Any]):
|
||||
POSTHOG_API_KEY, POSTHOG_HOST = posthogConfiguration()
|
||||
|
||||
if not (POSTHOG_API_KEY and POSTHOG_HOST):
|
||||
logger.warning("Event tracking is not configured")
|
||||
return
|
||||
|
||||
try:
|
||||
# preprocess the data properties for massaging the payload
|
||||
# in the correct format for posthog
|
||||
data_properties = preprocess_data_properties(user_id, event_name, slug, event_properties)
|
||||
groups = {
|
||||
"workspace": slug,
|
||||
}
|
||||
# track the event using posthog
|
||||
posthog = Posthog(POSTHOG_API_KEY, host=POSTHOG_HOST)
|
||||
posthog.capture(distinct_id=str(user_id), event=event_name, properties=data_properties, groups=groups)
|
||||
except Exception as e:
|
||||
log_exception(e)
|
||||
return False
|
||||
@@ -59,8 +59,6 @@ class InstanceEndpoint(BaseAPIView):
|
||||
ENABLE_MAGIC_LINK_LOGIN,
|
||||
ENABLE_EMAIL_PASSWORD,
|
||||
SLACK_CLIENT_ID,
|
||||
POSTHOG_API_KEY,
|
||||
POSTHOG_HOST,
|
||||
UNSPLASH_ACCESS_KEY,
|
||||
LLM_API_KEY,
|
||||
) = get_configuration_value(
|
||||
@@ -106,14 +104,6 @@ class InstanceEndpoint(BaseAPIView):
|
||||
"key": "SLACK_CLIENT_ID",
|
||||
"default": os.environ.get("SLACK_CLIENT_ID", None),
|
||||
},
|
||||
{
|
||||
"key": "POSTHOG_API_KEY",
|
||||
"default": os.environ.get("POSTHOG_API_KEY", None),
|
||||
},
|
||||
{
|
||||
"key": "POSTHOG_HOST",
|
||||
"default": os.environ.get("POSTHOG_HOST", None),
|
||||
},
|
||||
{
|
||||
"key": "UNSPLASH_ACCESS_KEY",
|
||||
"default": os.environ.get("UNSPLASH_ACCESS_KEY", ""),
|
||||
@@ -142,10 +132,6 @@ class InstanceEndpoint(BaseAPIView):
|
||||
# Slack client
|
||||
data["slack_client_id"] = SLACK_CLIENT_ID
|
||||
|
||||
# Posthog
|
||||
data["posthog_api_key"] = POSTHOG_API_KEY
|
||||
data["posthog_host"] = POSTHOG_HOST
|
||||
|
||||
# Unsplash
|
||||
data["has_unsplash_configured"] = bool(UNSPLASH_ACCESS_KEY)
|
||||
|
||||
|
||||
@@ -361,10 +361,6 @@ GITHUB_ACCESS_TOKEN = os.environ.get("GITHUB_ACCESS_TOKEN", False)
|
||||
ANALYTICS_SECRET_KEY = os.environ.get("ANALYTICS_SECRET_KEY", False)
|
||||
ANALYTICS_BASE_API = os.environ.get("ANALYTICS_BASE_API", False)
|
||||
|
||||
# Posthog settings
|
||||
POSTHOG_API_KEY = os.environ.get("POSTHOG_API_KEY", False)
|
||||
POSTHOG_HOST = os.environ.get("POSTHOG_HOST", False)
|
||||
|
||||
# Skip environment variable configuration
|
||||
SKIP_ENV_VAR = os.environ.get("SKIP_ENV_VAR", "1") == "1"
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
# Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
# See the LICENSE file for details.
|
||||
|
||||
USER_JOINED_WORKSPACE = "user_joined_workspace"
|
||||
USER_INVITED_TO_WORKSPACE = "user_invited_to_workspace"
|
||||
WORKSPACE_CREATED = "workspace_created"
|
||||
WORKSPACE_DELETED = "workspace_deleted"
|
||||
@@ -46,8 +46,6 @@ openpyxl==3.1.2
|
||||
python-json-logger==4.0.0
|
||||
# html parser
|
||||
beautifulsoup4==4.12.3
|
||||
# analytics
|
||||
posthog==3.5.0
|
||||
# crypto
|
||||
cryptography==50.0.0
|
||||
# html validator
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useCallback, useRef, useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
// plane imports
|
||||
import { EUserPermissions, EUserPermissionsLevel, PROJECT_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { EmptyStateCompact } from "@plane/propel/empty-state";
|
||||
import { PlusIcon, SearchIcon } from "@plane/propel/icons";
|
||||
@@ -117,7 +117,6 @@ export const ExtendedProjectSidebar = observer(function ExtendedProjectSidebar()
|
||||
<Tooltip tooltipHeading={t("create_project")} tooltipContent="">
|
||||
<button
|
||||
type="button"
|
||||
data-ph-element={PROJECT_TRACKER_ELEMENTS.EXTENDED_SIDEBAR_ADD_BUTTON}
|
||||
className="flex-shrink-0 rounded-sm p-0.5 text-tertiary transition-colors hover:bg-layer-1 hover:text-secondary"
|
||||
onClick={() => {
|
||||
setIsProjectModalOpen(true);
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
EUserPermissions,
|
||||
EUserPermissionsLevel,
|
||||
ISSUE_DISPLAY_FILTERS_BY_PAGE,
|
||||
WORK_ITEM_TRACKER_ELEMENTS,
|
||||
} from "@plane/constants";
|
||||
import { usePlatformOS } from "@plane/hooks";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
@@ -246,7 +245,6 @@ export const CycleIssuesHeader = observer(function CycleIssuesHeader() {
|
||||
onClick={() => {
|
||||
toggleCreateIssueModal(true, EIssuesStoreType.CYCLE);
|
||||
}}
|
||||
data-ph-element={WORK_ITEM_TRACKER_ELEMENTS.HEADER_ADD_BUTTON.CYCLE}
|
||||
>
|
||||
{t("issue.add.label")}
|
||||
</Button>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
// ui
|
||||
import { EUserPermissions, EUserPermissionsLevel, CYCLE_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { Button } from "@plane/propel/button";
|
||||
import { CycleIcon } from "@plane/propel/icons";
|
||||
@@ -63,7 +63,6 @@ export const CyclesListHeader = observer(function CyclesListHeader() {
|
||||
<Button
|
||||
variant="primary"
|
||||
size="lg"
|
||||
data-ph-element={CYCLE_TRACKER_ELEMENTS.RIGHT_HEADER_ADD_BUTTON}
|
||||
onClick={() => {
|
||||
toggleCreateCycleModal(true);
|
||||
}}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
// plane imports
|
||||
import { useTheme } from "next-themes";
|
||||
import { EUserPermissionsLevel, CYCLE_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { EUserPermissionsLevel } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { EmptyStateDetailed } from "@plane/propel/empty-state";
|
||||
import type { TCycleFilters } from "@plane/types";
|
||||
@@ -113,7 +113,6 @@ function ProjectCyclesPage({ params }: Route.ComponentProps) {
|
||||
onClick: () => setCreateModal(true),
|
||||
variant: "primary",
|
||||
disabled: !hasMemberLevelPermission,
|
||||
"data-ph-element": CYCLE_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
ISSUE_DISPLAY_FILTERS_BY_PAGE,
|
||||
EUserPermissions,
|
||||
EUserPermissionsLevel,
|
||||
WORK_ITEM_TRACKER_ELEMENTS,
|
||||
} from "@plane/constants";
|
||||
import { Button } from "@plane/propel/button";
|
||||
import { ModuleIcon } from "@plane/propel/icons";
|
||||
@@ -241,7 +240,6 @@ export const ModuleIssuesHeader = observer(function ModuleIssuesHeader() {
|
||||
onClick={() => {
|
||||
toggleCreateIssueModal(true, EIssuesStoreType.MODULE);
|
||||
}}
|
||||
data-ph-element={WORK_ITEM_TRACKER_ELEMENTS.HEADER_ADD_BUTTON.MODULE}
|
||||
>
|
||||
Add work item
|
||||
</Button>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
// plane imports
|
||||
import { EUserPermissions, EUserPermissionsLevel, MODULE_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
// ui
|
||||
import { Button } from "@plane/propel/button";
|
||||
@@ -67,7 +67,6 @@ export const ModulesListHeader = observer(function ModulesListHeader() {
|
||||
{canUserCreateModule ? (
|
||||
<Button
|
||||
variant="primary"
|
||||
data-ph-element={MODULE_TRACKER_ELEMENTS.RIGHT_HEADER_ADD_BUTTON}
|
||||
onClick={() => {
|
||||
toggleCreateModuleModal(true);
|
||||
}}
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
ISSUE_DISPLAY_FILTERS_BY_PAGE,
|
||||
EUserPermissions,
|
||||
EUserPermissionsLevel,
|
||||
WORK_ITEM_TRACKER_ELEMENTS,
|
||||
} from "@plane/constants";
|
||||
import { Button } from "@plane/propel/button";
|
||||
import { LockIcon, ViewsIcon } from "@plane/propel/icons";
|
||||
@@ -203,7 +202,6 @@ export const ProjectViewIssuesHeader = observer(function ProjectViewIssuesHeader
|
||||
onClick={() => {
|
||||
toggleCreateIssueModal(true, EIssuesStoreType.PROJECT_VIEW);
|
||||
}}
|
||||
data-ph-element={WORK_ITEM_TRACKER_ELEMENTS.HEADER_ADD_BUTTON.PROJECT_VIEW}
|
||||
>
|
||||
Add work item
|
||||
</Button>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
// ui
|
||||
import { PROJECT_VIEW_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { Button } from "@plane/propel/button";
|
||||
import { ViewsIcon } from "@plane/propel/icons";
|
||||
import { Breadcrumbs, Header } from "@plane/ui";
|
||||
@@ -48,12 +47,7 @@ export const ProjectViewsHeader = observer(function ProjectViewsHeader() {
|
||||
<Header.RightItem>
|
||||
<ViewListHeader />
|
||||
<div>
|
||||
<Button
|
||||
data-ph-element={PROJECT_VIEW_TRACKER_ELEMENTS.RIGHT_HEADER_ADD_BUTTON}
|
||||
variant="primary"
|
||||
size="lg"
|
||||
onClick={() => toggleCreateViewModal(true)}
|
||||
>
|
||||
<Button variant="primary" size="lg" onClick={() => toggleCreateViewModal(true)}>
|
||||
Add view
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -8,12 +8,7 @@ import { useCallback, useMemo, useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
// plane imports
|
||||
import {
|
||||
EIssueFilterType,
|
||||
ISSUE_DISPLAY_FILTERS_BY_PAGE,
|
||||
GLOBAL_VIEW_TRACKER_ELEMENTS,
|
||||
DEFAULT_GLOBAL_VIEWS_LIST,
|
||||
} from "@plane/constants";
|
||||
import { EIssueFilterType, ISSUE_DISPLAY_FILTERS_BY_PAGE, DEFAULT_GLOBAL_VIEWS_LIST } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { Button } from "@plane/propel/button";
|
||||
import { ViewsIcon } from "@plane/propel/icons";
|
||||
@@ -148,12 +143,7 @@ export const GlobalIssuesHeader = observer(function GlobalIssuesHeader() {
|
||||
/>
|
||||
</FiltersDropdown>
|
||||
)}
|
||||
<Button
|
||||
variant="primary"
|
||||
size="lg"
|
||||
data-ph-element={GLOBAL_VIEW_TRACKER_ELEMENTS.RIGHT_HEADER_ADD_BUTTON}
|
||||
onClick={() => setCreateViewModal(true)}
|
||||
>
|
||||
<Button variant="primary" size="lg" onClick={() => setCreateViewModal(true)}>
|
||||
{t("workspace_views.add_view")}
|
||||
</Button>
|
||||
<div className="hidden md:block">
|
||||
|
||||
@@ -8,7 +8,6 @@ import { observer } from "mobx-react";
|
||||
import Link from "next/link";
|
||||
import { useTheme } from "next-themes";
|
||||
// plane imports
|
||||
import { PROJECT_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { Button, getButtonStyling } from "@plane/propel/button";
|
||||
import { cn } from "@plane/utils";
|
||||
// assets
|
||||
@@ -35,12 +34,7 @@ function ProjectSettingsPage() {
|
||||
<Link href="https://plane.so/" target="_blank" className={cn(getButtonStyling("secondary", "base"))}>
|
||||
Learn more about projects
|
||||
</Link>
|
||||
<Button
|
||||
onClick={() => toggleCreateProjectModal(true)}
|
||||
data-ph-element={PROJECT_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_PROJECT_BUTTON}
|
||||
>
|
||||
Start your first project
|
||||
</Button>
|
||||
<Button onClick={() => toggleCreateProjectModal(true)}>Start your first project</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import Script from "next/script";
|
||||
|
||||
// styles
|
||||
import "@/styles/globals.css";
|
||||
|
||||
@@ -56,8 +54,6 @@ export const meta = () => [
|
||||
];
|
||||
|
||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
const isSessionRecorderEnabled = parseInt(process.env.VITE_ENABLE_SESSION_RECORDER || "0");
|
||||
|
||||
return (
|
||||
<html lang="en">
|
||||
<head>
|
||||
@@ -87,15 +83,6 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
</div>
|
||||
</AppProvider>
|
||||
</body>
|
||||
{!!isSessionRecorderEnabled && process.env.VITE_SESSION_RECORDER_KEY && (
|
||||
<Script id="clarity-tracking">
|
||||
{`(function(c,l,a,r,i,t,y){
|
||||
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
|
||||
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
|
||||
y=l.getElementsByTagName(r)[0];if(y){y.parentNode.insertBefore(t,y);}
|
||||
})(window, document, "clarity", "script", "${process.env.VITE_SESSION_RECORDER_KEY}");`}
|
||||
</Script>
|
||||
)}
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import Script from "next/script";
|
||||
import { Links, Meta, Outlet, Scripts } from "react-router";
|
||||
import type { LinksFunction } from "react-router";
|
||||
import { ThemeProvider, useTheme } from "next-themes";
|
||||
@@ -57,8 +56,6 @@ export const links: LinksFunction = () => [
|
||||
];
|
||||
|
||||
export function Layout({ children }: { children: ReactNode }) {
|
||||
const isSessionRecorderEnabled = parseInt(process.env.VITE_ENABLE_SESSION_RECORDER || "0");
|
||||
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<head>
|
||||
@@ -82,15 +79,6 @@ export function Layout({ children }: { children: ReactNode }) {
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
<Scripts />
|
||||
{!!isSessionRecorderEnabled && process.env.VITE_SESSION_RECORDER_KEY && (
|
||||
<Script id="clarity-tracking">
|
||||
{`(function(c,l,a,r,i,t,y){
|
||||
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
|
||||
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
|
||||
y=l.getElementsByTagName(r)[0];if(y){y.parentNode.insertBefore(t,y);}
|
||||
})(window, document, "clarity", "script", "${process.env.VITE_SESSION_RECORDER_KEY}");`}
|
||||
</Script>
|
||||
)}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
@@ -10,7 +10,7 @@ import Link from "next/link";
|
||||
// icons
|
||||
import { Eye, EyeOff, Info, XCircle } from "lucide-react";
|
||||
// plane imports
|
||||
import { API_BASE_URL, E_PASSWORD_STRENGTH, AUTH_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { API_BASE_URL, E_PASSWORD_STRENGTH } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { Button } from "@plane/propel/button";
|
||||
import { CloseIcon } from "@plane/propel/icons";
|
||||
@@ -86,7 +86,6 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||
<div className="w-full">
|
||||
{isSMTPConfigured ? (
|
||||
<Link
|
||||
data-ph-element={AUTH_TRACKER_ELEMENTS.FORGOT_PASSWORD_FROM_SIGNIN}
|
||||
href={`/accounts/forgot-password?email=${encodeURIComponent(email)}`}
|
||||
className="text-11 font-medium text-accent-primary"
|
||||
>
|
||||
@@ -292,7 +291,6 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||
{isSMTPConfigured && (
|
||||
<Button
|
||||
type="button"
|
||||
data-ph-element={AUTH_TRACKER_ELEMENTS.SIGN_IN_WITH_UNIQUE_CODE}
|
||||
onClick={redirectToUniqueCodeSignIn}
|
||||
variant="secondary"
|
||||
className="w-full"
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import { useState } from "react";
|
||||
import { XCircle } from "lucide-react";
|
||||
// plane imports
|
||||
import { PROFILE_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { Tooltip } from "@plane/propel/tooltip";
|
||||
import type { IApiToken } from "@plane/types";
|
||||
import { renderFormattedDate, calculateTimeAgo, renderFormattedTime } from "@plane/utils";
|
||||
@@ -35,7 +34,6 @@ export function ApiTokenListItem(props: Props) {
|
||||
<button
|
||||
onClick={() => setDeleteModalOpen(true)}
|
||||
className="absolute right-4 hidden place-items-center group-hover:grid"
|
||||
data-ph-element={PROFILE_SETTINGS_TRACKER_ELEMENTS.LIST_ITEM_DELETE_ICON}
|
||||
>
|
||||
<XCircle className="h-4 w-4 text-danger-primary" />
|
||||
</button>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import Link from "next/link";
|
||||
import { AUTH_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { PlaneLockup } from "@plane/propel/icons";
|
||||
import { PageHead } from "@/components/core/page-title";
|
||||
@@ -48,7 +47,6 @@ export const AuthHeader = observer(function AuthHeader({ type }: AuthHeaderProps
|
||||
<div className="flex flex-col items-end text-center text-13 font-medium text-tertiary sm:flex-row sm:items-center sm:gap-2">
|
||||
<span className="text-body-sm-regular text-tertiary">{t(authContentMap[type].text)}</span>
|
||||
<Link
|
||||
data-ph-element={AUTH_TRACKER_ELEMENTS.NAVIGATE_TO_SIGN_UP}
|
||||
href={authContentMap[type].linkHref}
|
||||
className="text-body-sm-semibold text-accent-primary hover:underline"
|
||||
>
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
import { observer } from "mobx-react";
|
||||
import { PROJECT_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { TrashIcon } from "@plane/propel/icons";
|
||||
|
||||
type TEstimateListItem = {
|
||||
@@ -26,7 +25,6 @@ export const EstimateListItemButtons = observer(function EstimateListItemButtons
|
||||
<button
|
||||
className="relative flex h-6 w-6 flex-shrink-0 cursor-pointer items-center justify-center overflow-hidden rounded-sm transition-colors hover:bg-layer-1"
|
||||
onClick={() => onDeleteClick && onDeleteClick(estimateId)}
|
||||
data-ph-element={PROJECT_SETTINGS_TRACKER_ELEMENTS.ESTIMATES_LIST_ITEM}
|
||||
>
|
||||
<TrashIcon width={12} height={12} />
|
||||
</button>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import { USER_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
// ui
|
||||
import { getButtonStyling } from "@plane/propel/button";
|
||||
@@ -29,7 +28,6 @@ export function ProductUpdatesFooter() {
|
||||
<circle cx={1} cy={1} r={1} />
|
||||
</svg>
|
||||
<a
|
||||
data-ph-element={USER_TRACKER_ELEMENTS.CHANGELOG_REDIRECTED}
|
||||
href="https://go.plane.so/p-changelog"
|
||||
target="_blank"
|
||||
className="text-13 text-secondary underline-offset-1 outline-none hover:text-primary hover:underline"
|
||||
|
||||
@@ -9,13 +9,7 @@ import { useParams } from "next/navigation";
|
||||
// icons
|
||||
import { Circle } from "lucide-react";
|
||||
// plane imports
|
||||
import {
|
||||
EUserPermissions,
|
||||
EUserPermissionsLevel,
|
||||
SPACE_BASE_PATH,
|
||||
SPACE_BASE_URL,
|
||||
WORK_ITEM_TRACKER_ELEMENTS,
|
||||
} from "@plane/constants";
|
||||
import { EUserPermissions, EUserPermissionsLevel, SPACE_BASE_PATH, SPACE_BASE_URL } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { Button } from "@plane/propel/button";
|
||||
import { NewTabIcon, WorkItemsIcon } from "@plane/propel/icons";
|
||||
@@ -125,7 +119,6 @@ export const IssuesHeader = observer(function IssuesHeader() {
|
||||
onClick={() => {
|
||||
toggleCreateIssueModal(true, EIssuesStoreType.PROJECT);
|
||||
}}
|
||||
data-ph-element={WORK_ITEM_TRACKER_ELEMENTS.HEADER_ADD_BUTTON.WORK_ITEMS}
|
||||
>
|
||||
<div className="block sm:hidden">{t("issue.label", { count: 1 })}</div>
|
||||
<div className="hidden sm:block">{t("issue.add.label")}</div>
|
||||
|
||||
@@ -9,7 +9,7 @@ import { isEmpty } from "lodash-es";
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
// plane imports
|
||||
import { EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { EUserPermissionsLevel } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { EmptyStateDetailed } from "@plane/propel/empty-state";
|
||||
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
||||
@@ -116,14 +116,12 @@ export const CycleEmptyState = observer(function CycleEmptyState() {
|
||||
},
|
||||
disabled: !canPerformEmptyStateActions,
|
||||
variant: "primary",
|
||||
"data-ph-element": WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.CYCLE,
|
||||
},
|
||||
{
|
||||
label: t("project_empty_state.cycle_work_items.cta_secondary"),
|
||||
onClick: () => setCycleIssuesListModal(true),
|
||||
disabled: !canPerformEmptyStateActions,
|
||||
variant: "secondary",
|
||||
"data-ph-element": WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.CYCLE,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
|
||||
import { useParams, useSearchParams } from "next/navigation";
|
||||
import useSWR from "swr";
|
||||
// plane imports
|
||||
import { GLOBAL_VIEW_TRACKER_ELEMENTS, ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants";
|
||||
import { ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants";
|
||||
import { EmptyStateDetailed } from "@plane/propel/empty-state";
|
||||
import type { EIssueLayoutTypes } from "@plane/types";
|
||||
import { EIssuesStoreType, STATIC_VIEW_TYPES } from "@plane/types";
|
||||
@@ -148,14 +148,7 @@ export const AllIssueLayoutRoot = observer(function AllIssueLayoutRoot(props: Pr
|
||||
{({ filter: globalWorkItemsFilter }) => (
|
||||
<div className="h-full overflow-hidden bg-surface-1">
|
||||
<div className="flex h-full w-full flex-col border-b border-strong">
|
||||
{globalWorkItemsFilter && (
|
||||
<WorkItemFiltersRow
|
||||
filter={globalWorkItemsFilter}
|
||||
trackerElements={{
|
||||
saveView: GLOBAL_VIEW_TRACKER_ELEMENTS.HEADER_SAVE_VIEW_BUTTON,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{globalWorkItemsFilter && <WorkItemFiltersRow filter={globalWorkItemsFilter} />}
|
||||
<WorkspaceActiveLayout
|
||||
activeLayout={activeLayout}
|
||||
isDefaultView={isDefaultView}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
import useSWR from "swr";
|
||||
// plane constants
|
||||
import { ISSUE_DISPLAY_FILTERS_BY_PAGE, PROJECT_VIEW_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants";
|
||||
import { EIssuesStoreType, EIssueLayoutTypes } from "@plane/types";
|
||||
// components
|
||||
import { TransferIssues } from "@/components/cycles/transfer-issues";
|
||||
@@ -111,14 +111,7 @@ export const CycleLayoutRoot = observer(function CycleLayoutRoot() {
|
||||
disabled={!isEmpty(cycleDetails?.progress_snapshot)}
|
||||
/>
|
||||
)}
|
||||
{cycleWorkItemsFilter && (
|
||||
<WorkItemFiltersRow
|
||||
filter={cycleWorkItemsFilter}
|
||||
trackerElements={{
|
||||
saveView: PROJECT_VIEW_TRACKER_ELEMENTS.CYCLE_HEADER_SAVE_AS_VIEW_BUTTON,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{cycleWorkItemsFilter && <WorkItemFiltersRow filter={cycleWorkItemsFilter} />}
|
||||
<div className="h-full w-full overflow-auto">
|
||||
<CycleIssueLayout activeLayout={activeLayout} cycleId={cycleId} isCompletedCycle={isCompletedCycle} />
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
import useSWR from "swr";
|
||||
// plane imports
|
||||
import { ISSUE_DISPLAY_FILTERS_BY_PAGE, PROJECT_VIEW_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants";
|
||||
import { EIssuesStoreType, EIssueLayoutTypes } from "@plane/types";
|
||||
import { Row, ERowVariant } from "@plane/ui";
|
||||
// hooks
|
||||
@@ -81,14 +81,7 @@ export const ModuleLayoutRoot = observer(function ModuleLayoutRoot() {
|
||||
>
|
||||
{({ filter: moduleWorkItemsFilter }) => (
|
||||
<div className="relative flex h-full w-full flex-col overflow-hidden">
|
||||
{moduleWorkItemsFilter && (
|
||||
<WorkItemFiltersRow
|
||||
filter={moduleWorkItemsFilter}
|
||||
trackerElements={{
|
||||
saveView: PROJECT_VIEW_TRACKER_ELEMENTS.MODULE_HEADER_SAVE_AS_VIEW_BUTTON,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{moduleWorkItemsFilter && <WorkItemFiltersRow filter={moduleWorkItemsFilter} />}
|
||||
<Row variant={ERowVariant.HUGGING} className="h-full w-full overflow-auto">
|
||||
<ModuleIssueLayout activeLayout={activeLayout} moduleId={moduleId} />
|
||||
</Row>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
import useSWR from "swr";
|
||||
// plane constants
|
||||
import { ISSUE_DISPLAY_FILTERS_BY_PAGE, PROJECT_VIEW_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants";
|
||||
import { EIssueLayoutTypes, EIssuesStoreType } from "@plane/types";
|
||||
import { Spinner } from "@plane/ui";
|
||||
// components
|
||||
@@ -78,14 +78,7 @@ export const ProjectLayoutRoot = observer(function ProjectLayoutRoot() {
|
||||
>
|
||||
{({ filter: projectWorkItemsFilter }) => (
|
||||
<div className="relative flex h-full w-full flex-col overflow-hidden">
|
||||
{projectWorkItemsFilter && (
|
||||
<WorkItemFiltersRow
|
||||
filter={projectWorkItemsFilter}
|
||||
trackerElements={{
|
||||
saveView: PROJECT_VIEW_TRACKER_ELEMENTS.PROJECT_HEADER_SAVE_AS_VIEW_BUTTON,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{projectWorkItemsFilter && <WorkItemFiltersRow filter={projectWorkItemsFilter} />}
|
||||
<div className="relative h-full w-full overflow-auto bg-surface-1">
|
||||
{/* mutation loader */}
|
||||
{issues?.getIssueLoader() === "mutation" && (
|
||||
|
||||
@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
import useSWR from "swr";
|
||||
// plane constants
|
||||
import { ISSUE_DISPLAY_FILTERS_BY_PAGE, PROJECT_VIEW_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants";
|
||||
import { EIssuesStoreType, EIssueLayoutTypes } from "@plane/types";
|
||||
// hooks
|
||||
import { ProjectLevelWorkItemFiltersHOC } from "@/components/work-item-filters/filters-hoc/project-level";
|
||||
@@ -101,14 +101,7 @@ export const ProjectViewLayoutRoot = observer(function ProjectViewLayoutRoot() {
|
||||
>
|
||||
{({ filter: projectViewWorkItemsFilter }) => (
|
||||
<div className="relative flex h-full w-full flex-col overflow-hidden">
|
||||
{projectViewWorkItemsFilter && (
|
||||
<WorkItemFiltersRow
|
||||
filter={projectViewWorkItemsFilter}
|
||||
trackerElements={{
|
||||
saveView: PROJECT_VIEW_TRACKER_ELEMENTS.HEADER_SAVE_VIEW_BUTTON,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{projectViewWorkItemsFilter && <WorkItemFiltersRow filter={projectViewWorkItemsFilter} />}
|
||||
<div className="relative h-full w-full overflow-auto">
|
||||
<ProjectViewIssueLayout activeLayout={activeLayout} viewId={viewId.toString()} />
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,6 @@ import type { MutableRefObject } from "react";
|
||||
import { useRef, useState } from "react";
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
// plane helpers
|
||||
import { PROJECT_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { useOutsideClickDetector } from "@plane/hooks";
|
||||
import type { ISvgIcons } from "@plane/propel/icons";
|
||||
import { CloseIcon } from "@plane/propel/icons";
|
||||
@@ -101,7 +100,6 @@ export function LabelItemBlock(props: ILabelItemBlock) {
|
||||
onClick={() => {
|
||||
handleLabelDelete(label);
|
||||
}}
|
||||
data-ph-element={PROJECT_SETTINGS_TRACKER_ELEMENTS.LABELS_DELETE_BUTTON}
|
||||
>
|
||||
<CloseIcon className="size-3.5 flex-shrink-0 text-tertiary" />
|
||||
</button>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
import { MODULE_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { CopyIcon, EditIcon, TrashIcon } from "@plane/propel/icons";
|
||||
// plane types
|
||||
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
||||
@@ -67,7 +66,6 @@ export const ModulesLinksListItem = observer(function ModulesLinksListItem(props
|
||||
<button
|
||||
type="button"
|
||||
className="grid place-items-center rounded-sm p-1 text-secondary hover:bg-layer-transparent-hover"
|
||||
data-ph-element={MODULE_TRACKER_ELEMENTS.LIST_ITEM}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -88,7 +86,6 @@ export const ModulesLinksListItem = observer(function ModulesLinksListItem(props
|
||||
<button
|
||||
type="button"
|
||||
className="grid place-items-center rounded-sm p-1 text-secondary hover:bg-layer-transparent-hover"
|
||||
data-ph-element={MODULE_TRACKER_ELEMENTS.LIST_ITEM}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams, useSearchParams } from "next/navigation";
|
||||
// components
|
||||
import { EUserPermissionsLevel, MODULE_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { EUserPermissionsLevel } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { EmptyStateDetailed } from "@plane/propel/empty-state";
|
||||
import { EUserProjectRoles } from "@plane/types";
|
||||
@@ -65,7 +65,6 @@ export const ModulesListView = observer(function ModulesListView() {
|
||||
onClick: () => toggleCreateModuleModal(true),
|
||||
disabled: !canPerformEmptyStateActions,
|
||||
variant: "primary",
|
||||
"data-ph-element": MODULE_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
@@ -8,7 +8,6 @@ import { useState, useRef } from "react";
|
||||
import { useNavigate } from "react-router";
|
||||
import { LogOut, MoreHorizontal, Settings, Share2, ArchiveIcon } from "lucide-react";
|
||||
// plane imports
|
||||
import { MEMBER_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { LinkIcon } from "@plane/propel/icons";
|
||||
import { CustomMenu } from "@plane/ui";
|
||||
@@ -103,10 +102,7 @@ export function ProjectActionsMenu({
|
||||
</CustomMenu.MenuItem>
|
||||
{/* Leave project */}
|
||||
{!isAuthorized && (
|
||||
<CustomMenu.MenuItem
|
||||
onClick={onLeaveProject}
|
||||
data-ph-element={MEMBER_TRACKER_ELEMENTS.SIDEBAR_PROJECT_QUICK_ACTIONS}
|
||||
>
|
||||
<CustomMenu.MenuItem onClick={onLeaveProject}>
|
||||
<div className="flex items-center justify-start gap-2">
|
||||
<LogOut className="h-3.5 w-3.5 stroke-[1.5]" />
|
||||
<span>{t("leave_project")}</span>
|
||||
|
||||
@@ -14,7 +14,6 @@ import { StateForm } from "@/components/project-states";
|
||||
|
||||
type TStateCreate = {
|
||||
groupKey: TStateGroups;
|
||||
shouldTrackEvents?: boolean;
|
||||
createStateCallback: TStateOperationsCallbacks["createState"];
|
||||
handleClose: () => void;
|
||||
};
|
||||
|
||||
@@ -14,7 +14,6 @@ import { StateForm } from "@/components/project-states";
|
||||
type TStateUpdate = {
|
||||
state: IState;
|
||||
updateStateCallback: TStateOperationsCallbacks["updateState"];
|
||||
shouldTrackEvents: boolean;
|
||||
handleClose: () => void;
|
||||
};
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useState, useRef } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
// plane imports
|
||||
import { EIconSize, STATE_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { EIconSize } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { PlusIcon, StateGroupIcon, ChevronDownIcon } from "@plane/propel/icons";
|
||||
import type { IState, TStateGroups, TStateOperationsCallbacks } from "@plane/types";
|
||||
@@ -23,7 +23,6 @@ type TGroupItem = {
|
||||
states: IState[];
|
||||
stateOperationsCallbacks: TStateOperationsCallbacks;
|
||||
isEditable: boolean;
|
||||
shouldTrackEvents: boolean;
|
||||
groupItemClassName?: string;
|
||||
stateItemClassName?: string;
|
||||
handleGroupCollapse: (groupKey: TStateGroups) => void;
|
||||
@@ -38,7 +37,6 @@ export const GroupItem = observer(function GroupItem(props: TGroupItem) {
|
||||
groupsExpanded,
|
||||
isEditable,
|
||||
stateOperationsCallbacks,
|
||||
shouldTrackEvents,
|
||||
groupItemClassName,
|
||||
stateItemClassName,
|
||||
handleExpand,
|
||||
@@ -82,7 +80,6 @@ export const GroupItem = observer(function GroupItem(props: TGroupItem) {
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
data-ph-element={STATE_TRACKER_ELEMENTS.STATE_GROUP_ADD_BUTTON}
|
||||
className={cn(
|
||||
"flex h-6 w-6 flex-shrink-0 cursor-pointer items-center justify-center overflow-hidden rounded-sm text-accent-primary/80 transition-colors hover:bg-layer-1 hover:text-accent-primary",
|
||||
(!isEditable || createState) && "cursor-not-allowed text-placeholder hover:text-placeholder"
|
||||
@@ -114,7 +111,6 @@ export const GroupItem = observer(function GroupItem(props: TGroupItem) {
|
||||
states={states}
|
||||
disabled={!isEditable}
|
||||
stateOperationsCallbacks={stateOperationsCallbacks}
|
||||
shouldTrackEvents={shouldTrackEvents}
|
||||
stateItemClassName={stateItemClassName}
|
||||
/>
|
||||
</div>
|
||||
@@ -126,7 +122,6 @@ export const GroupItem = observer(function GroupItem(props: TGroupItem) {
|
||||
groupKey={groupKey}
|
||||
handleClose={() => setCreateState(false)}
|
||||
createStateCallback={stateOperationsCallbacks.createState}
|
||||
shouldTrackEvents={shouldTrackEvents}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -16,7 +16,6 @@ type TGroupList = {
|
||||
groupedStates: Record<string, IState[]>;
|
||||
stateOperationsCallbacks: TStateOperationsCallbacks;
|
||||
isEditable: boolean;
|
||||
shouldTrackEvents: boolean;
|
||||
groupListClassName?: string;
|
||||
groupItemClassName?: string;
|
||||
stateItemClassName?: string;
|
||||
@@ -27,7 +26,6 @@ export const GroupList = observer(function GroupList(props: TGroupList) {
|
||||
groupedStates,
|
||||
stateOperationsCallbacks,
|
||||
isEditable,
|
||||
shouldTrackEvents,
|
||||
groupListClassName,
|
||||
groupItemClassName,
|
||||
stateItemClassName,
|
||||
@@ -72,7 +70,6 @@ export const GroupList = observer(function GroupList(props: TGroupList) {
|
||||
groupsExpanded={groupsExpanded}
|
||||
stateOperationsCallbacks={stateOperationsCallbacks}
|
||||
isEditable={isEditable}
|
||||
shouldTrackEvents={shouldTrackEvents}
|
||||
handleGroupCollapse={handleGroupCollapse}
|
||||
handleExpand={handleExpand}
|
||||
groupItemClassName={groupItemClassName}
|
||||
|
||||
@@ -21,7 +21,6 @@ type TStateDelete = {
|
||||
totalStates: number;
|
||||
state: IState;
|
||||
deleteStateCallback: TStateOperationsCallbacks["deleteState"];
|
||||
shouldTrackEvents?: boolean;
|
||||
};
|
||||
|
||||
export const StateDelete = observer(function StateDelete(props: TStateDelete) {
|
||||
|
||||
@@ -71,7 +71,6 @@ export const ProjectStateRoot = observer(function ProjectStateRoot(props: TProje
|
||||
groupedStates={groupedProjectStates}
|
||||
stateOperationsCallbacks={stateOperationsCallbacks}
|
||||
isEditable={isEditable}
|
||||
shouldTrackEvents
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import type { SetStateAction } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { GripVertical } from "lucide-react";
|
||||
import { EIconSize, STATE_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { EIconSize } from "@plane/constants";
|
||||
// plane imports
|
||||
import { EditIcon, StateGroupIcon } from "@plane/propel/icons";
|
||||
import type { IState, TStateOperationsCallbacks } from "@plane/types";
|
||||
@@ -25,7 +25,6 @@ type TBaseStateItemTitleProps = {
|
||||
type TEnabledStateItemTitleProps = TBaseStateItemTitleProps & {
|
||||
disabled: false;
|
||||
stateOperationsCallbacks: Pick<TStateOperationsCallbacks, "markStateAsDefault" | "deleteState">;
|
||||
shouldTrackEvents: boolean;
|
||||
};
|
||||
|
||||
type TDisabledStateItemTitleProps = TBaseStateItemTitleProps & {
|
||||
@@ -76,7 +75,6 @@ export const StateItemTitle = observer(function StateItemTitle(props: TStateItem
|
||||
<button
|
||||
className="flex h-5 w-5 flex-shrink-0 cursor-pointer items-center justify-center overflow-hidden rounded-sm text-secondary transition-colors hover:bg-layer-1 hover:text-primary"
|
||||
onClick={() => setUpdateStateModal(true)}
|
||||
data-ph-element={STATE_TRACKER_ELEMENTS.STATE_LIST_EDIT_BUTTON}
|
||||
>
|
||||
<EditIcon className="h-3 w-3" />
|
||||
</button>
|
||||
@@ -84,7 +82,6 @@ export const StateItemTitle = observer(function StateItemTitle(props: TStateItem
|
||||
totalStates={stateCount}
|
||||
state={state}
|
||||
deleteStateCallback={props.stateOperationsCallbacks.deleteState}
|
||||
shouldTrackEvents={props.shouldTrackEvents}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -23,7 +23,6 @@ type TStateItem = {
|
||||
totalStates: number;
|
||||
state: IState;
|
||||
stateOperationsCallbacks: TStateOperationsCallbacks;
|
||||
shouldTrackEvents: boolean;
|
||||
disabled?: boolean;
|
||||
stateItemClassName?: string;
|
||||
};
|
||||
@@ -35,7 +34,6 @@ export const StateItem = observer(function StateItem(props: TStateItem) {
|
||||
totalStates,
|
||||
state,
|
||||
stateOperationsCallbacks,
|
||||
shouldTrackEvents,
|
||||
disabled = false,
|
||||
stateItemClassName,
|
||||
} = props;
|
||||
@@ -123,7 +121,6 @@ export const StateItem = observer(function StateItem(props: TStateItem) {
|
||||
<StateUpdate
|
||||
state={state}
|
||||
updateStateCallback={stateOperationsCallbacks.updateState}
|
||||
shouldTrackEvents={shouldTrackEvents}
|
||||
handleClose={() => setUpdateStateModal(false)}
|
||||
/>
|
||||
);
|
||||
@@ -151,7 +148,6 @@ export const StateItem = observer(function StateItem(props: TStateItem) {
|
||||
markStateAsDefault: stateOperationsCallbacks.markStateAsDefault,
|
||||
deleteState: stateOperationsCallbacks.deleteState,
|
||||
}}
|
||||
shouldTrackEvents={shouldTrackEvents}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -14,21 +14,12 @@ type TStateList = {
|
||||
groupedStates: Record<string, IState[]>;
|
||||
states: IState[];
|
||||
stateOperationsCallbacks: TStateOperationsCallbacks;
|
||||
shouldTrackEvents: boolean;
|
||||
disabled?: boolean;
|
||||
stateItemClassName?: string;
|
||||
};
|
||||
|
||||
export const StateList = observer(function StateList(props: TStateList) {
|
||||
const {
|
||||
groupKey,
|
||||
groupedStates,
|
||||
states,
|
||||
stateOperationsCallbacks,
|
||||
shouldTrackEvents,
|
||||
disabled = false,
|
||||
stateItemClassName,
|
||||
} = props;
|
||||
const { groupKey, groupedStates, states, stateOperationsCallbacks, disabled = false, stateItemClassName } = props;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -41,7 +32,6 @@ export const StateList = observer(function StateList(props: TStateList) {
|
||||
state={state}
|
||||
disabled={disabled}
|
||||
stateOperationsCallbacks={stateOperationsCallbacks}
|
||||
shouldTrackEvents={shouldTrackEvents}
|
||||
stateItemClassName={stateItemClassName}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { observer } from "mobx-react";
|
||||
import { usePathname } from "next/navigation";
|
||||
// i18n
|
||||
import { EUserPermissions, EUserPermissionsLevel, PROJECT_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
// ui
|
||||
import { Button } from "@plane/propel/button";
|
||||
@@ -65,7 +65,6 @@ export const ProjectsBaseHeader = observer(function ProjectsBaseHeader() {
|
||||
onClick={() => {
|
||||
toggleCreateProjectModal(true);
|
||||
}}
|
||||
data-ph-element={PROJECT_TRACKER_ELEMENTS.CREATE_HEADER_BUTTON}
|
||||
className="items-center gap-1"
|
||||
>
|
||||
<span className="hidden sm:inline-block">{t("workspace_projects.create.label")}</span>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
// plane imports
|
||||
import { EUserPermissions, EUserPermissionsLevel, MEMBER_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { Button } from "@plane/propel/button";
|
||||
import { SearchIcon } from "@plane/propel/icons";
|
||||
@@ -105,7 +105,6 @@ export const ProjectMemberList = observer(function ProjectMemberList(props: TPro
|
||||
onClick={() => {
|
||||
setInviteModal(true);
|
||||
}}
|
||||
data-ph-element={MEMBER_TRACKER_ELEMENTS.HEADER_ADD_BUTTON}
|
||||
>
|
||||
{t("add_member")}
|
||||
</Button>
|
||||
|
||||
@@ -8,7 +8,6 @@ import { useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "react-router";
|
||||
// plane imports
|
||||
import { PROJECT_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { Button } from "@plane/propel/button";
|
||||
// components
|
||||
@@ -73,11 +72,7 @@ export const GeneralProjectSettingsControlSection = observer(function GeneralPro
|
||||
title={t("delete")}
|
||||
description="When deleting a project, all of the data and resources within that project will be permanently removed and cannot be recovered."
|
||||
control={
|
||||
<Button
|
||||
variant="error-outline"
|
||||
onClick={() => setSelectedProject(currentProjectDetails.id ?? null)}
|
||||
data-ph-element={PROJECT_TRACKER_ELEMENTS.DELETE_PROJECT_BUTTON}
|
||||
>
|
||||
<Button variant="error-outline" onClick={() => setSelectedProject(currentProjectDetails.id ?? null)}>
|
||||
{t("delete")}
|
||||
</Button>
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
import Link from "next/link";
|
||||
import { PROJECT_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { ChevronRightIcon } from "@plane/propel/icons";
|
||||
import { EPillVariant, Pill, EPillSize } from "@plane/propel/pill";
|
||||
import { ToggleSwitch } from "@plane/ui";
|
||||
@@ -41,7 +40,6 @@ export function ProjectFeatureToggle(props: Props) {
|
||||
onChange={() => handleSubmit(featureItem?.key, featureItem?.property)}
|
||||
disabled={disabled}
|
||||
size="sm"
|
||||
data-ph-element={PROJECT_TRACKER_ELEMENTS.TOGGLE_FEATURE}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Controller, useForm } from "react-hook-form";
|
||||
import { CircleMinus } from "lucide-react";
|
||||
import { Disclosure } from "@headlessui/react";
|
||||
// plane imports
|
||||
import { ROLE, EUserPermissions, MEMBER_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { ROLE, EUserPermissions } from "@plane/constants";
|
||||
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
||||
import type { EUserProjectRoles, IUser, IWorkspaceMember, TProjectMembership } from "@plane/types";
|
||||
import { CustomMenu, CustomSelect } from "@plane/ui";
|
||||
@@ -78,7 +78,6 @@ export function NameColumn(props: NameProps) {
|
||||
<CustomMenu.MenuItem>
|
||||
<div
|
||||
className="flex cursor-pointer items-center gap-x-1 font-medium text-danger-primary"
|
||||
data-ph-element={MEMBER_TRACKER_ELEMENTS.PROJECT_MEMBER_TABLE_CONTEXT_MENU}
|
||||
onClick={() => setRemoveMemberModal(rowData)}
|
||||
>
|
||||
<CircleMinus className="size-3.5 flex-shrink-0" />
|
||||
|
||||
@@ -23,23 +23,12 @@ export type TFiltersRowProps<K extends TFilterProperty, E extends TExternalFilte
|
||||
disabledAllOperations?: boolean;
|
||||
filter: IFilterInstance<K, E>;
|
||||
variant?: "modal" | "header";
|
||||
trackerElements?: {
|
||||
clearFilter?: string;
|
||||
saveView?: string;
|
||||
updateView?: string;
|
||||
};
|
||||
};
|
||||
|
||||
export const FiltersRow = observer(function FiltersRow<K extends TFilterProperty, E extends TExternalFilter>(
|
||||
props: TFiltersRowProps<K, E>
|
||||
) {
|
||||
const {
|
||||
buttonConfig,
|
||||
disabledAllOperations: disabledAllOperationsProp = false,
|
||||
filter,
|
||||
variant = "header",
|
||||
trackerElements,
|
||||
} = props;
|
||||
const { buttonConfig, disabledAllOperations: disabledAllOperationsProp = false, filter, variant = "header" } = props;
|
||||
// states
|
||||
const [isUpdating, setIsUpdating] = useState(false);
|
||||
// derived values
|
||||
@@ -90,22 +79,12 @@ export const FiltersRow = observer(function FiltersRow<K extends TFilterProperty
|
||||
const rightContent = !disabledAllOperations && (
|
||||
<>
|
||||
<ElementTransition show={filter.canClearFilters}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
className={COMMON_OPERATION_BUTTON_CLASSNAME}
|
||||
onClick={filter.clearFilters}
|
||||
data-ph-element={trackerElements?.clearFilter}
|
||||
>
|
||||
<Button variant="secondary" className={COMMON_OPERATION_BUTTON_CLASSNAME} onClick={filter.clearFilters}>
|
||||
{filter.clearFilterOptions?.label ?? "Clear all"}
|
||||
</Button>
|
||||
</ElementTransition>
|
||||
<ElementTransition show={filter.canSaveView}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
className={COMMON_OPERATION_BUTTON_CLASSNAME}
|
||||
onClick={filter.saveView}
|
||||
data-ph-element={trackerElements?.saveView}
|
||||
>
|
||||
<Button variant="secondary" className={COMMON_OPERATION_BUTTON_CLASSNAME} onClick={filter.saveView}>
|
||||
{filter.saveViewOptions?.label ?? "Save view"}
|
||||
</Button>
|
||||
</ElementTransition>
|
||||
@@ -116,7 +95,6 @@ export const FiltersRow = observer(function FiltersRow<K extends TFilterProperty
|
||||
onClick={handleUpdate}
|
||||
loading={isUpdating}
|
||||
disabled={isUpdating}
|
||||
data-ph-element={trackerElements?.updateView}
|
||||
>
|
||||
{isUpdating ? "Confirming" : (filter.updateViewOptions?.label ?? "Update view")}
|
||||
</Button>
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
import { Disclosure, Transition } from "@headlessui/react";
|
||||
import { WORKSPACE_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { Button } from "@plane/propel/button";
|
||||
import { ChevronDownIcon, ChevronUpIcon } from "@plane/propel/icons";
|
||||
|
||||
@@ -41,12 +40,7 @@ export function WebhookDeleteSection(props: Props) {
|
||||
webhook.
|
||||
</span>
|
||||
<div>
|
||||
<Button
|
||||
variant="error-fill"
|
||||
size="lg"
|
||||
onClick={openDeleteModal}
|
||||
data-ph-element={WORKSPACE_SETTINGS_TRACKER_ELEMENTS.WEBHOOK_DELETE_BUTTON}
|
||||
>
|
||||
<Button variant="error-fill" size="lg" onClick={openDeleteModal}>
|
||||
Delete webhook
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { WORKSPACE_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { Button } from "@plane/propel/button";
|
||||
import type { IWebhook, TWebhookEventTypes } from "@plane/types";
|
||||
@@ -98,12 +97,7 @@ export const WebhookForm = observer(function WebhookForm(props: Props) {
|
||||
{data ? (
|
||||
<div className="space-y-5 pt-0">
|
||||
<WebhookSecretKey data={data} />
|
||||
<Button
|
||||
size="lg"
|
||||
type="submit"
|
||||
loading={isSubmitting}
|
||||
data-ph-element={WORKSPACE_SETTINGS_TRACKER_ELEMENTS.WEBHOOK_UPDATE_BUTTON}
|
||||
>
|
||||
<Button size="lg" type="submit" loading={isSubmitting}>
|
||||
{isSubmitting ? t("updating") : t("update")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import { useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
// plane imports
|
||||
import { WORKSPACE_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { Button } from "@plane/propel/button";
|
||||
import type { IWorkspace } from "@plane/types";
|
||||
@@ -38,11 +37,7 @@ export const DeleteWorkspaceSection = observer(function DeleteWorkspaceSection(p
|
||||
title={t("workspace_settings.settings.general.delete_workspace")}
|
||||
description={t("workspace_settings.settings.general.delete_workspace_description")}
|
||||
control={
|
||||
<Button
|
||||
variant="error-outline"
|
||||
onClick={() => setDeleteWorkspaceModal(true)}
|
||||
data-ph-element={WORKSPACE_TRACKER_ELEMENTS.DELETE_WORKSPACE_BUTTON}
|
||||
>
|
||||
<Button variant="error-outline" onClick={() => setDeleteWorkspaceModal(true)}>
|
||||
{t("delete")}
|
||||
</Button>
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
import { Disclosure } from "@headlessui/react";
|
||||
// plane imports
|
||||
import { ROLE, EUserPermissions, EUserPermissionsLevel, MEMBER_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { ROLE, EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
|
||||
import { TrashIcon, SuspendedUserIcon } from "@plane/propel/icons";
|
||||
import { Pill, EPillVariant, EPillSize } from "@plane/propel/pill";
|
||||
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
||||
@@ -98,7 +98,6 @@ export function NameColumn(props: NameProps) {
|
||||
setRemoveMemberModal(rowData);
|
||||
}
|
||||
}}
|
||||
data-ph-element={MEMBER_TRACKER_ELEMENTS.WORKSPACE_MEMBER_TABLE_CONTEXT_MENU}
|
||||
>
|
||||
<TrashIcon className="size-3.5 align-middle" /> {id === currentUser?.id ? "Leave " : "Remove "}
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@ import scrollIntoView from "smooth-scroll-into-view-if-needed";
|
||||
import { Settings, Share2, LogOut, MoreHorizontal } from "lucide-react";
|
||||
import { Disclosure, Transition } from "@headlessui/react";
|
||||
// plane imports
|
||||
import { EUserPermissions, EUserPermissionsLevel, MEMBER_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
|
||||
import { useOutsideClickDetector } from "@plane/hooks";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { Logo } from "@plane/propel/emoji-icon-picker";
|
||||
@@ -434,10 +434,7 @@ export const SidebarProjectsListItem = observer(function SidebarProjectsListItem
|
||||
</CustomMenu.MenuItem>
|
||||
{/* leave project */}
|
||||
{!isAuthorized && (
|
||||
<CustomMenu.MenuItem
|
||||
onClick={handleLeaveProject}
|
||||
data-ph-element={MEMBER_TRACKER_ELEMENTS.SIDEBAR_PROJECT_QUICK_ACTIONS}
|
||||
>
|
||||
<CustomMenu.MenuItem onClick={handleLeaveProject}>
|
||||
<div className="flex items-center justify-start gap-2">
|
||||
<LogOut className="h-3.5 w-3.5 stroke-[1.5]" />
|
||||
<span>{t("leave_project")}</span>
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useParams, usePathname } from "next/navigation";
|
||||
import { Ellipsis } from "lucide-react";
|
||||
import { Disclosure, Transition } from "@headlessui/react";
|
||||
// plane imports
|
||||
import { EUserPermissions, EUserPermissionsLevel, PROJECT_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { PlusIcon, ChevronRightIcon } from "@plane/propel/icons";
|
||||
import { IconButton } from "@plane/propel/icon-button";
|
||||
@@ -195,7 +195,6 @@ export const SidebarProjectsList = observer(function SidebarProjectsList() {
|
||||
onClick={() => {
|
||||
setIsProjectModalOpen(true);
|
||||
}}
|
||||
data-ph-element={PROJECT_TRACKER_ELEMENTS.SIDEBAR_CREATE_PROJECT_TOOLTIP}
|
||||
className="hidden text-placeholder group-hover:inline-flex"
|
||||
aria-label={t("aria_labels.projects_sidebar.create_new_project")}
|
||||
/>
|
||||
@@ -277,7 +276,6 @@ export const SidebarProjectsList = observer(function SidebarProjectsList() {
|
||||
{isAuthorizedUser && joinedProjects?.length === 0 && (
|
||||
<button
|
||||
type="button"
|
||||
data-ph-element={PROJECT_TRACKER_ELEMENTS.SIDEBAR_CREATE_PROJECT_BUTTON}
|
||||
className="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-13 leading-5 font-medium text-secondary hover:bg-surface-2"
|
||||
onClick={() => {
|
||||
toggleCreateProjectModal(true);
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useRef, useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
// plane imports
|
||||
import { EUserPermissions, EUserPermissionsLevel, SIDEBAR_TRACKER_ELEMENTS } from "@plane/constants";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { AddWorkItemIcon } from "@plane/propel/icons";
|
||||
import type { TIssue } from "@plane/types";
|
||||
@@ -89,7 +89,6 @@ export const SidebarQuickActions = observer(function SidebarQuickActions() {
|
||||
disabled={disabled}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
data-ph-element={SIDEBAR_TRACKER_ELEMENTS.CREATE_WORK_ITEM_BUTTON}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user