Skip to content

feat(new-webui): Add panel to ingest page with mocked compression statistics.#824

Merged
davemarco merged 16 commits into
y-scope:mainfrom
davemarco:ingest
Apr 21, 2025
Merged

feat(new-webui): Add panel to ingest page with mocked compression statistics.#824
davemarco merged 16 commits into
y-scope:mainfrom
davemarco:ingest

Conversation

@davemarco

@davemarco davemarco commented Apr 14, 2025

Copy link
Copy Markdown
Contributor

Description

Adds a panel with compression statistics. Added a new switch to change between
space savings and compression ratio.

Also adds a basic grid.

This is only half the panel. I have a chart with bars like old webui, that I will add in later PR.

For now now values are hardcoded.
Screenshot 2025-04-13 at 11 40 04 PM

Checklist

  • The PR satisfies the contribution guidelines.
  • This is a breaking change and that has been indicated in the PR title, OR this isn't a
    breaking change.
  • Necessary docs have been updated, OR no docs need to be updated.

Validation performed

Summary by CodeRabbit

  • New Features

    • Introduced a new Ingest page with a grid layout.
    • Added a Space Savings card displaying percentage savings in storage.
    • Added a reusable StatCard component for displaying statistics with customizable styling.
  • Style

    • Implemented new CSS modules for grid layouts and StatCard styling.

@davemarco davemarco requested a review from a team as a code owner April 14, 2025 03:43
@coderabbitai

coderabbitai Bot commented Apr 14, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

A new user interface layout for an "Ingest Page" has been introduced in the application. This includes the creation of a grid-based page structure, a "Space Savings" statistic display, and a reusable "StatCard" component, each with associated CSS modules for styling. The "Ingest Page" renders the "Space Savings" card with placeholder data. All components are exported as defaults, and the code is structured to allow for future expansion and integration of dynamic data.

Changes

File(s) Change Summary
components/log-viewer-webui/client/src/pages/IngestPage/index.module.css New CSS module for the IngestPage component defining a grid layout with padding and gap.
components/log-viewer-webui/client/src/pages/IngestPage/index.tsx New IngestPage React component rendering a container div with the grid CSS class and displaying the SpaceSavings component.
components/log-viewer-webui/client/src/pages/IngestPage/SpaceSavings/index.tsx New SpaceSavings React component; calculates and displays space savings percentage using StatCard with placeholder data.
components/log-viewer-webui/client/src/components/StatCard/index.module.css New CSS module for StatCard component; styles card header, content, title, and statistic.
components/log-viewer-webui/client/src/components/StatCard/index.tsx New StatCard React component; displays a statistic card with customizable title, value, and colours.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant IngestPage
    participant SpaceSavings
    participant StatCard

    User->>IngestPage: Render page
    IngestPage->>SpaceSavings: Render SpaceSavings component
    SpaceSavings->>StatCard: Render StatCard with calculated percentage
    StatCard-->>SpaceSavings: Display statistic card
    SpaceSavings-->>IngestPage: Display SpaceSavings card
    IngestPage-->>User: Show grid layout with SpaceSavings
Loading

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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 generate docstrings to generate docstrings for this 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.

@davemarco davemarco requested a review from junhaoliao April 14, 2025 03:45

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (8)
components/log-viewer-webui/client/src/pages/IngestPage/Size/index.module.css (1)

26-34: Fix minor formatting inconsistencies in the CSS properties.

There are spacing inconsistencies in the CSS properties and a missing semicolon.

 .segmented {
     background-color: transparent;
-    color:white;
+    color: white;
 
 }
 
 .segmented :global(.ant-segmented-item-selected) {
-    color:rgba(0, 0, 0, 0.65)
+    color: rgba(0, 0, 0, 0.65);
 }
components/log-viewer-webui/client/src/pages/IngestPage/Size/index.tsx (7)

1-17: Imports look good, but consider organizing them better.

The imports are properly structured, but for better maintainability, you might want to organize them in logical groups - React-related imports first, followed by third-party libraries, then internal imports.

import {useState} from "react";

import {
    CloseOutlined,
    PercentageOutlined,
} from "@ant-design/icons";
import {
    Card,
    Segmented,
    Typography,
} from "antd";

import styles from "./index.module.css";
import {
    DEFAULT_SIZE_OPTION,
    SIZE_OPTION,
-} from "./typings.js";
+} from "./typings";

