Skip to content

feat: migrate to Vite + React Router and implement Carbon Design System dashboard#215

Merged
ameijer merged 22 commits intoopencost:mainfrom
maxvishy:vishy-carbon-design
Apr 1, 2026
Merged

feat: migrate to Vite + React Router and implement Carbon Design System dashboard#215
ameijer merged 22 commits intoopencost:mainfrom
maxvishy:vishy-carbon-design

Conversation

@maxvishy
Copy link
Copy Markdown
Contributor

@maxvishy maxvishy commented Feb 10, 2026

Migrate to Vite + React Router and implement Carbon Design System dashboard

What does this PR change?

This PR completely modernizes the opencost-ui project by migrating from a Parcel-based build system to Next.js 13 (App Router) and implementing a new dashboard using IBM's Carbon Design System.

Major Changes:

Build System & Framework:

  • Migrated from Parcel bundler to Next.js 13 with App Router
  • Removed legacy Babel configuration (Next.js uses SWC compiler)
  • Added Next.js configuration files (next.config.js, jsconfig.json, .eslintrc.json)
  • Updated .gitignore to exclude Next.js build artifacts (.next/)

UI Framework Migration:

  • Replaced Material-UI with Carbon Design System (@carbon/react v1.35.0)
  • Integrated Carbon Charts (@carbon/charts-react v1.13.0) for data visualization
  • Added Carbon Icons (@carbon/icons-react v11.14.0)
  • Implemented SCSS support with Carbon's design tokens

New Components:

  • Assets Visualization: Interactive asset management with cost tracking, carbon emissions, and utilization metrics
  • Dashboard Context: Centralized state management for dashboard configuration
  • Dashboard View: Customizable dashboard builder with widget system
  • Cost Summary Cards: Real-time cost metrics display
  • Cost Allocation Chart: Stacked bar chart for cost distribution
  • Cost by Service Chart: Area chart for service cost trends
  • External Services Widget: Tabs-based view for external service costs
  • Scoped Views: Filtered views with multi-select and tagging
  • Create Dashboard Modal: Interface for creating new dashboards

Data Layer:

  • Added assets-api.js utility for parsing OpenCost API responses
  • Support for multiple asset types (Node, Disk, LoadBalancer, ClusterManagement)
  • Sample data file (public/ss.json) for development and testing
  • Graceful fallback to demo data when API is unavailable

Application Structure:

  • Deleted legacy React entry point (src/app.js, src/index.html, src/route.js)
  • Implemented Next.js App Router structure (src/app/page.js, src/app/layout.js)
  • Created src/app/globals.scss for global styles with Carbon design tokens
  • Organized components in src/components/ directory
  • Added utilities in src/lib/ directory

Dependencies:

  • Updated React from 17.x to 18.2.0
  • Removed Material-UI, date-fns, axios, recharts (legacy dependencies)
  • Added Next.js 13.4.9
  • Added Carbon Design System packages
  • Added SASS support (v1.69.5)
  • Added ESLint with Next.js config

Does this PR relate to any other PRs?

  • This is a standalone modernization effort for the OpenCost UI

How will this PR impact users?

Positive Impacts:

  • Modern, Professional UI: Clean, accessible interface following IBM Carbon Design guidelines
  • Better Performance: Next.js optimizations (SSR, code splitting, automatic optimization)
  • Enhanced Visualizations: Interactive charts and graphs for cost analysis
  • Multi-Asset Support: Now displays all asset types (Nodes, Disks, LoadBalancers, Cluster Management)
  • Improved Accessibility: Carbon Design System provides WCAG-compliant components
  • Better Developer Experience: Hot module reloading, better debugging, TypeScript-ready

Breaking Changes:

  • Complete UI redesign - users will need to familiarize themselves with the new interface
  • URL structure may change due to Next.js routing
  • Configuration options may differ from the previous version

Does this PR address any GitHub or Zendesk issues?

  • Addresses the need for a modern, maintainable UI framework
  • Resolves build system complexity and dependency conflicts
  • Improves asset visualization capabilities

How was this PR tested?

