Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improvement: status type | edit/create mode #3185

Draft
wants to merge 3 commits into
base: develop
Choose a base branch
from

Conversation

CREDO23
Copy link
Contributor

@CREDO23 CREDO23 commented Oct 25, 2024

Description

FIX #3165

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings

Previous screenshots

Loom

Current screenshots

Loom

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced svgFetch function for asynchronous SVG retrieval.
    • Enhanced TaskStatus component with dynamic text color based on background.
    • Added localization support for sorting and icon representation across multiple languages.
  • Improvements

    • Updated IconItem component to utilize dynamic translations.
    • Enhanced StatusesListCard for flexible SVG icon handling.
    • Improved TaskStatusesForm with dynamic color assignment and icon selection.
  • Localization

    • Added new keys for sorting and icons in multiple languages, enhancing user interface support.

@CREDO23 CREDO23 added WEB Web app Improvement Improvement Ever Teams labels Oct 25, 2024
@CREDO23 CREDO23 self-assigned this Oct 25, 2024
@CREDO23 CREDO23 linked an issue Oct 25, 2024 that may be closed by this pull request
Copy link

coderabbitai bot commented Oct 25, 2024

Walkthrough

The pull request introduces several enhancements across multiple files, including new functions for fetching SVGs, determining text color, and managing task statuses with dynamic colors and icons. Localization files have been updated to include new keys for sorting and icons in various languages. The changes do not affect existing functionalities but expand the capabilities of the application, particularly in terms of visual representation and internationalization.

Changes

