Skip to content

Conversation

@yurimutti
Copy link

@yurimutti yurimutti commented Nov 5, 2024

What kind of change does this PR introduce?

Created a post preview page

Why was this change needed?

Related #218

Other information:

I am open to discuss more about this feature

Checklist:

Put a "X" in the boxes below to indicate you have followed the checklist;

  • I have read the CONTRIBUTING guide.
  • I checked that there were not similar issues or PRs already open for this.
  • This PR fixes just ONE issue (do not include multiple issues or types of change in the same PR) For example, don't try and fix a UI issue and include new dependencies in the same PR.

https://www.loom.com/share/ef80c01856314528a1a79ba0be3d72d7?sid=ea1248bf-b1d7-46fe-b5a8-036b102b65a8

Summary by CodeRabbit

  • New Features

    • Introduced a dynamic preview page for rendering content based on an ID.
    • Added a new Preview component for fetching and displaying posts.
    • Implemented a share functionality for posts with user feedback via toast notifications.
    • Enhanced text formatting in the GeneralPreviewComponent with visual indicators for truncated text.
  • Bug Fixes

    • Improved confirmation dialog for post deletion in the AddEditModal.
  • Style

    • Adjusted class name order for better readability in multiple components.
  • Chores

    • Enhanced type safety and state management in various components.

@vercel
Copy link

vercel bot commented Nov 5, 2024

@yurimutti is attempting to deploy a commit to the Listinai Team on Vercel.

A member of the Team first needs to authorize it.

@nevo-david
Copy link
Contributor

Hi @yurimutti, are you still working on it?
i see some more commits, can you resolve the conflicts?

@yurimutti
Copy link
Author

Hi @yurimutti, are you still working on it? i see some more commits, can you resolve the conflicts?

Hello @nevo-david I waiting for a review.

@yurimutti
Copy link
Author

Hi @yurimutti, are you still working on it? i see some more commits, can you resolve the conflicts?

I resolved the conflicts.

@vercel
Copy link

vercel bot commented Dec 6, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
gitroom ✅ Ready (Inspect) Visit Preview 💬 Add feedback Dec 6, 2024 2:51am
1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
postiz ⬜️ Ignored (Inspect) Visit Preview Dec 6, 2024 2:51am

@coderabbitai
Copy link

coderabbitai bot commented Dec 6, 2024

Important

Review skipped

More than 25% of the files skipped due to max files limit. The review is being skipped to prevent a low-quality review.

580 files out of 692 files are above the max files limit of 100.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The pull request introduces several updates across multiple components in a Next.js application. A new Preview component is added to render a dynamic preview page, while the AddEditModal component receives enhancements in its state management and rendering logic. Other components, such as GeneralPreviewComponent, ProvidersOptions, and high.order.provider, undergo minor modifications primarily focused on class name reordering and user interaction improvements. These changes collectively aim to enhance usability, maintainability, and visual consistency without altering core functionalities.

Changes

File Path Change Summary
apps/frontend/src/app/(site)/preview/[id]/page.tsx Introduced page.tsx with a dynamic preview component that exports a metadata object and an asynchronous function Index for rendering the Preview component.
apps/frontend/src/components/launches/add.edit.model.tsx Updated AddEditModal with typed event handlers, improved delete confirmation, refined publication logic, and adjusted button rendering for better usability.
apps/frontend/src/components/launches/calendar.tsx Cosmetic changes in calendar.tsx with reordering of class names for WeekView and MonthView, and whitespace adjustments in the export statement.
apps/frontend/src/components/launches/general.preview.component.tsx Enhanced GeneralPreviewComponent with new media path management, updated text slicing functionality, and class name reordering for styling purposes.
apps/frontend/src/components/launches/providers.options.tsx Modified ProvidersOptions to reorder class names in a div element, maintaining existing functionality.
apps/frontend/src/components/launches/providers/high.order.provider.tsx Added handleShare function for sharing posts, updated deletePost with confirmation dialog, and introduced a new "Share" button for user interaction.
apps/frontend/src/components/preview/preview.tsx Introduced new Preview component that fetches posts using useFetch and useSWR, managing loading and error states while rendering the GeneralPreviewComponent.

Possibly related PRs

Poem

🐰 In the land of code where rabbits play,
New previews hop in, brightening the day.
With buttons that share and modals that shine,
Our app's now a garden, oh how it aligns!
So let's celebrate changes, both big and small,
For every new feature, we cheer and we call! 🎉


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (6)
apps/frontend/src/app/(site)/preview/[id]/page.tsx (1)

7-10: Consider adding dynamic metadata based on post content.

While the current metadata is functional, consider enhancing it by including post-specific information (title, description) once the data is fetched.

Example implementation:

export async function generateMetadata({ params }: { params: { id: string } }): Promise<Metadata> {
  try {
    const post = await fetch(`/api/posts/${params.id}`).then(res => res.json());
    return {
      title: `${isGeneralServerSide() ? 'Postiz' : 'Gitroom'} - ${post.title}`,
      description: post.description || 'Make a preview link for your posts.',
    };
  } catch (error) {
    return {
      title: `${isGeneralServerSide() ? 'Postiz' : 'Gitroom'} Preview`,
      description: 'Make a preview link for your posts.',
    };
  }
}
apps/frontend/src/components/preview/preview.tsx (1)

