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

Analytics: Enhancements on More insights modal #2282

Merged
merged 3 commits into from
Dec 2, 2024
Merged

Conversation

OchiengPaul442
Copy link
Contributor

@OchiengPaul442 OchiengPaul442 commented Dec 1, 2024

Summary of Changes (What does this PR do?)

  • Added feature to select and deselect a location for the charts for better analysis
  • Optimized truncations on chart legend
  • Added the download data functionality to the More insights modal
  • If Analysis is being done on one location, user wont be able to deselect that location on the locaiton card unless the locations are greater than one.

Status of maturity (all need to be checked before merging):

  • I've tested this locally
  • I consider this code done
  • This change ready to hit production in its current state

Screenshots (optional)

image
image

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced TabButtons component with loading and disabled states, including a loading spinner for better user feedback.
    • Added disableToggle prop to LocationCard for optional toggle functionality.
    • Introduced data download capabilities in MoreInsights with error handling and user notifications.
  • Improvements

    • Streamlined tooltip rendering in chart legends for better performance.
    • Improved state management and user experience in the MoreInsights component.

These updates enhance usability and accessibility across the application.

@OchiengPaul442 OchiengPaul442 self-assigned this Dec 1, 2024
Copy link

gitguardian bot commented Dec 1, 2024

⚠️ GitGuardian has uncovered 2 secrets following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secrets in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
5583163 Triggered Google API Key 620249e mobile-v3/ios/Runner/AppDelegate.swift View secret
5583163 Triggered Google API Key 620249e mobile-v3/android/app/src/main/AndroidManifest.xml View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secrets safely. Learn here the best practices.
  3. Revoke and rotate these secrets.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

Copy link

coderabbitai bot commented Dec 1, 2024

📝 Walkthrough
📝 Walkthrough

Walkthrough

The pull request introduces several enhancements across multiple components. The TabButtons component is updated to manage loading and disabled states with new props and a Spinner for better user feedback. The LocationCard component gains a disableToggle prop to control toggle functionality. The MoreInsights component improves state management for data downloads, including error handling and user notifications. Additionally, tooltip rendering logic in the Charts component is simplified for better readability. These changes collectively improve usability, accessibility, and maintainability.

Changes

File Path Change Summary
platform/src/common/components/Button/TabButtons.jsx - Added isLoading and disabled props.
- Integrated Spinner for loading indication.
- Updated propTypes for Icon and tabRef.
- Adjusted button's class name for loading and disabled states.
platform/src/common/components/Charts/components/index.jsx - Simplified tooltip rendering logic in renderCustomizedLegend function, removing unnecessary div wrapper around tooltips.
platform/src/common/components/Modal/dataDownload/components/LocationCard.jsx - Introduced disableToggle prop to manage toggle functionality.
- Updated propTypes and defaultProps for disableToggle.
- Adjusted checkbox logic to prevent onToggle call when disableToggle is true.
platform/src/common/components/Modal/dataDownload/modules/MoreInsights.jsx - Added state variables for download management: downloadLoading, downloadError.
- Introduced handleDataDownload function for downloading data.
- Refined logic for site selection with toggleSiteSelection.
- Updated rendering logic for displaying sites and error messages.

Possibly related PRs

Suggested labels

ready for review

Suggested reviewers

  • Baalmart
  • Codebmk

🎉 In the code's dance, new props take the stage,
Loading spinners twirl, as users engage.
With toggles that toggle, and legends that shine,
Each change a step forward, in rhythm and rhyme.
So here's to the updates, both big and small,
Enhancing our app, we celebrate all! 🎊


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 or @coderabbitai title 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 (5)
platform/src/common/components/Modal/dataDownload/components/LocationCard.jsx (2)

39-41: Consider improving the display name logic.

The current nested fallback logic could be more readable using optional chaining and nullish coalescing.

Here's a cleaner approach:

-  const displayName = truncateName(
-    name || (search_name && search_name.split(',')[0]) || '',
-  );
+  const displayName = truncateName(
+    name ?? search_name?.split(',')[0] ?? ''
+  );
🧰 Tools
🪛 Biome (1.9.4)

[error] 40-40: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


85-101: Consider enhancing PropTypes validation.

While the current validation is good, we could make it more specific for better type safety.