File Change Summary
apps/web/app/services/server/fetch.ts Added export async function svgFetch(url: string): Promise<Response> for fetching SVGs.
apps/web/lib/features/task/task-status.tsx Introduced getTextColor function to determine text color based on background color.
apps/web/lib/settings/icon-items.tsx Updated IconItem to use useTranslations for dynamic title rendering based on localization.
apps/web/lib/settings/list-card.tsx Removed Image component; added loadSVG function to fetch SVGs dynamically into a div.
apps/web/lib/settings/task-statuses-form.tsx Added state variables selectedStatusType, randomColor, and functions getIcon, getRandomColor.
apps/web/locales/*.json Added keys for "SORT" and "ICON" in various localization files; updated "MOVE_TO" with trailing commas.

Assessment against linked issues

Objective Addressed Explanation
Bump http-proxy-middleware to version 2.0.7 (#3184) No changes related to dependency updates were made.

Possibly related PRs

  • 3155 bug settings enforce plans how it should work #3161: This PR modifies the useStartStopTimerHandler function to include a condition that checks if a plan exists before verifying if the active task is planned, which relates to the new svgFetch function's context of managing task-related functionalities.
  • [Fix](Web): load team members cards on home page #3167: This PR addresses loading issues related to user cards, which may involve similar data-fetching mechanisms as the newly introduced svgFetch function, indicating a potential overlap in handling asynchronous operations within the application.

Suggested labels

enhancement, Bug fix

Suggested reviewers

  • evereq
  • Cedric921
  • EverTechDevOps

Poem

🐇 In the code where rabbits play,
New functions hop in bright array.
SVGs and colors dance with glee,
Locales sing in harmony!
With every change, we grow and thrive,
In this code, our dreams arrive! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 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: 9

🧹 Outside diff range and nitpick comments (4)
apps/web/app/services/server/fetch.ts (1)

58-61: Add JSDoc documentation for the SVG fetch function.

The function lacks documentation about its purpose, parameters, and usage.

Add comprehensive documentation:

+/**
+ * Fetches SVG content from a given URL with validation and error handling.
+ * 
+ * @param url - The URL of the SVG resource to fetch
+ * @returns A Promise that resolves to the Response containing the SVG content
+ * @throws {Error} If the URL is invalid, the response is not OK, or the content is not SVG
+ * 
+ * @example
+ * ```typescript
+ * try {
+ *   const svgResponse = await fetchSvgContent('https://example.com/icon.svg');
+ *   const svgContent = await svgResponse.text();
+ * } catch (error) {
+ *   console.error('Failed to fetch SVG:', error);
+ * }
+ * ```
+ */
 export async function svgFetch(url: string): Promise<Response> {
apps/web/lib/settings/icon-items.tsx (1)

Line range hint 68-89: Consider improvements to the conditional rendering and error handling.

Several suggestions to enhance the component:

  1. The fallback case ignores the title prop, which might be unexpected
  2. The Image component lacks error handling for failed loads
  3. The translation key could be defined as a constant to avoid magic strings

Consider applying these improvements:

+ const ICON_TRANSLATION_KEY = 'common.ICON';
+ 
  return (
    <div
      title={title}
      className={clsxm(
        'flex items-center justify-start space-x-2 text-sm',
        'cursor-pointer mb-4 max-w-full',
        className
      )}
    >
      <div>
        {url ? (
          <div
            className={clsxm(
              'w-[17px] h-[17px]',
              'flex justify-center items-center',
              'rounded-full text-xs text-default dark:text-white',
              disabled && ['dark:text-default']
            )}
          >
            <Image
              src={url}
              alt={title || ''}
              width={20}
              height={20}
              decoding="async"
              data-nimg="1"
              loading="lazy"
+             onError={(e) => {
+               e.currentTarget.src = ''; // Add fallback image URL
+             }}
            />
          </div>
        ) : (
-         <span>{t('common.ICON')}</span>
+         <span>{title || t(ICON_TRANSLATION_KEY)}</span>
        )}
      </div>
    </div>
  );
apps/web/lib/settings/task-statuses-form.tsx (1)

33-34: Consider initializing randomColor with a value

Initialize randomColor with a random color value to avoid undefined states in the UI. This ensures the color picker always has a valid initial value.

-const [randomColor, setRandomColor] = useState<string | undefined>(undefined);
+const [randomColor, setRandomColor] = useState<string>(() => {
+  const letters = '0123456789ABCDEF';
+  let color = '#';
+  for (let i = 0; i < 6; i++) {
+    color += letters[Math.floor(Math.random() * 16)];
+  }
+  return color;
+});
apps/web/lib/features/task/task-status.tsx (1)

857-858: Consider handling edge cases in color determination.

While the implementation looks good, consider these improvements:

  1. The fallback color 'white' might not be suitable for all themes
  2. The background color could be undefined when active is false

Consider this improvement:

 style={{
   backgroundColor: active ? backgroundColor : undefined,
-  color: getTextColor(backgroundColor ?? 'white')
+  color: getTextColor(backgroundColor ?? (theme === 'dark' ? '#1B1D22' : 'white'))
 }}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 4efcacb and 74ffd3e.

📒 Files selected for processing (18)
  • apps/web/app/services/server/fetch.ts (1 hunks)
  • apps/web/lib/features/task/task-status.tsx (3 hunks)
  • apps/web/lib/settings/icon-items.tsx (4 hunks)
  • apps/web/lib/settings/list-card.tsx (4 hunks)
  • apps/web/lib/settings/task-statuses-form.tsx (8 hunks)
  • apps/web/locales/ar.json (1 hunks)
  • apps/web/locales/bg.json (1 hunks)
  • apps/web/locales/de.json (1 hunks)
  • apps/web/locales/en.json (1 hunks)
  • apps/web/locales/es.json (1 hunks)
  • apps/web/locales/fr.json (1 hunks)
  • apps/web/locales/he.json (1 hunks)
  • apps/web/locales/it.json (1 hunks)
  • apps/web/locales/nl.json (1 hunks)
  • apps/web/locales/pl.json (1 hunks)
  • apps/web/locales/pt.json (1 hunks)
  • apps/web/locales/ru.json (1 hunks)
  • apps/web/locales/zh.json (1 hunks)
🔇 Additional comments (23)
apps/web/app/services/server/fetch.ts (1)

58-61: Verify SVG fetch usage across the codebase.

Let's ensure this new function is properly integrated with other components that need SVG fetching.

✅ Verification successful

The new svgFetch function is only used in one place for loading SVG icons

The codebase analysis shows that the svgFetch function is only used in apps/web/lib/settings/list-card.tsx for loading SVG icons in the loadSVG function. All other SVG usages in the codebase are static imports or direct path references. The function's current implementation is appropriate for its limited usage.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find potential usage points of SVG fetching in the codebase

echo "Searching for SVG-related fetch calls..."
rg -l "fetch.*svg|loadSVG|getSVG" --type ts --type tsx

echo -e "\nSearching for SVG URL patterns..."
rg "\.svg['\"]|/icons?/|/images?/" --type ts --type tsx

Length of output: 346


Script:

#!/bin/bash
# Let's try a different approach to find SVG-related patterns
# First, let's find all TypeScript files
echo "Finding TypeScript files with SVG-related patterns..."
rg -t ts "\.svg|fetch.*svg|loadSVG|getSVG|/icons?/|/images?/" -l

echo -e "\nChecking for actual implementations and usages..."
rg -t ts "\.svg|fetch.*svg|loadSVG|getSVG" -C 2

Length of output: 23920

apps/web/lib/settings/icon-items.tsx (3)

5-5: LGTM: Clean import addition for internationalization.

The addition of useTranslations hook import is well-placed and aligns with the internationalization requirements.


57-57: LGTM: Clean hook initialization.

The translation hook is properly initialized at the component level.


88-88: Verify translation key existence and consistency.

Let's ensure the translation key is properly defined across all language files.

✅ Verification successful

Translation key is properly defined and consistent across all locales

The translation key 'ICON' is correctly defined in all language files (ar, bg, de, en, es, fr, he, it, nl, pl, pt, ru, zh) with appropriate translations for each locale. The usage in the code as t('common.ICON') is valid.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for the translation key in language files
echo "Checking for 'common.ICON' translation key in language files..."
rg -l '"ICON"' apps/web/messages/

Length of output: 237


Script:

#!/bin/bash
# First, let's find the correct location of translation files
fd -t f "en.json|de.json|fr.json|es.json" -x echo "=== {} ===" \; cat {}

# Also search for any usage of this translation key in the codebase
echo -e "\n=== Searching for translation key usage ==="
rg "common\.ICON"

Length of output: 414


Script:

#!/bin/bash
# Let's try a different approach to find translation files
echo "=== Looking for translation files ==="
fd -t f -e json . apps/web

# Let's also check the package.json to understand the i18n setup
echo -e "\n=== Checking package.json for i18n configuration ==="
fd -t f "package.json" -x cat {}

Length of output: 37255


Script:

#!/bin/bash
# Let's check the content of translation files to verify the key
echo "=== Checking translation files for 'common.ICON' key ==="
fd -t f -e json . apps/web/locales -x echo "=== {} ===" \; cat {}

# Also let's check for any other similar translation keys
echo -e "\n=== Checking for similar translation keys ==="
rg "ICON" apps/web/locales/

Length of output: 1418

apps/web/lib/settings/list-card.tsx (1)

8-9: LGTM! Imports are correctly added.

The new imports are necessary for the component's enhanced functionality.

apps/web/locales/zh.json (1)

232-234: LGTM! The translations are accurate and well-formatted.

The new Chinese translations for "MOVE_TO", "SORT", and "ICON" are correctly implemented and maintain consistency with the existing localization structure.

apps/web/locales/he.json (1)

232-234: LGTM! Verify consistency across other language files.

The Hebrew translations for the new keys look correct and properly formatted.

Let's verify that these translations are consistently added across all mentioned language files:

✅ Verification successful

Translations for "SORT" and "ICON" are consistently present across all language files

The verification confirms that both "SORT" and "ICON" keys are properly added with appropriate translations in all checked language files (ar, bg, de, es, fr, it, nl, pl, pt, ru, zh), maintaining consistency across the entire localization system.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if SORT and ICON keys are present in all language files
# Expected: All language files should have these keys

# Test: Check for SORT and ICON keys in all JSON files
for lang in ar bg de es fr it nl pl pt ru zh; do
  echo "Checking $lang.json:"
  rg -A 1 '"SORT":' "apps/web/locales/$lang.json"
  rg -A 1 '"ICON":' "apps/web/locales/$lang.json"
done

Length of output: 2672

apps/web/locales/ar.json (2)

232-232: LGTM: Valid JSON syntax.

The trailing comma addition maintains proper JSON formatting and enables easier version control diffs for future additions.


233-234: LGTM: New translations look accurate.

The Arabic translations for "SORT" (فرز) and "ICON" (أيقونة) are correct and commonly used terms in Arabic UI localization. They appropriately maintain RTL (Right-to-Left) text direction which is crucial for Arabic language support.

Let's verify the consistency of these new keys across other language files:

✅ Verification successful

Translation keys are consistent across all locale files

The verification confirms that both "SORT" and "ICON" keys are properly implemented across all language files (ar, bg, de, en, es, fr, he, it, nl, pl, pt, ru, zh) with appropriate translations for each language. The Arabic translations align well with the localization patterns used in other languages.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the new keys exist in other locale files
# Test: Search for SORT and ICON keys in all locale files
rg '"SORT":|"ICON":' apps/web/locales/

Length of output: 1188

apps/web/locales/en.json (1)

232-234: LGTM! Verify usage of new translations.

The new translations are clear and maintain consistency with the existing structure.

Let's verify that these new translations are being used in the UI components:

✅ Verification successful

✓ New translations are properly used in the UI

The new translation keys are actively used in the codebase:

  • "SORT" is used in apps/web/lib/settings/task-statuses-form.tsx
  • "ICON" is used in apps/web/lib/settings/icon-items.tsx
  • Both translations are properly integrated across multiple language files in both web and desktop apps
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the usage of new translation keys in the codebase
echo "Searching for SORT translation key usage:"
rg "['\"](common\.)?SORT['\"]" --type ts --type tsx

echo "Searching for ICON translation key usage:"
rg "['\"](common\.)?ICON['\"]" --type ts --type tsx

Length of output: 357


Script:

#!/bin/bash
# Search for the usage of new translation keys in the codebase
echo "Searching for SORT translation key usage:"
rg "['\"](common\.)?SORT['\"]"

echo -e "\nSearching for ICON translation key usage:"
rg "['\"](common\.)?ICON['\"]"

# Also search for t function calls which might use these keys
echo -e "\nSearching for t function calls with these keys:"
rg "t\(['\"](?:common\.)?(?:SORT|ICON)['\"]"

Length of output: 2532

apps/web/locales/nl.json (1)

232-234: LGTM! The new translations are well-structured and accurate.

The additions follow the existing conventions and provide correct Dutch translations for the new keys.

apps/web/locales/bg.json (1)

232-234: LGTM! Verify consistency across language files.

The changes look good. The new translations for sorting and icons are properly added, and the comma after "MOVE_TO" maintains valid JSON syntax.

Let's verify that these keys exist across all language files:

✅ Verification successful

All translation keys are present and properly translated across language files

The verification confirms that both "SORT" and "ICON" keys are consistently present across all language files (ar, bg, de, en, es, fr, he, it, nl, pl, pt, ru, zh) with appropriate translations for each language.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if SORT and ICON keys exist in all language files
# Expected: All language files should have these keys

# Test: Search for SORT and ICON keys in all locale files
echo "Checking SORT key..."
rg '"SORT"' apps/web/locales/
echo "Checking ICON key..."
rg '"ICON"' apps/web/locales/

Length of output: 1313

apps/web/locales/pl.json (1)

232-234: LGTM! The translations are properly structured and consistent.

The changes maintain proper JSON syntax and follow the localization patterns:

  • Added trailing comma after "MOVE_TO" translation
  • Added Polish translations for "SORT" ("Sortuj") and "ICON" ("Ikona")
apps/web/locales/it.json (1)

232-234: LGTM! The new localization keys are properly structured.

The added Italian translations for sorting and icon functionality maintain consistency with the existing localization patterns and appear to be grammatically correct.

apps/web/locales/ru.json (2)

232-234: LGTM! Translations and syntax are correct.

The changes look good:

  • The trailing comma after "MOVE_TO" maintains proper JSON syntax
  • The new translations for "SORT" ("Сортировать") and "ICON" ("Иконка") are accurate Russian translations
  • The changes are consistent with other language files mentioned in the summary

232-234: Verify consistency across all language files.

Let's ensure the new keys are present in all language files with proper translations.

✅ Verification successful

Let me try a different script to properly check the structure and content of these files.


Translation keys are consistent across all language files

The verification shows that both SORT and ICON keys are present in all language files (ar, bg, de, en, es, fr, he, it, nl, pl, pt, ru, zh) with appropriate translations for each language. The keys are correctly placed under the common section as expected.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if all language files have the required keys
# Expected: All language files should have SORT and ICON keys under the common section

echo "Checking language files for required keys..."
for lang_file in $(fd -e json . apps/web/locales); do
  echo "Checking $lang_file..."
  
  # Check if the file has the required keys
  jq -r '.common | select(.SORT == null or .ICON == null) | path | join(".")' "$lang_file"
  
  if [ $? -eq 0 ]; then
    echo "✓ File has all required keys"
  else
    echo "⚠ Missing required keys"
  fi
done

Length of output: 6748


Script:

#!/bin/bash
# Let's first check the actual structure of one of the files to understand how they're organized
echo "Checking structure of ru.json:"
cat apps/web/locales/ru.json | head -n 10

echo -e "\nNow checking for SORT and ICON keys in all locale files:"
for lang_file in $(fd -e json . apps/web/locales); do
  echo -e "\nFile: $lang_file"
  # Search for the exact keys, showing 2 lines of context
  rg -A 2 '"(SORT|ICON)":\s*"' "$lang_file"
done

Length of output: 3621

apps/web/locales/pt.json (1)

232-234: LGTM! Translations are accurate and well-formatted.

The new translations maintain consistency with the existing localization patterns and correctly handle Portuguese accents.

apps/web/locales/es.json (2)

232-232: LGTM: Proper JSON syntax correction.

The added comma after the "MOVE_TO" entry is correct and necessary for valid JSON syntax.


233-234: LGTM: Accurate Spanish translations added.

The new translations are linguistically correct:

  • "SORT" → "Ordenar"
  • "ICON" → "Ícono"

Both translations are accurate and properly use Spanish diacritical marks.

Let's verify the consistency of these new keys across other language files:

✅ Verification successful

Let me verify the actual content of these keys in all language files to ensure they are properly translated and not missing.


Spanish translations are consistent with other language files

The Spanish translations "Ordenar" for "SORT" and "Ícono" for "ICON" are properly implemented and consistent with the translations in all other language files. Each language file contains appropriate translations that reflect the correct meaning in their respective languages, including proper use of diacritical marks where needed (e.g. "Ícono" in Spanish and Portuguese, "Icône" in French).

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the new keys (SORT, ICON) exist in other language files
# Expected: These keys should be present in all language files

echo "Checking for SORT and ICON keys in all language files..."
rg -l '"SORT":|"ICON":' apps/web/locales/

Length of output: 491


Script:

#!/bin/bash
# Check the actual values of SORT and ICON in all locale files
for file in $(find apps/web/locales -name "*.json"); do
  echo "=== $file ==="
  rg -A 1 '"SORT":|"ICON":' "$file"
done

Length of output: 2955

apps/web/locales/de.json (1)

232-234: LGTM! Verify translations across all language files.

The German translations look appropriate:

  • "SORT": "Sortieren" (correct German translation for "Sort")
  • "ICON": "Symbol" (correct German translation for "Icon")

Let's verify that these new keys are consistently added across all language files mentioned in the AI summary:

✅ Verification successful

Both "SORT" and "ICON" keys are consistently present across all language files

The verification shows that:

  • "SORT" key is present in all 13 language files (ar, bg, de, en, es, fr, he, it, nl, pl, pt, ru, zh)
  • "ICON" key is present in all 13 language files with appropriate translations
  • Each translation appears culturally and linguistically appropriate for its target language
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the new keys "SORT" and "ICON" are present in all language files
# Expected: All language files should have these keys with appropriate translations

# Test: Search for SORT and ICON keys in all locale files
echo "Checking SORT translations:"
rg '"SORT"' apps/web/locales/
echo -e "\nChecking ICON translations:"
rg '"ICON"' apps/web/locales/

Length of output: 1347

apps/web/locales/fr.json (1)

232-234: LGTM! Verify translations across all locale files.

The French translations for "MOVE_TO", "SORT", and "ICON" are linguistically accurate and properly formatted.

Let's verify the consistency of these new keys across other locale files:

✅ Verification successful

All translation keys are properly synchronized across locale files

Based on the verification results:

  • "SORT" and "ICON" are present and properly translated in all web locale files (en, fr, de, es, it, nl, pl, pt, ru, zh, ar, bg, he)
  • "MOVE_TO" is also present and correctly translated across all locale files
  • The French translations are linguistically accurate:
    • "MOVE_TO": "Déplacer vers"
    • "SORT": "Trier"
    • "ICON": "Icône"
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the new keys exist in all locale files
# Expected: All locale files should have these keys

# Find all locale files and check for the presence of the new keys
fd -e json -x sh -c 'echo "=== Checking {}" && jq -r ".common | select(.SORT != null and .ICON != null) | {SORT, ICON}" {}' . apps/web/locales/

Length of output: 3299


Script:

#!/bin/bash
# Let's check for the MOVE_TO key specifically since it wasn't captured in the previous query
fd -e json -x sh -c 'echo "=== Checking {}" && jq -r ".common.MOVE_TO" {}' . apps/web/locales/

Length of output: 3083

apps/web/lib/features/task/task-status.tsx (2)

36-36: LGTM: Good addition of contrast helper.

The import of getTextColor helper function is a good practice for ensuring text readability by dynamically determining the text color based on the background color.


1032-1032: LGTM: Consistent height styling.

The addition of "h-full" className to the Tooltip component maintains consistency with the styling approach used throughout the file.

Comment on lines +58 to +61
export async function svgFetch(url: string): Promise<Response> {
// Fetch the SVG
return await fetch(url);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider implementing caching for SVG responses.

For better performance and reduced network calls, consider implementing a caching strategy for SVG responses.

Here's a suggested implementation using a simple in-memory cache:

const svgCache = new Map<string, {
  content: Response,
  timestamp: number
}>();

const CACHE_DURATION = 1000 * 60 * 60; // 1 hour

export async function fetchSvgContent(url: string): Promise<Response> {
  const cached = svgCache.get(url);
  const now = Date.now();
  
  if (cached && (now - cached.timestamp) < CACHE_DURATION) {
    return cached.content.clone();
  }
  
  const response = await /* previous implementation */;
  
  svgCache.set(url, {
    content: response.clone(),
    timestamp: now
  });
  
  return response;
}

⚠️ Potential issue

Add input validation and error handling for SVG fetching.

The current implementation lacks several important safety checks and error handling mechanisms:

  1. URL validation
  2. Response type verification
  3. Error handling
  4. Timeout handling

Consider implementing these improvements:

-export async function svgFetch(url: string): Promise<Response> {
-	// Fetch the SVG
-	return await fetch(url);
+export async function fetchSvgContent(url: string): Promise<Response> {
+	try {
+		// Validate URL
+		const validUrl = new URL(url);
+		
+		const response = await fetch(validUrl.toString(), {
+			timeout: 5000,
+			headers: {
+				'Accept': 'image/svg+xml'
+			}
+		});
+
+		if (!response.ok) {
+			throw new Error(`Failed to fetch SVG: ${response.statusText}`);
+		}
+
+		const contentType = response.headers.get('content-type');
+		if (!contentType?.includes('svg')) {
+			throw new Error('Response is not an SVG image');
+		}
+
+		return response;
+	} catch (error) {
+		if (error instanceof Error) {
+			throw new Error(`SVG fetch failed: ${error.message}`);
+		}
+		throw new Error('Unknown error occurred while fetching SVG');
+	}
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function svgFetch(url: string): Promise<Response> {
// Fetch the SVG
return await fetch(url);
}
export async function fetchSvgContent(url: string): Promise<Response> {
try {
// Validate URL
const validUrl = new URL(url);
const response = await fetch(validUrl.toString(), {
timeout: 5000,
headers: {
'Accept': 'image/svg+xml'
}
});
if (!response.ok) {
throw new Error(`Failed to fetch SVG: ${response.statusText}`);
}
const contentType = response.headers.get('content-type');
if (!contentType?.includes('svg')) {
throw new Error('Response is not an SVG image');
}
return response;
} catch (error) {
if (error instanceof Error) {
throw new Error(`SVG fetch failed: ${error.message}`);
}
throw new Error('Unknown error occurred while fetching SVG');
}
}

className="min-h-[20px]"
/>
)}
{statusIcon && <div id={'icon-container' + statusTitle}></div>}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improve ID generation security and uniqueness.

The current ID generation method has potential security and uniqueness issues:

  1. No sanitization of statusTitle when used in ID
  2. Non-unique IDs if multiple instances have the same title

Consider using a more secure approach:

-{statusIcon && <div id={'icon-container' + statusTitle}></div>}
+{statusIcon && (
+  <div
+    id={`icon-container-${encodeURIComponent(statusTitle)}-${Math.random().toString(36).substr(2, 9)}`}
+  />
+)}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{statusIcon && <div id={'icon-container' + statusTitle}></div>}
{statusIcon && (
<div
id={`icon-container-${encodeURIComponent(statusTitle)}-${Math.random().toString(36).substr(2, 9)}`}
/>
)}

Comment on lines +31 to +33
useEffect(() => {
loadSVG(statusIcon, 'icon-container' + statusTitle, textColor);
}, []);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add missing dependencies and cleanup to useEffect.

The current implementation has several issues:

  1. Missing dependencies: statusIcon and textColor should be in the dependency array
  2. No cleanup handling for unmounting during SVG loading

Here's the suggested fix:

 useEffect(() => {
-  loadSVG(statusIcon, 'icon-container' + statusTitle, textColor);
+  let mounted = true;
+  const loadIcon = async () => {
+    if (mounted) {
+      await loadSVG(statusIcon, 'icon-container' + statusTitle, textColor);
+    }
+  };
+  loadIcon();
+  return () => {
+    mounted = false;
+  };
-}, []);
+}, [statusIcon, statusTitle, textColor]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
loadSVG(statusIcon, 'icon-container' + statusTitle, textColor);
}, []);
useEffect(() => {
let mounted = true;
const loadIcon = async () => {
if (mounted) {
await loadSVG(statusIcon, 'icon-container' + statusTitle, textColor);
}
};
loadIcon();
return () => {
mounted = false;
};
}, [statusIcon, statusTitle, textColor]);