30-35: Enhance error handling and user feedback.

The current error messages could be more descriptive and user-friendly.

-      <main className="flex mx-auto">
-        <h1>{!data?.posts ? 'No post founded.' : 'Oops! Something went wrong.'} </h1>
+      <main className="flex flex-col items-center justify-center min-h-[200px] mx-auto">
+        <h1 className="text-xl font-semibold mb-2">
+          {!data?.posts ? 'Post not found' : 'Unable to load preview'}
+        </h1>
+        <p className="text-gray-600">
+          {!data?.posts 
+            ? 'The post you're looking for might have been deleted or is not accessible.'
+            : 'Please try again later or contact support if the issue persists.'}
+        </p>
       </main>
apps/frontend/src/components/launches/general.preview.component.tsx (3)

Line range hint 13-21: Extract text processing logic to a custom hook.

The text slicing and formatting logic would be more maintainable as a separate hook.

// hooks/useTextProcessing.ts
export const useTextProcessing = (text: string, maxChars: number, identifier: string) => {
  return useMemo(() => {
    const {start, end} = textSlicer(identifier, maxChars, text);
    return {
      processedText: text.slice(start, end),
      croppedText: text.slice(end),
      isCropped: end < text.length
    };
  }, [text, maxChars, identifier]);
};

Line range hint 82-82: Security Risk: Unsafe HTML rendering.

Using dangerouslySetInnerHTML with user-generated content poses XSS risks. Consider using a sanitization library.

+import DOMPurify from 'dompurify';

-<pre className={clsx('text-wrap', chakra.className)} dangerouslySetInnerHTML={{__html: value.text}} />
+<pre className={clsx('text-wrap', chakra.className)} 
+     dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(value.text)}} />

Line range hint 83-102: Add error handling for images.

The image rendering lacks error handling and loading states.

 <VideoOrImage
   autoplay={true}
   src={mediaDir.set(image.path)}
+  onError={(e) => {
+    e.currentTarget.src = '/fallback-image.png';
+  }}
+  loading="lazy"
 />
apps/frontend/src/components/launches/providers/high.order.provider.tsx (1)

411-434: Consider enhancing the Share button accessibility

While the implementation is good, consider adding ARIA attributes for better accessibility.

Add these attributes to improve accessibility:

 <Button
   onClick={handleShare}
+  aria-label="Share post"
   className="!h-[24px] rounded-[3px] flex gap-[4px] w-[102px] text-[12px] font-[500]"
 >
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between b263299 and bf6e9fb.

📒 Files selected for processing (8)
  • apps/frontend/src/app/(site)/preview/[id]/page.tsx (1 hunks)
  • apps/frontend/src/components/launches/add.edit.model.tsx (3 hunks)
  • apps/frontend/src/components/launches/calendar.tsx (3 hunks)
  • apps/frontend/src/components/launches/general.preview.component.tsx (2 hunks)
  • apps/frontend/src/components/launches/launches.component.tsx (1 hunks)
  • apps/frontend/src/components/launches/providers.options.tsx (1 hunks)
  • apps/frontend/src/components/launches/providers/high.order.provider.tsx (8 hunks)
  • apps/frontend/src/components/preview/preview.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • apps/frontend/src/components/launches/providers.options.tsx
  • apps/frontend/src/components/launches/calendar.tsx
🔇 Additional comments (6)
apps/frontend/src/app/(site)/preview/[id]/page.tsx (2)

5-5: LGTM! Dynamic rendering is appropriate for preview pages.

The force-dynamic setting ensures fresh data on each request, which is suitable for preview functionality.


12-16: LGTM! Clean and focused component implementation.

The component follows Next.js patterns and properly passes the ID parameter to the Preview component.

apps/frontend/src/components/preview/preview.tsx (1)

18-21: ⚠️ Potential issue

Add missing dependency to useCallback.

The fetch function is used within the callback but not included in the dependency array.

  }, [id]);
+  }, [id, fetch]);
apps/frontend/src/components/launches/launches.component.tsx (1)

153-153: LGTM!

Minor whitespace adjustment with no functional impact.

apps/frontend/src/components/launches/providers/high.order.provider.tsx (1)

222-234: LGTM: Share functionality implementation

The handleShare function is well-implemented with:

  • Proper URL construction using window.location.origin
  • Error handling with user feedback
  • Clipboard API usage
apps/frontend/src/components/launches/add.edit.model.tsx (1)

Line range hint 596-630: LGTM: Improved button section UI

The changes enhance the button section with:

  • Better conditional text rendering
  • Improved text alignment
  • Consistent styling

Copy link

@A1exKH A1exKH left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yurimutti this PR LGTM.
Could you resolve conflicts for this PR, please?

@yurimutti yurimutti requested a review from A1exKH December 13, 2024 11:24
@yurimutti
Copy link
Author

