From 6684dd4ab64a9e25ec19dad6043258b60735d4fc Mon Sep 17 00:00:00 2001 From: anmolsinghbhatia Date: Tue, 25 Apr 2023 16:51:50 +0530 Subject: [PATCH 1/7] feat: product updates service added --- apps/app/services/workspace.service.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/app/services/workspace.service.ts b/apps/app/services/workspace.service.ts index 6a67a1a7a..f6c319e64 100644 --- a/apps/app/services/workspace.service.ts +++ b/apps/app/services/workspace.service.ts @@ -206,6 +206,13 @@ class WorkspaceService extends APIService { throw error?.response?.data; }); } + async getProductUpdates(): Promise { + return this.get("/api/release-notes/") + .then((response) => response?.data) + .catch((error) => { + throw error?.response?.data; + }); + } } export default new WorkspaceService(); From eb99b4adc939b3af0ba6ac18eb7fd42eab27c9a7 Mon Sep 17 00:00:00 2001 From: anmolsinghbhatia Date: Tue, 25 Apr 2023 16:54:12 +0530 Subject: [PATCH 2/7] feat: markdown to custom component --- .../command-palette/command-pallette.tsx | 10 ++- apps/app/components/command-palette/index.ts | 1 + .../command-palette/product-updates-modal.tsx | 76 ++++++++++++++++++ apps/app/components/ui/index.ts | 1 + .../components/ui/markdown-to-component.tsx | 77 +++++++++++++++++++ apps/app/package.json | 1 + 6 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 apps/app/components/command-palette/product-updates-modal.tsx create mode 100644 apps/app/components/ui/markdown-to-component.tsx diff --git a/apps/app/components/command-palette/command-pallette.tsx b/apps/app/components/command-palette/command-pallette.tsx index 3feca33f6..101ae25fd 100644 --- a/apps/app/components/command-palette/command-pallette.tsx +++ b/apps/app/components/command-palette/command-pallette.tsx @@ -45,6 +45,7 @@ import { ChangeIssuePriority, ChangeIssueAssignee, ChangeInterfaceTheme, + ProductUpdatesModal, } from "components/command-palette"; import { BulkDeleteIssuesModal } from "components/core"; import { CreateUpdateCycleModal } from "components/cycles"; @@ -74,6 +75,7 @@ export const CommandPalette: React.FC = () => { const [isIssueModalOpen, setIsIssueModalOpen] = useState(false); const [isProjectModalOpen, setIsProjectModalOpen] = useState(false); const [isShortcutsModalOpen, setIsShortcutsModalOpen] = useState(false); + const [isProductUpdatesModalOpen, setIsProductUpdatesModalOpen] = useState(false); const [isCreateCycleModalOpen, setIsCreateCycleModalOpen] = useState(false); const [isCreateViewModalOpen, setIsCreateViewModalOpen] = useState(false); const [isCreateModuleModalOpen, setIsCreateModuleModalOpen] = useState(false); @@ -221,6 +223,8 @@ export const CommandPalette: React.FC = () => { setIsCreateCycleModalOpen(true); } else if (keyPressed === "m") { setIsCreateModuleModalOpen(true); + } else if (keyPressed === "u") { + setIsProductUpdatesModalOpen(true); } } }, @@ -324,6 +328,10 @@ export const CommandPalette: React.FC = () => { return ( <> + {workspaceSlug && ( )} @@ -393,7 +401,7 @@ export const CommandPalette: React.FC = () => { leaveFrom="opacity-100 translate-y-0 sm:scale-100" leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" > - + { if (value.toLowerCase().includes(search.toLowerCase())) return 1; diff --git a/apps/app/components/command-palette/index.ts b/apps/app/components/command-palette/index.ts index 858aba401..27bad1357 100644 --- a/apps/app/components/command-palette/index.ts +++ b/apps/app/components/command-palette/index.ts @@ -4,3 +4,4 @@ export * from "./change-issue-state"; export * from "./change-issue-priority"; export * from "./change-issue-assignee"; export * from "./change-interface-theme"; +export * from "./product-updates-modal"; diff --git a/apps/app/components/command-palette/product-updates-modal.tsx b/apps/app/components/command-palette/product-updates-modal.tsx new file mode 100644 index 000000000..c099cf505 --- /dev/null +++ b/apps/app/components/command-palette/product-updates-modal.tsx @@ -0,0 +1,76 @@ +import React from "react"; +import useSWR from "swr"; + +// headless ui +import { Dialog, Transition } from "@headlessui/react"; +// icons +import { XMarkIcon } from "@heroicons/react/20/solid"; +import workspaceService from "services/workspace.service"; +import { MarkdownRenderer } from "components/ui"; + +type Props = { + isOpen: boolean; + setIsOpen: React.Dispatch>; +}; + +export const ProductUpdatesModal: React.FC = ({ isOpen, setIsOpen }) => { + const { data: updates } = useSWR("PRODUCT_UPDATES", () => workspaceService.getProductUpdates()); + console.log("updates:", updates); + return ( + + + +
+ + +
+
+ + +
+
+
+ + Product Updates + + + + + {updates && + updates.length > 0 && + updates.map((item: any) => )} +
+
+
+
+
+
+
+
+
+ ); +}; diff --git a/apps/app/components/ui/index.ts b/apps/app/components/ui/index.ts index 855655062..5c23ecdf5 100644 --- a/apps/app/components/ui/index.ts +++ b/apps/app/components/ui/index.ts @@ -20,3 +20,4 @@ export * from "./progress-bar"; export * from "./spinner"; export * from "./tooltip"; export * from "./toggle-switch"; +export * from "./markdown-to-component"; diff --git a/apps/app/components/ui/markdown-to-component.tsx b/apps/app/components/ui/markdown-to-component.tsx new file mode 100644 index 000000000..cb716bc22 --- /dev/null +++ b/apps/app/components/ui/markdown-to-component.tsx @@ -0,0 +1,77 @@ +import React from "react"; +import ReactMarkdown from "react-markdown"; + +interface CustomComponentProps { + href: string; + children: React.ReactNode; +} + +type CustomComponent = React.ComponentType; + +interface Props { + markdown: string; + components?: { + a?: CustomComponent; + blockquote?: CustomComponent; + code?: CustomComponent; + del?: CustomComponent; + em?: CustomComponent; + heading?: CustomComponent; + hr?: CustomComponent; + image?: CustomComponent; + inlineCode?: CustomComponent; + link?: CustomComponent; + list?: CustomComponent; + listItem?: CustomComponent; + paragraph?: CustomComponent; + strong?: CustomComponent; + table?: CustomComponent; + tableCell?: CustomComponent; + tableHead?: CustomComponent; + tableRow?: CustomComponent; + }; + options?: any; +} + +const HeadingPrimary: CustomComponent = ({ children }) => ( +

{children}

+); + +const HeadingSecondary: CustomComponent = ({ children }) => ( +

{children}

+); + +const Paragraph: CustomComponent = ({ children }) => ( +

{children}

+); + +const OrderedList: CustomComponent = ({ children }) => ( +
    {children}
+); + +const UnorderedList: CustomComponent = ({ children }) => ( +
    {children}
+); + +const Link: CustomComponent = ({ href, children }) => ( + + {children} + +); + +export const MarkdownRenderer: React.FC = ({ markdown, options = {} }) => { + const customComponents = { + h1: HeadingPrimary, + h3: HeadingSecondary, + p: Paragraph, + ol: OrderedList, + ul: UnorderedList, + a: Link, + }; + + return ( + + {markdown} + + ); +}; diff --git a/apps/app/package.json b/apps/app/package.json index 6911625b2..d3c414210 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -36,6 +36,7 @@ "react-dom": "18.2.0", "react-dropzone": "^14.2.3", "react-hook-form": "^7.38.0", + "react-markdown": "^8.0.7", "recharts": "^2.3.2", "remirror": "^2.0.23", "swr": "^1.3.0", From 1364c842e0b6b3553f9ec354830e29454777f638 Mon Sep 17 00:00:00 2001 From: anmolsinghbhatia Date: Tue, 25 Apr 2023 17:33:53 +0530 Subject: [PATCH 3/7] feat: product updates button added --- .../command-palette/command-pallette.tsx | 8 -------- apps/app/components/command-palette/index.ts | 1 - apps/app/components/ui/index.ts | 1 + .../product-updates-modal.tsx | 12 ++++++------ apps/app/pages/[workspaceSlug]/index.tsx | 15 ++++++++++++--- 5 files changed, 19 insertions(+), 18 deletions(-) rename apps/app/components/{command-palette => ui}/product-updates-modal.tsx (89%) diff --git a/apps/app/components/command-palette/command-pallette.tsx b/apps/app/components/command-palette/command-pallette.tsx index 101ae25fd..26555ddf1 100644 --- a/apps/app/components/command-palette/command-pallette.tsx +++ b/apps/app/components/command-palette/command-pallette.tsx @@ -45,7 +45,6 @@ import { ChangeIssuePriority, ChangeIssueAssignee, ChangeInterfaceTheme, - ProductUpdatesModal, } from "components/command-palette"; import { BulkDeleteIssuesModal } from "components/core"; import { CreateUpdateCycleModal } from "components/cycles"; @@ -75,7 +74,6 @@ export const CommandPalette: React.FC = () => { const [isIssueModalOpen, setIsIssueModalOpen] = useState(false); const [isProjectModalOpen, setIsProjectModalOpen] = useState(false); const [isShortcutsModalOpen, setIsShortcutsModalOpen] = useState(false); - const [isProductUpdatesModalOpen, setIsProductUpdatesModalOpen] = useState(false); const [isCreateCycleModalOpen, setIsCreateCycleModalOpen] = useState(false); const [isCreateViewModalOpen, setIsCreateViewModalOpen] = useState(false); const [isCreateModuleModalOpen, setIsCreateModuleModalOpen] = useState(false); @@ -223,8 +221,6 @@ export const CommandPalette: React.FC = () => { setIsCreateCycleModalOpen(true); } else if (keyPressed === "m") { setIsCreateModuleModalOpen(true); - } else if (keyPressed === "u") { - setIsProductUpdatesModalOpen(true); } } }, @@ -328,10 +324,6 @@ export const CommandPalette: React.FC = () => { return ( <> - {workspaceSlug && ( )} diff --git a/apps/app/components/command-palette/index.ts b/apps/app/components/command-palette/index.ts index 27bad1357..858aba401 100644 --- a/apps/app/components/command-palette/index.ts +++ b/apps/app/components/command-palette/index.ts @@ -4,4 +4,3 @@ export * from "./change-issue-state"; export * from "./change-issue-priority"; export * from "./change-issue-assignee"; export * from "./change-interface-theme"; -export * from "./product-updates-modal"; diff --git a/apps/app/components/ui/index.ts b/apps/app/components/ui/index.ts index 5c23ecdf5..3f50d1a21 100644 --- a/apps/app/components/ui/index.ts +++ b/apps/app/components/ui/index.ts @@ -21,3 +21,4 @@ export * from "./spinner"; export * from "./tooltip"; export * from "./toggle-switch"; export * from "./markdown-to-component"; +export * from "./product-updates-modal"; diff --git a/apps/app/components/command-palette/product-updates-modal.tsx b/apps/app/components/ui/product-updates-modal.tsx similarity index 89% rename from apps/app/components/command-palette/product-updates-modal.tsx rename to apps/app/components/ui/product-updates-modal.tsx index c099cf505..b37517343 100644 --- a/apps/app/components/command-palette/product-updates-modal.tsx +++ b/apps/app/components/ui/product-updates-modal.tsx @@ -18,7 +18,7 @@ export const ProductUpdatesModal: React.FC = ({ isOpen, setIsOpen }) => { console.log("updates:", updates); return ( - + = ({ isOpen, setIsOpen }) => { leaveFrom="opacity-100" leaveTo="opacity-0" > -
+
@@ -42,19 +42,19 @@ export const ProductUpdatesModal: React.FC = ({ isOpen, setIsOpen }) => { leaveFrom="opacity-100 translate-y-0 sm:scale-100" leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" > - -
+ +
Product Updates diff --git a/apps/app/pages/[workspaceSlug]/index.tsx b/apps/app/pages/[workspaceSlug]/index.tsx index adf893f88..a39bc163a 100644 --- a/apps/app/pages/[workspaceSlug]/index.tsx +++ b/apps/app/pages/[workspaceSlug]/index.tsx @@ -15,6 +15,7 @@ import { IssuesPieChart, IssuesStats, } from "components/workspace"; +import { ProductUpdatesModal } from "components/ui"; // types import type { NextPage } from "next"; // fetch-keys @@ -22,6 +23,7 @@ import { USER_WORKSPACE_DASHBOARD } from "constants/fetch-keys"; const WorkspacePage: NextPage = () => { const [month, setMonth] = useState(new Date().getMonth() + 1); + const [isProductUpdatesModalOpen, setIsProductUpdatesModalOpen] = useState(false); const router = useRouter(); const { workspaceSlug } = router.query; @@ -39,6 +41,10 @@ const WorkspacePage: NextPage = () => { return ( +
{ Plane is open source, support us by starring us on GitHub.

- {/* - View roadmap - */} + Date: Tue, 25 Apr 2023 18:02:13 +0530 Subject: [PATCH 4/7] feat: product updates tag and date added --- .../components/ui/product-updates-modal.tsx | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/apps/app/components/ui/product-updates-modal.tsx b/apps/app/components/ui/product-updates-modal.tsx index b37517343..b3388d31e 100644 --- a/apps/app/components/ui/product-updates-modal.tsx +++ b/apps/app/components/ui/product-updates-modal.tsx @@ -3,10 +3,14 @@ import useSWR from "swr"; // headless ui import { Dialog, Transition } from "@headlessui/react"; +// component +import { MarkdownRenderer, Spinner } from "components/ui"; // icons import { XMarkIcon } from "@heroicons/react/20/solid"; +// services import workspaceService from "services/workspace.service"; -import { MarkdownRenderer } from "components/ui"; +// helper +import { renderLongDateFormat } from "helpers/date-time.helper"; type Props = { isOpen: boolean; @@ -15,7 +19,6 @@ type Props = { export const ProductUpdatesModal: React.FC = ({ isOpen, setIsOpen }) => { const { data: updates } = useSWR("PRODUCT_UPDATES", () => workspaceService.getProductUpdates()); - console.log("updates:", updates); return ( @@ -60,9 +63,29 @@ export const ProductUpdatesModal: React.FC = ({ isOpen, setIsOpen }) => { - {updates && - updates.length > 0 && - updates.map((item: any) => )} + {updates && updates.length > 0 ? ( + updates.map((item: any, index: number) => ( + <> +
+ + {item.tag_name} + + {renderLongDateFormat(item.published_at)} + {index === 0 && ( + + New + + )} +
+ + + )) + ) : ( +
+ + Loading... +
+ )}
From 3480b450f24e1642b79d082c1b040ee20090e879 Mon Sep 17 00:00:00 2001 From: anmolsinghbhatia Date: Tue, 25 Apr 2023 18:10:23 +0530 Subject: [PATCH 5/7] fix: build fix --- apps/app/pages/[workspaceSlug]/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app/pages/[workspaceSlug]/index.tsx b/apps/app/pages/[workspaceSlug]/index.tsx index a39bc163a..5edef60eb 100644 --- a/apps/app/pages/[workspaceSlug]/index.tsx +++ b/apps/app/pages/[workspaceSlug]/index.tsx @@ -59,7 +59,7 @@ const WorkspacePage: NextPage = () => { onClick={() => setIsProductUpdatesModalOpen(true)} className="rounded-md border-2 border-brand-base px-3 py-1.5 text-sm font-medium duration-300" > - What's New? + {`What's New?`} Date: Fri, 28 Apr 2023 18:28:43 +0530 Subject: [PATCH 6/7] chore: product update interface --- apps/app/services/workspace.service.ts | 3 +- apps/app/types/workspace.d.ts | 52 ++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/apps/app/services/workspace.service.ts b/apps/app/services/workspace.service.ts index f6c319e64..7fe1ec198 100644 --- a/apps/app/services/workspace.service.ts +++ b/apps/app/services/workspace.service.ts @@ -11,6 +11,7 @@ import { IWorkspaceMemberInvitation, ILastActiveWorkspaceDetails, IWorkspaceSearchResults, + IProductUpdateResponse, } from "types"; const trackEvent = @@ -206,7 +207,7 @@ class WorkspaceService extends APIService { throw error?.response?.data; }); } - async getProductUpdates(): Promise { + async getProductUpdates(): Promise { return this.get("/api/release-notes/") .then((response) => response?.data) .catch((error) => { diff --git a/apps/app/types/workspace.d.ts b/apps/app/types/workspace.d.ts index e31d8f481..91948af46 100644 --- a/apps/app/types/workspace.d.ts +++ b/apps/app/types/workspace.d.ts @@ -82,3 +82,55 @@ export interface IWorkspaceSearchResults { page: IWorkspaceDefaultSearchResult[]; }; } + +export interface IProductUpdateResponse { + url: string; + assets_url: string; + upload_url: string; + html_url: string; + id: number; + author: { + login: string; + id: string; + node_id: string; + avatar_url: string; + gravatar_id: ""; + url: string; + html_url: string; + followers_url: string; + following_url: string; + gists_url: string; + starred_url: string; + subscriptions_url: string; + organizations_url: string; + repos_url: string; + events_url: string; + received_events_url: string; + type: string; + site_admin: false; + }; + node_id: string; + tag_name: string; + target_commitish: string; + name: string; + draft: boolean; + prerelease: true; + created_at: string; + published_at: string; + assets: []; + tarball_url: string; + zipball_url: string; + body: string; + reactions: { + url: string; + total_count: number; + "+1": number; + "-1": number; + laugh: number; + hooray: number; + confused: number; + heart: number; + rocket: number; + eyes: number; + }; +} From 9464b5c00e8d7ea3699b19a20e24beb4033e425b Mon Sep 17 00:00:00 2001 From: anmolsinghbhatia Date: Fri, 28 Apr 2023 18:29:01 +0530 Subject: [PATCH 7/7] style: product update modal --- apps/app/components/ui/product-updates-modal.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/app/components/ui/product-updates-modal.tsx b/apps/app/components/ui/product-updates-modal.tsx index b3388d31e..24214b488 100644 --- a/apps/app/components/ui/product-updates-modal.tsx +++ b/apps/app/components/ui/product-updates-modal.tsx @@ -31,7 +31,7 @@ export const ProductUpdatesModal: React.FC = ({ isOpen, setIsOpen }) => { leaveFrom="opacity-100" leaveTo="opacity-0" > -
+
@@ -64,15 +64,15 @@ export const ProductUpdatesModal: React.FC = ({ isOpen, setIsOpen }) => { {updates && updates.length > 0 ? ( - updates.map((item: any, index: number) => ( + updates.map((item, index: number) => ( <> -
- +
+ {item.tag_name} {renderLongDateFormat(item.published_at)} {index === 0 && ( - + New )}