Comment on lines +90 to +113
const loadSVG = async (url: string, containerId: string, color: string): Promise<void> => {
try {
const response = await svgFetch(url);

if (!response.ok) {
throw new Error(`Failed to fetch SVG: ${response.statusText}`);
}

let svgContent = await response.text();

// Update the fill color in the SVG content
svgContent = svgContent.replace(/stroke="[^"]*"/g, `stroke="${color}"`);

const container = document.getElementById(containerId);

if (container) {
container.innerHTML = svgContent;
} else {
console.error(`Container with ID "${containerId}" not found.`);
}
} catch (error) {
console.error(`Error loading SVG: ${(error as Error).message}`);
}
};
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

Based on the context gathered, I can now generate the final response:

Security improvements needed for SVG loading implementation

The current implementation in list-card.tsx loads SVGs from status icons and directly injects them using innerHTML, which poses security risks. However, the usage context shows this is specifically for status icons within a controlled environment, where:

  1. SVGs are loaded via svgFetch service, suggesting a controlled fetching mechanism
  2. The usage is limited to status icons within the settings list card component
  3. The color modification is specifically for status indication

While the security concerns are valid, here's a more targeted improvement suggestion:

const loadSVG = async (url: string, containerId: string, color: string): Promise<void> => {
  try {
    const response = await svgFetch(url);
    if (!response.ok) {
      throw new Error(`Failed to fetch SVG: ${response.statusText}`);
    }

    const parser = new DOMParser();
    const svgDoc = parser.parseFromString(await response.text(), 'image/svg+xml');
    
    // Verify we have an SVG element
    const svgElement = svgDoc.querySelector('svg');
    if (!svgElement) {
      throw new Error('Invalid SVG content');
    }

    // Update stroke colors
    svgElement.querySelectorAll('*').forEach(el => {
      if (el instanceof Element && el.hasAttribute('stroke')) {
        el.setAttribute('stroke', color);
      }
    });

    const container = document.getElementById(containerId);
    if (container) {
      container.replaceChildren(svgElement);
    }
  } catch (error) {
    console.error(`Error loading SVG: ${(error as Error).message}`);
  }
};
  • Consider adding a whitelist of allowed SVG attributes to further restrict potential XSS vectors
  • Add MIME type validation in the svgFetch service