@yurimutti this PR LGTM. Could you resolve conflicts for this PR, please?

Done. Could you review again?

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (1)
apps/frontend/src/components/launches/providers/high.order.provider.tsx (1)

448-471: Improve Share button accessibility and maintainability

The Share button implementation could be enhanced in several ways:

  1. Add accessibility attributes
  2. Extract SVG to a separate component
  3. Make the button width responsive
  4. Add loading state during clipboard operation

Consider these improvements:

 <Button
   onClick={handleShare}
-  className="!h-[24px] rounded-[3px] flex gap-[4px] w-[102px] text-[12px] font-[500]"
+  className="!h-[24px] rounded-[3px] flex gap-[4px] min-w-[102px] text-[12px] font-[500]"
+  aria-label="Share post"
+  disabled={!existingData?.posts?.length}
 >
-  <div>
-    <svg
-      xmlns="http://www.w3.org/2000/svg"
-      version="1.1"
-      x="0px"
-      y="0px"
-      viewBox="0 0 800 1000"
-      className="max-w-[20px] max-h-[20px] fill-current h-[1.25em]"
-    >
-      <path
-        fill="white"
-        d="M443.25,529.42c2.9,1.32,6.32,0.83,8.73-1.27l211.28-183.37c1.79-1.55,2.81-3.79,2.81-6.16c0-2.37-1.02-4.61-2.81-6.16  L451.98,149.11c-2.41-2.1-5.83-2.59-8.73-1.27c-2.91,1.33-4.77,4.23-4.77,7.42v109.52c-168.67,5.27-304.54,173.69-304.54,379.94  c0,3.81,2.63,7.11,6.35,7.95c0.61,0.14,1.21,0.21,1.81,0.21c3.08,0,5.97-1.75,7.35-4.63c81.79-170.48,158.11-233.12,289.03-235.58  V522C438.47,525.19,440.34,528.09,443.25,529.42z M151.83,607.06c15.41-182.94,141.74-326.08,294.8-326.08  c4.51,0,8.16-3.65,8.16-8.16v-99.67l190.67,165.48L454.79,504.11v-99.67c0-4.51-3.65-8.16-8.16-8.16  C314.35,396.29,231.89,454.14,151.83,607.06z"
-      />
-    </svg>
-  </div>
+  <ShareIcon className="max-w-[20px] max-h-[20px] fill-current h-[1.25em]" />
   <div className="text-white">Share</div>
 </Button>

Create a new ShareIcon component:

// components/icons/ShareIcon.tsx
export const ShareIcon: React.FC<{ className?: string }> = ({ className }) => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 800 1000"
    className={className}
    aria-hidden="true"
  >
    <path
      fill="currentColor"
      d="M443.25,529.42c2.9,1.32,6.32,0.83,8.73-1.27l211.28-183.37c1.79-1.55,2.81-3.79,2.81-6.16c0-2.37-1.02-4.61-2.81-6.16  L451.98,149.11c-2.41-2.1-5.83-2.59-8.73-1.27c-2.91,1.33-4.77,4.23-4.77,7.42v109.52c-168.67,5.27-304.54,173.69-304.54,379.94  c0,3.81,2.63,7.11,6.35,7.95c0.61,0.14,1.21,0.21,1.81,0.21c3.08,0,5.97-1.75,7.35-4.63c81.79-170.48,158.11-233.12,289.03-235.58  V522C438.47,525.19,440.34,528.09,443.25,529.42z M151.83,607.06c15.41-182.94,141.74-326.08,294.8-326.08  c4.51,0,8.16-3.65,8.16-8.16v-99.67l190.67,165.48L454.79,504.11v-99.67c0-4.51-3.65-8.16-8.16-8.16  C314.35,396.29,231.89,454.14,151.83,607.06z"
    />
  </svg>
);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bf6e9fb and 6bc51ba.