Consider adding these validations:

 LocationCard.propTypes = {
   site: PropTypes.shape({
     _id: PropTypes.string.isRequired,
     name: PropTypes.string,
     search_name: PropTypes.string,
     country: PropTypes.string,
+    // Add validation for any other potential site properties
   }).isRequired,
   onToggle: PropTypes.func.isRequired,
-  isSelected: PropTypes.bool.isRequired,
+  isSelected: PropTypes.bool.isRequired,
   isLoading: PropTypes.bool,
-  disableToggle: PropTypes.bool, // New prop to disable toggle when needed
+  disableToggle: PropTypes.bool,
 };
platform/src/common/components/Charts/components/index.jsx (1)

253-259: Clean and efficient legend rendering!

The conditional rendering logic for truncated legends is well-implemented. However, consider adding a tooltip placement prop for better positioning control.

-            <Tooltip content={entry.value} className="w-auto">
+            <Tooltip content={entry.value} className="w-auto" placement="top">
platform/src/common/components/Modal/dataDownload/modules/MoreInsights.jsx (2)

211-258: Download functionality needs retry mechanism

The download functionality is well-implemented with proper error handling, but consider adding a retry mechanism for failed downloads.

 const handleDataDownload = async () => {
   setDownloadLoading(true);
+  let retryCount = 0;
+  const maxRetries = 3;
+
+  const attemptDownload = async () => {
   try {
     const { startDate, endDate } = dateRange;
     // ... existing code ...
     const response = await exportDataApi(apiData);
     // ... existing code ...
     setDownloadLoading(false);
     CustomToast();
   } catch (error) {
     console.error(error);
+    if (retryCount < maxRetries) {
+      retryCount++;
+      console.log(`Retrying download (${retryCount}/${maxRetries})...`);
+      await attemptDownload();
+    } else {
       setDownloadError(
         'There was an error downloading the data. Please try again later.',
       );
       setDownloadLoading(false);
+    }
   }
+ };
+
+ await attemptDownload();
 };

417-422: Consider enhancing AirQualityCard with real-time data

The AirQualityCard is currently using placeholder values. Consider enhancing it with real-time data from the chart.

 <AirQualityCard
-  airQuality="--"
-  pollutionSource="--"
+  airQuality={allSiteData?.length > 0 ? allSiteData[0].airQuality : '--'}
+  pollutionSource={allSiteData?.length > 0 ? allSiteData[0].source : '--'}
   pollutant={chartData.pollutionType === 'pm2_5' ? 'PM2.5' : 'PM10'}
   isLoading={chartLoading}
 />
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between bff9233 and 620249e.