🔗 Analysis chain

Enhance SVG loading security and robustness.

The current implementation has several security and reliability concerns:

  1. Direct innerHTML usage is vulnerable to XSS
  2. Simple regex replacement might miss complex SVG color attributes
  3. No sanitization of SVG content before insertion

Consider implementing these security improvements:

 const loadSVG = async (url: string, containerId: string, color: string): Promise<void> => {
   try {
     const response = await svgFetch(url);
 
     if (!response.ok) {
       throw new Error(`Failed to fetch SVG: ${response.statusText}`);
     }
 
     let svgContent = await response.text();
+    
+    // Create a DOMParser to safely parse the SVG
+    const parser = new DOMParser();
+    const doc = parser.parseFromString(svgContent, 'image/svg+xml');
+    
+    // Validate that we received an SVG
+    if (doc.documentElement.tagName !== 'svg') {
+      throw new Error('Invalid SVG content');
+    }
+    
+    // Update colors using DOM methods instead of regex
+    const elements = doc.querySelectorAll('*');
+    elements.forEach(el => {
+      if (el.hasAttribute('stroke')) {
+        el.setAttribute('stroke', color);
+      }
+    });
 
     const container = document.getElementById(containerId);
     if (container) {
-      container.innerHTML = svgContent;
+      // Clear existing content
+      while (container.firstChild) {
+        container.removeChild(container.firstChild);
+      }
+      // Safely append the new SVG
+      container.appendChild(doc.documentElement);
     } else {
       console.error(`Container with ID "${containerId}" not found.`);
     }
   } catch (error) {
     console.error(`Error loading SVG: ${(error as Error).message}`);
   }
 };