📒 Files selected for processing (4)
  • apps/frontend/src/components/launches/add.edit.model.tsx (3 hunks)
  • apps/frontend/src/components/launches/calendar.tsx (3 hunks)
  • apps/frontend/src/components/launches/general.preview.component.tsx (2 hunks)
  • apps/frontend/src/components/launches/providers/high.order.provider.tsx (8 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/frontend/src/components/launches/calendar.tsx
  • apps/frontend/src/components/launches/general.preview.component.tsx
  • apps/frontend/src/components/launches/add.edit.model.tsx
🔇 Additional comments (2)
apps/frontend/src/components/launches/providers/high.order.provider.tsx (2)

38-39: Clean up unused imports and variables

The static analysis tool has identified several unused declarations:

  • 'Component' is defined but never used
  • 'date' is defined but never used
  • 'modal' is assigned but never used

Line range hint 229-471: Verify integration with the preview feature

Let's ensure that the share functionality properly integrates with the preview feature mentioned in the PR objectives.

✅ Verification successful

Based on the search results, I can now provide a final response:

Share functionality is properly integrated with preview feature

The implementation is correctly integrated with the preview feature:

  • The Preview component exists and is properly implemented in apps/frontend/src/components/preview/preview.tsx
  • The share functionality in handleShare correctly constructs the preview URL using the post ID
  • The clipboard API is properly used with appropriate error handling and user feedback via toast messages
  • The preview URL format (/preview/${postId}) aligns with the existing preview component's route structure
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the preview route and component integration

# Check if the preview route exists
echo "Checking preview route..."
rg -l "preview/\[.*\]" --type tsx

# Check if the Preview component is properly imported and used
echo "Checking Preview component usage..."
ast-grep --pattern 'import { Preview } from "@gitroom/frontend/components/preview/preview"'

# Check for any existing share functionality to avoid duplication
echo "Checking for existing share functionality..."
rg -i "share.*link|copy.*link|clipboard" --type tsx

Length of output: 605


Script:

#!/bin/bash
# Let's try with more generic file extensions and patterns

# Check preview route and component implementation
echo "Checking preview route and component..."
rg -t js -t jsx -t ts -t tsx "preview/\[.*\]|route.*preview"

# Check the Preview component implementation
echo "Checking Preview component implementation..."
rg -t js -t jsx -t ts -t tsx -A 5 "export.*Preview"

# Check clipboard and share functionality
echo "Checking share functionality..."
rg -t js -t jsx -t ts -t tsx "navigator\.clipboard\.writeText|handleShare"

# Check if there are any other preview URLs being constructed
echo "Checking preview URL construction..."
rg -t js -t jsx -t ts -t tsx "preview/\$|/preview/.*id"

Length of output: 706


Script:

#!/bin/bash
# Let's try without file type restrictions since ripgrep seems to have issues with tsx/jsx

# Check preview route and component
echo "Checking preview route and component..."
rg "preview/\[.*\]|route.*preview"

# Check the Preview component
echo "Checking Preview component..."
rg -A 5 "export.*Preview"

# Check clipboard and share functionality
echo "Checking share functionality..."
rg "navigator\.clipboard\.writeText|handleShare"

# Check preview URL construction
echo "Checking preview URL construction..."
rg "/preview/.*id|preview/\$"

# Check if the preview page exists
echo "Checking preview page existence..."
fd "page.tsx" --full-path "preview"

Length of output: 3741

Copy link

@A1exKH A1exKH left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yurimutti please, could you resolve one ESLint warning?
After this PR can be approved.

@yurimutti yurimutti requested a review from A1exKH December 30, 2024 22:55
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/frontend/src/components/launches/providers/high.order.provider.tsx (1)

242-265: Consider enhancing the share functionality

The implementation has good practices like safe URL construction and proper error handling. However, consider these improvements:

  1. Allow sharing specific posts instead of always sharing the first one
  2. Add more specific error messages for clipboard permission issues
 const handleShare = async () => {
   if (!existingData.posts.length) {
     return toast.show('No posts available to share', 'warning');
   }

-  const postId = existingData.posts[0].id;
+  // Allow sharing specific posts
+  const postId = existingData.posts[index].id;

   const previewPath = new URL(
     `/preview/${postId}`,
     window.location.origin
   ).toString();

   try {
     if (!navigator.clipboard) {
-      throw new Error('Clipboard API not available');
+      throw new Error('Clipboard access denied. Please check browser permissions.');
     }
     await navigator.clipboard.writeText(previewPath);
     return toast.show('Link copied to clipboard.', 'success');
   } catch (err) {
     if (err instanceof Error)
-      toast.show(`Failed to copy the link. ${err.message}`, 'warning');
+      toast.show(
+        `Failed to copy the link. ${
+          err.message.includes('denied')
+            ? 'Please allow clipboard access in your browser settings.'
+            : err.message
+        }`,
+        'warning'
+      );
   }
 };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e151339 and 9933506.

📒 Files selected for processing (5)
  • apps/frontend/src/components/launches/add.edit.model.tsx (3 hunks)
  • apps/frontend/src/components/launches/calendar.tsx (3 hunks)
  • apps/frontend/src/components/launches/general.preview.component.tsx (2 hunks)
  • apps/frontend/src/components/launches/providers.options.tsx (1 hunks)
  • apps/frontend/src/components/launches/providers/high.order.provider.tsx (8 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/frontend/src/components/launches/providers.options.tsx
  • apps/frontend/src/components/launches/calendar.tsx
  • apps/frontend/src/components/launches/add.edit.model.tsx
  • apps/frontend/src/components/launches/general.preview.component.tsx

@yurimutti
Copy link
Author

@A1exKH Hello, do we need more approval to forward this feature?

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
apps/frontend/src/components/launches/providers/high.order.provider.tsx (1)

549-570: 🛠️ Refactor suggestion

Enhance Share button accessibility

The Share button implementation needs accessibility improvements as previously suggested.

 <Button
   onClick={handleShare}
   className="!h-[24px] rounded-[3px] flex gap-[4px] w-[102px] text-[12px] font-[500]"
+  aria-label="Share post"
+  role="button"
 >
   <div>
     <svg
       xmlns="http://www.w3.org/2000/svg"
       version="1.1"
-      x="0px"
-      y="0px"
       viewBox="0 0 800 1000"
       className="max-w-[20px] max-h-[20px] fill-current h-[1.25em]"
+      aria-hidden="true"
+      role="img"
     >
       <path
         fill="white"
         d="M443.25,529.42c2.9,1.32,6.32,0.83,8.73-1.27l211.28-183.37c1.79-1.55,2.81-3.79,2.81-6.16c0-2.37-1.02-4.61-2.81-6.16  L451.98,149.11c-2.41-2.1-5.83-2.59-8.73-1.27c-2.91,1.33-4.77,4.23-4.77,7.42v109.52c-168.67,5.27-304.54,173.69-304.54,379.94  c0,3.81,2.63,7.11,6.35,7.95c0.61,0.14,1.21,0.21,1.81,0.21c3.08,0,5.97-1.75,7.35-4.63c81.79-170.48,158.11-233.12,289.03-235.58  V522C438.47,525.19,440.34,528.09,443.25,529.42z M151.83,607.06c15.41-182.94,141.74-326.08,294.8-326.08  c4.51,0,8.16-3.65,8.16-8.16v-99.67l190.67,165.48L454.79,504.11v-99.67c0-4.51-3.65-8.16-8.16-8.16  C314.35,396.29,231.89,454.14,151.83,607.06z"
       />
     </svg>
   </div>
-  <div className="text-white">Share</div>
+  <span className="text-white">Share</span>
 </Button>
🧹 Nitpick comments (1)
apps/frontend/src/components/launches/providers/high.order.provider.tsx (1)

235-258: Enhance error handling in handleShare function

The implementation looks good and includes proper safety checks. Consider being more specific with error handling by checking for specific error types.

 } catch (err) {
-  if (err instanceof Error)
-    toast.show(`Failed to copy the link. ${err.message}`, 'warning');
+  if (err instanceof Error) {
+    const message = err.name === 'NotAllowedError' 
+      ? 'Permission denied. Please ensure clipboard access is allowed.'
+      : err.message;
+    toast.show(`Failed to copy the link. ${message}`, 'warning');
+  } else {
+    toast.show('Failed to copy the link. Unknown error occurred.', 'warning');
+  }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9933506 and 9714bc9.

📒 Files selected for processing (3)
  • apps/frontend/src/components/launches/add.edit.model.tsx (3 hunks)
  • apps/frontend/src/components/launches/calendar.tsx (3 hunks)
  • apps/frontend/src/components/launches/providers/high.order.provider.tsx (8 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/frontend/src/components/launches/calendar.tsx
  • apps/frontend/src/components/launches/add.edit.model.tsx

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/frontend/src/components/launches/providers/high.order.provider.tsx (1)

272-294: Enhance error handling and accessibility in share functionality.

The implementation is good but could be improved:

  1. Add keyboard support for the share button
  2. Consider adding a success message with the copied URL
 const handleShare = async () => {
   if (!existingData.posts.length) {
     return toast.show('No posts available to share', 'warning');
   }

   const postId = existingData.posts[0].id;

   const previewPath = new URL(
     `/preview/${postId}`,
     window.location.origin
   ).toString();

   try {
     if (!navigator.clipboard) {
       throw new Error('Clipboard API not available');
     }
     await navigator.clipboard.writeText(previewPath);
-    return toast.show('Link copied to clipboard.', 'success');
+    return toast.show(`Link copied to clipboard: ${previewPath}`, 'success');
   } catch (err) {
     if (err instanceof Error)
       toast.show(`Failed to copy the link. ${err.message}`, 'warning');
   }
 };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9714bc9 and 5eb129f.

📒 Files selected for processing (3)
  • apps/frontend/src/components/launches/add.edit.model.tsx (3 hunks)
  • apps/frontend/src/components/launches/calendar.tsx (3 hunks)
  • apps/frontend/src/components/launches/providers/high.order.provider.tsx (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/frontend/src/components/launches/calendar.tsx
  • apps/frontend/src/components/launches/add.edit.model.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
apps/frontend/src/components/launches/providers/high.order.provider.tsx

[error] 297-297: Shouldn't redeclare 'changeToEditor'. Consider to delete it or rename it.

'changeToEditor' is defined here:

(lint/suspicious/noRedeclare)


[error] 441-441: Unexpected token. Did you mean {'}'} or &rbrace;?

(parse)


[error] 459-459: Expected corresponding JSX closing tag for 'EditorWrapper'.

Opening tag

closing tag

(parse)


[error] 616-616: expected ) but instead found className

Remove className

(parse)


[error] 619-619: expected , but instead found onClick

Remove onClick

(parse)


[error] 620-620: expected , but instead found className

Remove className

(parse)


[error] 638-638: expected , but instead found className

Remove className

(parse)


[error] 638-638: expected , but instead found <

Remove <

(parse)


[error] 639-639: expected , but instead found <

Remove <

(parse)


[error] 641-641: expected , but instead found <

Remove <

(parse)


[error] 642-642: expected } but instead found )

Remove )