📒 Files selected for processing (4)
  • platform/src/common/components/Button/TabButtons.jsx (2 hunks)
  • platform/src/common/components/Charts/components/index.jsx (1 hunks)
  • platform/src/common/components/Modal/dataDownload/components/LocationCard.jsx (4 hunks)
  • platform/src/common/components/Modal/dataDownload/modules/MoreInsights.jsx (10 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
platform/src/common/components/Modal/dataDownload/components/LocationCard.jsx

[error] 40-40: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (9)
platform/src/common/components/Modal/dataDownload/components/LocationCard.jsx (3)

15-21: LGTM! Clean prop destructuring and naming.

The component signature is well-structured with clear, purpose-indicating prop names.


47-50: Great job on accessibility and visual feedback!

The styling properly reflects the component's state, and the aria-disabled attribute enhances accessibility.


72-74: Well-implemented toggle functionality.

Good practices observed:

  • Event propagation control with stopPropagation
  • Clean conditional toggle logic
  • Proper disabled state handling on the checkbox

Also applies to: 78-78

platform/src/common/components/Button/TabButtons.jsx (4)

4-4: Documentation and imports look good!

The component is well-documented with JSDoc comments, clearly describing its purpose and props.

Also applies to: 6-14


34-40: Great accessibility implementation!

The button's disabled state is properly handled with both disabled and aria-disabled attributes, and the cursor style changes appropriately.


42-51: Clean loading state implementation!

The loading state is well-implemented with a conditional render between Spinner and Icon.


72-84: PropTypes are well-defined!

The PropTypes are comprehensive and properly typed, especially the Icon prop which now accepts both function and element types.

platform/src/common/components/Modal/dataDownload/modules/MoreInsights.jsx (2)

47-49: Well-structured state management!

The download-related states are properly initialized and follow React best practices.


368-375: Download button implementation looks good!

The download button properly handles loading and disabled states using the TabButtons component.

Comment on lines +51 to +66
/**
* Ensure `allSites` is an array.
* If `modalData` is undefined, null, or not an array, default to an empty array.
*/
const allSites = useMemo(() => {
if (Array.isArray(modalData)) return modalData;
if (modalData) return [modalData];
return [];
}, [modalData]);

// Extract site IDs from selected sites for API requests
/**
* Local state to manage selected sites.
* Initializes with all sites selected by default.
*/
const [selectedSites, setSelectedSites] = useState(() => [...allSites]);

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Site selection logic needs error handling enhancement

The site selection logic is well-implemented, but consider adding error handling for edge cases.

 const toggleSiteSelection = useCallback(
   (siteId) => {
+    if (!siteId) {
+      console.error('Invalid site ID provided');
+      return;
+    }
     setSelectedSites((prevSelected) => {
       const isSelected = prevSelected.some((site) => site._id === siteId);
       if (isSelected) {
         return prevSelected.filter((site) => site._id !== siteId);
       } else {
         const siteToAdd = allSites.find((site) => site._id === siteId);
         if (siteToAdd) {
           return [...prevSelected, siteToAdd];
         }
+        console.error(`Site with ID ${siteId} not found`);
         return prevSelected;
       }
     });
   },
   [allSites],
 );

Also applies to: 120-141

Copy link
Contributor

github-actions bot commented Dec 1, 2024

New next-platform changes available for preview here

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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 620249e and d760033.

📒 Files selected for processing (1)
  • platform/src/common/components/Modal/dataDownload/modules/MoreInsights.jsx (10 hunks)
🔇 Additional comments (1)
platform/src/common/components/Modal/dataDownload/modules/MoreInsights.jsx (1)

126-141: Site selection logic needs error handling for edge cases

Consider adding error handling for invalid or non-existent site IDs.

As previously suggested, it's important to handle cases where siteId might be invalid or not found in allSites. This prevents potential runtime errors and improves the robustness of your code.

Apply this diff to enhance error handling:

const toggleSiteSelection = useCallback(
  (siteId) => {
+    if (!siteId) {
+      console.error('Invalid site ID provided');
+      return;
+    }
    setSelectedSites((prevSelected) => {
      const isSelected = prevSelected.some((site) => site._id === siteId);
      if (isSelected) {
        return prevSelected.filter((site) => site._id !== siteId);
      } else {
        const siteToAdd = allSites.find((site) => site._id === siteId);
        if (siteToAdd) {
          return [...prevSelected, siteToAdd];
        }
+       console.error(`Site with ID ${siteId} not found`);
        return prevSelected;
      }
    });
  },
  [allSites],
);

startDateTime: startDate,
endDateTime: endDate,
sites: selectedSiteIds,
network: chartData.organizationName,
Copy link

@coderabbitai coderabbitai bot Dec 1, 2024

Choose a reason for hiding this comment

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

⚠️ Potential issue

Inconsistent property naming: 'organisationName' vs 'organizationName'

In your API request data, you're using chartData.organizationName for the network parameter, but elsewhere you reference chartData.organisationName. This inconsistency might lead to undefined values and potential errors. Please ensure consistent property naming throughout your code.

Copy link
Collaborator

Choose a reason for hiding this comment

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

⚠️ Potential issue

Inconsistent property naming: 'organisationName' vs 'organizationName'

In your API request data, you're using chartData.organizationName for the network parameter, but elsewhere you reference chartData.organisationName. This inconsistency might lead to undefined values and potential errors. Please ensure consistent property naming throughout your code.

Hi @OchiengPaul442 , can we quickly start using GROUPS in new Analytics and quickly phase out "organisations" and "networks" from the new Analytics codebase? The earlier we are intentional about the entire process, the better for all of us. cc: @Codebmk

Copy link

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Contributor

github-actions bot commented Dec 1, 2024

New next-platform changes available for preview here

@Baalmart Baalmart merged commit cc76777 into staging Dec 2, 2024
29 of 31 checks passed
@Baalmart Baalmart deleted the analytics-fix branch December 2, 2024 14:33
@Baalmart Baalmart mentioned this pull request Dec 2, 2024
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants