From c455bbedf7b595798cdb0f5ec17a9aa38fd7a834 Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Tue, 24 Sep 2024 19:58:03 +0530 Subject: [PATCH 1/5] [WEB-2500] feat: Product updates modal (What's new in Plane) --- apiserver/Dockerfile.api | 1 + apiserver/Dockerfile.dev | 1 + apiserver/plane/license/api/views/__init__.py | 2 + .../plane/license/api/views/changelog.py | 35 ++++++ apiserver/plane/license/api/views/instance.py | 2 + apiserver/plane/license/urls.py | 6 + apiserver/plane/settings/common.py | 3 + web/ce/components/global/index.ts | 3 +- .../global/product-updates-header.tsx | 25 ++++ .../global/product-updates-modal.tsx | 9 -- web/ce/components/global/product-updates.tsx | 21 ---- web/core/components/common/index.ts | 1 - .../common/product-updates-modal.tsx | 111 ------------------ web/core/components/global/index.ts | 1 + .../global/product-updates/footer.tsx | 62 ++++++++++ .../global/product-updates/index.ts | 2 + .../global/product-updates/modal.tsx | 77 ++++++++++++ .../workspace/sidebar/help-section.tsx | 14 ++- web/core/services/instance.service.ts | 10 +- 19 files changed, 239 insertions(+), 147 deletions(-) create mode 100644 apiserver/plane/license/api/views/changelog.py create mode 100644 web/ce/components/global/product-updates-header.tsx delete mode 100644 web/ce/components/global/product-updates-modal.tsx delete mode 100644 web/ce/components/global/product-updates.tsx delete mode 100644 web/core/components/common/product-updates-modal.tsx create mode 100644 web/core/components/global/index.ts create mode 100644 web/core/components/global/product-updates/footer.tsx create mode 100644 web/core/components/global/product-updates/index.ts create mode 100644 web/core/components/global/product-updates/modal.tsx diff --git a/apiserver/Dockerfile.api b/apiserver/Dockerfile.api index cdb7e41ed53..97a2b2d4105 100644 --- a/apiserver/Dockerfile.api +++ b/apiserver/Dockerfile.api @@ -4,6 +4,7 @@ FROM python:3.12.5-alpine AS backend ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 ENV PIP_DISABLE_PIP_VERSION_CHECK=1 +ENV INSTANCE_CHANGELOG_URL https://api.plane.so/api/public/anchor/8e1c2e4c7bc5493eb7731be3862f6960/pages/ WORKDIR /code diff --git a/apiserver/Dockerfile.dev b/apiserver/Dockerfile.dev index 3cde896b97d..c81966de4f2 100644 --- a/apiserver/Dockerfile.dev +++ b/apiserver/Dockerfile.dev @@ -4,6 +4,7 @@ FROM python:3.12.5-alpine AS backend ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 ENV PIP_DISABLE_PIP_VERSION_CHECK=1 +ENV INSTANCE_CHANGELOG_URL https://api.plane.so/api/public/anchor/8e1c2e4c7bc5493eb7731be3862f6960/pages/ RUN apk --no-cache add \ "bash~=5.2" \ diff --git a/apiserver/plane/license/api/views/__init__.py b/apiserver/plane/license/api/views/__init__.py index b10702b8a15..ad1aaa58d96 100644 --- a/apiserver/plane/license/api/views/__init__.py +++ b/apiserver/plane/license/api/views/__init__.py @@ -18,3 +18,5 @@ InstanceAdminSignOutEndpoint, InstanceAdminUserSessionEndpoint, ) + +from .changelog import ChangeLogEndpoint diff --git a/apiserver/plane/license/api/views/changelog.py b/apiserver/plane/license/api/views/changelog.py new file mode 100644 index 00000000000..a81504e4780 --- /dev/null +++ b/apiserver/plane/license/api/views/changelog.py @@ -0,0 +1,35 @@ +# Python imports +import requests + +# Django imports +from django.conf import settings + +# Third party imports +from rest_framework.response import Response +from rest_framework import status +from rest_framework.permissions import AllowAny + +# plane imports +from .base import BaseAPIView + + +class ChangeLogEndpoint(BaseAPIView): + permission_classes = [ + AllowAny, + ] + + def fetch_change_logs(self): + response = requests.get(settings.INSTANCE_CHANGELOG_URL) + response.raise_for_status() + return response.json() + + def get(self, request): + # Fetch the changelog + if settings.INSTANCE_CHANGELOG_URL: + data = self.fetch_change_logs() + return Response(data, status=status.HTTP_200_OK) + else: + return Response( + {"error": "could not fetch changelog please try again later"}, + status=status.HTTP_400_BAD_REQUEST, + ) diff --git a/apiserver/plane/license/api/views/instance.py b/apiserver/plane/license/api/views/instance.py index 9aac3fb181f..c61b55bb611 100644 --- a/apiserver/plane/license/api/views/instance.py +++ b/apiserver/plane/license/api/views/instance.py @@ -177,6 +177,8 @@ def get(self, request): data["space_base_url"] = settings.SPACE_BASE_URL data["app_base_url"] = settings.APP_BASE_URL + data["instance_changelog_url"] = settings.INSTANCE_CHANGELOG_URL + instance_data = serializer.data instance_data["workspaces_exist"] = Workspace.objects.count() >= 1 diff --git a/apiserver/plane/license/urls.py b/apiserver/plane/license/urls.py index b4f19e52c35..444d2a11926 100644 --- a/apiserver/plane/license/urls.py +++ b/apiserver/plane/license/urls.py @@ -11,6 +11,7 @@ InstanceAdminUserMeEndpoint, InstanceAdminSignOutEndpoint, InstanceAdminUserSessionEndpoint, + ChangeLogEndpoint ) urlpatterns = [ @@ -19,6 +20,11 @@ InstanceEndpoint.as_view(), name="instance", ), + path( + "changelog/", + ChangeLogEndpoint.as_view(), + name="instance-changelog", + ), path( "admins/", InstanceAdminEndpoint.as_view(), diff --git a/apiserver/plane/settings/common.py b/apiserver/plane/settings/common.py index 007d8cecff5..96885f6f0fb 100644 --- a/apiserver/plane/settings/common.py +++ b/apiserver/plane/settings/common.py @@ -359,3 +359,6 @@ APP_BASE_URL = os.environ.get("APP_BASE_URL") HARD_DELETE_AFTER_DAYS = int(os.environ.get("HARD_DELETE_AFTER_DAYS", 60)) + +# Instance Changelog URL +INSTANCE_CHANGELOG_URL = os.environ.get("INSTANCE_CHANGELOG_URL", "") diff --git a/web/ce/components/global/index.ts b/web/ce/components/global/index.ts index 2d8930e19e1..c87c8ae0273 100644 --- a/web/ce/components/global/index.ts +++ b/web/ce/components/global/index.ts @@ -1,3 +1,2 @@ export * from "./version-number"; -export * from "./product-updates"; -export * from "./product-updates-modal"; +export * from "./product-updates-header"; diff --git a/web/ce/components/global/product-updates-header.tsx b/web/ce/components/global/product-updates-header.tsx new file mode 100644 index 00000000000..182fa5d4d88 --- /dev/null +++ b/web/ce/components/global/product-updates-header.tsx @@ -0,0 +1,25 @@ +import { observer } from "mobx-react"; +import Image from "next/image"; +import packageJson from "package.json"; +// helpers +import { cn } from "@/helpers/common.helper"; +// assets +import PlaneLogo from "@/public/plane-logos/blue-without-text.png"; + +export const ProductUpdatesHeader = observer(() => ( +
+
+
What's new
+
+ Version: v{packageJson.version} +
+
+
+ Plane +
+
+)); diff --git a/web/ce/components/global/product-updates-modal.tsx b/web/ce/components/global/product-updates-modal.tsx deleted file mode 100644 index da279583502..00000000000 --- a/web/ce/components/global/product-updates-modal.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { FC } from "react"; -import { observer } from "mobx-react"; - -export type ProductUpdatesModalProps = { - isOpen: boolean; - handleClose: () => void; -}; - -export const ProductUpdatesModal: FC = observer(() => <>); diff --git a/web/ce/components/global/product-updates.tsx b/web/ce/components/global/product-updates.tsx deleted file mode 100644 index 700883574c0..00000000000 --- a/web/ce/components/global/product-updates.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { FC } from "react"; -import { observer } from "mobx-react"; -import Link from "next/link"; -// ui -import { CustomMenu } from "@plane/ui"; - -export type ProductUpdatesProps = { - setIsChangeLogOpen: (isOpen: boolean) => void; -}; - -export const ProductUpdates: FC = observer(() => ( - - - What's new - - -)); diff --git a/web/core/components/common/index.ts b/web/core/components/common/index.ts index d6d34858403..28b73238862 100644 --- a/web/core/components/common/index.ts +++ b/web/core/components/common/index.ts @@ -1,4 +1,3 @@ -export * from "./product-updates-modal"; export * from "./empty-state"; export * from "./latest-feature-block"; export * from "./breadcrumb-link"; diff --git a/web/core/components/common/product-updates-modal.tsx b/web/core/components/common/product-updates-modal.tsx deleted file mode 100644 index 9e1112db1f4..00000000000 --- a/web/core/components/common/product-updates-modal.tsx +++ /dev/null @@ -1,111 +0,0 @@ -"use client"; -import React from "react"; -import useSWR from "swr"; -// headless ui -import { X } from "lucide-react"; -import { Dialog, Transition } from "@headlessui/react"; -// services -// components -import { Loader } from "@plane/ui"; -import { MarkdownRenderer } from "@/components/ui"; -// icons -// helpers -import { renderFormattedDate } from "@/helpers/date-time.helper"; -import { WorkspaceService } from "@/plane-web/services"; - -type Props = { - isOpen: boolean; - setIsOpen: React.Dispatch>; -}; - -// services -const workspaceService = new WorkspaceService(); - -export const ProductUpdatesModal: React.FC = ({ isOpen, setIsOpen }) => { - const { data: updates } = useSWR("PRODUCT_UPDATES", () => workspaceService.getProductUpdates()); - - return ( - - - -
- - -
-
- - -
- - Product Updates - - - - - {updates && updates.length > 0 ? ( -
- {updates.map((item, index) => ( - -
- - {item.tag_name} - - {renderFormattedDate(item.published_at)} - {index === 0 && ( - - New - - )} -
- -
- ))} -
- ) : ( -
- -
- - - -
-
- - - -
-
- - - -
-
-
- )} -
-
-
-
-
-
-
- ); -}; diff --git a/web/core/components/global/index.ts b/web/core/components/global/index.ts new file mode 100644 index 00000000000..1230b8384fc --- /dev/null +++ b/web/core/components/global/index.ts @@ -0,0 +1 @@ +export * from "./product-updates"; diff --git a/web/core/components/global/product-updates/footer.tsx b/web/core/components/global/product-updates/footer.tsx new file mode 100644 index 00000000000..6dd2638332b --- /dev/null +++ b/web/core/components/global/product-updates/footer.tsx @@ -0,0 +1,62 @@ +import Image from "next/image"; +// ui +import { getButtonStyling } from "@plane/ui"; +// helpers +import { cn } from "@/helpers/common.helper"; +// assets +import PlaneLogo from "@/public/plane-logos/blue-without-text.png"; + +export const ProductUpdatesFooter = () => ( + +); diff --git a/web/core/components/global/product-updates/index.ts b/web/core/components/global/product-updates/index.ts new file mode 100644 index 00000000000..6886b550381 --- /dev/null +++ b/web/core/components/global/product-updates/index.ts @@ -0,0 +1,2 @@ +export * from "./modal"; +export * from "./footer"; diff --git a/web/core/components/global/product-updates/modal.tsx b/web/core/components/global/product-updates/modal.tsx new file mode 100644 index 00000000000..fb3bf4f8ffe --- /dev/null +++ b/web/core/components/global/product-updates/modal.tsx @@ -0,0 +1,77 @@ +import { FC, useRef } from "react"; +import { observer } from "mobx-react-lite"; +import useSWR from "swr"; +// editor +import { DocumentReadOnlyEditorWithRef, EditorRefApi } from "@plane/editor"; +// ui +import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui"; +// helpers +import { LogoSpinner } from "@/components/common"; +import { ProductUpdatesFooter } from "@/components/global"; +// plane web components +import { ProductUpdatesHeader } from "@/plane-web/components/global"; +// services +import { InstanceService } from "@/services/instance.service"; + +const instanceService = new InstanceService(); + +export type ProductUpdatesModalProps = { + isOpen: boolean; + handleClose: () => void; +}; + +export const ProductUpdatesModal: FC = observer((props) => { + const { isOpen, handleClose } = props; + // refs + const editorRef = useRef(null); + // swr + const { data, isLoading, error } = useSWR(`INSTANCE_CHANGELOG`, () => instanceService.getInstanceChangeLog()); + + return ( + + +
+ {!isLoading && !!error ? ( +
+
We are having trouble fetching the updates.
+
+ Please visit{" "} + + our changelogs + {" "} + for the latest updates. +
+
+ ) : isLoading ? ( +
+ +
+ ) : ( +
+ {data?.id && ( +

"} + containerClassName="p-0 border-none" + mentionHandler={{ + highlights: () => Promise.resolve([]), + }} + embedHandler={{ + issue: { + widgetCallback: () => <>, + }, + }} + /> + )} +
+ )} +
+ +
+ ); +}); diff --git a/web/core/components/workspace/sidebar/help-section.tsx b/web/core/components/workspace/sidebar/help-section.tsx index c2af0c3b5ef..97e7edb9200 100644 --- a/web/core/components/workspace/sidebar/help-section.tsx +++ b/web/core/components/workspace/sidebar/help-section.tsx @@ -5,13 +5,15 @@ import { observer } from "mobx-react"; import { FileText, HelpCircle, MessagesSquare, MoveLeft, User } from "lucide-react"; // ui import { CustomMenu, Tooltip } from "@plane/ui"; +// components +import { ProductUpdatesModal } from "@/components/global"; // helpers import { cn } from "@/helpers/common.helper"; // hooks import { useAppTheme, useCommandPalette, useInstance, useTransient } from "@/hooks/store"; import { usePlatformOS } from "@/hooks/use-platform-os"; // plane web components -import { PlaneVersionNumber, ProductUpdates, ProductUpdatesModal } from "@/plane-web/components/global"; +import { PlaneVersionNumber } from "@/plane-web/components/global"; import { WorkspaceEditionBadge } from "@/plane-web/components/workspace"; export interface WorkspaceHelpSectionProps { @@ -114,7 +116,15 @@ export const SidebarHelpSection: React.FC = observer( Keyboard shortcuts - + + + { + return this.get("/api/instances/changelog/") + .then((response) => response.data) + .catch((error) => { + throw error; + }); + } } From 2b0f835d1cf6eafbde11ee18dce2d317b5d4cf7e Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Tue, 24 Sep 2024 20:02:30 +0530 Subject: [PATCH 2/5] fix: build errors. --- web/app/profile/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/profile/page.tsx b/web/app/profile/page.tsx index ccbd62446db..70e53ca98d8 100644 --- a/web/app/profile/page.tsx +++ b/web/app/profile/page.tsx @@ -34,8 +34,8 @@ import { USER_ROLES } from "@/constants/workspace"; import { useUser, useUserSettings } from "@/hooks/store"; // import { ProfileSettingsLayout } from "@/layouts/settings-layout"; // layouts -import { FileService } from "@/services/file.service"; import { ENABLE_LOCAL_DB_CACHE } from "@/plane-web/constants/issues"; +import { FileService } from "@/services/file.service"; // services // types From dae613327a53a9cbe096c54a6d33c396be46f7c5 Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Fri, 4 Oct 2024 13:42:11 +0530 Subject: [PATCH 3/5] fix: lint errors resolved. --- web/ce/components/global/product-updates-header.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/ce/components/global/product-updates-header.tsx b/web/ce/components/global/product-updates-header.tsx index 182fa5d4d88..a5965bb2d14 100644 --- a/web/ce/components/global/product-updates-header.tsx +++ b/web/ce/components/global/product-updates-header.tsx @@ -1,10 +1,11 @@ import { observer } from "mobx-react"; import Image from "next/image"; -import packageJson from "package.json"; // helpers import { cn } from "@/helpers/common.helper"; // assets import PlaneLogo from "@/public/plane-logos/blue-without-text.png"; +// package.json +import packageJson from "package.json"; export const ProductUpdatesHeader = observer(() => (
From 9c3f8250140ce180dbd8a0e258d9353c2a28392e Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Fri, 4 Oct 2024 14:09:55 +0530 Subject: [PATCH 4/5] chore: minor improvements. --- web/core/components/global/product-updates/modal.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/web/core/components/global/product-updates/modal.tsx b/web/core/components/global/product-updates/modal.tsx index fb3bf4f8ffe..7ccdd57c168 100644 --- a/web/core/components/global/product-updates/modal.tsx +++ b/web/core/components/global/product-updates/modal.tsx @@ -25,7 +25,11 @@ export const ProductUpdatesModal: FC = observer((props // refs const editorRef = useRef(null); // swr - const { data, isLoading, error } = useSWR(`INSTANCE_CHANGELOG`, () => instanceService.getInstanceChangeLog()); + const { data, isLoading, error } = useSWR(`INSTANCE_CHANGELOG`, () => instanceService.getInstanceChangeLog(), { + shouldRetryOnError: false, + revalidateIfStale: false, + revalidateOnFocus: false, + }); return ( From 4b30c35332dbf18b8f90dd5c75cd383a6d9b8c75 Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Tue, 29 Oct 2024 12:56:22 +0530 Subject: [PATCH 5/5] chore: minor fixes --- web/core/components/global/product-updates/modal.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/web/core/components/global/product-updates/modal.tsx b/web/core/components/global/product-updates/modal.tsx index 7ccdd57c168..607b62fe62e 100644 --- a/web/core/components/global/product-updates/modal.tsx +++ b/web/core/components/global/product-updates/modal.tsx @@ -70,6 +70,9 @@ export const ProductUpdatesModal: FC = observer((props widgetCallback: () => <>, }, }} + fileHandler={{ + getAssetSrc: () => "", + }} /> )}