chore: Updated meta information and updated the ssr for intake in space (#1873)

This commit is contained in:
guru_sainath
2024-12-04 19:30:53 +05:30
committed by GitHub
parent 39a3ad7504
commit 63ef0ccfb9
5 changed files with 143 additions and 70 deletions

View File

@@ -2,9 +2,17 @@
from django.urls import path
# Module imports
from plane.ee.views import IntakePublishedIssueEndpoint
from plane.ee.views import (
IntakePublishedIssueEndpoint,
IntakeMetaPublishedIssueEndpoint,
)
urlpatterns = [
path(
"anchor/<str:anchor>/intake/meta/",
IntakeMetaPublishedIssueEndpoint.as_view(),
name="intake-public-meta",
),
path(
"anchor/<str:anchor>/intake/",
IntakePublishedIssueEndpoint.as_view(),

View File

@@ -52,4 +52,7 @@ from plane.ee.views.space.views import (
IssueViewsPublicEndpoint,
ViewsMetaDataEndpoint,
)
from plane.ee.views.space.intake import IntakePublishedIssueEndpoint
from plane.ee.views.space.intake import (
IntakePublishedIssueEndpoint,
IntakeMetaPublishedIssueEndpoint,
)

View File

@@ -15,9 +15,8 @@ from plane.db.models import DeployBoard, Intake, IntakeIssue, Project, APIToken
from plane.payment.flags.flag import FeatureFlag
from plane.payment.flags.flag_decorator import check_workspace_feature_flag
from plane.payment.flags.flag_decorator import ErrorCodes
from plane.ee.serializers import (
IssueCreateSerializer,
)
from plane.ee.serializers import IssueCreateSerializer
from plane.space.serializer.project import ProjectLiteSerializer
from plane.bgtasks.issue_activities_task import issue_activity
## Enterprise imports
@@ -25,36 +24,62 @@ from plane.ee.views.base import BaseAPIView
from plane.ee.models import IntakeSetting
class IntakeMetaPublishedIssueEndpoint(BaseAPIView):
permission_classes = [AllowAny]
def get(self, request, anchor):
try:
deploy_board = DeployBoard.objects.get(anchor=anchor, entity_name="intake")
except DeployBoard.DoesNotExist:
return Response(
{"error": "Intake is not published"}, status=status.HTTP_404_NOT_FOUND
)
if check_workspace_feature_flag(
feature_key=FeatureFlag.INTAKE_PUBLISH, slug=deploy_board.workspace.slug
):
try:
project_id = deploy_board.project_id
project = Project.objects.get(id=project_id)
except Project.DoesNotExist:
return Response(
{"error": "Intake is not published"},
status=status.HTTP_404_NOT_FOUND,
)
serializer = ProjectLiteSerializer(project)
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response(
{
"error": "Payment required",
"error_code": ErrorCodes.PAYMENT_REQUIRED.value,
},
status=status.HTTP_402_PAYMENT_REQUIRED,
)
class IntakePublishedIssueEndpoint(BaseAPIView):
permission_classes = [
AllowAny,
]
permission_classes = [AllowAny]
def post(self, request, anchor):
# Get the deploy board object
deploy_board = DeployBoard.objects.get(
anchor=anchor, entity_name="intake"
)
deploy_board = DeployBoard.objects.get(anchor=anchor, entity_name="intake")
project = Project.objects.get(
workspace_id=deploy_board.workspace_id,
pk=deploy_board.project_id,
workspace_id=deploy_board.workspace_id, pk=deploy_board.project_id
)
intake_settings = IntakeSetting.objects.filter(
workspace_id=deploy_board.workspace_id,
project_id=deploy_board.project_id,
workspace_id=deploy_board.workspace_id, project_id=deploy_board.project_id
).first()
if not intake_settings.is_form_enabled or not project.intake_view:
return Response(
{
"error": "The current published url is disabled",
},
{"error": "The current published url is disabled"},
status=status.HTTP_403_FORBIDDEN,
)
# Check if the workspace has access to feature
if check_workspace_feature_flag(
feature_key=FeatureFlag.INTAKE_PUBLISH,
slug=deploy_board.workspace.slug,
feature_key=FeatureFlag.INTAKE_PUBLISH, slug=deploy_board.workspace.slug
):
intake = Intake.objects.filter(
workspace_id=deploy_board.workspace_id,
@@ -63,10 +88,7 @@ class IntakePublishedIssueEndpoint(BaseAPIView):
if request.data.get("name") is None:
return Response(
{
"error": "Name is required",
},
status=status.HTTP_400_BAD_REQUEST,
{"error": "Name is required"}, status=status.HTTP_400_BAD_REQUEST
)
api_token = APIToken.objects.filter(
@@ -99,16 +121,12 @@ class IntakePublishedIssueEndpoint(BaseAPIView):
issue_id=serializer.data["id"],
source=request.data.get("source", "FORMS"),
source_email=request.data.get("email", None),
extra={
"username": request.data.get("username", None),
},
extra={"username": request.data.get("username", None)},
)
# Create an Issue Activity
issue_activity.delay(
type="issue.activity.created",
requested_data=json.dumps(
request.data, cls=DjangoJSONEncoder
),
requested_data=json.dumps(request.data, cls=DjangoJSONEncoder),
actor_id=str(api_token.user_id),
issue_id=str(serializer.data["id"]),
project_id=str(deploy_board.project_id),
@@ -119,9 +137,7 @@ class IntakePublishedIssueEndpoint(BaseAPIView):
intake=str(intake_issue.id),
)
return Response(status=status.HTTP_204_NO_CONTENT)
return Response(
serializer.errors, status=status.HTTP_400_BAD_REQUEST
)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(
{

View File

@@ -0,0 +1,43 @@
"use client";
import { observer } from "mobx-react";
import useSWR from "swr";
// components
import { LogoSpinner } from "@/components/common";
import { SomethingWentWrongError } from "@/components/issues/issue-layouts/error";
// hooks
import { usePublish, usePublishList } from "@/hooks/store";
type Props = {
children: React.ReactNode;
anchor: string;
};
export const IntakeClientLayout = observer((props: Props) => {
const { children, anchor } = props;
// store hooks
const { fetchPublishSettings } = usePublishList();
const publishSettings = usePublish(anchor);
// fetch publish settings && view details
const { error } = useSWR(
anchor ? `PUBLISHED_VIEW_SETTINGS_${anchor}` : null,
anchor
? async () => {
const promises = [];
promises.push(fetchPublishSettings(anchor));
await Promise.all(promises);
}
: null
);
if (error) return <SomethingWentWrongError />;
if (!publishSettings) return <LogoSpinner />;
return (
<div className="relative flex h-screen min-h-[500px] w-screen flex-col overflow-hidden">
<div className="relative h-full w-full overflow-hidden bg-custom-primary-100/5 flex">{children}</div>
</div>
);
});

View File

@@ -1,12 +1,6 @@
"use client";
"use server";
import { observer } from "mobx-react";
import useSWR from "swr";
// components
import { LogoSpinner } from "@/components/common";
import { SomethingWentWrongError } from "@/components/issues/issue-layouts/error";
// hooks
import { usePublish, usePublishList } from "@/hooks/store";
import { IntakeClientLayout } from "./client-layout";
type Props = {
children: React.ReactNode;
@@ -15,35 +9,44 @@ type Props = {
};
};
const IntakeLayout = observer((props: Props) => {
const { children, params } = props;
// params
export async function generateMetadata({ params }: Props) {
const { anchor } = params;
// store hooks
const { fetchPublishSettings } = usePublishList();
const publishSettings = usePublish(anchor);
const DEFAULT_TITLE = "Plane";
const DEFAULT_DESCRIPTION = "Made with Plane, an AI-powered work management platform with publishing capabilities.";
try {
const response = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/public/anchor/${anchor}/intake/meta/`);
const data = await response.json();
return {
title: `${data?.name} - Intake` || DEFAULT_TITLE,
description: DEFAULT_DESCRIPTION,
openGraph: {
title: `${data?.name} - Intake` || DEFAULT_TITLE,
description: DEFAULT_DESCRIPTION,
type: "website",
images: [
{
url: data?.cover_image,
width: 800,
height: 600,
alt: data?.name || DEFAULT_TITLE,
},
],
},
twitter: {
card: "summary_large_image",
title: `${data?.name} - Intake` || DEFAULT_TITLE,
description: data?.description || DEFAULT_DESCRIPTION,
images: [data?.cover_image],
},
};
} catch {
return { title: `${DEFAULT_TITLE} - Intake`, description: DEFAULT_DESCRIPTION };
}
}
// fetch publish settings && view details
const { error } = useSWR(
anchor ? `PUBLISHED_VIEW_SETTINGS_${anchor}` : null,
anchor
? async () => {
const promises = [];
promises.push(fetchPublishSettings(anchor));
await Promise.all(promises);
}
: null
);
export default async function IntakeLayout(props: Props) {
const { children, params } = props;
const { anchor } = params;
if (error) return <SomethingWentWrongError />;
if (!publishSettings) return <LogoSpinner />;
return (
<div className="relative flex h-screen min-h-[500px] w-screen flex-col overflow-hidden">
<div className="relative h-full w-full overflow-hidden bg-custom-primary-100/5 flex">{children}</div>
</div>
);
});
export default IntakeLayout;
return <IntakeClientLayout anchor={anchor}>{children}</IntakeClientLayout>;
}