Local Development Testing:

  • ✅ Verified all components render correctly with real asset data
  • ✅ Tested asset filtering across all asset types (Node, Disk, LoadBalancer, ClusterManagement)
  • ✅ Validated cost calculations and carbon emission metrics
  • ✅ Confirmed tab navigation and data filtering functionality
  • ✅ Tested with sample data (ss.json) and verified fallback to demo data
  • ✅ Checked responsive layout and styling consistency
  • ✅ Verified chart rendering with Carbon Charts library
  • ✅ Validated Next.js hot reload and development server stability

Browser Compatibility:

  • Tested on modern browsers (Chrome, Firefox, Safari, Edge)
  • Verified Carbon Design System styles load correctly

Build & Production:

  • npm run dev - Development server runs successfully
  • npm run build - Production build completes without errors
  • npm run lint - ESLint passes with Next.js config

Does this PR require changes to documentation?

Yes, the following documentation should be updated:

  1. Installation Guide: Update dependencies and build commands
  2. Development Guide: Document Next.js development workflow
  3. Configuration: Document new config files (next.config.js, jsconfig.json)
  4. Component Guide: Document new Carbon-based components
  5. API Integration: Document asset API format and requirements
  6. Deployment: Update deployment instructions for Next.js applications
  7. Migration Guide: Provide guidance for users upgrading from the old UI

Have you labeled this PR and its corresponding Issue as "next release" if it should be part of the next OpenCost release? If not, why not?

  • Yes, this should be labeled as "next release" as it represents a major UI modernization
  • This is a significant feature addition that warrants inclusion in the next major or minor release
  • Recommended for a minor version bump (e.g., v1.x.0 → v1.y.0) due to breaking UI changes

- Removed Babel configuration file (.babelrc) as it is no longer needed.
- Added ESLint configuration file (.eslintrc.json) extending Next.js core web vitals.
- Updated .gitignore to exclude the .next directory.
- Introduced jsconfig.json for path mapping in the project.
- Created next.config.js for Next.js configuration with strict mode and SASS options.
- Updated package.json and package-lock.json to include new dependencies for Next.js and Carbon Design System.
- Deleted legacy React app files (app.js, index.html, route.js) and replaced with new structure using Next.js.
- Added new components for dashboard visualization and cost tracking.
- Introduced global styles and layout for the application.
- Added JSON data file for asset visualization.

This commit transitions the project to a Next.js framework, enhancing the structure and modernizing the codebase.

Signed-off-by: Vishy <maxvishy02@gmail.com>
@netlify
Copy link
Copy Markdown

netlify Bot commented Feb 10, 2026

Deploy Preview for opencost-ui ready!

Name Link
🔨 Latest commit ff0b145
🔍 Latest deploy log https://app.netlify.com/projects/opencost-ui/deploys/69cd2d6ca095cf00086246d1
😎 Deploy Preview https://deploy-preview-215--opencost-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@maxvishy
Copy link
Copy Markdown
Contributor Author

image image

Signed-off-by: Vishy <maxvishy02@gmail.com>
Signed-off-by: Vishy <maxvishy02@gmail.com>
@ameijer ameijer requested a review from Copilot February 24, 2026 17:12
@ameijer
Copy link
Copy Markdown
Member

ameijer commented Feb 24, 2026

@cursor review

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR migrates opencost-ui from a Parcel + React Router app to a Next.js 13 (App Router) application and introduces a new Carbon Design System-based dashboard experience, including chart/widgets and an assets visualization backed by OpenCost assets data (with demo fallbacks).