Additionally, consider implementing a content security policy (CSP) to restrict SVG sources to trusted domains.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if we have any Content-Security-Policy headers defined
rg -l "Content-Security-Policy" --type-add 'config:*.{json,js,ts}' -t config

Length of output: 76


Script:

#!/bin/bash
# Let's check where this SVG loading function is used and what SVG sources are being loaded
rg -A 2 "loadSVG\(" 

# Also check for any existing SVG security measures or sanitization
rg -l "DOMParser|createElementNS|sanitize.*svg" --type=typescript

# Check for any SVG-related utility functions or components
fd -e ts -e tsx -X rg "svg" -l

Length of output: 10728


Script:

#!/bin/bash
# Let's check the svgFetch implementation and where SVGs are being loaded from
rg -A 5 "svgFetch" --type=typescript

# Check the specific usage context in list-card.tsx
cat "apps/web/lib/settings/list-card.tsx"

# Look for any existing security configurations or middleware
rg -l "security|sanitize|xss" --type=typescript

Length of output: 3616

Comment on lines +259 to +264
onValueChange={(status) => {
setValue('template', status)
setSelectedStatusType(status)
} }
className="h-14 shrink-0"
defaultValue={edit?.value}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Handle defaultValue prop consistently

The defaultValue prop is only set for edit mode, which might lead to unexpected behavior when creating a new status.

 <StandardTaskStatusDropDown
   onValueChange={(status) => {
     setValue('template', status)
     setSelectedStatusType(status)
   }}
   className="h-14 shrink-0"