(parse)


[error] 642-642: Unexpected token. Did you mean {'}'} or &rbrace;?

(parse)


[error] 647-647: expected , but instead found {

Remove {

(parse)


[error] 647-647: Expected a property, a shorthand property, a getter, a setter, or a method but instead found '('.

Expected a property, a shorthand property, a getter, a setter, or a method here.

(parse)


[error] 647-647: expected , but instead found ===

Remove ===

(parse)


[error] 647-647: expected , but instead found showTab

Remove showTab

(parse)


[error] 647-647: expected , but instead found ===

Remove ===

(parse)


[error] 647-647: Expected a function body but instead found '&&'.

Expected a function body here.

(parse)


[error] 648-648: expected , but instead found <

Remove <

(parse)


[error] 648-648: expected , but instead found className

Remove className

(parse)


[error] 648-648: Expected a parameter but instead found ''mt-[20px]''.

Expected a parameter here.

(parse)


[error] 648-648: expected , but instead found !==

Remove !==

(parse)


[error] 649-649: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 649-649: expected , but instead found values

Remove values

(parse)


[error] 649-649: ';' expected'

An explicit or implicit semicolon is expected here...

(parse)


[error] 649-649: expected , but instead found /

Remove /

(parse)


[error] 650-650: Expected a parenthesis '(' but instead found '{'.

Expected a parenthesis '(' here.

(parse)


[error] 616-618: The assignment should not be in an expression.

The use of assignments in expressions is confusing.
Expressions are often considered as side-effect free.

(lint/suspicious/noAssignInExpressions)


[error] 619-619: The assignment should not be in an expression.

The use of assignments in expressions is confusing.
Expressions are often considered as side-effect free.

(lint/suspicious/noAssignInExpressions)


[error] 620-638: The assignment should not be in an expression.

The use of assignments in expressions is confusing.
Expressions are often considered as side-effect free.

(lint/suspicious/noAssignInExpressions)


[error] 638-638: The assignment should not be in an expression.

The use of assignments in expressions is confusing.
Expressions are often considered as side-effect free.

(lint/suspicious/noAssignInExpressions)


[error] 647-647: Duplicate parameter name.

The parameter overrides a preceding parameter by using the same name.

(lint/suspicious/noDuplicateParameters)

🔇 Additional comments (1)
apps/frontend/src/components/launches/providers/high.order.provider.tsx (1)

618-639: 🛠️ Refactor suggestion

Improve Share button accessibility.

The Share button needs accessibility enhancements:

 <Button
   onClick={handleShare}
   className="!h-[24px] rounded-[3px] flex gap-[4px] w-[102px] text-[12px] font-[500]"
+  aria-label="Share post"
+  role="button"
 >
   <div>
     <svg
       xmlns="http://www.w3.org/2000/svg"
       version="1.1"
-      x="0px"
-      y="0px"
       viewBox="0 0 800 1000"
       className="max-w-[20px] max-h-[20px] fill-current h-[1.25em]"
+      aria-hidden="true"
+      role="img"
     >
       <path
         fill="white"
         d="M443.25,529.42c2.9,1.32,6.32,0.83,8.73-1.27l211.28-183.37c1.79-1.55,2.81-3.79,2.81-6.16c0-2.37-1.02-4.61-2.81-6.16  L451.98,149.11c-2.41-2.1-5.83-2.59-8.73-1.27c-2.91,1.33-4.77,4.23-4.77,7.42v109.52c-168.67,5.27-304.54,173.69-304.54,379.94  c0,3.81,2.63,7.11,6.35,7.95c0.61,0.14,1.21,0.21,1.81,0.21c3.08,0,5.97-1.75,7.35-4.63c81.79-170.48,158.11-233.12,289.03-235.58V522C438.47,525.19,440.34,528.09,443.25,529.42z M151.83,607.06c15.41-182.94,141.74-326.08,294.8-326.08  c4.51,0,8.16-3.65,8.16-8.16v-99.67l190.67,165.48L454.79,504.11v-99.67c0-4.51-3.65-8.16-8.16-8.16  C314.35,396.29,231.89,454.14,151.83,607.06z"
       />
     </svg>
   </div>
-  <div className="text-white">Share</div>
+  <span className="text-white">Share</span>
 </Button>

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 619-619: expected , but instead found onClick

Remove onClick

(parse)


[error] 620-620: expected , but instead found className

Remove className

(parse)


[error] 638-638: expected , but instead found className

Remove className

(parse)


[error] 638-638: expected , but instead found <

Remove <

(parse)


[error] 639-639: expected , but instead found <

Remove <

(parse)


[error] 619-619: The assignment should not be in an expression.

The use of assignments in expressions is confusing.
Expressions are often considered as side-effect free.

(lint/suspicious/noAssignInExpressions)


[error] 620-638: The assignment should not be in an expression.

The use of assignments in expressions is confusing.
Expressions are often considered as side-effect free.

(lint/suspicious/noAssignInExpressions)


[error] 638-638: The assignment should not be in an expression.

The use of assignments in expressions is confusing.
Expressions are often considered as side-effect free.

(lint/suspicious/noAssignInExpressions)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
apps/frontend/src/components/launches/providers/high.order.provider.tsx (3)

459-480: Improve Share button accessibility.

The Share button lacks proper accessibility attributes and has unnecessary SVG attributes.

Apply this diff to enhance accessibility:

   <Button
     onClick={handleShare}
     className="!h-[24px] rounded-[3px] flex gap-[4px] w-[102px] text-[12px] font-[500]"
+    aria-label="Share post"
+    role="button"
   >
     <div>
       <svg
         xmlns="http://www.w3.org/2000/svg"
         version="1.1"
-        x="0px"
-        y="0px"
         viewBox="0 0 800 1000"
         className="max-w-[20px] max-h-[20px] fill-current h-[1.25em]"
+        aria-hidden="true"
+        role="img"
       >
         <path
           fill="white"
           d="M443.25,529.42c2.9,1.32,6.32,0.83,8.73-1.27l211.28-183.37c1.79-1.55,2.81-3.79,2.81-6.16c0-2.37-1.02-4.61-2.81-6.16  L451.98,149.11c-2.41-2.1-5.83-2.59-8.73-1.27c-2.91,1.33-4.77,4.23-4.77,7.42v109.52c-168.67,5.27-304.54,173.69-304.54,379.94  c0,3.81,2.63,7.11,6.35,7.95c0.61,0.14,1.21,0.21,1.81,0.21c3.08,0,5.97-1.75,7.35-4.63c81.79-170.48,158.11-233.12,289.03-235.58  V522C438.47,525.19,440.34,528.09,443.25,529.42z M151.83,607.06c15.41-182.94,141.74-326.08,294.8-326.08  c4.51,0,8.16-3.65,8.16-8.16v-99.67l190.67,165.48L454.79,504.11v-99.67c0-4.51-3.65-8.16-8.16-8.16  C314.35,396.29,231.89,454.14,151.83,607.06z"
         />
       </svg>
     </div>
-    <div className="text-white">Share</div>
+    <span className="text-white">Share</span>
   </Button>

401-405: Consider using a constant for minimum content length.

The minimum content length check is hardcoded. Consider extracting it to a named constant for better maintainability.

+const MIN_CONTENT_LENGTH = 6;
+
 {(!val.content || val.content.length < 6) && (
   <div className="my-[5px] text-customColor19 text-[12px] font-[500]">
-    The post should be at least 6 characters long
+    The post should be at least {MIN_CONTENT_LENGTH} characters long
   </div>
 )}

254-276: Simplify changeToEditor function.

The function contains duplicate confirmation dialog text and could be simplified.

 const changeToEditor = useCallback(async () => {
+  const confirmMessage = !editInPlace
+    ? 'Are you sure you want to edit only this?'
+    : 'Are you sure you want to revert it back to global editing?';
+
   if (
-    !(await deleteDialog(
-      !editInPlace
-        ? 'Are you sure you want to edit only this?'
-        : 'Are you sure you want to revert it back to global editing?',
-      'Yes, edit in place!'
-    ))
+    !(await deleteDialog(confirmMessage, 'Yes, edit in place!'))
   ) {
     return false;
   }

   setEditInPlace(!editInPlace);
   setInPlaceValue(
     editInPlace
       ? [{ content: '' }]
       : props.value.map((p) => ({
           id: p.id,
           content: p.content,
           image: p.image,
         }))
   );
 }, [props.value, editInPlace]);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 77bc611 and 2549de4.

📒 Files selected for processing (1)
  • apps/frontend/src/components/launches/providers/high.order.provider.tsx (2 hunks)
🔇 Additional comments (2)
apps/frontend/src/components/launches/providers/high.order.provider.tsx (2)

229-251: ⚠️ Potential issue

Enhance error handling in share functionality.

The share functionality has several potential issues:

  1. No type checking for existingData.posts[0].id
  2. No validation of the generated URL
  3. Generic error handling could expose internal details

Apply this diff to improve error handling:

   const handleShare = async () => {
-    if (!existingData.posts.length) {
+    if (!existingData?.posts?.length) {
       return toast.show('No posts available to share', 'warning');
     }
 
     const postId = existingData.posts[0].id;
+    if (!postId) {
+      return toast.show('Invalid post ID', 'warning');
+    }
 
     const previewPath = new URL(
       `/preview/${postId}`,
       window.location.origin
     ).toString();
 
     try {
       if (!navigator.clipboard) {
         throw new Error('Clipboard API not available');
       }
       await navigator.clipboard.writeText(previewPath);
       return toast.show('Link copied to clipboard.', 'success');
     } catch (err) {
-      if (err instanceof Error)
-        toast.show(`Failed to copy the link. ${err.message}`, 'warning');
+      toast.show('Failed to copy the link to clipboard', 'warning');
+      console.error('Share error:', err);
     }
   };

Likely invalid or redundant comment.


89-89: 🛠️ Refactor suggestion

Consider making id required for post objects.

The id property is marked as optional but appears to be required for the share functionality. This could lead to runtime errors if posts without IDs are processed.

-      id?: string;
+      id: string;
✅ Verification successful

Making id required is the correct approach

The share functionality explicitly requires a post ID to generate preview URLs and there's no fallback mechanism for posts without IDs. Making the field required would prevent potential runtime errors and better reflect its actual usage in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there are any posts without IDs in the codebase
rg -A 5 "content:\s*['\"]" | rg -v "id:"

Length of output: 65579


Script:

#!/bin/bash
# Search for share-related functionality and post ID usage
echo "=== Share functionality implementation ==="
ast-grep --pattern 'handleShare($$$)' -l typescript

echo -e "\n=== Post object creation patterns ==="
ast-grep --pattern 'new Post($$$)' -l typescript
ast-grep --pattern '{ content: $_, id: $_ }' -l typescript

echo -e "\n=== ID usage in share operations ==="
rg -l "share.*id" --type ts

Length of output: 470


Script:

#!/bin/bash
# Search with broader patterns and include context
echo "=== Share-related code ==="
rg -A 5 "share" --type ts

echo -e "\n=== Post type definitions ==="
rg -A 5 "type.*Post.*=|interface.*Post.*{" --type ts

echo -e "\n=== ID usage in component ==="
rg -A 5 "id.*:" "apps/frontend/src/components/launches/providers/high.order.provider.tsx"

Length of output: 6993

))}
</div>
</EditorWrapper>,
document.querySelector('#renderEditor')!
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