Changes:

  • Replaces legacy Parcel entrypoints/routing with Next.js App Router structure (src/app/*) and Next config files.
  • Adds Carbon-based dashboard components (dashboard list/view/builder, scoped filters, charts, assets visualization).
  • Removes legacy pages/routes and comments out large portions of the old Material UI implementation (effectively deprecating it).

Reviewed changes

Copilot reviewed 58 out of 63 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
src/app/page.js New Carbon dashboard landing page + dashboard selection flow.
src/app/layout.js Next.js root layout + metadata + font setup.
src/app/globals.scss Global styling for the Next.js app + dashboard utility classes.
src/components/dashboard-context.js Client-side dashboard state/context provider.
src/components/dashboard-view.js Dashboard view page (widgets grid, filter toggle, edit mode).
src/components/dashboard-builder.js Dashboard widget layout/builder UI.
src/components/create-dashboard-modal.js Modal flow for creating a new dashboard.
src/components/scoped-views.js Scoped view/filter UI.
src/components/cost-summary-cards.js Summary metric cards widget.
src/components/cost-allocation-chart.js Carbon stacked bar chart widget (sample data).
src/components/cost-by-service-chart.js Carbon area chart widget (sample data).
src/components/external-services-chart-widget.js External services widget with tabs + chart/table (sample data).
src/components/assets-visualization.js Assets visualization widget fetching public/ss.json / OpenCost API / demo data.
src/lib/assets-api.js Asset response parsing + fetch helper.
src/css/index.css Updated legacy stylesheet (appears to be leftover post-migration).
netlify.toml Adds Netlify Next.js build configuration/plugin.
next.config.js Next.js config + sass options.
jsconfig.json Adds @/* path mapping for imports.
package.json Swaps Parcel/MUI dependencies for Next.js + Carbon + Sass tooling.
.eslintrc.json Adds Next.js ESLint config preset.
.gitignore Ignores .next build artifacts.
src/app.js Removes Parcel ReactDOM bootstrap entrypoint.
src/index.html Removes Parcel HTML entrypoint.
src/route.js Removes React Router routing setup.
src/pages/Allocations.js Removes legacy page (allocation report).
src/pages/CloudCosts.js Removes legacy page (cloud cost report).
src/pages/ExternalCosts.js Removes legacy page (external costs report).
src/tempPages/Allocations.js Adds commented-out legacy page snapshot (unused).
src/tempPages/CloudCosts.js Adds commented-out legacy page snapshot (unused).
src/tempPages/ExternalCosts.js Adds commented-out legacy page snapshot (unused).
.babelrc Removes legacy Babel config.
src/components/Page.js Comments out legacy layout component.
src/components/Header.js Comments out legacy header component.
src/components/Footer.js Comments out legacy footer component.
src/components/Warnings.js Comments out legacy warnings component.
src/components/Subtitle.js Comments out legacy subtitle component.
src/components/SelectWindow.js Comments out legacy date range control.
src/components/Nav/SidebarNav.js Comments out legacy sidebar nav.
src/components/Nav/NavItem.js Comments out legacy nav item.
src/components/Controls/index.js Comments out legacy controls wrapper.
src/components/Controls/Edit.js Comments out legacy edit controls.
src/components/Controls/Download.js Comments out legacy download control.
src/components/AllocationChart/index.js Comments out legacy allocation chart.
src/components/AllocationChart/RangeChart.js Comments out legacy allocation range chart.
src/components/AllocationChart/SummaryChart.js Comments out legacy allocation summary chart.
src/components/externalCosts/externalCostsChart.js Comments out legacy external costs chart wrapper.
src/components/externalCosts/rangeChart.js Comments out legacy external costs range chart.
src/components/externalCosts/externalCostsControls.js Comments out legacy external costs controls.
src/components/externalCosts/externalCostsTable.js Comments out legacy external costs table.
src/components/externalCosts/externalCostRow.js Comments out legacy external costs row.
src/components/externalCosts/externalCostDetailModal.js Comments out legacy external costs detail modal.
src/components/cloudCost/tokens.js Comments out legacy cloud cost tokens.
src/components/cloudCost/cloudCost.js Comments out legacy cloud cost main component.
src/components/cloudCost/cloudCostRow.js Comments out legacy cloud cost row component.
src/components/cloudCost/cloudCostDetails.js Comments out legacy cloud cost details modal.
src/components/cloudCost/cloudCostChart/index.js Comments out legacy cloud cost chart wrapper.
src/components/cloudCost/controls/cloudCostEditControls.js Comments out legacy cloud cost edit controls.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/components/assets-visualization.js Outdated
Comment on lines +86 to +90
const [selectedAssetType, setSelectedAssetType] = useState(null);
const [sortBy, setSortBy] = useState('cost');
const [assets, setAssets] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

setSortBy is never used, which will fail next lint (no-unused-vars). If sorting controls aren’t implemented yet, remove this state; otherwise add UI that updates sortBy.

Copilot uses AI. Check for mistakes.
Comment thread src/components/dashboard-view.js Outdated
Comment on lines +4 to +6
import { Button, Tile, OverflowMenu, OverflowMenuItem } from '@carbon/react';
import { ArrowLeft, OverflowMenuVertical, Edit, Share, Home, TrashCan, Filter } from '@carbon/icons-react';
import DashboardBuilder from './dashboard-builder';
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

Several imported icons (Share, Home, TrashCan) are not used, which will fail next lint (no-unused-vars). Remove unused imports or add UI that uses them.

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +12
} from '@carbon/react';
import { Close } from '@carbon/icons-react';
import { useDashboard } from './dashboard-context';
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

Close is imported but never used, which will fail next lint (no-unused-vars). Remove it, or add a close button that uses this icon.

Copilot uses AI. Check for mistakes.
Comment thread src/tempPages/ExternalCosts.js Outdated
Comment on lines +1 to +5
// import * as React from "react";
// import Page from "../components/Page";
// import Header from "../components/Header";
// import Footer from "../components/Footer";
// import IconButton from "@material-ui/core/IconButton";
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

This new file contains only commented-out legacy code and isn’t referenced anywhere (no tempPages imports). Keeping large commented blocks in the shipped codebase adds noise and maintenance cost; consider deleting these temp pages or moving the legacy code to git history/docs.

Copilot uses AI. Check for mistakes.
Comment thread src/css/index.css Outdated
Comment on lines +25 to +31
/* Custom styles for the new dashboard */
.dashboard-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
width: 100%;
}
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