-  defaultValue={edit?.value}
+  defaultValue={edit?.value || selectedStatusType}
 />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onValueChange={(status) => {
setValue('template', status)
setSelectedStatusType(status)
} }
className="h-14 shrink-0"
defaultValue={edit?.value}
onValueChange={(status) => {
setValue('template', status)
setSelectedStatusType(status)
} }
className="h-14 shrink-0"
defaultValue={edit?.value || selectedStatusType}

Comment on lines +58 to +63
const iconList: IIcon[] = useMemo(() => [
...taskStatusIconList,
...taskSizesIconList,
...taskPrioritiesIconList
];
// eslint-disable-next-line react-hooks/exhaustive-deps
],[]) ;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add dependencies to useMemo

The empty dependency array means the iconList will never be recomputed even if the source lists change. Add the source lists as dependencies.

  const iconList: IIcon[] = useMemo(() => [
    ...taskStatusIconList,
    ...taskSizesIconList,
    ...taskPrioritiesIconList
-  // eslint-disable-next-line react-hooks/exhaustive-deps
-  ],[]) ;
+  ],[taskStatusIconList, taskSizesIconList, taskPrioritiesIconList]) ;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const iconList: IIcon[] = useMemo(() => [
...taskStatusIconList,
...taskSizesIconList,
...taskPrioritiesIconList
];
// eslint-disable-next-line react-hooks/exhaustive-deps
],[]) ;
const iconList: IIcon[] = useMemo(() => [
...taskStatusIconList,
...taskSizesIconList,
...taskPrioritiesIconList
],[taskStatusIconList, taskSizesIconList, taskPrioritiesIconList]) ;