⚠️ Potential issue

The non-null assertion on querySelector('#renderEditor') is unsafe and should be fixed.

The element is defined in a different component (add.edit.model.tsx) and its existence depends on component mounting order and conditional rendering. The suggested fallback to document.body provides a safe default target.

  • The element is conditionally rendered with a 'hidden' class in add.edit.model.tsx
  • No guarantees exist about component lifecycle ordering
  • Runtime errors are possible if the target element isn't mounted when the querySelector runs
🔗 Analysis chain

Verify DOM element existence.

The code assumes #renderEditor element exists in the DOM. This could cause runtime errors if the element is not present.

Add a safety check:

-  document.querySelector('#renderEditor')!
+  document.querySelector('#renderEditor') || document.body
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for #renderEditor element definition
rg -l "id=['\"]renderEditor['\"]"

Length of output: 96


Script:

#!/bin/bash
# Get the element definition context
rg -A 5 -B 5 'id=["\']renderEditor["\']' apps/frontend/src/components/launches/add.edit.model.tsx

# Check if high.order.provider is imported in add.edit.model
rg "from ['\"].*high\.order\.provider" apps/frontend/src/components/launches/add.edit.model.tsx

# Check if add.edit.model is imported in high.order.provider
rg "from ['\"].*add\.edit\.model" apps/frontend/src/components/launches/providers/high.order.provider.tsx

