From ba1298792100ea0b809045fc52217a963911a9a8 Mon Sep 17 00:00:00 2001 From: MatthewHawkins Date: Thu, 14 Aug 2025 09:07:44 -0400 Subject: [PATCH 1/2] feat: switch to spring/spring boot --- webforj-dashboard/pom.xml | 204 +++++++++--------- .../dashboard/Application.java | 19 ++ .../dashboard/CryptocurrencyTable.java | 8 +- .../dashboard/config/DataInitializer.java | 114 ++++++++++ .../dashboard/models/Cryptocurrency.java | 28 +++ .../dashboard/models/NewsArticle.java | 24 +++ .../repository/CryptocurrencyRepository.java | 12 ++ .../dashboard/repository/NewsRepository.java | 11 + .../services/CryptocurrencyService.java | 93 +++++--- .../dashboard/services/NewsService.java | 20 +- .../dashboard/views/AboutView.java | 5 +- .../dashboard/views/DashboardView.java | 6 +- .../dashboard/views/MainLayout.java | 5 +- .../dashboard/views/NewsView.java | 5 +- .../src/main/resources/application.properties | 43 ++++ .../src/main/webapp/WEB-INF/web.xml | 13 -- 16 files changed, 454 insertions(+), 156 deletions(-) create mode 100644 webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/config/DataInitializer.java create mode 100644 webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/repository/CryptocurrencyRepository.java create mode 100644 webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/repository/NewsRepository.java create mode 100644 webforj-dashboard/src/main/resources/application.properties delete mode 100644 webforj-dashboard/src/main/webapp/WEB-INF/web.xml diff --git a/webforj-dashboard/pom.xml b/webforj-dashboard/pom.xml index c7bf5e6..a6c3097 100644 --- a/webforj-dashboard/pom.xml +++ b/webforj-dashboard/pom.xml @@ -3,40 +3,39 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - org.example + + + + + org.springframework.boot + spring-boot-starter-parent + 3.5.3 + + + com.webforj.builtwithwebforj webforj-dashboard webforj-dashboard 1.0-SNAPSHOT - war + + jar UTF-8 - 21 21 - - 25.02-SNAPSHOT - - 12.0.14 - - 0 - 8080 - 9966 + 25.03-SNAPSHOT - - snapshots-repo - https://s01.oss.sonatype.org/content/repositories/snapshots + + Central Portal Snapshots + central-portal-snapshots + https://central.sonatype.com/repository/maven-snapshots/ false + true @@ -62,88 +61,96 @@ + com.webforj webforj ${webforj.version} + + + + + com.webforj + webforj-spring-boot-starter + + + + + org.springframework.boot + spring-boot-starter-validation + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + + + com.h2database + h2 + runtime + + + + + com.webforj + webforj-spring-devtools + true + + + + + org.springframework.boot + spring-boot-devtools + true + + com.webforj webforj-googlecharts + - org.slf4j - slf4j-simple - 2.0.16 + org.springframework.boot + spring-boot-starter-test + test + + + com.vaadin.external.google + android-json + + - com.microsoft.playwright playwright 1.49.0 test - - org.junit.jupiter - junit-jupiter-api - test - + + spring-boot:run + + - org.apache.maven.plugins - maven-war-plugin - 3.4.0 + org.springframework.boot + spring-boot-maven-plugin - - - true - src/main/webapp - - **/web.xml - - - + + true - - org.eclipse.jetty.ee10 - jetty-ee10-maven-plugin - ${jetty.version} - - ${jetty.scan} - ${jetty.stopPort} - ${project.artifactId} - - ${jetty.port} - - - / - - - - - start-jetty - pre-integration-test - - start - - - - stop-jetty - post-integration-test - - stop - - - - - - + org.apache.maven.plugins maven-failsafe-plugin @@ -160,47 +167,38 @@ false - - - org.apache.maven.plugins - maven-antrun-plugin - 3.1.0 - - - copy-webforj-config - process-resources - - - - - - - run - - - - + prod - - - - webforj-prod.conf - + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + com.webforj + webforj-spring-devtools + + + + + + + dev true - - webforj-dev.conf - diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/Application.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/Application.java index a167de7..5beb6b7 100644 --- a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/Application.java +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/Application.java @@ -1,15 +1,34 @@ package com.webforj.builtwithwebforj.dashboard; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; import com.webforj.App; import com.webforj.annotation.AppProfile; import com.webforj.annotation.AppTheme; import com.webforj.annotation.Routify; import com.webforj.annotation.StyleSheet; +/** + * Main Spring Boot application class. + * + * @SpringBootApplication combines three annotations: + * - @Configuration: Marks this as a configuration class + * - @EnableAutoConfiguration: Enables Spring Boot's auto-configuration + * - @ComponentScan: Scans for Spring components in this package and below + */ +@SpringBootApplication @Routify(packages = "com.webforj.builtwithwebforj.dashboard.views") @StyleSheet("ws://app.css") @StyleSheet("ws://dashboard-view.css") @AppTheme("light") @AppProfile(name = "webforj-dashboard", shortName = "webforj-dashboard") public class Application extends App { + + /** + * Main method - Entry point for Spring Boot application. + * SpringApplication.run() bootstraps the Spring context and starts the embedded server. + */ + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } } diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/components/dashboard/CryptocurrencyTable.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/components/dashboard/CryptocurrencyTable.java index 54ed355..adf95c6 100644 --- a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/components/dashboard/CryptocurrencyTable.java +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/components/dashboard/CryptocurrencyTable.java @@ -47,17 +47,23 @@ private void initializeTable() { volumeColumn = table.addColumn("Volume (24h)", c -> FormatUtils.formatLargeNumber(c.getVolume24h())) .setSortable(true); table.addColumn("Price Chart", Cryptocurrency::getCurrentPrice) - .setRenderer(new PriceChartRenderer()); + .setRenderer(new PriceChartRenderer()) + .setResizable(true) + .setMovable(true); table.addColumn("PriceHistory", Cryptocurrency::getPriceHistoryJson) .setHidden(true); // Configure table properties table.setMultiSorting(true); table.setRowHeight(65); + table.setColumnsToMovable(true); + table.setColumnsToResizable(true); } public void setData(List cryptocurrencies) { table.setRepository(new CollectionRepository<>(cryptocurrencies)); + table.setColumnsToMovable(true); + table.setColumnsToResizable(true); } public CollectionRepository getRepository() { diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/config/DataInitializer.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/config/DataInitializer.java new file mode 100644 index 0000000..43ba4e1 --- /dev/null +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/config/DataInitializer.java @@ -0,0 +1,114 @@ +package com.webforj.builtwithwebforj.dashboard.config; + +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.webforj.builtwithwebforj.dashboard.models.Cryptocurrency; +import com.webforj.builtwithwebforj.dashboard.models.NewsArticle; +import com.webforj.builtwithwebforj.dashboard.repository.CryptocurrencyRepository; +import com.webforj.builtwithwebforj.dashboard.repository.NewsRepository; + +import java.util.Arrays; +import java.util.List; + +/** + * Data initializer that loads initial data into the database on application startup. + * + * @Component - Makes this a Spring-managed bean + * @Transactional - Ensures all database operations happen in a single transaction + * + * The constructor runs automatically when Spring creates this component, + * loading initial data into the H2 database. + */ +@Component +@Transactional +public class DataInitializer { + + private final CryptocurrencyRepository cryptoRepository; + private final NewsRepository newsRepository; + + // Constructor injection - Spring automatically provides the repositories + public DataInitializer(CryptocurrencyRepository cryptoRepository, + NewsRepository newsRepository) { + this.cryptoRepository = cryptoRepository; + this.newsRepository = newsRepository; + + // Initialize data when the component is created + initializeCryptocurrencies(); + initializeNews(); + } + + private void initializeCryptocurrencies() { + // Check if data already exists to avoid duplicates + if (cryptoRepository.count() > 0) { + return; + } + + // Sample cryptocurrency data + List cryptos = Arrays.asList( + new Cryptocurrency("BTC", "Bitcoin", 107356.60, 2140000000000.0, 13260000000.0, 1), + new Cryptocurrency("ETH", "Ethereum", 2638.47, 318750000000.0, 9350000000.0, 2), + new Cryptocurrency("USDT", "Tether", 1.00, 153010000000.0, 31500000000.0, 3), + new Cryptocurrency("XRP", "XRP", 2.26, 132940000000.0, 926830000.0, 4), + new Cryptocurrency("BNB", "BNB", 684.31, 98550000000.0, 461830000.0, 5), + new Cryptocurrency("SOL", "Solana", 170.49, 88770000000.0, 2220000000.0, 6), + new Cryptocurrency("USDC", "USDC", 1.00, 61370000000.0, 4980000000.0, 7), + new Cryptocurrency("DOGE", "Dogecoin", 0.22, 32900000000.0, 859790000.0, 8), + new Cryptocurrency("ADA", "Cardano", 0.74, 26380000000.0, 304620000.0, 9), + new Cryptocurrency("AVAX", "Avalanche", 23.04, 9710000000.0, 194480000.0, 10) + ); + + // Save all cryptocurrencies to database + cryptoRepository.saveAll(cryptos); + } + + private void initializeNews() { + // Check if data already exists + if (newsRepository.count() > 0) { + return; + } + + // Sample news articles + List articles = Arrays.asList( + new NewsArticle( + "Bitcoin Surges Past $107,000 as Institutional Interest Grows", + "Major financial institutions continue to show interest in Bitcoin as the cryptocurrency reaches new highs for the year.", + "CoinDesk", + "2 hours ago", + "https://example.com/bitcoin-surge", + "https://images.unsplash.com/photo-1639762681485-074b7f938ba0?w=400&h=250&fit=crop" + ), + new NewsArticle( + "Ethereum 2.0 Staking Reaches New Milestone", + "The Ethereum network sees record participation in staking as the ecosystem continues to evolve.", + "CryptoNews", + "4 hours ago", + "https://example.com/ethereum-staking" + ), + new NewsArticle( + "Federal Reserve Discusses Digital Dollar Progress", + "Central bank digital currency discussions intensify as the Fed releases new research on potential implementation.", + "Reuters", + "6 hours ago", + "https://example.com/fed-digital-dollar" + ), + new NewsArticle( + "DeFi Protocol Launches Revolutionary Lending Platform", + "New decentralized finance platform promises to transform how users interact with lending and borrowing services.", + "DeFi Times", + "8 hours ago", + "https://example.com/defi-launch" + ), + new NewsArticle( + "Crypto Market Analysis: Bulls Take Control", + "Technical indicators suggest continued positive momentum across major cryptocurrency markets.", + "TradingView", + "1 day ago", + "https://example.com/market-analysis" + ) + ); + + // Save all articles to database + newsRepository.saveAll(articles); + } +} \ No newline at end of file diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/models/Cryptocurrency.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/models/Cryptocurrency.java index 3d14320..e542cbc 100644 --- a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/models/Cryptocurrency.java +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/models/Cryptocurrency.java @@ -1,11 +1,22 @@ package com.webforj.builtwithwebforj.dashboard.models; +import jakarta.persistence.*; import java.util.ArrayList; import java.util.List; +@Entity +@Table(name = "cryptocurrencies") public class Cryptocurrency { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(unique = true, nullable = false) private String symbol; + + @Column(nullable = false) private String name; + private double currentPrice; private double previousPrice; private double priceChange24h; @@ -17,9 +28,18 @@ public class Cryptocurrency { private long totalSupply; private long circulatingSupply; private int rank; + + @ElementCollection(fetch = FetchType.EAGER) + @CollectionTable(name = "price_history", joinColumns = @JoinColumn(name = "crypto_id")) private List priceHistory; + private long lastUpdated; + public Cryptocurrency() { + // Default constructor required by JPA + this.priceHistory = new ArrayList<>(); + } + public Cryptocurrency(String symbol, String name, double currentPrice, double marketCap, double volume24h, int rank) { this.symbol = symbol; @@ -33,6 +53,14 @@ public Cryptocurrency(String symbol, String name, double currentPrice, double ma this.lastUpdated = System.currentTimeMillis(); } + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + public String getSymbol() { return symbol; } diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/models/NewsArticle.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/models/NewsArticle.java index 92cee01..0a6036c 100644 --- a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/models/NewsArticle.java +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/models/NewsArticle.java @@ -1,13 +1,29 @@ package com.webforj.builtwithwebforj.dashboard.models; +import jakarta.persistence.*; + +@Entity +@Table(name = "news_articles") public class NewsArticle { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) private String title; + + @Column(length = 1000) private String description; + private String source; private String timeAgo; private String url; private String imageUrl; + public NewsArticle() { + // Default constructor required by JPA + } + public NewsArticle(String title, String description, String source, String timeAgo, String url) { this.title = title; this.description = description; @@ -25,6 +41,14 @@ public NewsArticle(String title, String description, String source, String timeA this.imageUrl = imageUrl; } + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + public String getTitle() { return title; } diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/repository/CryptocurrencyRepository.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/repository/CryptocurrencyRepository.java new file mode 100644 index 0000000..a24dfd0 --- /dev/null +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/repository/CryptocurrencyRepository.java @@ -0,0 +1,12 @@ +package com.webforj.builtwithwebforj.dashboard.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.webforj.builtwithwebforj.dashboard.models.Cryptocurrency; + +@Repository +public interface CryptocurrencyRepository extends JpaRepository { + // JpaRepository provides all basic CRUD operations automatically: + // save(), findAll(), findById(), deleteById(), etc. +} \ No newline at end of file diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/repository/NewsRepository.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/repository/NewsRepository.java new file mode 100644 index 0000000..25aca89 --- /dev/null +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/repository/NewsRepository.java @@ -0,0 +1,11 @@ +package com.webforj.builtwithwebforj.dashboard.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.webforj.builtwithwebforj.dashboard.models.NewsArticle; + +@Repository +public interface NewsRepository extends JpaRepository { + // JpaRepository provides all basic CRUD operations automatically +} \ No newline at end of file diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/CryptocurrencyService.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/CryptocurrencyService.java index a1b50c7..d40406f 100644 --- a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/CryptocurrencyService.java +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/CryptocurrencyService.java @@ -4,10 +4,22 @@ import java.util.List; import java.util.Random; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + import com.webforj.builtwithwebforj.dashboard.models.Cryptocurrency; +import com.webforj.builtwithwebforj.dashboard.repository.CryptocurrencyRepository; +@Service public class CryptocurrencyService { + private final CryptocurrencyRepository repository; + + @Autowired + public CryptocurrencyService(CryptocurrencyRepository repository) { + this.repository = repository; + } + private final String[][] CRYPTO_DATA = { { "BTC", "Bitcoin", "107356.60", "2140000000000", "13260000000" }, { "ETH", "Ethereum", "2638.47", "318750000000", "9350000000" }, @@ -53,32 +65,56 @@ public class CryptocurrencyService { private Random random = new Random(); public List generateCryptocurrencies() { - List cryptocurrencies = new ArrayList<>(); - - for (int i = 0; i < CRYPTO_DATA.length; i++) { - String[] data = CRYPTO_DATA[i]; - double basePrice = Double.parseDouble(data[2]); - double marketCap = Double.parseDouble(data[3]); - double volume = Double.parseDouble(data[4]); - - // Add some initial price variation - double initialVariation = 0.95 + (random.nextDouble() * 0.1); // -5% to +5% - double currentPrice = basePrice * initialVariation; - - Cryptocurrency crypto = new Cryptocurrency( - data[0], // symbol - data[1], // name - currentPrice, - marketCap, - volume, - i + 1 // rank - ); - - // Set additional fields - crypto.setHigh24h(currentPrice * (1 + random.nextDouble() * 0.05)); - crypto.setLow24h(currentPrice * (1 - random.nextDouble() * 0.05)); - crypto.setCirculatingSupply((long) (marketCap / currentPrice)); - crypto.setTotalSupply((long) (crypto.getCirculatingSupply() * (1.1 + random.nextLong() * 0.3))); + // Fetch all cryptocurrencies from the database + List cryptocurrencies = repository.findAll(); + + // Convert to detached entities for real-time updates (copy constructor approach) + List detachedCryptos = new ArrayList<>(); + for (Cryptocurrency crypto : cryptocurrencies) { + Cryptocurrency detached = new Cryptocurrency(crypto.getSymbol(), crypto.getName(), + crypto.getCurrentPrice(), crypto.getMarketCap(), + crypto.getVolume24h(), crypto.getRank()); + // Copy other properties + detached.setId(crypto.getId()); + detached.setHigh24h(crypto.getHigh24h()); + detached.setLow24h(crypto.getLow24h()); + detached.setCirculatingSupply(crypto.getCirculatingSupply()); + detached.setTotalSupply(crypto.getTotalSupply()); + detached.setPriceChangePercentage24h(crypto.getPriceChangePercentage24h()); + detached.setPriceChange24h(crypto.getPriceChange24h()); + + // Create new ArrayList for price history to avoid Hibernate proxy issues + detached.setPriceHistory(new ArrayList<>(crypto.getPriceHistory())); + + detachedCryptos.add(detached); + } + + // If database is empty, create some data on the fly (fallback) + if (detachedCryptos.isEmpty()) { + for (int i = 0; i < Math.min(CRYPTO_DATA.length, 10); i++) { + String[] data = CRYPTO_DATA[i]; + double basePrice = Double.parseDouble(data[2]); + double marketCap = Double.parseDouble(data[3]); + double volume = Double.parseDouble(data[4]); + + // Add some initial price variation + double initialVariation = 0.95 + (random.nextDouble() * 0.1); // -5% to +5% + double currentPrice = basePrice * initialVariation; + + Cryptocurrency crypto = new Cryptocurrency( + data[0], // symbol + data[1], // name + currentPrice, + marketCap, + volume, + i + 1 // rank + ); + + // Set additional fields + crypto.setHigh24h(currentPrice * (1 + random.nextDouble() * 0.05)); + crypto.setLow24h(currentPrice * (1 - random.nextDouble() * 0.05)); + crypto.setCirculatingSupply((long) (marketCap / currentPrice)); + crypto.setTotalSupply((long) (crypto.getCirculatingSupply() * (1.1 + random.nextDouble() * 0.3))); // Generate initial price history List history = new ArrayList<>(); @@ -94,10 +130,11 @@ public List generateCryptocurrencies() { crypto.setPriceChangePercentage24h(change24h); crypto.setPriceChange24h(currentPrice - basePrice); - cryptocurrencies.add(crypto); + detachedCryptos.add(crypto); + } } - return cryptocurrencies; + return detachedCryptos; } public void updatePrices(List cryptocurrencies) { diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/NewsService.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/NewsService.java index 17bfdeb..fd27099 100644 --- a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/NewsService.java +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/NewsService.java @@ -3,12 +3,29 @@ import java.util.ArrayList; import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + import com.webforj.builtwithwebforj.dashboard.models.NewsArticle; +import com.webforj.builtwithwebforj.dashboard.repository.NewsRepository; +@Service public class NewsService { + private final NewsRepository repository; + + @Autowired + public NewsService(NewsRepository repository) { + this.repository = repository; + } + public List getMockCryptoNews() { - List articles = new ArrayList<>(); + // Try to get news from database first + List articles = repository.findAll(); + + // If database is empty, return some fallback data + if (articles.isEmpty()) { + articles = new ArrayList<>(); articles.add(new NewsArticle( "Bitcoin Surges Past $50,000 as Institutional Interest Grows", @@ -81,6 +98,7 @@ public List getMockCryptoNews() { "https://example.com/digital-euro", "https://images.unsplash.com/photo-1566228015668-4c45dbc4e2f5?w=400&h=250&fit=crop" )); + } return articles; } diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/AboutView.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/AboutView.java index 8cf3736..e197c81 100644 --- a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/AboutView.java +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/AboutView.java @@ -16,7 +16,6 @@ import com.webforj.component.layout.flexlayout.FlexWrap; import com.webforj.router.annotation.FrameTitle; import com.webforj.router.annotation.Route; -import com.webforj.component.Component; @Route(value = "about", outlet = MainLayout.class) @StyleSheet("ws://about-view.css") @@ -217,7 +216,7 @@ private void createGitHubSection() { } - private Component createAppCard(String title, String description, String icon, String url) { + private Div createAppCard(String title, String description, String icon, String url) { Div card = new Div(); card.addClassName("about-view__card about-view__app-card about-view__card--clickable"); card.onClick(e -> Page.getCurrent().open(url, "_blank")); @@ -240,7 +239,7 @@ private Component createAppCard(String title, String description, String icon, S return card; } - private Component createContributeCard() { + private Div createContributeCard() { Div card = new Div(); card.addClassName("about-view__card about-view__app-card about-view__card--clickable"); card.onClick(e -> Page.getCurrent().open("https://github.com/webforj/built-with-webforj", "_blank")); diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/DashboardView.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/DashboardView.java index c5e28c3..661ebda 100644 --- a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/DashboardView.java +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/DashboardView.java @@ -21,7 +21,7 @@ @FrameTitle("Cryptocurrency Dashboard") public class DashboardView extends Composite implements ChartRedrawable { private final FlexLayout self = getBoundComponent(); - private final CryptocurrencyService cryptoService = new CryptocurrencyService(); + private final CryptocurrencyService cryptoService; private final DashboardChartBuilder chartBuilder = new DashboardChartBuilder(); private CryptocurrencyTable cryptoTable; private DashboardToolbar toolbar; @@ -31,7 +31,8 @@ public class DashboardView extends Composite implements ChartRedrawa private DashboardCard card2; private DashboardCard card3; - public DashboardView() { + public DashboardView(CryptocurrencyService cryptoService) { + this.cryptoService = cryptoService; self.addClassName("dashboard-view"); self.setDirection(FlexDirection.COLUMN); @@ -44,6 +45,7 @@ public DashboardView() { // Generate and set data cryptocurrencies = cryptoService.generateCryptocurrencies(); cryptoTable.setData(cryptocurrencies); + // Create dashboard cards using the new architecture card1 = createCard("Global Market Cap", 2875000000000.0, 3.45, GoogleChart.Type.AREA); diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/MainLayout.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/MainLayout.java index 499a224..30e9ec1 100644 --- a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/MainLayout.java +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/MainLayout.java @@ -8,7 +8,6 @@ import com.webforj.builtwithwebforj.dashboard.components.DrawerFooter; import com.webforj.builtwithwebforj.dashboard.components.DrawerLogo; import com.webforj.builtwithwebforj.dashboard.utils.charts.ChartRedrawable; -import com.webforj.component.Component; import com.webforj.component.Composite; import com.webforj.component.html.elements.H1; import com.webforj.component.html.elements.Div; @@ -165,8 +164,8 @@ private void setNavDrawer() { } private void onNavigate(NavigateEvent ev) { - Set components = ev.getContext().getAllComponents(); - Component view = components.stream().filter(c -> c.getClass().getSimpleName().endsWith("View")).findFirst() + Set components = ev.getContext().getAllComponents(); + com.webforj.component.Component view = components.stream().filter(c -> c.getClass().getSimpleName().endsWith("View")).findFirst() .orElse(null); if (view != null) { diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/NewsView.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/NewsView.java index 194363e..bce546b 100644 --- a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/NewsView.java +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/NewsView.java @@ -40,7 +40,7 @@ public class NewsView extends Composite { private static final int POPULAR_ARTICLES_LIMIT = 4; private static final int MAIN_ARTICLES_LIMIT = 6; private final FlexLayout self = getBoundComponent(); - private final NewsService newsService = new NewsService(); + private final NewsService newsService; private List allArticles; private FlexLayout mainContentArea; private FlexLayout sidebarArea; @@ -48,7 +48,8 @@ public class NewsView extends Composite { private FlexLayout articlesGrid; private FlexLayout articlesContainer; - public NewsView() { + public NewsView(NewsService newsService) { + this.newsService = newsService; self.addClassName("news-view") .setDirection(FlexDirection.COLUMN) .setSpacing("var(--dwc-space-xl)"); diff --git a/webforj-dashboard/src/main/resources/application.properties b/webforj-dashboard/src/main/resources/application.properties new file mode 100644 index 0000000..731dc55 --- /dev/null +++ b/webforj-dashboard/src/main/resources/application.properties @@ -0,0 +1,43 @@ +# Spring Boot Application Configuration +# This file configures Spring Boot's behavior and features + +# Application name - used in logs and monitoring +spring.application.name=webforj-dashboard + +# Server configuration +# Immediate shutdown allows the app to stop quickly during development +server.shutdown=immediate + +# DevTools configuration +# spring.devtools.livereload.enabled=false because webforJ has its own livereload +spring.devtools.livereload.enabled=false +# webforJ's livereload system - better integrated with webforJ components +webforj.devtools.livereload.enabled=true +webforj.devtools.livereload.static-resources-enabled=true + +# H2 Database Configuration +# jdbc:h2:mem:dashboarddb - Creates an in-memory database named "dashboarddb" +# Data is lost when the application stops (perfect for demo/development) +spring.datasource.url=jdbc:h2:mem:dashboarddb +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password= + +# JPA/Hibernate Configuration +# H2Dialect tells Hibernate to use H2-specific SQL syntax +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect +# update: Hibernate will update the database schema based on entity classes +# Other options: create (drop and create), create-drop, validate, none +spring.jpa.hibernate.ddl-auto=update +# Show SQL queries in console (useful for development/debugging) +spring.jpa.show-sql=false + +# H2 Web Console - Provides a web UI to inspect the database +# Access at http://localhost:8080/h2-console when the app is running +spring.h2.console.enabled=true +spring.h2.console.path=/h2-console + +# Logging configuration (optional) +# Set to DEBUG to see more Spring Boot startup information +logging.level.com.webforj.builtwithwebforj.dashboard=INFO +logging.level.org.springframework.web=INFO \ No newline at end of file diff --git a/webforj-dashboard/src/main/webapp/WEB-INF/web.xml b/webforj-dashboard/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index e33890c..0000000 --- a/webforj-dashboard/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - ${project.name} - - WebforjServlet - com.webforj.servlet.WebforjServlet - 1 - - - WebforjServlet - /* - - From 9a82380eb81a2a259548d8de3f1aaa77750a2a7b Mon Sep 17 00:00:00 2001 From: MatthewHawkins Date: Fri, 15 Aug 2025 10:58:49 -0400 Subject: [PATCH 2/2] chore: cleaning unused code --- .../dashboard/components/news/NewsCard.java | 18 +- .../dashboard/config/DataInitializer.java | 172 +++++++++--------- .../services/CryptocurrencyService.java | 87 --------- .../dashboard/services/NewsService.java | 85 +-------- .../dashboard/views/NewsView.java | 4 +- 5 files changed, 97 insertions(+), 269 deletions(-) diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/components/news/NewsCard.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/components/news/NewsCard.java index d525919..e00758a 100644 --- a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/components/news/NewsCard.java +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/components/news/NewsCard.java @@ -13,24 +13,16 @@ public class NewsCard extends Composite { private FlexLayout self = getBoundComponent(); - // Stock images for crypto/finance news - private static final String[] STOCK_IMAGES = { - "https://images.unsplash.com/photo-1611974789855-9c2a0a7236a3?w=400&h=200&fit=crop", - "https://images.unsplash.com/photo-1639762681485-074b7f938ba0?w=400&h=200&fit=crop", - "https://images.unsplash.com/photo-1640340434855-6084b1f4901c?w=400&h=200&fit=crop", - "https://images.unsplash.com/photo-1640826843968-011c0d0c4fbb?w=400&h=200&fit=crop", - "https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=200&fit=crop" - }; - - public NewsCard(String title, String description, String source, String timeAgo, String url) { + public NewsCard(String title, String description, String source, String timeAgo, String url, String imageUrl) { self.addClassName("news-card") .setDirection(FlexDirection.COLUMN) .setSpacing("var(--dwc-space-m)"); - // Add image (random stock image) + // Add image Div imageDiv = new Div(); imageDiv.addClassName("news-image"); - String imageUrl = STOCK_IMAGES[(int) (Math.random() * STOCK_IMAGES.length)]; - imageDiv.setStyle("background-image", "url('" + imageUrl + "')"); + if (imageUrl != null && !imageUrl.isEmpty()) { + imageDiv.setStyle("background-image", "url('" + imageUrl + "')"); + } // Content container FlexLayout contentDiv = new FlexLayout(); diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/config/DataInitializer.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/config/DataInitializer.java index 43ba4e1..64653a1 100644 --- a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/config/DataInitializer.java +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/config/DataInitializer.java @@ -12,103 +12,107 @@ import java.util.List; /** - * Data initializer that loads initial data into the database on application startup. + * Data initializer that loads initial data into the database on application + * startup. * * @Component - Makes this a Spring-managed bean - * @Transactional - Ensures all database operations happen in a single transaction + * @Transactional - Ensures all database operations happen in a single + * transaction * - * The constructor runs automatically when Spring creates this component, - * loading initial data into the H2 database. + * The constructor runs automatically when Spring creates this + * component, + * loading initial data into the H2 database. */ @Component @Transactional public class DataInitializer { - private final CryptocurrencyRepository cryptoRepository; - private final NewsRepository newsRepository; + private final CryptocurrencyRepository cryptoRepository; + private final NewsRepository newsRepository; - // Constructor injection - Spring automatically provides the repositories - public DataInitializer(CryptocurrencyRepository cryptoRepository, - NewsRepository newsRepository) { - this.cryptoRepository = cryptoRepository; - this.newsRepository = newsRepository; - - // Initialize data when the component is created - initializeCryptocurrencies(); - initializeNews(); - } + // Constructor injection - Spring automatically provides the repositories + public DataInitializer(CryptocurrencyRepository cryptoRepository, + NewsRepository newsRepository) { + this.cryptoRepository = cryptoRepository; + this.newsRepository = newsRepository; - private void initializeCryptocurrencies() { - // Check if data already exists to avoid duplicates - if (cryptoRepository.count() > 0) { - return; - } + // Initialize data when the component is created + initializeCryptocurrencies(); + initializeNews(); + } - // Sample cryptocurrency data - List cryptos = Arrays.asList( - new Cryptocurrency("BTC", "Bitcoin", 107356.60, 2140000000000.0, 13260000000.0, 1), - new Cryptocurrency("ETH", "Ethereum", 2638.47, 318750000000.0, 9350000000.0, 2), - new Cryptocurrency("USDT", "Tether", 1.00, 153010000000.0, 31500000000.0, 3), - new Cryptocurrency("XRP", "XRP", 2.26, 132940000000.0, 926830000.0, 4), - new Cryptocurrency("BNB", "BNB", 684.31, 98550000000.0, 461830000.0, 5), - new Cryptocurrency("SOL", "Solana", 170.49, 88770000000.0, 2220000000.0, 6), - new Cryptocurrency("USDC", "USDC", 1.00, 61370000000.0, 4980000000.0, 7), - new Cryptocurrency("DOGE", "Dogecoin", 0.22, 32900000000.0, 859790000.0, 8), - new Cryptocurrency("ADA", "Cardano", 0.74, 26380000000.0, 304620000.0, 9), - new Cryptocurrency("AVAX", "Avalanche", 23.04, 9710000000.0, 194480000.0, 10) - ); + private void initializeCryptocurrencies() { + // Check if data already exists to avoid duplicates + if (cryptoRepository.count() > 0) { + return; + } - // Save all cryptocurrencies to database - cryptoRepository.saveAll(cryptos); - } + // Sample cryptocurrency data + List cryptos = Arrays.asList( + new Cryptocurrency("BTC", "Bitcoin", 107356.60, 2140000000000.0, 13260000000.0, 1), + new Cryptocurrency("ETH", "Ethereum", 2638.47, 318750000000.0, 9350000000.0, 2), + new Cryptocurrency("USDT", "Tether", 1.00, 153010000000.0, 31500000000.0, 3), + new Cryptocurrency("XRP", "XRP", 2.26, 132940000000.0, 926830000.0, 4), + new Cryptocurrency("BNB", "BNB", 684.31, 98550000000.0, 461830000.0, 5), + new Cryptocurrency("SOL", "Solana", 170.49, 88770000000.0, 2220000000.0, 6), + new Cryptocurrency("USDC", "USDC", 1.00, 61370000000.0, 4980000000.0, 7), + new Cryptocurrency("DOGE", "Dogecoin", 0.22, 32900000000.0, 859790000.0, 8), + new Cryptocurrency("ADA", "Cardano", 0.74, 26380000000.0, 304620000.0, 9), + new Cryptocurrency("AVAX", "Avalanche", 23.04, 9710000000.0, 194480000.0, 10)); - private void initializeNews() { - // Check if data already exists - if (newsRepository.count() > 0) { - return; - } + // Save all cryptocurrencies to database + cryptoRepository.saveAll(cryptos); + } - // Sample news articles - List articles = Arrays.asList( - new NewsArticle( - "Bitcoin Surges Past $107,000 as Institutional Interest Grows", - "Major financial institutions continue to show interest in Bitcoin as the cryptocurrency reaches new highs for the year.", - "CoinDesk", - "2 hours ago", - "https://example.com/bitcoin-surge", - "https://images.unsplash.com/photo-1639762681485-074b7f938ba0?w=400&h=250&fit=crop" - ), - new NewsArticle( - "Ethereum 2.0 Staking Reaches New Milestone", - "The Ethereum network sees record participation in staking as the ecosystem continues to evolve.", - "CryptoNews", - "4 hours ago", - "https://example.com/ethereum-staking" - ), - new NewsArticle( - "Federal Reserve Discusses Digital Dollar Progress", - "Central bank digital currency discussions intensify as the Fed releases new research on potential implementation.", - "Reuters", - "6 hours ago", - "https://example.com/fed-digital-dollar" - ), - new NewsArticle( - "DeFi Protocol Launches Revolutionary Lending Platform", - "New decentralized finance platform promises to transform how users interact with lending and borrowing services.", - "DeFi Times", - "8 hours ago", - "https://example.com/defi-launch" - ), - new NewsArticle( - "Crypto Market Analysis: Bulls Take Control", - "Technical indicators suggest continued positive momentum across major cryptocurrency markets.", - "TradingView", - "1 day ago", - "https://example.com/market-analysis" - ) - ); + private void initializeNews() { + // Check if data already exists + if (newsRepository.count() > 0) { + return; + } - // Save all articles to database - newsRepository.saveAll(articles); - } + // Sample news articles + List articles = Arrays.asList( + new NewsArticle( + "Bitcoin Surges Past $107,000 as Institutional Interest Grows", + "Major financial institutions continue to show interest in Bitcoin as the cryptocurrency reaches new highs for the year.", + "CoinDesk", + "2 hours ago", + "https://example.com/bitcoin-surge", + "https://images.unsplash.com/photo-1639762681485-074b7f938ba0?w=400&h=250&fit=crop"), + new NewsArticle( + "Ethereum 2.0 Staking Reaches New Milestone", + "The Ethereum network sees record participation in staking as the ecosystem continues to evolve.", + "CryptoNews", + "4 hours ago", + "https://example.com/ethereum-staking", + "https://images.unsplash.com/photo-1611974789855-9c2a0a7236a3?w=400&h=200&fit=crop"), + new NewsArticle( + "Federal Reserve Discusses Digital Dollar Progress", + "Central bank digital currency discussions intensify as the Fed releases new research on potential implementation.", + "Reuters", + "6 hours ago", + "https://example.com/fed-digital-dollar", + "https://images.unsplash.com/photo-1640340434855-6084b1f4901c?w=400&h=200&fit=crop" + + ), + new NewsArticle( + "DeFi Protocol Launches Revolutionary Lending Platform", + "New decentralized finance platform promises to transform how users interact with lending and borrowing services.", + "DeFi Times", + "8 hours ago", + "https://example.com/defi-launch", + "https://images.unsplash.com/photo-1640826843968-011c0d0c4fbb?w=400&h=200&fit=crop" + + ), + new NewsArticle( + "Crypto Market Analysis: Bulls Take Control", + "Technical indicators suggest continued positive momentum across major cryptocurrency markets.", + "TradingView", + "1 day ago", + "https://example.com/market-analysis", + "https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=200&fit=crop")); + + // Save all articles to database + newsRepository.saveAll(articles); + } } \ No newline at end of file diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/CryptocurrencyService.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/CryptocurrencyService.java index d40406f..1fb8b1a 100644 --- a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/CryptocurrencyService.java +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/CryptocurrencyService.java @@ -20,48 +20,6 @@ public CryptocurrencyService(CryptocurrencyRepository repository) { this.repository = repository; } - private final String[][] CRYPTO_DATA = { - { "BTC", "Bitcoin", "107356.60", "2140000000000", "13260000000" }, - { "ETH", "Ethereum", "2638.47", "318750000000", "9350000000" }, - { "USDT", "Tether", "1.00", "153010000000", "31500000000" }, - { "XRP", "XRP", "2.26", "132940000000", "926830000" }, - { "BNB", "BNB", "684.31", "98550000000", "461830000" }, - { "SOL", "Solana", "170.49", "88770000000", "2220000000" }, - { "USDC", "USDC", "1.00", "61370000000", "4980000000" }, - { "DOGE", "Dogecoin", "0.22", "32900000000", "859790000" }, - { "ADA", "Cardano", "0.74", "26380000000", "304620000" }, - { "STETH", "Lido Staked ETH", "2634.67", "23730000000", "8930000" }, - { "WBTC", "Wrapped Bitcoin", "107369.39", "13850000000", "96940000" }, - { "HYPE", "Hyperliquid", "34.49", "11570000000", "239100000" }, - { "LINK", "Chainlink", "15.48", "10180000000", "175310000" }, - { "AVAX", "Avalanche", "23.04", "9710000000", "194480000" }, - { "WETH", "Wrapped ETH", "2638.47", "8910000000", "547080000" }, - { "XLM", "Stellar", "0.28", "8810000000", "91290000" }, - { "TON", "Toncoin", "3.35", "8380000000", "569210000" }, - { "SHIB", "Shiba Inu", "0.000014", "8320000000", "83840000" }, - { "HBAR", "Hedera", "0.18", "7760000000", "52380000" }, - { "BTCB", "Bitcoin BEP2", "107281.09", "7010000000", "20830000" }, - { "DOT", "Polkadot", "4.51", "6870000000", "110420000" }, - { "PEPE", "Pepe", "0.000013", "5750000000", "825540000" }, - { "DAI", "Dai", "0.99", "5370000000", "57180000" }, - { "USDE", "Ethena USDe", "1.00", "5220000000", "30260000" }, - { "AAVE", "Aave", "264.11", "4000000000", "176990000" }, - { "NEAR", "Near Protocol", "2.80", "3410000000", "89760000" }, - { "OKB", "OKB", "51.95", "3120000000", "1910000" }, - { "ONDO", "Ondo", "0.92", "2930000000", "109190000" }, - { "CRO", "Cronos", "0.096", "2570000000", "12380000" }, - { "GT", "GateToken", "20.46", "2520000000", "10560000" }, - { "MNT", "Mantle", "0.72", "2440000000", "109680000" }, - { "VET", "VeChain", "0.026", "2320000000", "26540000" }, - { "RENDER", "Render", "4.37", "2260000000", "160830000" }, - { "FIL", "Filecoin", "2.82", "1900000000", "84930000" }, - { "ALGO", "Algorand", "0.21", "1860000000", "32050000" }, - { "ATOM", "Cosmos", "4.72", "1850000000", "69970000" }, - { "JUP", "Jupiter", "0.59", "1730000000", "45070000" }, - { "FDUSD", "First Digital USD", "0.99", "1620000000", "3950000000" }, - { "BONK", "Bonk", "0.000019", "1540000000", "113550000" } - }; - private Random random = new Random(); public List generateCryptocurrencies() { @@ -88,51 +46,6 @@ public List generateCryptocurrencies() { detachedCryptos.add(detached); } - - // If database is empty, create some data on the fly (fallback) - if (detachedCryptos.isEmpty()) { - for (int i = 0; i < Math.min(CRYPTO_DATA.length, 10); i++) { - String[] data = CRYPTO_DATA[i]; - double basePrice = Double.parseDouble(data[2]); - double marketCap = Double.parseDouble(data[3]); - double volume = Double.parseDouble(data[4]); - - // Add some initial price variation - double initialVariation = 0.95 + (random.nextDouble() * 0.1); // -5% to +5% - double currentPrice = basePrice * initialVariation; - - Cryptocurrency crypto = new Cryptocurrency( - data[0], // symbol - data[1], // name - currentPrice, - marketCap, - volume, - i + 1 // rank - ); - - // Set additional fields - crypto.setHigh24h(currentPrice * (1 + random.nextDouble() * 0.05)); - crypto.setLow24h(currentPrice * (1 - random.nextDouble() * 0.05)); - crypto.setCirculatingSupply((long) (marketCap / currentPrice)); - crypto.setTotalSupply((long) (crypto.getCirculatingSupply() * (1.1 + random.nextDouble() * 0.3))); - - // Generate initial price history - List history = new ArrayList<>(); - double historyPrice = currentPrice * 0.95; - for (int j = 0; j < 20; j++) { - historyPrice = historyPrice * (0.98 + random.nextDouble() * 0.04); - history.add(historyPrice); - } - crypto.setPriceHistory(history); - - // Set initial 24h change - double change24h = (currentPrice - basePrice) / basePrice * 100; - crypto.setPriceChangePercentage24h(change24h); - crypto.setPriceChange24h(currentPrice - basePrice); - - detachedCryptos.add(crypto); - } - } return detachedCryptos; } diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/NewsService.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/NewsService.java index fd27099..035f73c 100644 --- a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/NewsService.java +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/services/NewsService.java @@ -1,6 +1,5 @@ package com.webforj.builtwithwebforj.dashboard.services; -import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; @@ -19,87 +18,7 @@ public NewsService(NewsRepository repository) { this.repository = repository; } - public List getMockCryptoNews() { - // Try to get news from database first - List articles = repository.findAll(); - - // If database is empty, return some fallback data - if (articles.isEmpty()) { - articles = new ArrayList<>(); - - articles.add(new NewsArticle( - "Bitcoin Surges Past $50,000 as Institutional Interest Grows", - "Major financial institutions continue to show interest in Bitcoin as the cryptocurrency reaches new highs for the year. Analysts point to growing adoption and regulatory clarity.", - "CoinDesk", - "2 hours ago", - "https://example.com/bitcoin-surge", - "https://images.unsplash.com/photo-1639762681485-074b7f938ba0?w=400&h=250&fit=crop" - )); - - articles.add(new NewsArticle( - "Ethereum 2.0 Staking Hits New Milestone", - "The Ethereum network has reached a new all-time high in staked ETH, with over 28 million ETH now locked in staking contracts, representing significant confidence in the network's future.", - "The Block", - "4 hours ago", - "https://example.com/ethereum-staking", - "https://images.unsplash.com/photo-1621761191319-c6fb62004040?w=400&h=250&fit=crop" - )); - - articles.add(new NewsArticle( - "SEC Approves First Spot Bitcoin ETF Applications", - "In a landmark decision, the Securities and Exchange Commission has approved multiple spot Bitcoin ETF applications, marking a significant milestone for cryptocurrency adoption.", - "Reuters", - "6 hours ago", - "https://example.com/sec-bitcoin-etf", - "https://images.unsplash.com/photo-1560472354-b33ff0c44a43?w=400&h=250&fit=crop" - )); - - articles.add(new NewsArticle( - "Solana Network Sees Record Transaction Volume", - "The Solana blockchain processed over 65 million transactions in a single day, showcasing the network's scalability and growing ecosystem of decentralized applications.", - "CryptoSlate", - "8 hours ago", - "https://example.com/solana-record", - "https://images.unsplash.com/photo-1559526324-4b87b5e36e44?w=400&h=250&fit=crop" - )); - - articles.add(new NewsArticle( - "Major Bank Launches Cryptocurrency Custody Service", - "One of the world's largest banks announced the launch of its digital asset custody service, catering to institutional clients looking to securely store cryptocurrencies.", - "Bloomberg", - "12 hours ago", - "https://example.com/bank-crypto-custody", - "https://images.unsplash.com/photo-1560472355-536de3962603?w=400&h=250&fit=crop" - )); - - articles.add(new NewsArticle( - "DeFi Protocol TVL Reaches $100 Billion", - "The total value locked in decentralized finance protocols has surpassed $100 billion, indicating renewed confidence in the DeFi sector after recent market volatility.", - "DeFi Pulse", - "1 day ago", - "https://example.com/defi-tvl", - "https://images.unsplash.com/photo-1611974789855-9c2a0a7236a3?w=400&h=250&fit=crop" - )); - - articles.add(new NewsArticle( - "Ripple Wins Key Legal Battle Against SEC", - "In a significant development, Ripple Labs has won a crucial legal victory in its ongoing case with the SEC, with implications for the broader cryptocurrency industry.", - "Forbes", - "1 day ago", - "https://example.com/ripple-sec", - "https://images.unsplash.com/photo-1518546305927-5a555bb7020d?w=400&h=250&fit=crop" - )); - - articles.add(new NewsArticle( - "Central Bank Digital Currency Pilot Launches in Europe", - "The European Central Bank has begun its pilot program for a digital euro, testing the infrastructure needed for a potential central bank digital currency.", - "Financial Times", - "2 days ago", - "https://example.com/digital-euro", - "https://images.unsplash.com/photo-1566228015668-4c45dbc4e2f5?w=400&h=250&fit=crop" - )); - } - - return articles; + public List getAllNews() { + return repository.findAll(); } } \ No newline at end of file diff --git a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/NewsView.java b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/NewsView.java index bce546b..69f44b0 100644 --- a/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/NewsView.java +++ b/webforj-dashboard/src/main/java/com/webforj/builtwithwebforj/dashboard/views/NewsView.java @@ -54,7 +54,7 @@ public NewsView(NewsService newsService) { .setDirection(FlexDirection.COLUMN) .setSpacing("var(--dwc-space-xl)"); - allArticles = newsService.getMockCryptoNews(); + allArticles = newsService.getAllNews(); createHeader(); createHeroSection(); createToolbar(); @@ -309,7 +309,7 @@ private boolean matchesSearch(NewsArticle article, String search) { private void refreshNews() { // Simulate refreshing news - allArticles = newsService.getMockCryptoNews(); + allArticles = newsService.getAllNews(); loadContent(); }