Comment on lines +183 to +190
const getRandomColor = useCallback(() => {
const letters = '0123456789ABCDEF';
let color = '#';
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}, []);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Simplify random color generation

The current implementation can be simplified using array methods.

 const getRandomColor = useCallback(() => {
-  const letters = '0123456789ABCDEF';
-  let color = '#';
-  for (let i = 0; i < 6; i++) {
-    color += letters[Math.floor(Math.random() * 16)];
-  }
-  return color;
+  return '#' + Array.from({ length: 6 }, () => 
+    Math.floor(Math.random() * 16).toString(16)
+  ).join('');
 }, []);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const getRandomColor = useCallback(() => {
const letters = '0123456789ABCDEF';
let color = '#';
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}, []);
const getRandomColor = useCallback(() => {
return '#' + Array.from({ length: 6 }, () =>
Math.floor(Math.random() * 16).toString(16)
).join('');
}, []);

Comment on lines +165 to +175
const getIcon = useCallback((iconName: string) => {
const name = iconName == "ready-for-review" ? "ready" : iconName;
const icon = iconList.find(icon => icon.title === name)

if(icon){
setValue("icon", icon.path)
}

return icon

},[iconList, setValue])
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance getIcon function robustness

The function needs better error handling and could use a more maintainable approach for icon name mapping.