Length of output: 116


Script:

#!/bin/bash
# Get the element definition context
rg -A 5 -B 5 "renderEditor" apps/frontend/src/components/launches/add.edit.model.tsx

# Get the querySelector context
rg -A 5 -B 5 "querySelector.*renderEditor" apps/frontend/src/components/launches/providers/high.order.provider.tsx

# Check component relationships
rg "high\.order\.provider" apps/frontend/src/components/launches/add.edit.model.tsx
rg "add\.edit\.model" apps/frontend/src/components/launches/providers/high.order.provider.tsx

Length of output: 1165

return [...prev];
});
},
[InPlaceValue]

Check warning

Code scanning / ESLint

verifies the list of dependencies for Hooks like useEffect and similar

React Hook useCallback has an unnecessary dependency: 'InPlaceValue'. Either exclude it or remove the dependency array.
<Fragment key={`edit_inner_${index}`}>
<div>
<div className="flex gap-[4px]">
<div className="flex-1 text-textColor editor">

Check warning

Code scanning / ESLint

Disallow non-null assertions using the `!` postfix operator

Forbidden non-null assertion.
<div>
<div className="flex gap-[4px]">
<div className="flex-1 text-textColor editor">
{integration?.identifier === 'linkedin' && (

Check warning

Code scanning / ESLint

Disallow non-null assertions using the `!` postfix operator

Forbidden non-null assertion.
Copy link

@A1exKH A1exKH left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@egelhaus
Copy link
Collaborator

egelhaus commented Feb 4, 2025

@nevo-david Can you Review this?

@egelhaus egelhaus added this to the v1.37.1 milestone Mar 10, 2025
@egelhaus egelhaus changed the title Feat/preview post Feat/preview post Mar 11, 2025
@github-actions github-actions bot changed the base branch from main to dev March 11, 2025 15:50
@github-actions
Copy link

Your PR's base branch was set to main, PRs should be set to target dev.
The base branch of this PR has been automatically changed to development, please check that there are no merge conflicts

@egelhaus
Copy link
Collaborator

Looks like the Postiz-CI/CD Check failed, could you have a look at it?

@egelhaus egelhaus modified the milestones: v1.37.1, v1.38.1 Apr 2, 2025
@egelhaus egelhaus modified the milestones: v1.38.1, v1.39.1, dev 1 Apr 11, 2025
@egelhaus egelhaus deleted the branch gitroomhq:dev April 12, 2025 15:15
@egelhaus egelhaus closed this Apr 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants