fix: merge conflicts and build errors (#1469)
* dev: private bucket implementation (#1339) * chore: migrations and backmigration to move attachments to file asset * chore: move attachments to file assets * chore: update migration file to include created by and updated by and size * chore: remove uninmport errors * chore: make size as float field * fix: file asset uploads * chore: asset uploads migration changes * chore: v2 assets endpoint * chore: remove unused imports * chore: issue attachments * chore: issue attachments * chore: workspace logo endpoints * chore: private bucket changes * chore: user asset endpoint * chore: add logo_url validation * chore: cover image urlk * chore: change asset max length * chore: pages endpoint * chore: store the storage_metadata only when none * chore: attachment asset apis * chore: update create private bucket * chore: make bucket private * chore: fix response of user uploads * fix: response of user uploads * fix: job to fix file asset uploads * fix: user asset endpoints * chore: avatar for user profile * chore: external apis user url endpoint * chore: upload workspace and user asset actions updated * chore: analytics endpoint * fix: analytics export * chore: avatar urls * chore: update user avatar instances * chore: avatar urls for assignees and creators * chore: bucket permission script * fix: all user avatr instances in the web app * chore: update project cover image logic * fix: issue attachment endpoint * chore: patch endpoint for issue attachment * chore: attachments * chore: change attachment storage class * chore: update issue attachment endpoints * fix: issue attachment * chore: update issue attachment implementation * chore: page asset endpoints * fix: web build errors * chore: attachments * chore: page asset urls * chore: comment and issue asset endpoints * chore: asset endpoints * chore: attachment endpoints * chore: bulk asset endpoint * chore: restore endpoint * chore: project assets endpoints * chore: asset url * chore: add delete asset endpoints * chore: fix asset upload endpoint * chore: update patch endpoints * chore: update patch endpoint * chore: update editor image handling * chore: asset restore endpoints * chore: avatar url for space assets * chore: space app assets migration * fix: space app urls * chore: space endpoints * fix: old editor images rendering logic * fix: issue archive and attachment activity * chore: asset deletes * chore: update images * chore: attachment delete * fix: issue attachment * fix: issue attachment get * chore: cover image url for projects * chore: remove duplicate py file * fix: url check function * chore: chore project cover asset delete * fix: migrations * chore: delete migration files --------- Co-authored-by: pablohashescobar <[email protected]> * fix: private bucket build errors (#1347) * fix: private bucket build errors * fix: build errors * revert: issue type select changes. (#1355) * chore: private bucket implementation for workspace level pages (#1371) * chore: update project modal * chore: update rich-text read-only editor * chore: update workspace pages' components * chore: remove entity identifier in favour of multiple columns of entities (#1405) * fix: issue attachments (#1411) * fix: issue attachments (#1422) * chore: file size limit for pro workspaces (#1437) * chore: file size limit for pro * chore: update maximum file size logic * chore: update editor max file size logic * chore: update max file size limit logic * chore: add comments * fix: close modal after removing workspace logo * chore: update uploaded asstes' status post issue creation * chore: memoize max file size var * chore: check for pro file size limits * chore: added file size limit to the space app --------- Co-authored-by: Aaryan Khandelwal <[email protected]> * chore: add max file size limit to workspace pages (#1440) * fix: remove old workspace logo and user avatar (#1445) * fix: intake exception error (#5810) * chore: filtered active cycles for guest (#1468) * fix: build error --------- Co-authored-by: pablohashescobar <[email protected]> Co-authored-by: Nikhil <[email protected]> Co-authored-by: Prateek Shourya <[email protected]> Co-authored-by: sriram veeraghanta <[email protected]> Co-authored-by: Anmol Singh Bhatia <[email protected]> Co-authored-by: Bavisetti Narayan <[email protected]>
This commit is contained in:
co-authored by
pablohashescobar
Nikhil
Prateek Shourya
sriram veeraghanta
Anmol Singh Bhatia
Bavisetti Narayan
parent
fcb4cd11b6
commit
b9ce8ea8b1
@@ -21,6 +21,8 @@ from plane.db.models import (
|
||||
)
|
||||
from plane.settings.storage import S3Storage
|
||||
from plane.app.permissions import allow_permission, ROLE
|
||||
from plane.payment.flags.flag_decorator import check_workspace_feature_flag
|
||||
from plane.payment.flags.flag import FeatureFlag
|
||||
|
||||
|
||||
class UserAssetsV2Endpoint(BaseAPIView):
|
||||
@@ -82,6 +84,9 @@ class UserAssetsV2Endpoint(BaseAPIView):
|
||||
size = int(request.data.get("size", settings.FILE_SIZE_LIMIT))
|
||||
entity_type = request.data.get("entity_type", False)
|
||||
|
||||
# Check if the file size is within the limit
|
||||
size_limit = min(size, settings.FILE_SIZE_LIMIT)
|
||||
|
||||
# Check if the entity type is allowed
|
||||
if not entity_type or entity_type not in ["USER_AVATAR", "USER_COVER"]:
|
||||
return Response(
|
||||
@@ -103,9 +108,6 @@ class UserAssetsV2Endpoint(BaseAPIView):
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
# Get the size limit
|
||||
size_limit = min(settings.FILE_SIZE_LIMIT, size)
|
||||
|
||||
# asset key
|
||||
asset_key = f"{uuid.uuid4().hex}-{name}"
|
||||
|
||||
@@ -174,16 +176,19 @@ class WorkspaceFileAssetEndpoint(BaseAPIView):
|
||||
"""This endpoint is used to upload cover images/logos etc for workspace, projects and users."""
|
||||
|
||||
def get_entity_id_field(self, entity_type, entity_id):
|
||||
# Workspace Logo
|
||||
if entity_type == FileAsset.EntityTypeContext.WORKSPACE_LOGO:
|
||||
return {
|
||||
"workspace_id": entity_id,
|
||||
}
|
||||
|
||||
# Project Cover
|
||||
if entity_type == FileAsset.EntityTypeContext.PROJECT_COVER:
|
||||
return {
|
||||
"project_id": entity_id,
|
||||
}
|
||||
|
||||
# User Avatar and Cover
|
||||
if entity_type in [
|
||||
FileAsset.EntityTypeContext.USER_AVATAR,
|
||||
FileAsset.EntityTypeContext.USER_COVER,
|
||||
@@ -192,6 +197,7 @@ class WorkspaceFileAssetEndpoint(BaseAPIView):
|
||||
"user_id": entity_id,
|
||||
}
|
||||
|
||||
# Issue Attachment and Description
|
||||
if entity_type in [
|
||||
FileAsset.EntityTypeContext.ISSUE_ATTACHMENT,
|
||||
FileAsset.EntityTypeContext.ISSUE_DESCRIPTION,
|
||||
@@ -200,11 +206,13 @@ class WorkspaceFileAssetEndpoint(BaseAPIView):
|
||||
"issue_id": entity_id,
|
||||
}
|
||||
|
||||
# Page Description
|
||||
if entity_type == FileAsset.EntityTypeContext.PAGE_DESCRIPTION:
|
||||
return {
|
||||
"page_id": entity_id,
|
||||
}
|
||||
|
||||
# Comment Description
|
||||
if entity_type == FileAsset.EntityTypeContext.COMMENT_DESCRIPTION:
|
||||
return {
|
||||
"comment_id": entity_id,
|
||||
@@ -301,8 +309,20 @@ class WorkspaceFileAssetEndpoint(BaseAPIView):
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
# Get the size limit
|
||||
size_limit = min(settings.FILE_SIZE_LIMIT, size)
|
||||
if entity_type in [
|
||||
FileAsset.EntityTypeContext.WORKSPACE_LOGO,
|
||||
FileAsset.EntityTypeContext.PROJECT_COVER,
|
||||
]:
|
||||
size_limit = min(size, settings.FILE_SIZE_LIMIT)
|
||||
else:
|
||||
if settings.IS_MULTI_TENANT and check_workspace_feature_flag(
|
||||
feature_key=FeatureFlag.FILE_SIZE_LIMIT_PRO,
|
||||
slug=slug,
|
||||
user_id=str(request.user.id),
|
||||
):
|
||||
size_limit = min(size, settings.PRO_FILE_SIZE_LIMIT)
|
||||
else:
|
||||
size_limit = min(size, settings.FILE_SIZE_LIMIT)
|
||||
|
||||
# Get the workspace
|
||||
workspace = Workspace.objects.get(slug=slug)
|
||||
@@ -454,7 +474,7 @@ class AssetRestoreEndpoint(BaseAPIView):
|
||||
class ProjectAssetEndpoint(BaseAPIView):
|
||||
"""This endpoint is used to upload cover images/logos etc for workspace, projects and users."""
|
||||
|
||||
def get_entity_id_fiekd(self, entity_type, entity_id):
|
||||
def get_entity_id_field(self, entity_type, entity_id):
|
||||
if entity_type == FileAsset.EntityTypeContext.WORKSPACE_LOGO:
|
||||
return {
|
||||
"workspace_id": entity_id,
|
||||
@@ -513,7 +533,7 @@ class ProjectAssetEndpoint(BaseAPIView):
|
||||
)
|
||||
|
||||
# Check if the file type is allowed
|
||||
allowed_types = ["image/jpeg", "image/png", "image/webp"]
|
||||
allowed_types = ["image/jpeg", "image/png", "image/webp", "image/jpg"]
|
||||
if type not in allowed_types:
|
||||
return Response(
|
||||
{
|
||||
@@ -523,8 +543,20 @@ class ProjectAssetEndpoint(BaseAPIView):
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
# Get the size limit
|
||||
size_limit = min(settings.FILE_SIZE_LIMIT, size)
|
||||
if entity_type in [
|
||||
FileAsset.EntityTypeContext.WORKSPACE_LOGO,
|
||||
FileAsset.EntityTypeContext.PROJECT_COVER,
|
||||
]:
|
||||
size_limit = min(size, settings.FILE_SIZE_LIMIT)
|
||||
else:
|
||||
if check_workspace_feature_flag(
|
||||
feature_key=FeatureFlag.FILE_SIZE_LIMIT_PRO,
|
||||
slug=slug,
|
||||
user_id=str(request.user.id),
|
||||
):
|
||||
size_limit = min(size, settings.PRO_FILE_SIZE_LIMIT)
|
||||
else:
|
||||
size_limit = min(size, settings.FILE_SIZE_LIMIT)
|
||||
|
||||
# Get the workspace
|
||||
workspace = Workspace.objects.get(slug=slug)
|
||||
@@ -545,7 +577,7 @@ class ProjectAssetEndpoint(BaseAPIView):
|
||||
created_by=request.user,
|
||||
entity_type=entity_type,
|
||||
project_id=project_id,
|
||||
**self.get_entity_id_fiekd(entity_type, entity_identifier),
|
||||
**self.get_entity_id_field(entity_type, entity_identifier),
|
||||
)
|
||||
|
||||
# Get the presigned URL
|
||||
@@ -633,7 +665,6 @@ class ProjectAssetEndpoint(BaseAPIView):
|
||||
|
||||
|
||||
class ProjectBulkAssetEndpoint(BaseAPIView):
|
||||
|
||||
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
|
||||
def post(self, request, slug, project_id, entity_id):
|
||||
asset_ids = request.data.get("asset_ids", [])
|
||||
|
||||
@@ -20,6 +20,8 @@ from plane.db.models import FileAsset, Workspace
|
||||
from plane.bgtasks.issue_activities_task import issue_activity
|
||||
from plane.app.permissions import allow_permission, ROLE
|
||||
from plane.settings.storage import S3Storage
|
||||
from plane.payment.flags.flag_decorator import check_workspace_feature_flag
|
||||
from plane.payment.flags.flag import FeatureFlag
|
||||
|
||||
|
||||
class IssueAttachmentEndpoint(BaseAPIView):
|
||||
@@ -71,7 +73,6 @@ class IssueAttachmentEndpoint(BaseAPIView):
|
||||
notification=True,
|
||||
origin=request.META.get("HTTP_ORIGIN"),
|
||||
)
|
||||
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
@allow_permission(
|
||||
@@ -97,7 +98,27 @@ class IssueAttachmentV2Endpoint(BaseAPIView):
|
||||
def post(self, request, slug, project_id, issue_id):
|
||||
name = request.data.get("name")
|
||||
type = request.data.get("type", False)
|
||||
size = int(request.data.get("size", settings.FILE_SIZE_LIMIT))
|
||||
size = request.data.get("size")
|
||||
|
||||
# Check if the request is valid
|
||||
if not name or not size:
|
||||
return Response(
|
||||
{
|
||||
"error": "Invalid request.",
|
||||
"status": False,
|
||||
},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
# Check if the file size is greater than the limit
|
||||
if check_workspace_feature_flag(
|
||||
feature_key=FeatureFlag.FILE_SIZE_LIMIT_PRO,
|
||||
slug=slug,
|
||||
user_id=str(request.user.id),
|
||||
):
|
||||
size_limit = min(size, settings.PRO_FILE_SIZE_LIMIT)
|
||||
else:
|
||||
size_limit = min(size, settings.FILE_SIZE_LIMIT)
|
||||
|
||||
if not type or type not in settings.ATTACHMENT_MIME_TYPES:
|
||||
return Response(
|
||||
@@ -114,9 +135,6 @@ class IssueAttachmentV2Endpoint(BaseAPIView):
|
||||
# asset key
|
||||
asset_key = f"{workspace.id}/{uuid.uuid4().hex}-{name}"
|
||||
|
||||
# Get the size limit
|
||||
size_limit = min(size, settings.FILE_SIZE_LIMIT)
|
||||
|
||||
# Create a File Asset
|
||||
asset = FileAsset.objects.create(
|
||||
attributes={
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
# Django imports
|
||||
from django.db.models import (
|
||||
Exists,
|
||||
OuterRef,
|
||||
Prefetch,
|
||||
)
|
||||
from django.db.models import Exists, OuterRef, Prefetch, Q
|
||||
from django.utils import timezone
|
||||
|
||||
# Module imports
|
||||
@@ -69,6 +65,15 @@ class WorkspaceActiveCycleEndpoint(BaseAPIView):
|
||||
.order_by("-is_favorite", "name")
|
||||
.distinct()
|
||||
)
|
||||
|
||||
active_cycles = active_cycles.filter(
|
||||
~Q(
|
||||
project__project_projectmember__role=5,
|
||||
project__project_projectmember__member=self.request.user,
|
||||
project__project_projectmember__is_active=True,
|
||||
)
|
||||
)
|
||||
|
||||
return self.paginate(
|
||||
request=request,
|
||||
queryset=active_cycles,
|
||||
|
||||
@@ -27,7 +27,7 @@ from plane.db.models import (
|
||||
IssueVote,
|
||||
IssueView,
|
||||
IssueLink,
|
||||
IssueAttachment,
|
||||
FileAsset,
|
||||
)
|
||||
from plane.utils.issue_filters import issue_filters
|
||||
from plane.ee.serializers import (
|
||||
@@ -131,8 +131,9 @@ class IssueViewsPublicEndpoint(BaseAPIView):
|
||||
.values("count")
|
||||
)
|
||||
.annotate(
|
||||
attachment_count=IssueAttachment.objects.filter(
|
||||
issue=OuterRef("id")
|
||||
attachment_count=FileAsset.objects.filter(
|
||||
entity_type=FileAsset.EntityTypeContext.ISSUE_ATTACHMENT,
|
||||
entity_identifier=OuterRef("id"),
|
||||
)
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
|
||||
@@ -24,7 +24,7 @@ from plane.db.models import (
|
||||
IssueAssignee,
|
||||
IssueLabel,
|
||||
Workspace,
|
||||
IssueAttachment,
|
||||
FileAsset,
|
||||
IssueSubscriber,
|
||||
)
|
||||
|
||||
@@ -291,9 +291,10 @@ class IssueAttachmentMutation:
|
||||
issue: strawberry.ID,
|
||||
attachment: strawberry.ID,
|
||||
) -> bool:
|
||||
issue_attachment = await sync_to_async(IssueAttachment.objects.get)(
|
||||
issue_attachment = await sync_to_async(FileAsset.objects.get)(
|
||||
id=attachment,
|
||||
issue_id=issue,
|
||||
entity_type=FileAsset.EntityTypeContext.ISSUE_ATTACHMENT,
|
||||
entity_identifier=issue,
|
||||
project_id=project,
|
||||
workspace__slug=slug,
|
||||
)
|
||||
|
||||
@@ -9,7 +9,7 @@ from strawberry.types import Info
|
||||
from strawberry.permission import PermissionExtension
|
||||
|
||||
# Module Imports
|
||||
from plane.db.models import IssueAttachment
|
||||
from plane.db.models import FileAsset
|
||||
from plane.graphql.types.attachment import IssueAttachmentType
|
||||
from plane.graphql.permissions.project import ProjectBasePermission
|
||||
|
||||
@@ -28,8 +28,11 @@ class IssueAttachmentQuery:
|
||||
) -> list[IssueAttachmentType]:
|
||||
|
||||
issue_attachments = await sync_to_async(list)(
|
||||
IssueAttachment.objects.filter(
|
||||
issue_id=issue, workspace__slug=slug, project_id=project
|
||||
FileAsset.objects.filter(
|
||||
entity_identifier=issue,
|
||||
entity_type=FileAsset.EntityTypeContext.ISSUE_ATTACHMENT,
|
||||
workspace__slug=slug,
|
||||
project_id=project,
|
||||
)
|
||||
)
|
||||
return issue_attachments
|
||||
|
||||
@@ -8,10 +8,10 @@ import strawberry_django
|
||||
from strawberry.scalars import JSON
|
||||
|
||||
# Module Imports
|
||||
from plane.db.models import IssueAttachment
|
||||
from plane.db.models import FileAsset
|
||||
|
||||
|
||||
@strawberry_django.type(IssueAttachment)
|
||||
@strawberry_django.type(FileAsset)
|
||||
class IssueAttachmentType:
|
||||
id: strawberry.ID
|
||||
created_at: datetime
|
||||
@@ -24,7 +24,8 @@ class IssueAttachmentType:
|
||||
updated_by: strawberry.ID
|
||||
project: strawberry.ID
|
||||
workspace: strawberry.ID
|
||||
issue: strawberry.ID
|
||||
entity_identifier: strawberry.ID
|
||||
entity_type: str
|
||||
|
||||
@strawberry.field
|
||||
def workspace(self) -> int:
|
||||
@@ -36,7 +37,7 @@ class IssueAttachmentType:
|
||||
|
||||
@strawberry.field
|
||||
def issue(self) -> int:
|
||||
return self.issue_id
|
||||
return self.entity_identifier
|
||||
|
||||
@strawberry.field
|
||||
def created_by(self) -> int:
|
||||
|
||||
@@ -30,6 +30,8 @@ class FeatureFlag(Enum):
|
||||
PROJECT_GROUPING = "PROJECT_GROUPING"
|
||||
# Active cycle progress
|
||||
ACTIVE_CYCLE_PRO = "ACTIVE_CYCLE_PRO"
|
||||
# Pro file size limit
|
||||
FILE_SIZE_LIMIT_PRO = "FILE_SIZE_LIMIT_PRO"
|
||||
|
||||
|
||||
class AdminFeatureFlag(Enum):
|
||||
|
||||
@@ -340,6 +340,7 @@ if bool(os.environ.get("SENTRY_DSN", False)) and os.environ.get(
|
||||
# Application Envs
|
||||
SLACK_BOT_TOKEN = os.environ.get("SLACK_BOT_TOKEN", False)
|
||||
FILE_SIZE_LIMIT = int(os.environ.get("FILE_SIZE_LIMIT", 5242880))
|
||||
PRO_FILE_SIZE_LIMIT = int(os.environ.get("PRO_FILE_SIZE_LIMIT", 104857600))
|
||||
|
||||
# Unsplash Access key
|
||||
UNSPLASH_ACCESS_KEY = os.environ.get("UNSPLASH_ACCESS_KEY")
|
||||
|
||||
@@ -20,8 +20,8 @@ interface IDocumentReadOnlyEditor {
|
||||
containerClassName: string;
|
||||
displayConfig?: TDisplayConfig;
|
||||
editorClassName?: string;
|
||||
fileHandler: Pick<TFileHandler, "getAssetSrc">;
|
||||
embedHandler: TReadOnlyEmbedConfig;
|
||||
fileHandler: Pick<TFileHandler, "getAssetSrc">;
|
||||
tabIndex?: number;
|
||||
handleEditorReady?: (value: boolean) => void;
|
||||
mentionHandler: {
|
||||
|
||||
@@ -6,6 +6,8 @@ import { FileText } from "lucide-react";
|
||||
import { DocumentReadOnlyEditorWithRef, EditorRefApi } from "@plane/editor";
|
||||
// ui
|
||||
import { Logo } from "@plane/ui";
|
||||
// helpers
|
||||
import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper";
|
||||
// hooks
|
||||
import { usePublish } from "@/hooks/store";
|
||||
import { useMention } from "@/hooks/use-mention";
|
||||
@@ -63,6 +65,9 @@ export const PageDetailsMainContent: React.FC<Props> = observer((props) => {
|
||||
id={pageDetails.id}
|
||||
initialValue={pageDetails.description_html ?? "<p></p>"}
|
||||
containerClassName="p-0 pb-64 border-none"
|
||||
fileHandler={getReadOnlyEditorFileHandlers({
|
||||
anchor,
|
||||
})}
|
||||
mentionHandler={{
|
||||
highlights: mentionHighlights,
|
||||
}}
|
||||
|
||||
@@ -21,11 +21,11 @@ import { EIssuesStoreType } from "@/constants/issue";
|
||||
// helpers
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
import { renderFormattedDate, renderFormattedDateWithoutYear } from "@/helpers/date-time.helper";
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
// hooks
|
||||
import { useIssues, useProjectState } from "@/hooks/store";
|
||||
import useLocalStorage from "@/hooks/use-local-storage";
|
||||
|
||||
|
||||
export type ActiveCycleStatsProps = {
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
@@ -165,7 +165,7 @@ export const ActiveCycleStats: FC<ActiveCycleStatsProps> = observer((props) => {
|
||||
<div className="flex items-center gap-1.5 flex-shrink-0">
|
||||
<StateDropdown
|
||||
value={issue.state_id ?? undefined}
|
||||
onChange={() => { }}
|
||||
onChange={() => {}}
|
||||
projectId={projectId?.toString() ?? ""}
|
||||
disabled
|
||||
buttonVariant="background-with-text"
|
||||
@@ -216,7 +216,10 @@ export const ActiveCycleStats: FC<ActiveCycleStatsProps> = observer((props) => {
|
||||
key={assignee.assignee_id}
|
||||
title={
|
||||
<div className="flex items-center gap-2">
|
||||
<Avatar name={assignee?.display_name ?? undefined} src={assignee?.avatar ?? undefined} />
|
||||
<Avatar
|
||||
name={assignee?.display_name ?? undefined}
|
||||
src={getFileURL(assignee?.avatar_url ?? "")}
|
||||
/>
|
||||
|
||||
<span>{assignee.display_name}</span>
|
||||
</div>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { ICycle, TCycleGroups } from "@plane/types";
|
||||
import { Tooltip, CycleGroupIcon, getButtonStyling, Avatar, AvatarGroup } from "@plane/ui";
|
||||
// helpers
|
||||
import { renderFormattedDate, findHowManyDaysLeft } from "@/helpers/date-time.helper";
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
import { truncateText } from "@/helpers/string.helper";
|
||||
// hooks
|
||||
import { useMember } from "@/hooks/store";
|
||||
@@ -48,7 +49,7 @@ export const ActiveCycleHeader: FC<ActiveCycleHeaderProps> = (props) => {
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="rounded-sm text-sm">
|
||||
<div className="flex gap-2 divide-x spac divide-x-border-300 text-sm whitespace-nowrap text-custom-text-300 font-medium">
|
||||
<Avatar name={cycleOwnerDetails?.display_name} src={cycleOwnerDetails?.avatar} />
|
||||
<Avatar name={cycleOwnerDetails?.display_name} src={getFileURL(cycleOwnerDetails?.avatar_url ?? "")} />
|
||||
{cycleAssignee.length > 0 && (
|
||||
<span className="pl-2">
|
||||
<AvatarGroup showTooltip>
|
||||
@@ -56,7 +57,7 @@ export const ActiveCycleHeader: FC<ActiveCycleHeaderProps> = (props) => {
|
||||
<Avatar
|
||||
key={member.assignee_id}
|
||||
name={member?.display_name ?? ""}
|
||||
src={member?.avatar ?? ""}
|
||||
src={getFileURL(member?.avatar_url ?? "")}
|
||||
showTooltip={false}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import { FC } from "react";
|
||||
import Link from "next/link";
|
||||
// icons
|
||||
import { UserCircle2 } from "lucide-react";
|
||||
// types
|
||||
import { ICycle, TCycleGroups } from "@plane/types";
|
||||
// ui
|
||||
import { Tooltip, CycleGroupIcon, getButtonStyling } from "@plane/ui";
|
||||
// helpers
|
||||
import { renderFormattedDate, findHowManyDaysLeft } from "@/helpers/date-time.helper";
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
import { truncateText } from "@/helpers/string.helper";
|
||||
// hooks
|
||||
import { useMember } from "@/hooks/store";
|
||||
|
||||
export type ActiveCycleHeaderProps = {
|
||||
cycle: ICycle;
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
};
|
||||
|
||||
export const ActiveCycleHeader: FC<ActiveCycleHeaderProps> = (props) => {
|
||||
const { cycle, workspaceSlug, projectId } = props;
|
||||
// store
|
||||
const { getUserDetails } = useMember();
|
||||
const cycleOwnerDetails = cycle && cycle.owned_by_id ? getUserDetails(cycle.owned_by_id) : undefined;
|
||||
|
||||
const daysLeft = findHowManyDaysLeft(cycle.end_date) ?? 0;
|
||||
const currentCycleStatus = cycle?.status?.toLocaleLowerCase() as TCycleGroups;
|
||||
return (
|
||||
<div className="flex items-center justify-between px-3 py-1.5 rounded-lg border-[0.5px] border-custom-border-100 bg-custom-background-90">
|
||||
<div className="flex items-center gap-2 cursor-default">
|
||||
<CycleGroupIcon cycleGroup={currentCycleStatus} className="h-4 w-4" />
|
||||
<Tooltip tooltipContent={cycle.name} position="top-left">
|
||||
<h3 className="break-words text-lg font-medium">{truncateText(cycle.name, 70)}</h3>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
tooltipContent={`Start date: ${renderFormattedDate(cycle.start_date ?? "")} Due Date: ${renderFormattedDate(
|
||||
cycle.end_date ?? ""
|
||||
)}`}
|
||||
position="top-left"
|
||||
>
|
||||
<span className="flex gap-1 whitespace-nowrap rounded-sm text-custom-text-400 font-semibold text-sm leading-5">
|
||||
{`${daysLeft} ${daysLeft > 1 ? "days" : "day"} left`}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="rounded-sm text-sm">
|
||||
<div className="flex gap-2 text-sm whitespace-nowrap text-custom-text-300 font-medium">
|
||||
<span className="flex items-center gap-1.5">
|
||||
<UserCircle2 className="h-4 w-4" />
|
||||
<span className="text-base leading-5">Lead</span>
|
||||
</span>
|
||||
<div className="flex items-center gap-1.5">
|
||||
{cycleOwnerDetails?.avatar_url && cycleOwnerDetails?.avatar_url !== "" ? (
|
||||
<img
|
||||
src={getFileURL(cycleOwnerDetails?.avatar_url)}
|
||||
className="rounded-full flex-shrink-0 w-5 h-5 object-cover"
|
||||
alt={cycleOwnerDetails?.display_name}
|
||||
/>
|
||||
) : (
|
||||
<span className="flex h-5 w-5 items-center justify-center rounded-full bg-custom-background-100 capitalize">
|
||||
{cycleOwnerDetails?.display_name.charAt(0)}
|
||||
</span>
|
||||
)}
|
||||
<span className="text-base leading-5">{cycleOwnerDetails?.display_name}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Link
|
||||
href={`/${workspaceSlug}/projects/${projectId}/cycles/${cycle.id}`}
|
||||
className={`${getButtonStyling("primary", "sm")} cursor-pointer`}
|
||||
>
|
||||
View Cycle
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,15 +1,18 @@
|
||||
import { FC, useRef, useState } from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import Image from "next/image";
|
||||
import { useParams } from "next/navigation";
|
||||
import useSWR from "swr";
|
||||
import { ExternalLink, RefreshCw } from "lucide-react";
|
||||
// editor
|
||||
// plane editor
|
||||
import { DocumentReadOnlyEditorWithRef, EditorRefApi } from "@plane/editor";
|
||||
// ui
|
||||
// plane ui
|
||||
import { Button, EModalPosition, EModalWidth, getButtonStyling, ModalCore, setToast, TOAST_TYPE } from "@plane/ui";
|
||||
// helpers
|
||||
// components
|
||||
import { LogoSpinner } from "@/components/common";
|
||||
// helpers
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper";
|
||||
// hooks
|
||||
import { useInstance } from "@/hooks/store";
|
||||
// assets
|
||||
@@ -29,6 +32,8 @@ export const ProductUpdatesModal: FC<ProductUpdatesModalProps> = observer((props
|
||||
const { isOpen, handleClose } = props;
|
||||
// states
|
||||
const [isCheckingForUpdates, setIsCheckingForUpdates] = useState(false);
|
||||
// params
|
||||
const { workspaceSlug, projectId } = useParams();
|
||||
// store
|
||||
const { isUpdateAvailable, updateInstanceInfo } = useInstance();
|
||||
const { currentWorkspaceSubscribedPlanDetail: subscriptionDetail } = useWorkspaceSubscription();
|
||||
@@ -137,6 +142,10 @@ export const ProductUpdatesModal: FC<ProductUpdatesModalProps> = observer((props
|
||||
id={data.id}
|
||||
initialValue={data.description_html ?? "<p></p>"}
|
||||
containerClassName="p-0 border-none"
|
||||
fileHandler={getReadOnlyEditorFileHandlers({
|
||||
projectId: projectId?.toString() ?? "",
|
||||
workspaceSlug: workspaceSlug?.toString() ?? "",
|
||||
})}
|
||||
mentionHandler={{
|
||||
highlights: () => Promise.resolve([]),
|
||||
}}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
renderFormattedDate,
|
||||
renderFormattedTime,
|
||||
} from "@/helpers/date-time.helper";
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
// hooks
|
||||
import { useMember } from "@/hooks/store";
|
||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
@@ -69,9 +70,9 @@ export const IssueActivityWorklog: FC<TIssueActivityWorklog> = observer((props)
|
||||
>
|
||||
<div className="absolute left-[13px] top-0 bottom-0 w-0.5 bg-custom-background-80" aria-hidden />
|
||||
<div className="flex-shrink-0 relative w-7 h-7 rounded-full flex justify-center items-center z-10 bg-gray-500 text-white border border-white uppercase font-medium">
|
||||
{currentUser?.member?.avatar && currentUser?.member?.avatar !== "" ? (
|
||||
{currentUser?.member?.avatar_url && currentUser?.member?.avatar_url !== "" ? (
|
||||
<img
|
||||
src={currentUser?.member?.avatar}
|
||||
src={getFileURL(currentUser?.member?.avatar_url)}
|
||||
alt={currentUser?.member?.display_name}
|
||||
height={30}
|
||||
width={30}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import React, { RefObject, useEffect, useRef, useState } from "react";
|
||||
import { useParams } from "next/navigation";
|
||||
import { ChevronRight, CornerDownRight, LucideIcon, PencilLine, RefreshCcw, Sparkles } from "lucide-react";
|
||||
// plane editor
|
||||
import { EditorRefApi } from "@plane/editor";
|
||||
@@ -21,6 +20,8 @@ type Props = {
|
||||
editorRef: RefObject<EditorRefApi>;
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
projectId?: string;
|
||||
workspaceSlug: string;
|
||||
};
|
||||
|
||||
const MENU_ITEMS: {
|
||||
@@ -93,15 +94,13 @@ const TONES_LIST = [
|
||||
];
|
||||
|
||||
export const EditorAIMenu: React.FC<Props> = (props) => {
|
||||
const { editorRef, isOpen, onClose } = props;
|
||||
const { editorRef, isOpen, onClose, projectId, workspaceSlug } = props;
|
||||
// states
|
||||
const [activeTask, setActiveTask] = useState<AI_EDITOR_TASKS | null>(null);
|
||||
const [response, setResponse] = useState<string | undefined>(undefined);
|
||||
const [isRegenerating, setIsRegenerating] = useState(false);
|
||||
// refs
|
||||
const responseContainerRef = useRef<HTMLDivElement>(null);
|
||||
// params
|
||||
const { workspaceSlug } = useParams();
|
||||
const handleGenerateResponse = async (payload: TTaskPayload) => {
|
||||
if (!workspaceSlug) return;
|
||||
await aiService.performEditorTask(workspaceSlug.toString(), payload).then((res) => setResponse(res.response));
|
||||
@@ -235,6 +234,8 @@ export const EditorAIMenu: React.FC<Props> = (props) => {
|
||||
initialValue={response}
|
||||
containerClassName="!p-0 border-none"
|
||||
editorClassName="!pl-0"
|
||||
projectId={projectId}
|
||||
workspaceSlug={workspaceSlug}
|
||||
/>
|
||||
<div className="mt-3 flex items-center gap-4">
|
||||
<button
|
||||
|
||||
@@ -14,10 +14,12 @@ import {
|
||||
} from "@plane/editor";
|
||||
// types
|
||||
import { IUserLite } from "@plane/types";
|
||||
import { EFileAssetType } from "@plane/types/src/enums";
|
||||
// components
|
||||
import { PageContentBrowser, PageEditorTitle, PageContentLoader } from "@/components/pages";
|
||||
// helpers
|
||||
import { cn, LIVE_BASE_PATH, LIVE_BASE_URL } from "@/helpers/common.helper";
|
||||
import { getEditorFileHandlers, getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper";
|
||||
import { generateRandomColor } from "@/helpers/string.helper";
|
||||
// hooks
|
||||
import { useMember, useUser, useWorkspace } from "@/hooks/store";
|
||||
@@ -26,6 +28,7 @@ import { usePageFilters } from "@/hooks/use-page-filters";
|
||||
import { EditorAIMenu, IssueEmbedCard } from "@/plane-web/components/pages";
|
||||
// plane web hooks
|
||||
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
|
||||
import { useFileSize } from "@/plane-web/hooks/use-file-size";
|
||||
import { useWorkspaceIssueEmbed } from "@/plane-web/hooks/use-workspace-issue-embed";
|
||||
import { useWorkspaceMention } from "@/plane-web/hooks/use-workspace-mention";
|
||||
// store
|
||||
@@ -69,7 +72,7 @@ export const WorkspacePageEditorBody: React.FC<Props> = observer((props) => {
|
||||
const pageId = page?.id;
|
||||
const pageTitle = page?.name ?? "";
|
||||
const pageDescription = page?.description_html;
|
||||
const { isContentEditable, updateTitle, setIsSubmitting } = page;
|
||||
const { isContentEditable, updateTitle } = page;
|
||||
const workspaceMemberDetails = workspaceMemberIds?.map((id) => getUserDetails(id) as IUserLite);
|
||||
// use-mention
|
||||
const { mentionHighlights, mentionSuggestions } = useWorkspaceMention({
|
||||
@@ -83,6 +86,8 @@ export const WorkspacePageEditorBody: React.FC<Props> = observer((props) => {
|
||||
const { fontSize, fontStyle, isFullWidth } = usePageFilters();
|
||||
// issue-embed
|
||||
const { fetchIssues } = useWorkspaceIssueEmbed(workspaceSlug?.toString() ?? "");
|
||||
// file size
|
||||
const { maxFileSize } = useFileSize();
|
||||
|
||||
const displayConfig: TDisplayConfig = {
|
||||
fontSize,
|
||||
@@ -90,8 +95,15 @@ export const WorkspacePageEditorBody: React.FC<Props> = observer((props) => {
|
||||
};
|
||||
|
||||
const getAIMenu = useCallback(
|
||||
({ isOpen, onClose }: TAIMenuProps) => <EditorAIMenu editorRef={editorRef} isOpen={isOpen} onClose={onClose} />,
|
||||
[editorRef]
|
||||
({ isOpen, onClose }: TAIMenuProps) => (
|
||||
<EditorAIMenu
|
||||
editorRef={editorRef}
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
||||
/>
|
||||
),
|
||||
[editorRef, workspaceSlug]
|
||||
);
|
||||
|
||||
const handleServerConnect = useCallback(() => {
|
||||
@@ -171,12 +183,22 @@ export const WorkspacePageEditorBody: React.FC<Props> = observer((props) => {
|
||||
{isContentEditable ? (
|
||||
<CollaborativeDocumentEditorWithRef
|
||||
id={pageId}
|
||||
fileHandler={{
|
||||
cancel: fileService.cancelUpload,
|
||||
delete: fileService.getDeleteImageFunction(workspaceId),
|
||||
restore: fileService.getRestoreImageFunction(workspaceId),
|
||||
upload: fileService.getUploadFileFunction(workspaceSlug as string, setIsSubmitting),
|
||||
}}
|
||||
fileHandler={getEditorFileHandlers({
|
||||
maxFileSize,
|
||||
uploadFile: async (file) => {
|
||||
const { asset_id } = await fileService.uploadWorkspaceAsset(
|
||||
workspaceSlug?.toString() ?? "",
|
||||
{
|
||||
entity_identifier: pageId,
|
||||
entity_type: EFileAssetType.PAGE_DESCRIPTION,
|
||||
},
|
||||
file
|
||||
);
|
||||
return asset_id;
|
||||
},
|
||||
workspaceId,
|
||||
workspaceSlug: workspaceSlug?.toString() ?? "",
|
||||
})}
|
||||
handleEditorReady={handleEditorReady}
|
||||
ref={editorRef}
|
||||
containerClassName="h-full p-0 pb-64"
|
||||
@@ -237,6 +259,9 @@ export const WorkspacePageEditorBody: React.FC<Props> = observer((props) => {
|
||||
containerClassName="p-0 pb-64 border-none"
|
||||
displayConfig={displayConfig}
|
||||
editorClassName="pl-10"
|
||||
fileHandler={getReadOnlyEditorFileHandlers({
|
||||
workspaceSlug: workspaceSlug?.toString() ?? "",
|
||||
})}
|
||||
mentionHandler={{
|
||||
highlights: mentionHighlights,
|
||||
}}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Earth, Info, Lock, Minus } from "lucide-react";
|
||||
import { Avatar, FavoriteStar, TOAST_TYPE, Tooltip, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { renderFormattedDate } from "@/helpers/date-time.helper";
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
// hooks
|
||||
import { useMember } from "@/hooks/store";
|
||||
// plane web components
|
||||
@@ -53,7 +54,7 @@ export const PageListBlockItemAction: FC<Props> = observer((props) => {
|
||||
{/* page details */}
|
||||
<div className="cursor-default">
|
||||
<Tooltip tooltipHeading="Owned by" tooltipContent={ownerDetails?.display_name}>
|
||||
<Avatar src={ownerDetails?.avatar} name={ownerDetails?.display_name} />
|
||||
<Avatar src={getFileURL(ownerDetails?.avatar_url ?? "")} name={ownerDetails?.display_name} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="cursor-default text-custom-text-300">
|
||||
|
||||
@@ -17,6 +17,7 @@ import { Avatar, Loader, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
import { WorkspaceLogo } from "@/components/workspace";
|
||||
// helpers
|
||||
import { cn, GOD_MODE_URL } from "@/helpers/common.helper";
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
// hooks
|
||||
import { useAppTheme, useUser, useUserProfile, useWorkspace } from "@/hooks/store";
|
||||
|
||||
@@ -107,7 +108,7 @@ export const PagesAppSidebarDropdown = observer(() => {
|
||||
)}
|
||||
>
|
||||
<div className="flex-grow flex items-center gap-2 truncate">
|
||||
<WorkspaceLogo logo={activeWorkspace?.logo} name={activeWorkspace?.name} />
|
||||
<WorkspaceLogo logo={getFileURL(activeWorkspace?.logo_url ?? "")} name={activeWorkspace?.name} />
|
||||
{!sidebarCollapsed && (
|
||||
<h4 className="truncate text-base font-medium text-custom-text-100">
|
||||
{activeWorkspace?.name ?? "Loading..."}
|
||||
@@ -160,17 +161,17 @@ export const PagesAppSidebarDropdown = observer(() => {
|
||||
<div className="flex items-center justify-start gap-2.5 truncate">
|
||||
<span
|
||||
className={`relative flex h-6 w-6 flex-shrink-0 items-center justify-center p-2 text-xs uppercase ${
|
||||
!workspace?.logo && "rounded bg-custom-primary-500 text-white"
|
||||
!workspace?.logo_url && "rounded bg-custom-primary-500 text-white"
|
||||
}`}
|
||||
>
|
||||
{workspace?.logo && workspace.logo !== "" ? (
|
||||
{workspace?.logo_url && workspace.logo_url !== "" ? (
|
||||
<img
|
||||
src={workspace.logo}
|
||||
src={getFileURL(workspace.logo_url)}
|
||||
className="absolute left-0 top-0 h-full w-full rounded object-cover"
|
||||
alt="Workspace Logo"
|
||||
/>
|
||||
) : (
|
||||
workspace?.name?.charAt(0) ?? "..."
|
||||
(workspace?.name?.charAt(0) ?? "...")
|
||||
)}
|
||||
</span>
|
||||
<h5
|
||||
@@ -250,7 +251,7 @@ export const PagesAppSidebarDropdown = observer(() => {
|
||||
<Menu.Button className="grid place-items-center outline-none" ref={setReferenceElement}>
|
||||
<Avatar
|
||||
name={currentUser?.display_name}
|
||||
src={currentUser?.avatar || undefined}
|
||||
src={getFileURL(currentUser?.avatar_url ?? "")}
|
||||
size={24}
|
||||
shape="square"
|
||||
className="!text-base"
|
||||
|
||||
@@ -8,6 +8,8 @@ import { IUserLite } from "@plane/types";
|
||||
import { Loader } from "@plane/ui";
|
||||
// components
|
||||
import { TVersionEditorProps } from "@/components/pages";
|
||||
// helpers
|
||||
import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper";
|
||||
// hooks
|
||||
import { useMember, useUser } from "@/hooks/store";
|
||||
import { usePageFilters } from "@/hooks/use-page-filters";
|
||||
@@ -94,6 +96,9 @@ export const WorkspacePagesVersionEditor: React.FC<TVersionEditorProps> = observ
|
||||
containerClassName="p-0 pb-64 border-none"
|
||||
displayConfig={displayConfig}
|
||||
editorClassName="pl-10"
|
||||
fileHandler={getReadOnlyEditorFileHandlers({
|
||||
workspaceSlug: workspaceSlug?.toString() ?? "",
|
||||
})}
|
||||
mentionHandler={{
|
||||
highlights: mentionHighlights,
|
||||
}}
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
|
||||
import { observer } from "mobx-react";
|
||||
import { X } from "lucide-react";
|
||||
// ui
|
||||
// plane ui
|
||||
import { Avatar } from "@plane/ui";
|
||||
// helpers
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
// types
|
||||
import { useMember } from "@/hooks/store";
|
||||
|
||||
@@ -29,7 +31,7 @@ export const AppliedMembersFilters: React.FC<Props> = observer((props) => {
|
||||
|
||||
return (
|
||||
<div key={memberId} className="flex items-center gap-1 rounded bg-custom-background-80 p-1 text-xs">
|
||||
<Avatar name={memberDetails.display_name} src={memberDetails.avatar} showTooltip={false} />
|
||||
<Avatar name={memberDetails.display_name} src={getFileURL(memberDetails.avatar_url)} showTooltip={false} />
|
||||
<span className="normal-case">{memberDetails.display_name}</span>
|
||||
{editable && (
|
||||
<button
|
||||
|
||||
@@ -5,6 +5,8 @@ import { observer } from "mobx-react";
|
||||
import { useForm, FormProvider } from "react-hook-form";
|
||||
// ui
|
||||
import { Button, setToast, TOAST_TYPE } from "@plane/ui";
|
||||
// types
|
||||
import { TCreateProjectFormProps } from "@/ce/components/projects/create/root";
|
||||
// constants
|
||||
import ProjectCommonAttributes from "@/components/project/create/common-attributes";
|
||||
import ProjectCreateHeader from "@/components/project/create/header";
|
||||
@@ -21,16 +23,8 @@ import { TProject } from "@/plane-web/types/projects";
|
||||
import { EWorkspaceFeatures } from "@/plane-web/types/workspace-feature";
|
||||
import ProjectAttributes from "./attributes";
|
||||
|
||||
type Props = {
|
||||
setToFavorite?: boolean;
|
||||
workspaceSlug: string;
|
||||
onClose: () => void;
|
||||
handleNextStep: (projectId: string) => void;
|
||||
data?: Partial<TProject>;
|
||||
};
|
||||
|
||||
const defaultValues: Partial<TProject> = {
|
||||
cover_image: PROJECT_UNSPLASH_COVERS[Math.floor(Math.random() * PROJECT_UNSPLASH_COVERS.length)],
|
||||
cover_image_url: PROJECT_UNSPLASH_COVERS[Math.floor(Math.random() * PROJECT_UNSPLASH_COVERS.length)],
|
||||
description: "",
|
||||
logo_props: {
|
||||
in_use: "emoji",
|
||||
@@ -44,8 +38,8 @@ const defaultValues: Partial<TProject> = {
|
||||
project_lead: null,
|
||||
};
|
||||
|
||||
export const CreateProjectForm: FC<Props> = observer((props) => {
|
||||
const { setToFavorite, workspaceSlug, onClose, handleNextStep, data } = props;
|
||||
export const CreateProjectForm: FC<TCreateProjectFormProps> = observer((props) => {
|
||||
const { setToFavorite, workspaceSlug, onClose, handleNextStep, data, updateCoverImageStatus } = props;
|
||||
// store
|
||||
const { captureProjectEvent } = useEventTracker();
|
||||
const { addProjectToFavorites, createProject } = useProject();
|
||||
@@ -97,23 +91,27 @@ export const CreateProjectForm: FC<Props> = observer((props) => {
|
||||
id,
|
||||
member_id: id,
|
||||
role: EUserPermissions.MEMBER,
|
||||
member__avatar: memberMap[id]?.avatar,
|
||||
member__avatar_url: memberMap[id]?.avatar_url,
|
||||
member__display_name: memberMap[id]?.display_name,
|
||||
}));
|
||||
formData.identifier = formData.identifier?.toUpperCase();
|
||||
if (members) formData.members = members;
|
||||
const coverImage = formData.cover_image_url;
|
||||
|
||||
return createProject(workspaceSlug.toString(), formData)
|
||||
.then((res) => {
|
||||
.then(async (res) => {
|
||||
if (coverImage) {
|
||||
await updateCoverImageStatus(res.id, coverImage);
|
||||
}
|
||||
const newPayload = {
|
||||
...res,
|
||||
state: "SUCCESS",
|
||||
};
|
||||
isProjectGroupingEnabled &&
|
||||
members &&
|
||||
if (isProjectGroupingEnabled && members) {
|
||||
bulkAddMembersToProject(workspaceSlug.toString(), res.id, {
|
||||
members,
|
||||
});
|
||||
}
|
||||
captureProjectEvent({
|
||||
eventName: PROJECT_CREATED,
|
||||
payload: newPayload,
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
|
||||
import { useMemo, useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
// plane ui
|
||||
import { Avatar } from "@plane/ui";
|
||||
// components
|
||||
import { FilterHeader, FilterOption } from "@/components/issues";
|
||||
// helpers
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
// hooks
|
||||
import { useMember } from "@/hooks/store";
|
||||
|
||||
@@ -86,7 +89,14 @@ export const FilterUser: React.FC<TFilterUser> = observer((props) => {
|
||||
key={member.id}
|
||||
isChecked={appliedFilters?.includes(member.id) ? true : false}
|
||||
onClick={() => member.id && handleFilter(member.id)}
|
||||
icon={<Avatar name={member.display_name} src={member.avatar} showTooltip={false} size="md" />}
|
||||
icon={
|
||||
<Avatar
|
||||
name={member.display_name}
|
||||
src={getFileURL(member.avatar_url)}
|
||||
showTooltip={false}
|
||||
size="md"
|
||||
/>
|
||||
}
|
||||
title={member.display_name.charAt(0).toUpperCase() + member.display_name.slice(1)}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -6,6 +6,7 @@ import { IWorkspace } from "@plane/types";
|
||||
import { Avatar, PriorityIcon, Tooltip } from "@plane/ui";
|
||||
import { DateRangeDropdown, MemberDropdown } from "@/components/dropdowns";
|
||||
import { renderFormattedPayloadDate, getDate } from "@/helpers/date-time.helper";
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
import { useMember, useUserPermissions } from "@/hooks/store";
|
||||
import { EUserPermissions } from "@/plane-web/constants/user-permissions";
|
||||
import { TProject } from "@/plane-web/types/projects";
|
||||
@@ -111,7 +112,13 @@ const Attributes: React.FC<Props> = observer((props) => {
|
||||
{ "cursor-not-allowed": !isEditingAllowed }
|
||||
)}
|
||||
>
|
||||
<Avatar key={lead.id} name={lead.display_name} src={lead.avatar} size={14} className="text-[9px]" />
|
||||
<Avatar
|
||||
key={lead.id}
|
||||
name={lead.display_name}
|
||||
src={getFileURL(lead.avatar_url)}
|
||||
size={14}
|
||||
className="text-[9px]"
|
||||
/>
|
||||
<div>{lead.first_name}</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import smoothScrollIntoView from "smooth-scroll-into-view-if-needed";
|
||||
import { IWorkspace, IWorkspaceMember } from "@plane/types";
|
||||
import { Avatar, PriorityIcon } from "@plane/ui";
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
import { ProjectStateIcon } from "@/plane-web/components/workspace-project-states";
|
||||
import { PROJECT_PRIORITY_MAP } from "@/plane-web/constants/project";
|
||||
import { WORKSPACE_PROJECT_STATE_GROUPS } from "@/plane-web/constants/workspace-project-states";
|
||||
@@ -82,7 +83,12 @@ export const groupDetails = (
|
||||
return {
|
||||
title: memberDetails?.display_name || "Created By",
|
||||
icon: memberDetails ? (
|
||||
<Avatar name={memberDetails.display_name} src={memberDetails.avatar} showTooltip={false} size="md" />
|
||||
<Avatar
|
||||
name={memberDetails.display_name}
|
||||
src={getFileURL(memberDetails.avatar_url)}
|
||||
showTooltip={false}
|
||||
size="md"
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
),
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
import { Logo } from "@/components/common";
|
||||
// constants
|
||||
// helpers
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
import { copyUrlToClipboard } from "@/helpers/string.helper";
|
||||
// hooks
|
||||
import { useProject, useUserPermissions } from "@/hooks/store";
|
||||
@@ -140,10 +141,10 @@ const Details: React.FC<Props> = observer((props) => {
|
||||
<div className="relative ">
|
||||
<div>
|
||||
<img
|
||||
src={
|
||||
project.cover_image ??
|
||||
"https://images.unsplash.com/photo-1672243775941-10d763d9adef?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80"
|
||||
}
|
||||
src={getFileURL(
|
||||
project.cover_image_url ??
|
||||
"https://images.unsplash.com/photo-1672243775941-10d763d9adef?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80"
|
||||
)}
|
||||
alt={project.name}
|
||||
className="relative w-full rounded-t object-cover h-[120px]"
|
||||
// ref={projectCardRef}
|
||||
|
||||
@@ -4,6 +4,7 @@ import Link from "next/link";
|
||||
import { useParams } from "next/navigation";
|
||||
// helpers
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
// hooks
|
||||
import { useMember } from "@/hooks/store";
|
||||
import { TProject } from "@/plane-web/types/projects";
|
||||
@@ -30,12 +31,12 @@ export const SpreadsheetLeadColumn: React.FC<Props> = observer((props: Props) =>
|
||||
>
|
||||
{lead ? (
|
||||
<>
|
||||
{lead.member.avatar && lead.member.avatar.trim() !== "" ? (
|
||||
{lead.member.avatar_url && lead.member.avatar_url.trim() !== "" ? (
|
||||
<Link href={`/${workspaceSlug}/profile/${lead.member.id}`}>
|
||||
<span className="relative flex h-5 w-5 items-center justify-center rounded-full capitalize text-white ">
|
||||
<img
|
||||
width={20}
|
||||
src={lead.member.avatar}
|
||||
src={getFileURL(lead.member.avatar_url)}
|
||||
className="absolute left-0 top-0 h-5 w-5 rounded-full object-cover"
|
||||
alt={lead.member.display_name || lead.member.email}
|
||||
/>
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
import { FC } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
// plane ui
|
||||
import { Avatar } from "@plane/ui";
|
||||
// helpers
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
// hooks
|
||||
import { useMember } from "@/hooks/store";
|
||||
// plane web components
|
||||
@@ -46,7 +49,7 @@ export const WorkspaceWorklogAppliedFilterUsers: FC<TWorkspaceWorklogAppliedFilt
|
||||
<div className="flex items-center gap-1">
|
||||
<Avatar
|
||||
name={userDetails?.member?.display_name}
|
||||
src={userDetails?.member?.avatar ?? undefined}
|
||||
src={getFileURL(userDetails?.member?.avatar_url ?? "")}
|
||||
shape="circle"
|
||||
size="sm"
|
||||
showTooltip={false}
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
import { FC } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
// plane ui
|
||||
import { Avatar, CustomSearchSelect } from "@plane/ui";
|
||||
// helpers
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
// hooks
|
||||
import { useMember } from "@/hooks/store";
|
||||
import { useWorkspaceWorklogs } from "@/plane-web/hooks/store";
|
||||
@@ -42,7 +45,7 @@ export const WorkspaceWorklogFilterUsers: FC<TWorkspaceWorklogFilterUsers> = obs
|
||||
<div className="flex items-center gap-2">
|
||||
<Avatar
|
||||
name={userDetails?.member?.display_name}
|
||||
src={userDetails?.member?.avatar ?? undefined}
|
||||
src={getFileURL(userDetails?.member?.avatar_url ?? "")}
|
||||
shape="circle"
|
||||
size="sm"
|
||||
showTooltip={false}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { FC } from "react";
|
||||
import { Avatar, Table } from "@plane/ui";
|
||||
// helpers
|
||||
import { convertMinutesToHoursMinutesString, renderFormattedDate } from "@/helpers/date-time.helper";
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
// hooks
|
||||
import { useMember, useProject } from "@/hooks/store";
|
||||
// plane web hooks
|
||||
@@ -62,7 +63,7 @@ export const WorklogsPaginatedTableRoot: FC<TWorklogsPaginatedTableRoot> = (prop
|
||||
<div className="flex items-center gap-2">
|
||||
<Avatar
|
||||
name={currentUser?.member?.display_name}
|
||||
src={currentUser?.member?.avatar ?? undefined}
|
||||
src={getFileURL(currentUser?.member?.avatar_url ?? "")}
|
||||
shape="circle"
|
||||
size="sm"
|
||||
showTooltip={false}
|
||||
|
||||
@@ -7,6 +7,8 @@ import { cn } from "@plane/editor";
|
||||
import { Button, EModalWidth, Input, ModalCore, setToast, TOAST_TYPE } from "@plane/ui";
|
||||
// components
|
||||
import { WorkspaceLogo } from "@/components/workspace";
|
||||
// helpers
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
// hooks
|
||||
import { useUserPermissions, useWorkspace } from "@/hooks/store";
|
||||
// plane web constants
|
||||
@@ -83,7 +85,7 @@ export const SubscriptionActivationModal: FC<TSubscriptionActivationModal> = obs
|
||||
<h3 className="flex items-center whitespace-nowrap flex-wrap gap-2 text-xl font-medium">
|
||||
Activate
|
||||
<WorkspaceLogo
|
||||
logo={currentWorkspace?.logo}
|
||||
logo={getFileURL(currentWorkspace?.logo_url ?? "")}
|
||||
name={currentWorkspace?.name}
|
||||
classNames="text-lg font-medium h-5 w-5"
|
||||
/>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export const MAX_PRO_FILE_SIZE = 100 * 1024 * 1024; // 100MB
|
||||
@@ -47,4 +47,4 @@ export const filterActivityOnSelectedFilters = (
|
||||
|
||||
export { EActivityFilterType };
|
||||
|
||||
export const ENABLE_LOCAL_DB_CACHE = true;
|
||||
export const ENABLE_LOCAL_DB_CACHE = false;
|
||||
|
||||
@@ -22,6 +22,7 @@ export enum E_FEATURE_FLAGS {
|
||||
PROJECT_GROUPING = "PROJECT_GROUPING",
|
||||
ACTIVE_CYCLE_PRO = "ACTIVE_CYCLE_PRO",
|
||||
NO_LOAD = "NO_LOAD",
|
||||
FILE_SIZE_LIMIT_PRO = "FILE_SIZE_LIMIT_PRO",
|
||||
// integrations
|
||||
SILO_INTEGRATION = "SILO_INTEGRATION",
|
||||
SILO_JIRA_INTEGRATION = "SILO_JIRA_INTEGRATION",
|
||||
|
||||
@@ -1 +1,33 @@
|
||||
export * from "ce/hooks/use-file-size";
|
||||
import { useMemo } from "react";
|
||||
import { useParams } from "next/navigation";
|
||||
// constants
|
||||
import { MAX_STATIC_FILE_SIZE } from "@/constants/common";
|
||||
// hooks
|
||||
import { useInstance } from "@/hooks/store";
|
||||
// local constants
|
||||
import { MAX_PRO_FILE_SIZE } from "../constants/common";
|
||||
// local hooks
|
||||
import { useFlag, useWorkspaceSubscription } from "./store";
|
||||
|
||||
type TReturnProps = {
|
||||
maxFileSize: number;
|
||||
};
|
||||
|
||||
export const useFileSize = (): TReturnProps => {
|
||||
// params
|
||||
const { workspaceSlug } = useParams();
|
||||
// store hooks
|
||||
const { config } = useInstance();
|
||||
const { currentWorkspaceSubscribedPlanDetail: planDetails } = useWorkspaceSubscription();
|
||||
// derived values
|
||||
const isProPlanEnabled = useFlag(workspaceSlug?.toString() ?? "", "FILE_SIZE_LIMIT_PRO");
|
||||
|
||||
let maxFileSize: number | undefined = useMemo(() => config?.file_size_limit, [config?.file_size_limit]);
|
||||
if (!planDetails?.is_self_managed && isProPlanEnabled) {
|
||||
maxFileSize = MAX_PRO_FILE_SIZE;
|
||||
}
|
||||
|
||||
return {
|
||||
maxFileSize: maxFileSize ?? MAX_STATIC_FILE_SIZE,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -75,7 +75,7 @@ export const useWorkspaceMention = (props: Props) => {
|
||||
type: "User",
|
||||
title: `${memberDetails?.display_name}`,
|
||||
subtitle: memberDetails?.email ?? "",
|
||||
avatar: `${memberDetails?.avatar}`,
|
||||
avatar: `${memberDetails?.avatar_url}`,
|
||||
redirect_uri: `/${workspaceSlug}/profile/${memberDetails?.id}`,
|
||||
}));
|
||||
} else {
|
||||
@@ -88,7 +88,7 @@ export const useWorkspaceMention = (props: Props) => {
|
||||
type: "User",
|
||||
title: `${memberDetails?.display_name}`,
|
||||
subtitle: memberDetails?.email ?? "",
|
||||
avatar: `${memberDetails?.avatar}`,
|
||||
avatar: `${memberDetails?.avatar_url}`,
|
||||
redirect_uri: `/${workspaceSlug}/profile/${memberDetails?.id}`,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -92,7 +92,6 @@ const nextConfig = {
|
||||
destination: `${GOD_MODE_BASE_URL}/:path*`,
|
||||
});
|
||||
}
|
||||
|
||||
return rewrites;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1749,33 +1749,33 @@
|
||||
"@tanstack/react-virtual" "^3.0.0-beta.60"
|
||||
client-only "^0.0.1"
|
||||
|
||||
"@hocuspocus/common@^2.13.6":
|
||||
version "2.13.6"
|
||||
resolved "https://registry.yarnpkg.com/@hocuspocus/common/-/common-2.13.6.tgz#952076654d2497a9c9de63e9a33b1b9307ccb294"
|
||||
integrity sha512-jeEawHoaBckfbjMRPqjANjtQkeHgCBsk3XN7CEs/1jvUm60d86FT4y5fp3MWTEE18qkZacbZldn32za+72RBdg==
|
||||
"@hocuspocus/common@^2.13.7":
|
||||
version "2.13.7"
|
||||
resolved "https://registry.yarnpkg.com/@hocuspocus/common/-/common-2.13.7.tgz#fe5530757f0937865e6188c633c9e52f997a1485"
|
||||
integrity sha512-ROqYfW15XlAGd+qb/FVyp0zUC9Rosv7kdcck9LRMdfW3jT66wK9pDDWL2ily4Qj/zhbLCFtjAUPB4UKln/GYNQ==
|
||||
dependencies:
|
||||
lib0 "^0.2.87"
|
||||
|
||||
"@hocuspocus/extension-database@^2.11.3":
|
||||
version "2.13.6"
|
||||
resolved "https://registry.yarnpkg.com/@hocuspocus/extension-database/-/extension-database-2.13.6.tgz#8d30b66348e58851bad691a8548d750ac0b50715"
|
||||
integrity sha512-lFt9yKzQ8VeErPyaRvqJsoNa6rBFISq5FehqjblsfrfIZvOvBiVwsyc+3d5gQnnQmJJ0rShGCIuLRGJi+MmUaA==
|
||||
version "2.13.7"
|
||||
resolved "https://registry.yarnpkg.com/@hocuspocus/extension-database/-/extension-database-2.13.7.tgz#d71aee885a91a050efacf85c2fec763c8dae65db"
|
||||
integrity sha512-GMSnluhmfpy3V+P8uCyR/dwh7nNqIERSAf+Jpkg0GVSeOuGdDuoWTJr+gkQWTAVDVMwNAqlp+ZLpzc0Y/L34mg==
|
||||
dependencies:
|
||||
"@hocuspocus/server" "^2.13.6"
|
||||
"@hocuspocus/server" "^2.13.7"
|
||||
|
||||
"@hocuspocus/extension-logger@^2.11.3":
|
||||
version "2.13.6"
|
||||
resolved "https://registry.yarnpkg.com/@hocuspocus/extension-logger/-/extension-logger-2.13.6.tgz#32ac413ba2d44d433235c1d7a8516953f341111e"
|
||||
integrity sha512-DQ1zBGFdRBCEmGfo3bcR2W3P/6SQmMmSYq4iqKB98U54901fKJz7cI+vrp6Xfr447Z1j2sfdlN9YTPaVMjv4rQ==
|
||||
version "2.13.7"
|
||||
resolved "https://registry.yarnpkg.com/@hocuspocus/extension-logger/-/extension-logger-2.13.7.tgz#22443cc4df445b923416e168633636ef5978943a"
|
||||
integrity sha512-mjlY0RjocWg4Qe1uVVL5lYXQs9yy80/5vrSuHMh9oFaXGGBOiVM7sOoM2IWl9k3ehBvlCid1xgNnNkNIJKDOPw==
|
||||
dependencies:
|
||||
"@hocuspocus/server" "^2.13.6"
|
||||
"@hocuspocus/server" "^2.13.7"
|
||||
|
||||
"@hocuspocus/extension-redis@^2.13.5":
|
||||
version "2.13.6"
|
||||
resolved "https://registry.yarnpkg.com/@hocuspocus/extension-redis/-/extension-redis-2.13.6.tgz#b1410b63b197ef863bee24c86565a215e000ed7b"
|
||||
integrity sha512-9H2MpXsSbHEUPvRTkm7kxsD7Ia0G4JbM5L5klN9+RqUecOAnQknx7GUfvjr7/6PLGVEymXK2e+NJVCvrx6N9Vg==
|
||||
version "2.13.7"
|
||||
resolved "https://registry.yarnpkg.com/@hocuspocus/extension-redis/-/extension-redis-2.13.7.tgz#eaee70944b9446d1fd17c4b313b0f7624e0ba50e"
|
||||
integrity sha512-th6fo7LfTQKgOenJHbW55PWPZTv95bGgiDh7zOr+WSIiyKPHKXv4dXYUN5e2lcKr2MV76FJYheaW5uNE1hnkDQ==
|
||||
dependencies:
|
||||
"@hocuspocus/server" "^2.13.6"
|
||||
"@hocuspocus/server" "^2.13.7"
|
||||
ioredis "^4.28.2"
|
||||
kleur "^4.1.4"
|
||||
lodash.debounce "^4.0.8"
|
||||
@@ -1783,21 +1783,21 @@
|
||||
uuid "^10.0.0"
|
||||
|
||||
"@hocuspocus/provider@^2.13.5":
|
||||
version "2.13.6"
|
||||
resolved "https://registry.yarnpkg.com/@hocuspocus/provider/-/provider-2.13.6.tgz#feef3a3732897a4e70262ce71299e8a0b42ccc68"
|
||||
integrity sha512-84tBdGU8275SXQirRQ5FbBGwsQ6iLNuIbmV2SV6/f361phBoAVUSobJ+CYAzdIJPlfIYSL2BwGJSRbbDhqJdJw==
|
||||
version "2.13.7"
|
||||
resolved "https://registry.yarnpkg.com/@hocuspocus/provider/-/provider-2.13.7.tgz#2595a85b78318bf6f927247d9d76f18ee6bbcec1"
|
||||
integrity sha512-BjZIIV8tWf/MD/8IcEMSFA+sW4wtR/M9MmhN+XSssYJOZxnszw44Gdwda23TmhsXvCV+qggS8lGEs+SfZSzEag==
|
||||
dependencies:
|
||||
"@hocuspocus/common" "^2.13.6"
|
||||
"@hocuspocus/common" "^2.13.7"
|
||||
"@lifeomic/attempt" "^3.0.2"
|
||||
lib0 "^0.2.87"
|
||||
ws "^8.17.1"
|
||||
|
||||
"@hocuspocus/server@^2.11.3", "@hocuspocus/server@^2.13.6":
|
||||
version "2.13.6"
|
||||
resolved "https://registry.yarnpkg.com/@hocuspocus/server/-/server-2.13.6.tgz#a39b0eef7cdb4cf23aaf3abb032d330fdd90e273"
|
||||
integrity sha512-VqiHkkQlfa2A5mFTe+rdePLt3kHJrk9ZzqDqWJfqQDlYHdyAXpW53cddsXYYDWQ/tZjYj3zQgZAT+78AHrnb/A==
|
||||
"@hocuspocus/server@^2.11.3", "@hocuspocus/server@^2.13.7":
|
||||
version "2.13.7"
|
||||
resolved "https://registry.yarnpkg.com/@hocuspocus/server/-/server-2.13.7.tgz#e794382952337110c3283ee31bbf2db610b33596"
|
||||
integrity sha512-D9juGX9NZoKT9/Ty/HGhaimHJe71DyKbYssC831oetYF33x3WSYV6GY82RhHo9xjKZE6r0Le7jgxgQb+u08slw==
|
||||
dependencies:
|
||||
"@hocuspocus/common" "^2.13.6"
|
||||
"@hocuspocus/common" "^2.13.7"
|
||||
async-lock "^1.3.1"
|
||||
kleur "^4.1.4"
|
||||
lib0 "^0.2.47"
|
||||
@@ -2136,62 +2136,62 @@
|
||||
prop-types "^15.8.1"
|
||||
react-is "^18.3.1"
|
||||
|
||||
"@next/[email protected]4":
|
||||
version "14.2.14"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.14.tgz#08f5175dab727102da02301ba61f7239773670fa"
|
||||
integrity sha512-/0hWQfiaD5//LvGNgc8PjvyqV50vGK0cADYzaoOOGN8fxzBn3iAiaq3S0tCRnFBldq0LVveLcxCTi41ZoYgAgg==
|
||||
"@next/[email protected]5":
|
||||
version "14.2.15"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.15.tgz#06d984e37e670d93ddd6790af1844aeb935f332f"
|
||||
integrity sha512-S1qaj25Wru2dUpcIZMjxeMVSwkt8BK4dmWHHiBuRstcIyOsMapqT4A4jSB6onvqeygkSSmOkyny9VVx8JIGamQ==
|
||||
|
||||
"@next/[email protected]4":
|
||||
version "14.2.14"
|
||||
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.14.tgz#091581faecd7f2c434b2ba85dbe935d743d542a2"
|
||||
integrity sha512-kV+OsZ56xhj0rnTn6HegyTGkoa16Mxjrpk7pjWumyB2P8JVQb8S9qtkjy/ye0GnTr4JWtWG4x/2qN40lKZ3iVQ==
|
||||
"@next/[email protected]5":
|
||||
version "14.2.15"
|
||||
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.15.tgz#796ae942a95b859e1add58e5b7ae78cfd55d59bb"
|
||||
integrity sha512-pKU0iqKRBlFB/ocOI1Ip2CkKePZpYpnw5bEItEkuZ/Nr9FQP1+p7VDWr4VfOdff4i9bFmrOaeaU1bFEyAcxiMQ==
|
||||
dependencies:
|
||||
glob "10.3.10"
|
||||
|
||||
"@next/[email protected]4":
|
||||
version "14.2.14"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.14.tgz#6dde2dac699dfe948b527385f2b350b3151989f4"
|
||||
integrity sha512-bsxbSAUodM1cjYeA4o6y7sp9wslvwjSkWw57t8DtC8Zig8aG8V6r+Yc05/9mDzLKcybb6EN85k1rJDnMKBd9Gw==
|
||||
"@next/[email protected]5":
|
||||
version "14.2.15"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.15.tgz#6386d585f39a1c490c60b72b1f76612ba4434347"
|
||||
integrity sha512-Rvh7KU9hOUBnZ9TJ28n2Oa7dD9cvDBKua9IKx7cfQQ0GoYUwg9ig31O2oMwH3wm+pE3IkAQ67ZobPfEgurPZIA==
|
||||
|
||||
"@next/[email protected]4":
|
||||
version "14.2.14"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.14.tgz#25800213c4dc0f8cd765c88073d28a3144698e31"
|
||||
integrity sha512-cC9/I+0+SK5L1k9J8CInahduTVWGMXhQoXFeNvF0uNs3Bt1Ub0Azb8JzTU9vNCr0hnaMqiWu/Z0S1hfKc3+dww==
|
||||
"@next/[email protected]5":
|
||||
version "14.2.15"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.15.tgz#b7baeedc6a28f7545ad2bc55adbab25f7b45cb89"
|
||||
integrity sha512-5TGyjFcf8ampZP3e+FyCax5zFVHi+Oe7sZyaKOngsqyaNEpOgkKB3sqmymkZfowy3ufGA/tUgDPPxpQx931lHg==
|
||||
|
||||
"@next/[email protected]4":
|
||||
version "14.2.14"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.14.tgz#9c66bd1287d0c3633e7bf354f9c01e1b79747615"
|
||||
integrity sha512-RMLOdA2NU4O7w1PQ3Z9ft3PxD6Htl4uB2TJpocm+4jcllHySPkFaUIFacQ3Jekcg6w+LBaFvjSPthZHiPmiAUg==
|
||||
"@next/[email protected]5":
|
||||
version "14.2.15"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.15.tgz#fa13c59d3222f70fb4cb3544ac750db2c6e34d02"
|
||||
integrity sha512-3Bwv4oc08ONiQ3FiOLKT72Q+ndEMyLNsc/D3qnLMbtUYTQAmkx9E/JRu0DBpHxNddBmNT5hxz1mYBphJ3mfrrw==
|
||||
|
||||
"@next/[email protected]4":
|
||||
version "14.2.14"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.14.tgz#da2ae16a24bb2b2a46447154e95da85c557ab09a"
|
||||
integrity sha512-WgLOA4hT9EIP7jhlkPnvz49iSOMdZgDJVvbpb8WWzJv5wBD07M2wdJXLkDYIpZmCFfo/wPqFsFR4JS4V9KkQ2A==
|
||||
"@next/[email protected]5":
|
||||
version "14.2.15"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.15.tgz#30e45b71831d9a6d6d18d7ac7d611a8d646a17f9"
|
||||
integrity sha512-k5xf/tg1FBv/M4CMd8S+JL3uV9BnnRmoe7F+GWC3DxkTCD9aewFRH1s5rJ1zkzDa+Do4zyN8qD0N8c84Hu96FQ==
|
||||
|
||||
"@next/[email protected]4":
|
||||
version "14.2.14"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.14.tgz#635c62109b9cf0464e6322955a36931ebb9ed3e2"
|
||||
integrity sha512-lbn7svjUps1kmCettV/R9oAvEW+eUI0lo0LJNFOXoQM5NGNxloAyFRNByYeZKL3+1bF5YE0h0irIJfzXBq9Y6w==
|
||||
"@next/[email protected]5":
|
||||
version "14.2.15"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.15.tgz#5065db17fc86f935ad117483f21f812dc1b39254"
|
||||
integrity sha512-kE6q38hbrRbKEkkVn62reLXhThLRh6/TvgSP56GkFNhU22TbIrQDEMrO7j0IcQHcew2wfykq8lZyHFabz0oBrA==
|
||||
|
||||
"@next/[email protected]4":
|
||||
version "14.2.14"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.14.tgz#1565caf6fa77c3280d8b05ffc8c542ff144a4855"
|
||||
integrity sha512-7TcQCvLQ/hKfQRgjxMN4TZ2BRB0P7HwrGAYL+p+m3u3XcKTraUFerVbV3jkNZNwDeQDa8zdxkKkw2els/S5onQ==
|
||||
"@next/[email protected]5":
|
||||
version "14.2.15"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.15.tgz#3c4a4568d8be7373a820f7576cf33388b5dab47e"
|
||||
integrity sha512-PZ5YE9ouy/IdO7QVJeIcyLn/Rc4ml9M2G4y3kCM9MNf1YKvFY4heg3pVa/jQbMro+tP6yc4G2o9LjAz1zxD7tQ==
|
||||
|
||||
"@next/[email protected]4":
|
||||
version "14.2.14"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.14.tgz#8df4feb3c9280155e9299f3cdfa32f3cface336a"
|
||||
integrity sha512-8i0Ou5XjTLEje0oj0JiI0Xo9L/93ghFtAUYZ24jARSeTMXLUx8yFIdhS55mTExq5Tj4/dC2fJuaT4e3ySvXU1A==
|
||||
"@next/[email protected]5":
|
||||
version "14.2.15"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.15.tgz#fb812cc4ca0042868e32a6a021da91943bb08b98"
|
||||
integrity sha512-2raR16703kBvYEQD9HNLyb0/394yfqzmIeyp2nDzcPV4yPjqNUG3ohX6jX00WryXz6s1FXpVhsCo3i+g4RUX+g==
|
||||
|
||||
"@next/[email protected]4":
|
||||
version "14.2.14"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.14.tgz#1f0a2bafbb63147c8db102ca1524db9ffa959d0c"
|
||||
integrity sha512-2u2XcSaDEOj+96eXpyjHjtVPLhkAFw2nlaz83EPeuK4obF+HmtDJHqgR1dZB7Gb6V/d55FL26/lYVd0TwMgcOQ==
|
||||
"@next/[email protected]5":
|
||||
version "14.2.15"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.15.tgz#ec26e6169354f8ced240c1427be7fd485c5df898"
|
||||
integrity sha512-fyTE8cklgkyR1p03kJa5zXEaZ9El+kDNM5A+66+8evQS5e/6v0Gk28LqA0Jet8gKSOyP+OTm/tJHzMlGdQerdQ==
|
||||
|
||||
"@next/[email protected]4":
|
||||
version "14.2.14"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.14.tgz#9d6446b3a8d5e67e199049d59ce7c0b8bd33ab51"
|
||||
integrity sha512-MZom+OvZ1NZxuRovKt1ApevjiUJTcU2PmdJKL66xUPaJeRywnbGGRWUlaAOwunD6dX+pm83vj979NTC8QXjGWg==
|
||||
"@next/[email protected]5":
|
||||
version "14.2.15"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.15.tgz#18d68697002b282006771f8d92d79ade9efd35c4"
|
||||
integrity sha512-SzqGbsLsP9OwKNUG9nekShTwhj6JSB9ZLMWQ8g1gG6hdE5gQLncbnbymrwy2yVmH9nikSLYRYxYMFu78Ggp7/g==
|
||||
|
||||
"@nicolo-ribaudo/[email protected]":
|
||||
version "2.1.8-no-fsevents.3"
|
||||
@@ -6498,10 +6498,10 @@ [email protected]:
|
||||
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
||||
integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
|
||||
|
||||
cookie@0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051"
|
||||
integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
|
||||
cookie@0.7.1:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9"
|
||||
integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==
|
||||
|
||||
core-js-compat@^3.38.0, core-js-compat@^3.38.1:
|
||||
version "3.38.1"
|
||||
@@ -7404,9 +7404,9 @@ es-get-iterator@^1.1.3:
|
||||
stop-iteration-iterator "^1.0.0"
|
||||
|
||||
es-iterator-helpers@^1.0.19:
|
||||
version "1.0.19"
|
||||
resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz#117003d0e5fec237b4b5c08aded722e0c6d50ca8"
|
||||
integrity sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.1.0.tgz#f6d745d342aea214fe09497e7152170dc333a7a6"
|
||||
integrity sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==
|
||||
dependencies:
|
||||
call-bind "^1.0.7"
|
||||
define-properties "^1.2.1"
|
||||
@@ -7415,12 +7415,12 @@ es-iterator-helpers@^1.0.19:
|
||||
es-set-tostringtag "^2.0.3"
|
||||
function-bind "^1.1.2"
|
||||
get-intrinsic "^1.2.4"
|
||||
globalthis "^1.0.3"
|
||||
globalthis "^1.0.4"
|
||||
has-property-descriptors "^1.0.2"
|
||||
has-proto "^1.0.3"
|
||||
has-symbols "^1.0.3"
|
||||
internal-slot "^1.0.7"
|
||||
iterator.prototype "^1.1.2"
|
||||
iterator.prototype "^1.1.3"
|
||||
safe-array-concat "^1.1.2"
|
||||
|
||||
es-module-lexer@^1.2.1, es-module-lexer@^1.5.0:
|
||||
@@ -7586,11 +7586,11 @@ escodegen@^2.1.0:
|
||||
source-map "~0.6.1"
|
||||
|
||||
eslint-config-next@^14.1.0:
|
||||
version "14.2.14"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-14.2.14.tgz#b2b5dedadd4afe20e2103b0ec44eb2f1d211fc63"
|
||||
integrity sha512-TXwyjGICAlWC9O0OufS3koTsBKQH8l1xt3SY/aDuvtKHIwjTHplJKWVb1WOEX0OsDaxGbFXmfD2EY1sNfG0Y/w==
|
||||
version "14.2.15"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-14.2.15.tgz#ff9661835eaf9f2ef1717ace55073a8f71037fab"
|
||||
integrity sha512-mKg+NC/8a4JKLZRIOBplxXNdStgxy7lzWuedUaCc8tev+Al9mwDUTujQH6W6qXDH9kycWiVo28tADWGvpBsZcQ==
|
||||
dependencies:
|
||||
"@next/eslint-plugin-next" "14.2.14"
|
||||
"@next/eslint-plugin-next" "14.2.15"
|
||||
"@rushstack/eslint-patch" "^1.3.3"
|
||||
"@typescript-eslint/eslint-plugin" "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
"@typescript-eslint/parser" "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
@@ -7957,16 +7957,16 @@ express-ws@^5.0.2:
|
||||
ws "^7.4.6"
|
||||
|
||||
express@^4.19.2, express@^4.20.0:
|
||||
version "4.21.0"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.21.0.tgz#d57cb706d49623d4ac27833f1cbc466b668eb915"
|
||||
integrity sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==
|
||||
version "4.21.1"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.21.1.tgz#9dae5dda832f16b4eec941a4e44aa89ec481b281"
|
||||
integrity sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==
|
||||
dependencies:
|
||||
accepts "~1.3.8"
|
||||
array-flatten "1.1.1"
|
||||
body-parser "1.20.3"
|
||||
content-disposition "0.5.4"
|
||||
content-type "~1.0.4"
|
||||
cookie "0.6.0"
|
||||
cookie "0.7.1"
|
||||
cookie-signature "1.0.6"
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
@@ -8534,7 +8534,7 @@ globals@^14.0.0:
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e"
|
||||
integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==
|
||||
|
||||
globalthis@^1.0.3:
|
||||
globalthis@^1.0.3, globalthis@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236"
|
||||
integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==
|
||||
@@ -9319,7 +9319,7 @@ isomorphic.js@^0.2.4:
|
||||
resolved "https://registry.yarnpkg.com/isomorphic.js/-/isomorphic.js-0.2.5.tgz#13eecf36f2dba53e85d355e11bf9d4208c6f7f88"
|
||||
integrity sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==
|
||||
|
||||
iterator.prototype@^1.1.2:
|
||||
iterator.prototype@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.3.tgz#016c2abe0be3bbdb8319852884f60908ac62bf9c"
|
||||
integrity sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==
|
||||
@@ -10342,11 +10342,11 @@ next-themes@^0.2.1:
|
||||
integrity sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==
|
||||
|
||||
next@^14.2.12:
|
||||
version "14.2.14"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-14.2.14.tgz#115f29443dfb96d23b4b5ab5c4547de339202ba7"
|
||||
integrity sha512-Q1coZG17MW0Ly5x76shJ4dkC23woLAhhnDnw+DfTc7EpZSGuWrlsZ3bZaO8t6u1Yu8FVfhkqJE+U8GC7E0GLPQ==
|
||||
version "14.2.15"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-14.2.15.tgz#348e5603e22649775d19c785c09a89c9acb5189a"
|
||||
integrity sha512-h9ctmOokpoDphRvMGnwOJAedT6zKhwqyZML9mDtspgf4Rh3Pn7UTYKqePNoDvhsWBAO5GoPNYshnAUGIazVGmw==
|
||||
dependencies:
|
||||
"@next/env" "14.2.14"
|
||||
"@next/env" "14.2.15"
|
||||
"@swc/helpers" "0.5.5"
|
||||
busboy "1.6.0"
|
||||
caniuse-lite "^1.0.30001579"
|
||||
@@ -10354,15 +10354,15 @@ next@^14.2.12:
|
||||
postcss "8.4.31"
|
||||
styled-jsx "5.1.1"
|
||||
optionalDependencies:
|
||||
"@next/swc-darwin-arm64" "14.2.14"
|
||||
"@next/swc-darwin-x64" "14.2.14"
|
||||
"@next/swc-linux-arm64-gnu" "14.2.14"
|
||||
"@next/swc-linux-arm64-musl" "14.2.14"
|
||||
"@next/swc-linux-x64-gnu" "14.2.14"
|
||||
"@next/swc-linux-x64-musl" "14.2.14"
|
||||
"@next/swc-win32-arm64-msvc" "14.2.14"
|
||||
"@next/swc-win32-ia32-msvc" "14.2.14"
|
||||
"@next/swc-win32-x64-msvc" "14.2.14"
|
||||
"@next/swc-darwin-arm64" "14.2.15"
|
||||
"@next/swc-darwin-x64" "14.2.15"
|
||||
"@next/swc-linux-arm64-gnu" "14.2.15"
|
||||
"@next/swc-linux-arm64-musl" "14.2.15"
|
||||
"@next/swc-linux-x64-gnu" "14.2.15"
|
||||
"@next/swc-linux-x64-musl" "14.2.15"
|
||||
"@next/swc-win32-arm64-msvc" "14.2.15"
|
||||
"@next/swc-win32-ia32-msvc" "14.2.15"
|
||||
"@next/swc-win32-x64-msvc" "14.2.15"
|
||||
|
||||
no-case@^3.0.4:
|
||||
version "3.0.4"
|
||||
@@ -13503,9 +13503,9 @@ typescript@^4.7.2:
|
||||
integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
|
||||
|
||||
typescript@^5.2.2, typescript@^5.3.3:
|
||||
version "5.6.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.2.tgz#d1de67b6bef77c41823f822df8f0b3bcff60a5a0"
|
||||
integrity sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==
|
||||
version "5.6.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b"
|
||||
integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==
|
||||
|
||||
uc.micro@^2.0.0, uc.micro@^2.1.0:
|
||||
version "2.1.0"
|
||||
|
||||
Reference in New Issue
Block a user