+const ICON_NAME_MAP: Record<string, string> = {
+  'ready-for-review': 'ready'
+};

 const getIcon = useCallback((iconName: string) => {
-  const name = iconName == "ready-for-review" ? "ready" : iconName;
+  const name = ICON_NAME_MAP[iconName] || iconName;
   const icon = iconList.find(icon => icon.title === name)

+  if (!icon) {
+    console.warn(`Icon not found for status: ${iconName}`);
+  }

   if(icon){
     setValue("icon", icon.path)
   }

   return icon
 },[iconList, setValue])
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const getIcon = useCallback((iconName: string) => {
const name = iconName == "ready-for-review" ? "ready" : iconName;
const icon = iconList.find(icon => icon.title === name)
if(icon){
setValue("icon", icon.path)
}
return icon
},[iconList, setValue])
const ICON_NAME_MAP: Record<string, string> = {
'ready-for-review': 'ready'
};
const getIcon = useCallback((iconName: string) => {
const name = ICON_NAME_MAP[iconName] || iconName;
const icon = iconList.find(icon => icon.title === name)
if (!icon) {
console.warn(`Icon not found for status: ${iconName}`);
}
if(icon){
setValue("icon", icon.path)
}
return icon
},[iconList, setValue])

@evereq
Copy link
Member

evereq commented Oct 25, 2024

@CREDO23 :

  1. Please review suggestions by Coderabbit and resolve each one (adjust code or close each one)
  2. Please look in picture below, why selector for status has different default color compared to other, e.g. icon selector!?

image

@evereq evereq requested a review from Cedric921 October 25, 2024 16:53
@Cedric921 Cedric921 added this to the v0.2.0 milestone Oct 25, 2024
@CREDO23
Copy link
Contributor Author

CREDO23 commented Oct 25, 2024

@CREDO23 :

  1. Please review suggestions by Coderabbit and resolve each one (adjust code or close each one)
  2. Please look in picture below, why selector for status has different default color compared to other, e.g. icon selector!?

image

@evereq , @KostyaEver suggested stopping working on this ! I will continue after having a call with him and @GloireMutaliko21 !
So I will keep this as a draft for now !

@CREDO23 CREDO23 marked this pull request as draft October 25, 2024 17:12
Copy link
Member

@Cedric921 Cedric921 left a comment

Choose a reason for hiding this comment

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

I've just reviewed it,
The RabbitAI refactor suggestions is very pertinent (especially the ones I've stuck with 👍🏽) , When you will continue to work on this Task, try to integrate/fix them.
@CREDO23

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug] Settings | Status - add Status type issue in Edit/Create mode
3 participants