Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
204 changes: 101 additions & 103 deletions webforj-dashboard/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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">
<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>

<!-- Spring Boot Parent POM - Provides dependency management and plugin configurations -->
<!-- This parent POM manages versions of common dependencies so we don't have to -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.3</version>
</parent>

<groupId>com.webforj.builtwithwebforj</groupId>
<artifactId>webforj-dashboard</artifactId>
<name>webforj-dashboard</name>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<!-- Changed from 'war' to 'jar' - Spring Boot creates executable JARs by default -->
<packaging>jar</packaging>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>

<webforj.version>25.02-SNAPSHOT</webforj.version>

<jetty.version>12.0.14</jetty.version>
<!--
Configures automatic reload of Jetty server
(with 1 second timeout) when new classes are compiled.
Should be disabled when using a live reload system, such as JRebel.
-->
<jetty.scan>0</jetty.scan>
<jetty.port>8080</jetty.port>
<jetty.stopPort>9966</jetty.stopPort>
<webforj.version>25.03-SNAPSHOT</webforj.version>
</properties>

<repositories>
<repository>
<id>snapshots-repo</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
<repository>
<name>Central Portal Snapshots</name>
<id>central-portal-snapshots</id>
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
Expand All @@ -62,88 +61,96 @@
</dependencyManagement>

<dependencies>
<!-- Core webforJ dependency -->
<dependency>
<groupId>com.webforj</groupId>
<artifactId>webforj</artifactId>
<version>${webforj.version}</version>
</dependency>

<!-- webforJ Spring Boot integration - bridges webforJ with Spring Boot -->
<!-- Allows webforJ apps to use Spring's dependency injection and features -->
<dependency>
<groupId>com.webforj</groupId>
<artifactId>webforj-spring-boot-starter</artifactId>
</dependency>

<!-- Spring Boot Validation - provides @Valid, @NotNull, @Size etc. annotations -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<!-- Spring Data JPA - ORM layer for database operations -->
<!-- Provides @Entity, @Repository, and automatic CRUD operations -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!-- H2 Database - In-memory database, perfect for demos and development -->
<!-- Data is stored in memory and lost on restart (configurable) -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>

<!-- webforJ DevTools - Hot reload for webforJ resources -->
<dependency>
<groupId>com.webforj</groupId>
<artifactId>webforj-spring-devtools</artifactId>
<optional>true</optional>
</dependency>

<!-- Spring Boot DevTools - Auto-restart on code changes -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>com.webforj</groupId>
<artifactId>webforj-googlecharts</artifactId>
</dependency>

<!-- Test dependencies -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.16</version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>com.microsoft.playwright</groupId>
<artifactId>playwright</artifactId>
<version>1.49.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<!-- Default goal - what runs when you just type 'mvn' -->
<defaultGoal>spring-boot:run</defaultGoal>
<plugins>
<!-- Spring Boot Maven Plugin - Creates executable JAR and provides 'mvn spring-boot:run' -->
<!-- This replaces the need for Jetty plugin and WAR packaging -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.4.0</version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<webResources>
<resource>
<filtering>true</filtering>
<directory>src/main/webapp</directory>
<includes>
<include>**/web.xml</include>
</includes>
</resource>
</webResources>
<!-- Excludes DevTools from production builds -->
<excludeDevtools>true</excludeDevtools>
</configuration>
</plugin>

<plugin>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-maven-plugin</artifactId>
<version>${jetty.version}</version>
<configuration>
<scan>${jetty.scan}</scan>
<stopPort>${jetty.stopPort}</stopPort>
<stopKey>${project.artifactId}</stopKey>
<httpConnector>
<port>${jetty.port}</port>
</httpConnector>
<webApp>
<contextPath>/</contextPath>
</webApp>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>

<!-- Runs the integration tests (*IT) after the server is started -->
<!-- Integration test plugin (keeping from original) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
Expand All @@ -160,47 +167,38 @@
<trimStackTrace>false</trimStackTrace>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy-webforj-config</id>
<phase>process-resources</phase>
<configuration>
<target>
<copy file="src/main/resources/${config.file}"
tofile="${project.build.outputDirectory}/webforj.conf" />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

<profiles>
<!-- Production profile - excludes DevTools for smaller JAR size -->
<profile>
<id>prod</id>
<activation>
</activation>
<properties>
<config.file>webforj-prod.conf</config.file>
</properties>
<activation />
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludeDevtools>true</excludeDevtools>
<excludes>
<exclude>
<groupId>com.webforj</groupId>
<artifactId>webforj-spring-devtools</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<!-- Development profile - active by default, includes DevTools -->
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<config.file>webforj-dev.conf</config.file>
</properties>
</profile>
</profiles>
</project>
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Cryptocurrency> cryptocurrencies) {
table.setRepository(new CollectionRepository<>(cryptocurrencies));
table.setColumnsToMovable(true);
table.setColumnsToResizable(true);
}

public CollectionRepository<Cryptocurrency> getRepository() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,16 @@
public class NewsCard extends Composite<FlexLayout> {
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();
Expand Down
Loading