This file adds dashboard styling that appears duplicated in src/app/globals.scss, and there are no references to src/css/index.css in the codebase after the Next.js migration. Consider deleting this stylesheet (or moving the remaining needed rules into globals.scss) to avoid dead/duplicated CSS.

Copilot uses AI. Check for mistakes.
Comment thread src/app/page.js Outdated
'use client';

import { useState } from 'react';
import { Button, Header, HeaderName, Tile, Tag } from '@carbon/react';
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

Tile is imported but never used, which will fail next lint (no-unused-vars). Remove it from the @carbon/react import.

Suggested change
import { Button, Header, HeaderName, Tile, Tag } from '@carbon/react';
import { Button, Header, HeaderName, Tag } from '@carbon/react';

Copilot uses AI. Check for mistakes.
Comment thread src/app/page.js Outdated
Comment on lines +123 to +127
<div
key={dashboard.id}
className="card-enhanced"
onClick={() => setSelectedDashboard(dashboard.id)}
style={{
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

This dashboard card is a clickable <div> without keyboard support, which is an accessibility issue. Use a semantic interactive element (e.g., Button, Link, or add role="button", tabIndex={0}, and keyboard handlers).

Copilot uses AI. Check for mistakes.
Comment thread netlify.toml Outdated
Comment on lines +3 to +6
publish = ".next"

[[plugins]]
package = "@netlify/plugin-nextjs" No newline at end of file
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

netlify.toml config references @netlify/plugin-nextjs, but the dependency isn’t present in package.json. Add it to devDependencies (or remove the plugin stanza) to avoid Netlify build failures.

Suggested change
publish = ".next"
[[plugins]]
package = "@netlify/plugin-nextjs"
publish = ".next"

Copilot uses AI. Check for mistakes.
Comment thread src/components/scoped-views.js Outdated
Comment on lines +3 to +5
import { useState } from 'react';
import { Tile, Button, Select, SelectItem, MultiSelect, TextInput, Tag } from '@carbon/react';
import { Filter, TrashCan, Save } from '@carbon/icons-react';
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

MultiSelect is imported but never used, which will fail next lint (no-unused-vars). Remove it from the import list or use it for one of the filters.

Copilot uses AI. Check for mistakes.
Comment thread package.json Outdated
Comment on lines +18 to +23
"@carbon/charts": "^1.13.0",
"@carbon/charts-react": "^1.13.0",
"@carbon/icons-react": "^11.14.0",
"@carbon/react": "1.36.0",
"next": "13.4.9",
"react": "18.2.0",
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

PR description says @carbon/react v1.35.0, but package.json pins @carbon/react to 1.36.0. Please update the PR description or align the version so the metadata matches what’s being shipped.

Copilot uses AI. Check for mistakes.
@aligon
Copy link
Copy Markdown

aligon commented Feb 25, 2026

I'm really liking the carbon look! Couple of quick thoughts:

  1. Can we move some of the app state (eg the active dashboard) into the URL, so that the user stays in the same place on a refresh and can easily share what they are seeing with someone else?
  2. What do you think about moving from Next.js to SPA with Vite + React Router? SSR can speed up load times, but it comes at a cost of increased server usage. Also it can be tricky to get the caching right for dynamic data like this. While a SPA is essentially infinites for rendering with the latest data.

maxvishy added 2 commits March 9, 2026 10:44
Signed-off-by: Vishy <maxvishy02@gmail.com>
- Updated Node version in .nvmrc to 20.
- Enhanced netlify.toml with environment variables for NODE_VERSION and VITE_BASE_API_URL.
- Refactored cost allocation chart and summary cards components to support additional props for aggregation and filtering.
- Improved dashboard builder and context to accommodate new widget configurations and filters.
- Updated API client to use environment variable for base URL.

These changes improve the flexibility and maintainability of the cost allocation features.

Signed-off-by: Vishy <maxvishy02@gmail.com>
@maxvishy maxvishy changed the title feat: migrate to Next.js and implement Carbon Design System dashboard feat: migrate to Vite + React Router and implement Carbon Design System dashboard Mar 10, 2026
Comment thread Dockerfile Outdated

RUN npx parcel build src/index.html --public-url ${UI_PATH}
ADD . ./
RUN npm run build
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.

add npm run build legacy underneath this

Comment thread Dockerfile
Comment thread Dockerfile
Comment thread vite.config.ts
Comment thread app/components/dashboard-builder.tsx Outdated
onClick={() => setSelectedWidget(widget)}
>
<div>
<h3 style={{ fontSize: "1rem", fontWeight: "600", marginBottom: "0.5rem" }}>{widget.title}</h3>
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.

use from carbon?

Cloud infrastructure costs over time
</p>
<CostByServiceChart />
</Tile>
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.

split out into components, add to registry by name? would allow easier contribution of widgets

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.

bonus - add editor into registry? to get widget inputs easier when building widgets

maxvishy added 12 commits March 16, 2026 12:52
- Updated NGINX configuration to use dynamic root paths based on LEGACY_MODE.
- Modified Docker entrypoint to set document root for legacy and default UIs.
- Enhanced Dockerfile to build both standard and legacy UIs, ensuring proper output verification.
- Added new build script in package.json for building both UIs in one command.
- Improved cost allocation chart component with additional props for better data handling.

These changes improve the application's flexibility in serving different UI versions and enhance the overall build process.

Signed-off-by: Vishy <maxvishy02@gmail.com>
- Removed the unnecessary `// @ts-nocheck` directive from SelectWindow.jsx to improve code quality and maintainability.

This change enhances the clarity of the code and ensures TypeScript checks are applied where applicable.
…PI client URL resolution

- Added support for using mock data in the AllocationService when the backend is unavailable, improving resilience during development.
- Refactored the API client to dynamically resolve the base URL from environment variables, enhancing flexibility for different deployment environments.
- Removed unused components and files to streamline the codebase.

These changes improve the application's robustness and maintainability.

Signed-off-by: Vishy <maxvishy02@gmail.com>
- Added new cloud cost widgets for displaying cloud service spend and utilization.
- Updated dashboard builder to include options for cloud costs table and chart.
- Introduced cloud filters in scoped views for better data aggregation and currency selection.
- Refactored widget renderer to accommodate new cloud cost components.

These changes improve the dashboard's functionality and user experience by providing more detailed insights into cloud costs.

Signed-off-by: Vishy <maxvishy02@gmail.com>
…services

- Implemented caching mechanism in AllocationService and CloudCostService to improve data retrieval efficiency.
- Added deduplication for in-flight requests to prevent redundant API calls.
- Refactored data fetching logic to utilize cached results, reducing load times and enhancing performance.
- Updated CostAllocationChart component to manage raw data separately, improving clarity and maintainability.

These changes significantly enhance the application's performance and user experience by optimizing data handling and reducing unnecessary API requests.

Signed-off-by: Vishy <maxvishy02@gmail.com>
Signed-off-by: Vishy <maxvishy02@gmail.com>
…er functionality

- Introduced FilterableWidgetHeader component for improved filter management across cost-related components.
- Updated CloudCostTableWidget, CloudCostWidget, CostAllocationChart, CostAllocationTable, and CostSummaryCards to utilize the new filterable header for better user experience.
- Implemented shared filter context for allocation and cloud cost components, allowing for consistent filter application across related widgets.
- Enhanced component props to support titles and descriptions for better context.

Signed-off-by: Vishy <maxvishy02@gmail.com>
… and sharing capabilities

- Added grid size selection for new widgets in the DashboardBuilder component, allowing users to customize widget width.
- Implemented sharing functionality in the DashboardView component, enabling users to copy a shareable link for dashboards.
- Updated DashboardList to handle shared dashboard imports, providing a modal for users to confirm importing shared configurations.
- Enhanced overall layout and styling for better user experience across dashboard components.

Signed-off-by: Vishy <maxvishy02@gmail.com>
- Added Tailwind CSS and its Vite plugin to the project for improved styling capabilities.
- Updated various components to utilize Tailwind classes for consistent styling and responsive design.
- Refactored layout and styling in the DashboardBuilder, DashboardView, and widget components to enhance user experience.
- Included Tailwind CSS configuration and stylesheets in the project.

Signed-off-by: Vishy <maxvishy02@gmail.com>
Signed-off-by: Vishy <maxvishy02@gmail.com>
…ard components

Signed-off-by: Vishy <maxvishy02@gmail.com>
@maxvishy maxvishy requested a review from Copilot March 24, 2026 15:04
@maxvishy
Copy link
Copy Markdown
Contributor Author

I’ve asked Copilot to review the code again, since a lot has changed.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 99 out of 109 changed files in this pull request and generated 11 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .env.example Outdated
Comment thread jsconfig.json
Comment thread app/routes/dashboard-list.tsx Outdated
Comment thread app/components/cost-summary-cards.tsx Outdated
Comment thread app/components/cost-allocation-chart.tsx Outdated
Comment thread default.nginx.conf.template
Comment thread app/components/external-services-chart-widget.tsx
Comment thread app/components/dashboard-view.tsx
Comment thread app/routes/dashboard-list.tsx Outdated
Comment thread Dockerfile
Comment on lines +1 to +8
FROM node:20-alpine AS builder
WORKDIR /opt/ui
ADD package*.json ./
RUN npm install
ADD src /opt/ui/src

ARG ui_path=/
ENV UI_PATH=${ui_path}

RUN npx parcel build src/index.html --public-url ${UI_PATH}
ADD . ./
# Save first build outside build/ so build:legacy (which overwrites build/) doesn't remove it
RUN npm run build && cp -r build/client /opt/standard
RUN npm run build:legacy
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

The image build runs npm run build/build:legacy without setting VITE_BASE_API_URL, so the resulting bundle will use whatever default is compiled in (currently the demo endpoint). If this image is intended for self-hosting, pass VITE_BASE_API_URL (e.g. /model) as a build arg/env before the build steps so the UI targets the in-container nginx proxy by default.

Copilot uses AI. Check for mistakes.
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.

@maxvishy I think we do want this, right? or will we default to local service by default via some other mechanism?

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.

We already default to local via VITE_BASE_API_URL || "/model" + nginx /model proxy, so behavior is correct now.

- Added currency selection to allocation filters, cost allocation chart, and cost allocation table components for improved flexibility.
- Updated value formatting in charts and tables to utilize the selected currency, enhancing user experience and data presentation.
- Refactored related components to ensure consistent currency handling across the application.

Signed-off-by: Vishy <maxvishy02@gmail.com>
Signed-off-by: Vishy <maxvishy02@gmail.com>
Comment thread app/components/legacy/Subtitle.jsx Outdated
// link: {
// cursor: "pointer",
// },
// });
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.

dead?

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.

fixed.

Comment thread app/components/legacy/Subtitle.jsx Outdated
// @ts-nocheck
import * as React from "react";
// import { makeStyles } from "@material-ui/styles";
// // import { makeStyles } from "@material-ui/styles";
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.

dead?

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.

fixed

Comment thread justfile Outdated
--rm \
--platform "linux/amd64" \
-f 'Dockerfile.cross' \
-f 'Dockerfile' \
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.

so, here you are now moving to an in-container compilation of the app, vs using the CI to build the app then bring it into the container. What was your thinking behind this change?

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.

That said, I see the benefit of the previous approach being faster.
Let me revert it

Comment thread jsconfig.json
Comment thread default.nginx.conf.template
Comment thread docker-entrypoint.sh Outdated
if [ -n "$BASE_URL_OVERRIDE" ]; then
echo "running with BASE_URL=${BASE_URL_OVERRIDE}"
sed -i "s^{PLACEHOLDER_BASE_URL}^$BASE_URL_OVERRIDE^g" /var/www/*.js
find "$WWW_ROOT" -name "*.js" -exec sed -i "s^{PLACEHOLDER_BASE_URL}^$BASE_URL_OVERRIDE^g" {} \; 2>/dev/null || true
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.

to you really want || true? wont that swallow errors?

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.

fixed

Comment thread Dockerfile
Comment on lines +1 to +8
FROM node:20-alpine AS builder
WORKDIR /opt/ui
ADD package*.json ./
RUN npm install
ADD src /opt/ui/src

ARG ui_path=/
ENV UI_PATH=${ui_path}

RUN npx parcel build src/index.html --public-url ${UI_PATH}
ADD . ./
# Save first build outside build/ so build:legacy (which overwrites build/) doesn't remove it
RUN npm run build && cp -r build/client /opt/standard
RUN npm run build:legacy
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.

@maxvishy I think we do want this, right? or will we default to local service by default via some other mechanism?

@@ -1,3 +1,4 @@
// @ts-nocheck
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

probably should avoid turning off type checking

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.

Comment thread app/components/assets-visualization.tsx Outdated
} from "./scoped-views";

function formatUtilPct(v: number | null): string {
return v === null ? "N/A" : `${v}%`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Should we use the Intl NumberFormat here?

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.

if (windowName === "" && checkCustomWindow(window)) {
windowName = toVerboseTimeRange(window) ?? window;
}
if (windowName === "") windowName = window;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Should we be running eslint/prettier? Some of the formatting seems a little off

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.

}, [chartData, currency]);

if (loading) {
return <div className="h-[400px] flex items-center justify-center text-[#8d8d8d]">Loading...</div>;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think Carbon has some loading/skeleton states that might be worth exploring

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.

Comment thread app/constants/colors.ts
@@ -0,0 +1,38 @@
import {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Any way we could grab these from carbon?

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.

done ✅

maxvishy added 3 commits April 1, 2026 10:26
- Changed BASE_API_URL to VITE_BASE_API_URL in .env.example for better compatibility with Vite.
- Updated NGINX configuration to use dynamic UI_PATH for serving the application, improving routing flexibility.
- Refactored Docker entrypoint script to replace placeholders in JavaScript files, enhancing deployment customization.
- Added new environment variable UI_PATH in Dockerfile for better configuration management.
- Updated package dependencies to include new versions of @carbon/colors and @mui/styles for improved styling capabilities.

Signed-off-by: Vishy <maxvishy02@gmail.com>
- Added support for drilldown filters and aggregate options in allocation filters context, cost allocation chart, and cost allocation table components.
- Updated state management to handle local and shared drilldown filters effectively.
- Refactored filter setting functions to reset drilldown states when filters are updated, improving user experience and consistency across components.

Signed-off-by: Vishy <maxvishy02@gmail.com>
Signed-off-by: Vishy <maxvishy02@gmail.com>
@ameijer ameijer merged commit 2fcf935 into opencost:main Apr 1, 2026
8 of 9 checks passed
@ameijer ameijer mentioned this pull request Apr 1, 2026
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.

4 participants