27-32: Complete the JSDoc comment.

The JSDoc comment is incomplete. It has @return but doesn't specify what is returned.

/**
 * Presents space savings or compression ratio from the given statistics.
 *
-* @return
+* @return {JSX.Element} A card component displaying compression statistics
 */

32-36: Add type annotation for the component.

Consider adding a type annotation for the component to improve type safety and documentation.

-const Size = () => {
+const Size: React.FC = () => {
    const [segmentedOption, setSegmentedOption] = useState<SIZE_OPTION>(DEFAULT_SIZE_OPTION);
    const compressedSize = DUMMY_COMPRESSED_SIZE;
    const uncompressedSize = DUMMY_UNCOMPRESSED_SIZE;

38-41: Use more common comparison style.

According to the project's coding guidelines, we should prefer false == <expression> rather than !<expression>. While you're not using ! directly, the expression 0 < compressedSize is less common than compressedSize > 0, which might reduce readability.

// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
-const spaceSavingsPercent = 0 < compressedSize ?
+const spaceSavingsPercent = compressedSize > 0 ?
    100 * (1 - (compressedSize / uncompressedSize)) :
    0;

43-46: Use more common comparison style.

Similar to the previous comment, use a more common comparison style for better readability.

// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
-const compressionRatio = 0 < compressedSize ?
+const compressionRatio = compressedSize > 0 ?
    uncompressedSize / compressedSize :
    0;

51-77: Simplify boolean props and fix CSS class handling.

There are a few improvements that can be made in the render method:

  1. Boolean props like hoverable={true} can be simplified to just hoverable
  2. The pattern styles["card"] || "" is unusual - if you're trying to handle potential missing styles, use the logical nullish operator (??) instead

Additionally, consider adding aria labels to improve accessibility.

return (
    <Card
-        className={styles["card"] || ""}
+        className={styles.card ?? ""}
-        hoverable={true}
+        hoverable
    >
        <div className={styles["cardContent"]}>
            <div className={styles["header"]}>
-                <Text className={styles["title"] || ""}>
+                <Text className={styles.title ?? ""}>
                    {segmentedOption}
                </Text>
                <Segmented
-                    className={styles["segmented"] || ""}
+                    className={styles.segmented ?? ""}
                    defaultValue={DEFAULT_SIZE_OPTION}
                    options={[
                        {value: SIZE_OPTION.SPACE_SAVINGS, icon: <PercentageOutlined/>},
                        {value: SIZE_OPTION.COMPRESSION_RATIO, icon: <CloseOutlined/>},
                    ]}
+                    aria-label="Select statistic type"
                    onChange={handleChange}/>
            </div>
-            <Text className={styles["statistic"] || ""}>
+            <Text className={styles.statistic ?? ""}>
                {segmentedOption === SIZE_OPTION.SPACE_SAVINGS ?
                    `${spaceSavingsPercent.toFixed(2)}%` :
                    `${compressionRatio.toFixed(2)}x`}
            </Text>
        </div>
    </Card>
);

22-25: Use constants for improved readability and maintainability.

Consider creating named constants for significant values, especially ones mentioned in the TODO comment as pending replacement.

// eslint-disable-next-line no-warning-comments
// TODO: Replace with values from database once api implemented.
-const DUMMY_COMPRESSED_SIZE = 1004023;
-const DUMMY_UNCOMPRESSED_SIZE = 110300010;
+const DUMMY_COMPRESSED_SIZE = 1004023; // ~1 MB
+const DUMMY_UNCOMPRESSED_SIZE = 110300010; // ~110 MB
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2e7f63c and e1bee56.

📒 Files selected for processing (5)
  • components/log-viewer-webui/client/src/pages/IngestPage/Size/index.module.css (1 hunks)
  • components/log-viewer-webui/client/src/pages/IngestPage/Size/index.tsx (1 hunks)
  • components/log-viewer-webui/client/src/pages/IngestPage/Size/typings.ts (1 hunks)
  • components/log-viewer-webui/client/src/pages/IngestPage/index.module.css (1 hunks)
  • components/log-viewer-webui/client/src/pages/IngestPage/index.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == ` rather than `!`.

**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}: - Prefer false == <expression> rather than !<expression>.

  • components/log-viewer-webui/client/src/pages/IngestPage/index.tsx
  • components/log-viewer-webui/client/src/pages/IngestPage/Size/typings.ts
  • components/log-viewer-webui/client/src/pages/IngestPage/Size/index.tsx
🧬 Code Graph Analysis (1)
components/log-viewer-webui/client/src/pages/IngestPage/Size/index.tsx (2)
components/log-viewer-webui/client/src/pages/IngestPage/Size/typings.ts (2)
  • SIZE_OPTION (9-9)
  • DEFAULT_SIZE_OPTION (9-9)
components/webui/imports/ui/IngestView/panels/IngestionJobs/IngestionJobRow.jsx (2)
  • compressedSize (57-57)
  • uncompressedSize (52-52)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: lint-check (ubuntu-latest)
  • GitHub Check: lint-check (macos-latest)
🔇 Additional comments (10)
components/log-viewer-webui/client/src/pages/IngestPage/index.module.css (1)

1-6: Clean grid layout implementation.

The CSS grid layout is well-structured with three equal columns, which aligns perfectly with the new panel feature described in the PR objectives.

components/log-viewer-webui/client/src/pages/IngestPage/index.tsx (2)

1-3: Appropriate imports added for the new Size component.

The imports are clean and follow the proper pattern for both style modules and component imports.


12-13: Clean implementation of the Size component in the grid layout.

The implementation properly uses the CSS grid class and incorporates the new Size component, which aligns with the PR objective to add a compression statistics panel.

components/log-viewer-webui/client/src/pages/IngestPage/Size/typings.ts (3)

1-4: Well-defined enum for size options.

The enum properly defines the two display options mentioned in the PR objectives: space savings and compression ratio.


6-6: Appropriate default setting.

Setting the default to space savings makes sense as the primary view option.


8-10: Clean exports.

The exports are properly structured for TypeScript best practices.

components/log-viewer-webui/client/src/pages/IngestPage/Size/index.module.css (4)

1-7: Good styling for the card component.

The blue background and removal of default card borders create a clean panel appearance.


9-18: Well-structured layout classes.

The flex layouts for both the card content and header provide proper organization of elements.


20-24: Clean title styling.

The title styling with appropriate size, color, and weight creates good visual hierarchy.


36-39: Good statistic styling.

The large font size ensures good visibility of the key metrics, which aligns with the panel's purpose of highlighting compression statistics.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (5)
components/log-viewer-webui/client/src/pages/IngestPage/Size/index.tsx (5)

15-19: Complete the JSDoc @return tag.

The JSDoc comment has an empty @return tag. Please complete it by documenting what the component returns.

 /**
  * Presents space savings or compression ratio from the given statistics.
  *
- * @return
+ * @return {JSX.Element} A Card component displaying space savings statistics
  */

31-32: Simplify className assignment.

Using the || "" pattern is defensive but TypeScript should be able to guarantee that styles["card"] is a string if properly typed.

-    className={styles["card"] || ""}
+    className={styles.card}

35-36: Simplify className assignment.

Same as above, the defensive pattern can be simplified.

-    <Text className={styles["title"] || ""}>
+    <Text className={styles.title}>

38-39: Simplify className assignment.

Same as above, the defensive pattern can be simplified.

-    <Text className={styles["statistic"] || ""}>
+    <Text className={styles.statistic}>

1-48: Add loading and error states for future API integration.

Since this component will eventually fetch data from an API (as indicated by the TODO comment), consider adding loading and error states now to make the future integration smoother.

Here's how you might structure this:

import { Card, Typography, Spin } from "antd";
import { useState, useEffect } from "react";
import styles from "./index.module.css";

const { Text } = Typography;

// TODO: Replace with API call once implemented
const fetchCompressionData = (): Promise<{ compressedSize: number, uncompressedSize: number }> => {
  return Promise.resolve({
    compressedSize: 1004023,
    uncompressedSize: 110300010,
  });
};

/**
 * Presents space savings or compression ratio from the given statistics.
 *
 * @return {JSX.Element} A Card component displaying space savings statistics
 */
const SpaceSavings = () => {
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [data, setData] = useState<{ compressedSize: number, uncompressedSize: number } | null>(null);

  useEffect(() => {
    const loadData = async () => {
      try {
        const result = await fetchCompressionData();
        setData(result);
        setError(null);
      } catch (err) {
        setError("Failed to load compression data");
        console.error(err);
      } finally {
        setLoading(false);
      }
    };

    loadData();
  }, []);

  const calculateSpaceSavings = () => {
    if (!data) return 0;
    
    const { compressedSize, uncompressedSize } = data;
    return (0 < compressedSize && 0 < uncompressedSize) ?
      100 * (1 - (compressedSize / uncompressedSize)) :
      0;
  };

  const spaceSavingsPercent = calculateSpaceSavings();

  return (
    <Card
      className={styles.card}
      hoverable={true}
    >
      <div className={styles.cardContent}>
        <Text className={styles.title}>
          Space Savings
        </Text>
        {loading ? (
          <Spin />
        ) : error ? (
          <Text type="danger">{error}</Text>
        ) : (
          <Text className={styles.statistic}>
            {spaceSavingsPercent.toFixed(2)}%
          </Text>
        )}
      </div>
    </Card>
  );
};

export default SpaceSavings;
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e1bee56 and 0aca620.

📒 Files selected for processing (4)
  • components/log-viewer-webui/client/src/pages/IngestPage/Size/index.module.css (1 hunks)
  • components/log-viewer-webui/client/src/pages/IngestPage/Size/index.tsx (1 hunks)
  • components/log-viewer-webui/client/src/pages/IngestPage/index.module.css (1 hunks)
  • components/log-viewer-webui/client/src/pages/IngestPage/index.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • components/log-viewer-webui/client/src/pages/IngestPage/index.module.css
  • components/log-viewer-webui/client/src/pages/IngestPage/index.tsx
  • components/log-viewer-webui/client/src/pages/IngestPage/Size/index.module.css
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == ` rather than `!`.

**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}: - Prefer false == <expression> rather than !<expression>.

  • components/log-viewer-webui/client/src/pages/IngestPage/Size/index.tsx
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: lint-check (ubuntu-latest)
  • GitHub Check: lint-check (macos-latest)
  • GitHub Check: build (macos-latest)
🔇 Additional comments (1)
components/log-viewer-webui/client/src/pages/IngestPage/Size/index.tsx (1)

20-44:

Details

❓ Verification inconclusive

Implement the toggle feature mentioned in PR objectives.

According to the PR objectives, the panel should allow users to toggle between viewing space savings and compression ratios, but this functionality is missing from the implementation.

Please verify if the toggle feature is planned to be implemented in this component or in a parent component. If it should be part of this component, consider adding it with a state variable to track the current view mode.


🌐 Web query:

What is compression ratio and how does it differ from space savings in data compression?

💡 Result:

Compression Ratio in Data Compression

The compression ratio is a key metric used to quantify the effectiveness of a data compression process. It is defined as the ratio of the uncompressed (original) data size to the compressed data size. This is usually expressed as a simple ratio, such as 5:1 or 10:1, indicating that the compressed data is five or ten times smaller than the original, respectively[1][2][5][7].

Formula:
[
\text{Compression Ratio} = \frac{\text{Uncompressed Size}}{\text{Compressed Size}}
]

Example:
If a file originally takes up 100 MB and, after compression, is reduced to 20 MB:
[
\text{Compression Ratio} = \frac{100\ \text{MB}}{20\ \text{MB}} = 5:1
]

Space Savings in Data Compression

Space savings expresses how much storage space has been freed as a result of compression. Rather than a ratio, it is typically given as a percentage of the original size that is saved.

Formula:
[
\text{Space Savings} = \left(1 - \frac{\text{Compressed Size}}{\text{Uncompressed Size}}\right) \times 100%
]

Example:
With the same 100 MB to 20 MB compression:
[
\text{Space Savings} = \left(1 - \frac{20}{100}\right) \times 100% = 80%
]

Key Differences: Compression Ratio vs. Space Savings

Metric Formula Typical Notation What It Tells You Example (100 MB to 20 MB)
Compression Ratio Uncompressed Size / Compressed Size 5:1, 4:1, etc. How many times smaller the result is compared to the original 5:1
Space Savings (1 -) (Compressed Size / Uncompressed Size) %, e.g., 80% What percentage of space has been saved 80%

Summary:

  • Compression ratio shows how many times smaller the compressed data is compared to the original and is written as a ratio (e.g., 5:1)[1][2][5][7].
  • Space savings is the percentage reduction in size, showing what fraction of the original size has been eliminated (e.g., 80% saved)[1][7][10].
  • Both metrics describe compression, but they present the data from different perspectives: ratio versus percentage of size reduced.

Additional Clarification

It's common to confuse these terms or use them interchangeably, but compression ratio is never expressed as a percentage, and space savings should not be called 'compression ratio'[10]. Both are standard measurements for evaluating data compression efficiency, but serve different reporting preferences and clarity needs.

Citations:


Toggle Feature Required for Data Compression Metrics

The current implementation only displays the space savings metric. According to the PR objectives, users should be able to toggle between space savings and compression ratios (where compression ratio is defined as the uncompressed size divided by the compressed size, e.g. 5:1, compared to space savings, which is expressed as a percentage).

  • Please confirm whether the toggle functionality is intended to be implemented within this SpaceSavings component or managed by a parent component.
  • If it’s to be implemented here, consider adding a state variable (e.g. viewMode) that conditionally renders either:
    • Space Savings: Calculated as 100 * (1 - (compressedSize / uncompressedSize)) (displayed as a percentage), or
    • Compression Ratio: Calculated as (uncompressedSize / compressedSize) and formatted as a ratio (e.g. X:1).

Comment on lines +24 to +27
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
const spaceSavingsPercent = 0 < compressedSize ?
100 * (1 - (compressedSize / uncompressedSize)) :
0;

@coderabbitai coderabbitai Bot Apr 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding validation for uncompressedSize being zero.

The calculation handles the case where compressedSize is less than or equal to zero, but doesn't check if uncompressedSize is zero, which could lead to division by zero or NaN results.

 // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
-const spaceSavingsPercent = 0 < compressedSize ?
-    100 * (1 - (compressedSize / uncompressedSize)) :
-    0;
+const spaceSavingsPercent = (0 < compressedSize && 0 < uncompressedSize) ?
+    100 * (1 - (compressedSize / uncompressedSize)) :
+    0;
📝 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
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
const spaceSavingsPercent = 0 < compressedSize ?
100 * (1 - (compressedSize / uncompressedSize)) :
0;
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
const spaceSavingsPercent = (0 < compressedSize && 0 < uncompressedSize) ?
100 * (1 - (compressedSize / uncompressedSize)) :
0;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I modfied to check only if uncompressedSize === 0. It should not be possible for compressed size or uncompressed size to be less than 0.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@davemarco Thanks for implementing that check! Your approach of checking specifically for uncompressedSize === 0 is perfectly valid for preventing division by zero. And your explanation makes sense - if the data inherently cannot be negative, then checking for zero is indeed the only validation needed here. That's a more precise check than what I suggested.

@davemarco

Copy link
Copy Markdown
Contributor Author

@junhaoliao made changes we discussed on call

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (7)
components/log-viewer-webui/client/src/pages/IngestPage/SpaceSavings/index.tsx (7)

16-20: Complete the JSDoc comment with return type information

The JSDoc comment is incomplete, missing the return type description after the @return tag.

/**
 * Presents space savings or compression ratio from the given statistics.
 *
 * @return
+ * @returns {JSX.Element} A Card component displaying space savings percentage
 */

21-24: Consider adding props interface for future API integration

Currently the component uses hardcoded values, but as indicated by the TODO comment, it will eventually use API data. It would be beneficial to define a TypeScript interface for the props now to make future integration smoother.

+ interface SpaceSavingsProps {
+   compressedSize?: number;
+   uncompressedSize?: number;
+ }
+
- const SpaceSavings = () => {
+ const SpaceSavings: React.FC<SpaceSavingsProps> = ({ 
+   compressedSize = DUMMY_COMPRESSED_SIZE, 
+   uncompressedSize = DUMMY_UNCOMPRESSED_SIZE 
+ }) => {
-   const compressedSize = DUMMY_COMPRESSED_SIZE;
-   const uncompressedSize = DUMMY_UNCOMPRESSED_SIZE;

25-28: Invert condition for better readability

Although the current condition style aligns with the project's preference for false == <expression> rather than !<expression>, in this case, using compressedSize > 0 would be more intuitive and readable.

- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
- const spaceSavingsPercent = 0 < compressedSize ?
+ const spaceSavingsPercent = compressedSize > 0 ?
    100 * (1 - (compressedSize / uncompressedSize)) :
    0;

32-33: Remove fallback empty string for CSS class

The || "" pattern is unnecessary when using CSS modules as they guarantee the existence of the class. TypeScript should properly type the styles object.

- className={styles["card"] || ""}
+ className={styles.card}
  hoverable={true}

36-37: Remove fallback empty string for CSS class

Similar to the above, the fallback empty string is unnecessary when using CSS modules.

- <Text className={styles["title"] || ""}>
+ <Text className={styles.title}>

39-42: Remove fallback empty string for CSS class and add more detailed statistics

The fallback empty string is unnecessary, and consider enhancing this component to show more detailed statistics, similar to the old implementation that showed sizes before and after compression.

- <Text className={styles["statistic"] || ""}>
+ <Text className={styles.statistic}>
    {spaceSavingsPercent.toFixed(2)}
    %
</Text>
+ <Text className={styles.details}>
+   {/* TODO: Implement function to format size in human-readable form */}
+   {compressedSize} / {uncompressedSize} bytes
+ </Text>

13-14: Add comment explaining the dummy data values

Add a comment explaining what these values represent or where they came from to help other developers understand the context.

// TODO: Replace with values from database once api implemented.
- const DUMMY_COMPRESSED_SIZE = 1004023;
- const DUMMY_UNCOMPRESSED_SIZE = 110300010;
+ // Roughly 1MB compressed size and 110MB uncompressed size (about 99% savings)
+ const DUMMY_COMPRESSED_SIZE = 1004023; // bytes
+ const DUMMY_UNCOMPRESSED_SIZE = 110300010; // bytes
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0aca620 and 760d8b2.

📒 Files selected for processing (3)
  • components/log-viewer-webui/client/src/pages/IngestPage/SpaceSavings/index.module.css (1 hunks)
  • components/log-viewer-webui/client/src/pages/IngestPage/SpaceSavings/index.tsx (1 hunks)
  • components/log-viewer-webui/client/src/pages/IngestPage/index.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • components/log-viewer-webui/client/src/pages/IngestPage/SpaceSavings/index.module.css
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/log-viewer-webui/client/src/pages/IngestPage/index.tsx
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == ` rather than `!`.

**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}: - Prefer false == <expression> rather than !<expression>.

  • components/log-viewer-webui/client/src/pages/IngestPage/SpaceSavings/index.tsx
🧬 Code Graph Analysis (1)
components/log-viewer-webui/client/src/pages/IngestPage/SpaceSavings/index.tsx (2)
components/webui/imports/ui/IngestView/panels/SpaceSavings.jsx (1)
  • SpaceSavings (19-71)
components/webui/imports/ui/IngestView/panels/IngestionJobs/IngestionJobRow.jsx (2)
  • compressedSize (57-57)
  • uncompressedSize (52-52)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: lint-check (macos-latest)

Comment on lines +30 to +44
return (
<Card
className={styles["card"] || ""}
hoverable={true}
>
<div className={styles["cardContent"]}>
<Text className={styles["title"] || ""}>
Space Savings
</Text>
<Text className={styles["statistic"] || ""}>
{spaceSavingsPercent.toFixed(2)}
%
</Text>
</div>
</Card>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Implement toggle for compression ratio display

According to the PR objectives, the panel should include a switch to toggle between space savings and compression ratios. This functionality is currently missing from the implementation.

+import { Card, Typography, Switch } from "antd";
+import { useState } from "react";

// ...

const SpaceSavings = () => {
    const compressedSize = DUMMY_COMPRESSED_SIZE;
    const uncompressedSize = DUMMY_UNCOMPRESSED_SIZE;
+   const [showSpaceSavings, setShowSpaceSavings] = useState(true);

    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
    const spaceSavingsPercent = 0 < compressedSize ?
        100 * (1 - (compressedSize / uncompressedSize)) :
        0;
+   const compressionRatio = 0 < compressedSize && 0 < uncompressedSize ?
+       uncompressedSize / compressedSize :
+       0;

    return (
        <Card
            className={styles["card"] || ""}
            hoverable={true}
        >
            <div className={styles["cardContent"]}>
                <Text className={styles["title"] || ""}>
                    Space Savings
+                   <Switch
+                       className={styles["toggle"] || ""}
+                       checked={showSpaceSavings}
+                       onChange={setShowSpaceSavings}
+                       checkedChildren="Savings"
+                       unCheckedChildren="Ratio"
+                       size="small"
+                   />
                </Text>
                <Text className={styles["statistic"] || ""}>
+                   {showSpaceSavings ? (
                    {spaceSavingsPercent.toFixed(2)}
                    %
+                   ) : (
+                   {compressionRatio.toFixed(2)}
+                   :1
+                   )}
                </Text>
            </div>
        </Card>
    );
};

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Following the direction to make the panels generic, can we do one change to extract the Card component into one with props

interface StatsProps {
   title: string;
   value: string;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I made a new stat card

Comment on lines +6 to +8
.card :global(.ant-card-head) {
border: 0px;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What's the use of this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The default card has this line in it which looks ugly if you make the card blue.
https://ant.design/components/card

@@ -0,0 +1,24 @@
.card {
background-color: #1888fa;
min-width: 300px;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It doesn't work when we add multiple of the cards, right?

image

Can we see the comment

"Can we do one change to extract the Card component into one with props"

extract a component as

<Col xs={{ flex: '100%' }}
          sm={{ flex: '50%' }}
          md={{ flex: '40%' }}
          lg={{ flex: '20%' }}
          xl={{ flex: '10%' }}
>
  <Card>
  ...
  </Card>
</Col>

see https://ant.design/components/grid#grid-demo-responsive-flex

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I moved to css grid... anyways u can see the code, and see what you think


.statistic {
font-size: 80px;
color: white;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

would this work when dark mode is added? shall we use some variable (from antd?) instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think it will always be white regardless, but i changed at least to take color from the global theme

Comment on lines +17 to +18
<div className={styles["ingestPageGrid"]}>
<Row>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

how about

Suggested change
<div className={styles["ingestPageGrid"]}>
<Row>
<Row className={styles["ingestPageGrid"]}>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i got rid of antd grid..

Comment on lines +19 to +21
<Col span={8}>
<SpaceSavings/>
</Col>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's see the comment about

It doesn't work when we add multiple of the cards, right?

I feel it's better to use Col as a parent component in the Stats component, assuming all our Stats panels are placed on this dashboard, which is currently a Row.

Suggested change
<Col span={8}>
<SpaceSavings/>
</Col>
<Col span={8}>
<SpaceSavings/>
</Col>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

same got rid of antd grid...

@junhaoliao junhaoliao requested a review from hoophalab April 16, 2025 22:24

.title {
font-size: 24px;
color: white;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ditto. let's see the comment about "dark mode"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i passed the theme white instead of hardcoding. it will still be white, but i guess for flexible to change later

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (6)
components/log-viewer-webui/client/src/components/StatCard/index.tsx (6)

19-19: Fix the typo in the JSDoc comment.

There's a minor typo in the documentation: "dislays" should be "displays".

-/**
- * Renders a card that dislays a statistic.
+ * Renders a card that displays a statistic.

26-27: Complete the JSDoc return type.

The JSDoc is missing the return type information.

 * @param root0.textColor
 * @param root0.backgroundColor
- * @return
+ * @return {JSX.Element} A card component displaying the statistic
 */

31-31: Consider simplifying the className assignment.

The || "" fallback is unnecessary when using CSS modules, as the imported styles object will always contain the keys defined in the CSS file.

-            className={styles["card"] || ""}
+            className={styles.card}

37-38: Consider simplifying the className assignment and conditional styling.

Similar to the previous comment, the || "" fallback is unnecessary. Also, consider including a check for the existence of textColor before applying it to the style object.

-                    className={styles["title"] || ""}
-                    style={{color: textColor}}
+                    className={styles.title}
+                    style={textColor ? {color: textColor} : undefined}

43-44: Consider simplifying the className assignment and conditional styling.

Similar to the previous comments, the || "" fallback is unnecessary, and a check for textColor would make the code more robust.

-                    className={styles["statistic"] || ""}
-                    style={{color: textColor}}
+                    className={styles.statistic}
+                    style={textColor ? {color: textColor} : undefined}

32-33: Consider adding conditional styling for backgroundColor.

Similar to the suggestion for textColor, consider checking if backgroundColor exists before applying it.

-            hoverable={true}
-            style={{backgroundColor}}
+            hoverable
+            style={backgroundColor ? {backgroundColor} : undefined}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 72bb4be and 3ca51e4.

📒 Files selected for processing (4)
  • components/log-viewer-webui/client/src/components/StatCard/index.module.css (1 hunks)
  • components/log-viewer-webui/client/src/components/StatCard/index.tsx (1 hunks)
  • components/log-viewer-webui/client/src/pages/IngestPage/SpaceSavings/index.tsx (1 hunks)
  • components/log-viewer-webui/client/src/pages/IngestPage/index.module.css (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • components/log-viewer-webui/client/src/components/StatCard/index.module.css
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/log-viewer-webui/client/src/pages/IngestPage/SpaceSavings/index.tsx
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == ` rather than `!`.

**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}: - Prefer false == <expression> rather than !<expression>.

  • components/log-viewer-webui/client/src/components/StatCard/index.tsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: lint-check (ubuntu-latest)
🔇 Additional comments (1)
components/log-viewer-webui/client/src/pages/IngestPage/index.module.css (1)

1-6: LGTM - Clean and responsive grid layout implementation.

The CSS grid implementation provides a responsive layout that will adapt well to different screen sizes. The use of minmax with auto-fit is a good approach for creating a responsive grid that automatically adjusts the number of columns based on available space.

@davemarco davemarco requested a review from junhaoliao April 17, 2025 18:26

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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)
components/log-viewer-webui/client/src/pages/IngestPage/index.tsx (1)

5-9: Complete the JSDoc documentation

The JSDoc comment for the IngestPage component has an incomplete @return tag. Consider adding a description of what the component returns for better code documentation.

 /**
  * Presents compression statistics.
  *
- * @return
+ * @return {JSX.Element} The rendered IngestPage component
  */
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0d9a840 and 735c949.

📒 Files selected for processing (2)
  • components/log-viewer-webui/client/src/pages/IngestPage/index.module.css (1 hunks)
  • components/log-viewer-webui/client/src/pages/IngestPage/index.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/log-viewer-webui/client/src/pages/IngestPage/index.module.css
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == ` rather than `!`.

**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}: - Prefer false == <expression> rather than !<expression>.

  • components/log-viewer-webui/client/src/pages/IngestPage/index.tsx
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: lint-check (macos-latest)
  • GitHub Check: lint-check (ubuntu-latest)
  • GitHub Check: build (macos-latest)
🔇 Additional comments (1)
components/log-viewer-webui/client/src/pages/IngestPage/index.tsx (1)

10-16: The IngestPage component structure looks good

The component follows React best practices by using a functional component and CSS modules for styling. Based on the PR objectives, this sets up the initial grid layout for adding compression statistics.

Comment on lines +1 to +19
import styles from "./index.module.css";
import SpaceSavings from "./SpaceSavings";


/**
* Presents compression statistics.
*
* @return
*/
const IngestPage = () => {
return (
<div className={styles["ingestPageGrid"]}>
<SpaceSavings/>
</div>
);
};


export default IngestPage;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify this implementation matches the requirements

According to the PR objectives, the panel should include a toggle between space savings and compression ratios. The current implementation only shows the SpaceSavings component without any toggle functionality. Is this planned for a future update?


🏁 Script executed:

#!/bin/bash
# Check if there's any toggle implementation in the SpaceSavings component
cd components/log-viewer-webui/client/src/pages/IngestPage
if [ -d "SpaceSavings" ]; then
  echo "Examining SpaceSavings component:"
  grep -r "toggle\|switch" SpaceSavings
fi

Length of output: 203


Implement toggle control for Space Savings / Compression Ratios

The IngestPage currently renders only the SpaceSavings component and does not include any toggle or switch to show compression ratios as required by the PR objectives.

Locations needing updates:

  • components/log-viewer-webui/client/src/pages/IngestPage/index.tsx:
    • Import and render a toggle UI (e.g. tabs, switch)
    • Import and conditionally render a CompressionRatio component alongside SpaceSavings

Please add the missing toggle functionality and ensure both views can be selected by the user.

@junhaoliao junhaoliao left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For the title, how about:

feat(new-webui): Add panel to ingest page with mocked compression statistics.

@davemarco davemarco changed the title feat(new-webui): Add panel to ingest page with compression statistics. feat(new-webui): Add panel to ingest page with mocked compression statistics. Apr 21, 2025
@davemarco davemarco merged commit 9589c6f into y-scope:main Apr 21, 2025
anlowee pushed a commit to anlowee/clp that referenced this pull request Apr 25, 2025
junhaoliao pushed a commit to junhaoliao/clp that referenced this pull request May 17, 2026
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.

2 participants