Generated project
This commit is contained in:
26
src/main/frontend/themes/website/main-layout.css
Normal file
26
src/main/frontend/themes/website/main-layout.css
Normal file
@@ -0,0 +1,26 @@
|
||||
header nav a:any-link {
|
||||
text-decoration: none;
|
||||
padding: 0 var(--lumo-space-s);
|
||||
border-radius: var(--lumo-border-radius-m);
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
header nav a:hover {
|
||||
color: var(--lumo-header-text-color);
|
||||
}
|
||||
|
||||
header nav a:active {
|
||||
background-color: var(--lumo-contrast-5pct);
|
||||
}
|
||||
|
||||
header nav a:focus-visible {
|
||||
box-shadow: 0 0 0 2px var(--lumo-primary-color-50pct);
|
||||
}
|
||||
|
||||
header nav a[highlight] vaadin-icon {
|
||||
color: var(--lumo-primary-text-color);
|
||||
}
|
||||
|
||||
header nav a[highlight] {
|
||||
background-color: var(--lumo-primary-color-10pct);
|
||||
}
|
30
src/main/frontend/themes/website/styles.css
Normal file
30
src/main/frontend/themes/website/styles.css
Normal file
@@ -0,0 +1,30 @@
|
||||
@import url('./main-layout.css');
|
||||
@import url('./views/dashboard-view.css');
|
||||
@import url('./views/checkout-form-view.css');
|
||||
@import url('./views/my-view-view.css'); html {
|
||||
--lumo-shade-5pct: rgba(33, 33, 33, 0.05);
|
||||
--lumo-shade-10pct: rgba(33, 33, 33, 0.1);
|
||||
--lumo-shade-20pct: rgba(33, 33, 33, 0.2);
|
||||
--lumo-shade-30pct: rgba(33, 33, 33, 0.3);
|
||||
--lumo-shade-40pct: rgba(33, 33, 33, 0.4);
|
||||
--lumo-shade-50pct: rgba(33, 33, 33, 0.5);
|
||||
--lumo-shade-60pct: rgba(33, 33, 33, 0.6);
|
||||
--lumo-shade-70pct: rgba(33, 33, 33, 0.7);
|
||||
--lumo-shade-80pct: rgba(33, 33, 33, 0.8);
|
||||
--lumo-shade-90pct: rgba(33, 33, 33, 0.9);
|
||||
--lumo-primary-color-50pct: rgba(235, 89, 5, 0.5);
|
||||
--lumo-primary-color-10pct: rgba(235, 89, 5, 0.1);
|
||||
--lumo-error-color-50pct: rgba(231, 24, 24, 0.5);
|
||||
--lumo-error-color-10pct: rgba(231, 24, 24, 0.1);
|
||||
--lumo-success-color-50pct: rgba(62, 229, 170, 0.5);
|
||||
--lumo-success-color-10pct: rgba(62, 229, 170, 0.1);
|
||||
--lumo-shade: hsl(0, 0%, 13%);
|
||||
--lumo-primary-color: hsl(22, 96%, 47%);
|
||||
--lumo-primary-text-color: hsl(22, 100%, 42%);
|
||||
--lumo-error-color: hsl(0, 81%, 50%);
|
||||
--lumo-error-text-color: hsl(0, 86%, 45%);
|
||||
--lumo-success-color: hsl(159, 76%, 57%);
|
||||
--lumo-success-contrast-color: hsl(159, 29%, 10%);
|
||||
--lumo-success-text-color: hsl(159, 61%, 40%);
|
||||
|
||||
}
|
3
src/main/frontend/themes/website/theme.json
Normal file
3
src/main/frontend/themes/website/theme.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"lumoImports" : [ "typography", "color", "spacing", "badge", "utility" ]
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
.checkout-form-view aside {
|
||||
top: calc(var(--lumo-space-xl) + var(--_vaadin-app-layout-navbar-offset-size));
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.checkout-form-view main {
|
||||
grid-template-columns: auto 324px;
|
||||
}
|
||||
}
|
19
src/main/frontend/themes/website/views/dashboard-view.css
Normal file
19
src/main/frontend/themes/website/views/dashboard-view.css
Normal file
@@ -0,0 +1,19 @@
|
||||
/* Borders */
|
||||
|
||||
.dashboard-view vaadin-board-row > * {
|
||||
border-bottom: 1px solid var(--lumo-contrast-10pct);
|
||||
border-right: 1px solid var(--lumo-contrast-10pct);
|
||||
}
|
||||
|
||||
.dashboard-view vaadin-board-row.small > * {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.dashboard-view vaadin-board-row.medium > *:nth-child(even),
|
||||
.dashboard-view vaadin-board-row.medium > *:only-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.dashboard-view vaadin-board-row.large > *:last-child {
|
||||
border-right: none;
|
||||
}
|
166
src/main/frontend/themes/website/views/my-view-view.css
Normal file
166
src/main/frontend/themes/website/views/my-view-view.css
Normal file
@@ -0,0 +1,166 @@
|
||||
.my-view-view {
|
||||
padding: 2px;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
--cv-blue: 212 96% 54%;
|
||||
--cv-purple: 259 97% 66%;
|
||||
--cv-dropzone-border-color: hsl(var(--cv-blue) / 0.5);
|
||||
--cv-dropzone-bg-color: hsl(var(--cv-blue) / 0.2);
|
||||
--cv-droptarget-border-color: hsl(var(--cv-purple) / 1);
|
||||
--cv-droptarget-bg-color: hsl(var(--cv-purple) / 0.4);
|
||||
--cv-stripe-width: 1.5px;
|
||||
--cv-stripe-gap: 9px;
|
||||
--cv-stripe-color: hsl(var(--cv-blue) / 0.2);
|
||||
--cv-layout-border-color: var(--lumo-contrast-40pct);
|
||||
--cv-checkerboard-color1: hsl(0 0% 0% / 0.05);
|
||||
--cv-checkerboard-color2: hsl(0 0% 100% / 0.05);
|
||||
--cv-checkerboard-size: 16px;
|
||||
}
|
||||
|
||||
.my-view-view[dragging] {
|
||||
--cv-checkerboard-color1: hsl(var(--cv-blue) / 0.2);
|
||||
--cv-checkerboard-color2: hsl(var(--cv-blue) / 0.1);
|
||||
--cv-layout-border-color: var(--cv-dropzone-border-color);
|
||||
}
|
||||
|
||||
.my-view-view .preview-container {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
/* The root layout is not necessarily inside a flex box so width/height needs to be used */
|
||||
.my-view-view .preview-container > .layout[style*='align-self: stretch'] {
|
||||
width: 100%;
|
||||
}
|
||||
.my-view-view .preview-container > .layout[style*='flex-grow: 1'] {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Apply some default gap and padding to layouts that don't have inline styles for them while dragging. */
|
||||
.my-view-view[dragging] .layout:not([style*='gap:']) {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.my-view-view[dragging] .layout:not([style*='padding:'], [empty]) {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.my-view-view .cover-overlay {
|
||||
position: absolute;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.my-view-view:not([starting-drag]) .cover-overlay.editable-hovering {
|
||||
outline: 2px solid hsl(var(--cv-blue) / 1);
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
.my-view-view:not([starting-drag]) .cover-overlay.editable-editing {
|
||||
outline: 1px solid hsl(var(--cv-blue) / 1);
|
||||
outline-offset: -1px;
|
||||
box-shadow: inset 0 0 0 2px var(--lumo-base-color);
|
||||
}
|
||||
|
||||
.my-view-view .overlays,
|
||||
.my-view-view .drop-zones {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.my-view-view:not([dragging]) .drop-zones {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.my-view-view .drop-zone {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
border-radius: 1px;
|
||||
min-height: 10px;
|
||||
min-width: 10px;
|
||||
}
|
||||
|
||||
.my-view-view[dragging] .drop-zone:not([empty-layout]) {
|
||||
outline: 1px dashed var(--cv-dropzone-border-color);
|
||||
outline-offset: -2px;
|
||||
background-color: var(--cv-dropzone-bg-color);
|
||||
}
|
||||
|
||||
.my-view-view .drop-zone[remaining-space] {
|
||||
background: repeating-linear-gradient(
|
||||
-45deg,
|
||||
var(--cv-stripe-color),
|
||||
var(--cv-stripe-color) var(--cv-stripe-width),
|
||||
transparent var(--cv-stripe-width),
|
||||
transparent var(--cv-stripe-gap)
|
||||
);
|
||||
}
|
||||
|
||||
.my-view-view[dragging] .drop-zone[drag-over] {
|
||||
background: var(--cv-droptarget-bg-color);
|
||||
outline: 1px solid var(--cv-droptarget-border-color);
|
||||
outline-offset: -1px;
|
||||
box-shadow: inset 0 0 0 2px var(--lumo-base-color);
|
||||
}
|
||||
|
||||
.drop-zone[empty-layout] {
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.my-view-view:not([readonly]) .layout[empty],vaadin-form-layout[empty] {
|
||||
border-radius: 1px;
|
||||
background: repeating-conic-gradient(var(--cv-checkerboard-color1) 0% 25%, var(--cv-checkerboard-color2) 0% 50%) 50% /
|
||||
var(--cv-checkerboard-size) var(--cv-checkerboard-size);
|
||||
background-clip: content-box;
|
||||
outline: 1px dashed var(--cv-layout-border-color);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
.my-view-view[dragging]:not([readonly]) vaadin-form-layout[empty]{
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
|
||||
.my-view-view .layout[empty]::before {
|
||||
content: '';
|
||||
display: block;
|
||||
min-width: 64px;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.my-view-view[readonly] .drop-zones,
|
||||
.my-view-view[readonly] .overlays {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.my-view-view[inline-editing] .drop-zones,
|
||||
.my-view-view[inline-editing] .overlays {
|
||||
display: none;
|
||||
}
|
||||
.my-view-view .content-wrapper[contenteditable='true']{
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.my-view-view[dragging] vaadin-form-layout {
|
||||
padding: 8px;
|
||||
}
|
||||
.my-view-view vaadin-form-layout[empty]::before {
|
||||
content: '';
|
||||
display: block;
|
||||
min-width: 64px;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.my-view-view[dragging] vaadin-form-layout:not([empty])::after {
|
||||
content: '';
|
||||
display: block;
|
||||
min-width: 64px;
|
||||
min-height: 32px;
|
||||
}
|
23
src/main/java/dev/mars3142/fhq/Application.java
Normal file
23
src/main/java/dev/mars3142/fhq/Application.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package dev.mars3142.fhq;
|
||||
|
||||
import com.vaadin.flow.component.page.AppShellConfigurator;
|
||||
import com.vaadin.flow.theme.Theme;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* The entry point of the Spring Boot application.
|
||||
*
|
||||
* Use the @PWA annotation make the application installable on phones, tablets
|
||||
* and some desktop browsers.
|
||||
*
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@Theme(value = "website")
|
||||
public class Application implements AppShellConfigurator {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
114
src/main/java/dev/mars3142/fhq/views/MainLayout.java
Normal file
114
src/main/java/dev/mars3142/fhq/views/MainLayout.java
Normal file
@@ -0,0 +1,114 @@
|
||||
package dev.mars3142.fhq.views;
|
||||
|
||||
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.applayout.AppLayout;
|
||||
import com.vaadin.flow.component.html.Div;
|
||||
import com.vaadin.flow.component.html.H1;
|
||||
import com.vaadin.flow.component.html.Header;
|
||||
import com.vaadin.flow.component.html.ListItem;
|
||||
import com.vaadin.flow.component.html.Nav;
|
||||
import com.vaadin.flow.component.html.Span;
|
||||
import com.vaadin.flow.component.html.UnorderedList;
|
||||
import com.vaadin.flow.router.RouterLink;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.AlignItems;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.BoxSizing;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Display;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FlexDirection;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FontSize;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FontWeight;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Gap;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Height;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.ListStyleType;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Margin;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Overflow;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Padding;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.TextColor;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Whitespace;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Width;
|
||||
import dev.mars3142.fhq.views.checkoutform.CheckoutFormView;
|
||||
import dev.mars3142.fhq.views.dashboard.DashboardView;
|
||||
import dev.mars3142.fhq.views.myview.MyViewView;
|
||||
import org.vaadin.lineawesome.LineAwesomeIcon;
|
||||
|
||||
/**
|
||||
* The main view is a top-level placeholder for other views.
|
||||
*/
|
||||
public class MainLayout extends AppLayout {
|
||||
|
||||
/**
|
||||
* A simple navigation item component, based on ListItem element.
|
||||
*/
|
||||
public static class MenuItemInfo extends ListItem {
|
||||
|
||||
private final Class<? extends Component> view;
|
||||
|
||||
public MenuItemInfo(String menuTitle, Component icon, Class<? extends Component> view) {
|
||||
this.view = view;
|
||||
RouterLink link = new RouterLink();
|
||||
// Use Lumo classnames for various styling
|
||||
link.addClassNames(Display.FLEX, Gap.XSMALL, Height.MEDIUM, AlignItems.CENTER, Padding.Horizontal.SMALL,
|
||||
TextColor.BODY);
|
||||
link.setRoute(view);
|
||||
|
||||
Span text = new Span(menuTitle);
|
||||
// Use Lumo classnames for various styling
|
||||
text.addClassNames(FontWeight.MEDIUM, FontSize.MEDIUM, Whitespace.NOWRAP);
|
||||
|
||||
if (icon != null) {
|
||||
link.add(icon);
|
||||
}
|
||||
link.add(text);
|
||||
add(link);
|
||||
}
|
||||
|
||||
public Class<?> getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public MainLayout() {
|
||||
addToNavbar(createHeaderContent());
|
||||
}
|
||||
|
||||
private Component createHeaderContent() {
|
||||
Header header = new Header();
|
||||
header.addClassNames(BoxSizing.BORDER, Display.FLEX, FlexDirection.COLUMN, Width.FULL);
|
||||
|
||||
Div layout = new Div();
|
||||
layout.addClassNames(Display.FLEX, AlignItems.CENTER, Padding.Horizontal.LARGE);
|
||||
|
||||
H1 appName = new H1("Firmware HQ");
|
||||
appName.addClassNames(Margin.Vertical.MEDIUM, Margin.End.AUTO, FontSize.LARGE);
|
||||
layout.add(appName);
|
||||
|
||||
Nav nav = new Nav();
|
||||
nav.addClassNames(Display.FLEX, Overflow.AUTO, Padding.Horizontal.MEDIUM, Padding.Vertical.XSMALL);
|
||||
|
||||
// Wrap the links in a list; improves accessibility
|
||||
UnorderedList list = new UnorderedList();
|
||||
list.addClassNames(Display.FLEX, Gap.SMALL, ListStyleType.NONE, Margin.NONE, Padding.NONE);
|
||||
nav.add(list);
|
||||
|
||||
for (MenuItemInfo menuItem : createMenuItems()) {
|
||||
list.add(menuItem);
|
||||
|
||||
}
|
||||
|
||||
header.add(layout, nav);
|
||||
return header;
|
||||
}
|
||||
|
||||
private MenuItemInfo[] createMenuItems() {
|
||||
return new MenuItemInfo[]{ //
|
||||
new MenuItemInfo("Dashboard", LineAwesomeIcon.CHART_AREA_SOLID.create(), DashboardView.class), //
|
||||
|
||||
new MenuItemInfo("Checkout Form", LineAwesomeIcon.CREDIT_CARD.create(), CheckoutFormView.class), //
|
||||
|
||||
new MenuItemInfo("My View", LineAwesomeIcon.PENCIL_RULER_SOLID.create(), MyViewView.class), //
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,312 @@
|
||||
package dev.mars3142.fhq.views.checkoutform;
|
||||
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.checkbox.Checkbox;
|
||||
import com.vaadin.flow.component.combobox.ComboBox;
|
||||
import com.vaadin.flow.component.html.*;
|
||||
import com.vaadin.flow.component.icon.Icon;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.select.Select;
|
||||
import com.vaadin.flow.component.textfield.EmailField;
|
||||
import com.vaadin.flow.component.textfield.TextArea;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.AlignItems;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Background;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.BorderRadius;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.BoxSizing;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Display;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Flex;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FlexDirection;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FlexWrap;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FontSize;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Gap;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Height;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.JustifyContent;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.ListStyleType;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Margin;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.MaxWidth;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Padding;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Position;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.TextColor;
|
||||
import dev.mars3142.fhq.views.MainLayout;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@PageTitle("Checkout Form")
|
||||
@Route(value = "checkout-form", layout = MainLayout.class)
|
||||
public class CheckoutFormView extends Div {
|
||||
|
||||
private static final Set<String> states = new LinkedHashSet<>();
|
||||
private static final Set<String> countries = new LinkedHashSet<>();
|
||||
|
||||
static {
|
||||
states.addAll(Arrays.asList("Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut",
|
||||
"Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas",
|
||||
"Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi",
|
||||
"Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York",
|
||||
"North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island",
|
||||
"South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington",
|
||||
"West Virginia", "Wisconsin", "Wyoming"));
|
||||
|
||||
countries.addAll(Arrays.asList("Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra", "Angola",
|
||||
"Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina", "Armenia", "Aruba", "Australia",
|
||||
"Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize",
|
||||
"Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Bouvet Island",
|
||||
"Brazil", "British Indian Ocean Territory", "British Virgin Islands", "Brunei Darussalam", "Bulgaria",
|
||||
"Burkina Faso", "Burundi", "Cambodia", "Cameroon", "Canada", "Cape Verde", "Cayman Islands",
|
||||
"Central African Republic", "Chad", "Chile", "China", "Christmas Island", "Cocos (Keeling) Islands",
|
||||
"Colombia", "Comoros", "Congo", "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus",
|
||||
"Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "East Timor", "Ecuador",
|
||||
"Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands",
|
||||
"Faroe Islands", "Federated States of Micronesia", "Fiji", "Finland", "France", "French Guiana",
|
||||
"French Polynesia", "French Southern Territories", "Gabon", "Gambia", "Georgia", "Germany", "Ghana",
|
||||
"Gibraltar", "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea",
|
||||
"Guinea-Bissau", "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong",
|
||||
"Hungary", "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Ivory Coast",
|
||||
"Jamaica", "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
|
||||
"Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Macau",
|
||||
"Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
|
||||
"Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Moldova", "Monaco", "Mongolia",
|
||||
"Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru", "Nepal", "Netherlands",
|
||||
"Netherlands Antilles", "New Caledonia", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Niue",
|
||||
"Norfolk Island", "North Korea", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau",
|
||||
"Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Pitcairn", "Poland", "Portugal",
|
||||
"Puerto Rico", "Qatar", "Reunion", "Romania", "Russian Federation", "Rwanda", "Saint Kitts and Nevis",
|
||||
"Saint Lucia", "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Sao Tome and Principe",
|
||||
"Saudi Arabia", "Senegal", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia",
|
||||
"Solomon Islands", "Somalia", "South Africa", "South Georgia and the South Sandwich Islands",
|
||||
"South Korea", "Spain", "Sri Lanka", "St. Helena", "St. Pierre and Miquelon", "Sudan", "Suriname",
|
||||
"Svalbard and Jan Mayen Islands", "Swaziland", "Sweden", "Switzerland", "Syrian Arab Republic",
|
||||
"Taiwan", "Tajikistan", "Tanzania", "Thailand", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago",
|
||||
"Tunisia", "Turkey", "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Uganda", "Ukraine",
|
||||
"United Arab Emirates", "United Kingdom", "United States", "United States Minor Outlying Islands",
|
||||
"United States Virgin Islands", "Uruguay", "Uzbekistan", "Vanuatu", "Vatican City State", "Venezuela",
|
||||
"Vietnam", "Wallis and Futuna Islands", "Western Sahara", "Yemen", "Yugoslavia", "Zaire", "Zambia",
|
||||
"Zimbabwe"));
|
||||
}
|
||||
|
||||
public CheckoutFormView() {
|
||||
addClassNames("checkout-form-view");
|
||||
addClassNames(Display.FLEX, FlexDirection.COLUMN, Height.FULL);
|
||||
|
||||
Main content = new Main();
|
||||
content.addClassNames(Display.GRID, Gap.XLARGE, AlignItems.START, JustifyContent.CENTER, MaxWidth.SCREEN_MEDIUM,
|
||||
Margin.Horizontal.AUTO, Padding.Bottom.LARGE, Padding.Horizontal.LARGE);
|
||||
|
||||
content.add(createCheckoutForm());
|
||||
content.add(createAside());
|
||||
add(content);
|
||||
}
|
||||
|
||||
private Component createCheckoutForm() {
|
||||
Section checkoutForm = new Section();
|
||||
checkoutForm.addClassNames(Display.FLEX, FlexDirection.COLUMN, Flex.GROW);
|
||||
|
||||
H2 header = new H2("Checkout");
|
||||
header.addClassNames(Margin.Bottom.NONE, Margin.Top.XLARGE, FontSize.XXXLARGE);
|
||||
Paragraph note = new Paragraph("All fields are required unless otherwise noted");
|
||||
note.addClassNames(Margin.Bottom.XLARGE, Margin.Top.NONE, TextColor.SECONDARY);
|
||||
checkoutForm.add(header, note);
|
||||
|
||||
checkoutForm.add(createPersonalDetailsSection());
|
||||
checkoutForm.add(createShippingAddressSection());
|
||||
checkoutForm.add(createPaymentInformationSection());
|
||||
checkoutForm.add(new Hr());
|
||||
checkoutForm.add(createFooter());
|
||||
|
||||
return checkoutForm;
|
||||
}
|
||||
|
||||
private Section createPersonalDetailsSection() {
|
||||
Section personalDetails = new Section();
|
||||
personalDetails.addClassNames(Display.FLEX, FlexDirection.COLUMN, Margin.Bottom.XLARGE, Margin.Top.MEDIUM);
|
||||
|
||||
Paragraph stepOne = new Paragraph("Checkout 1/3");
|
||||
stepOne.addClassNames(Margin.NONE, FontSize.SMALL, TextColor.SECONDARY);
|
||||
|
||||
H3 header = new H3("Personal details");
|
||||
header.addClassNames(Margin.Bottom.MEDIUM, Margin.Top.SMALL, FontSize.XXLARGE);
|
||||
|
||||
TextField name = new TextField("Name");
|
||||
name.setRequiredIndicatorVisible(true);
|
||||
name.setPattern("[\\p{L} \\-]+");
|
||||
name.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
EmailField email = new EmailField("Email address");
|
||||
email.setRequiredIndicatorVisible(true);
|
||||
email.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
TextField phone = new TextField("Phone number");
|
||||
phone.setRequiredIndicatorVisible(true);
|
||||
phone.setPattern("[\\d \\-\\+]+");
|
||||
phone.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
Checkbox rememberDetails = new Checkbox("Remember personal details for next time");
|
||||
rememberDetails.addClassNames(Margin.Top.SMALL);
|
||||
|
||||
personalDetails.add(stepOne, header, name, email, phone, rememberDetails);
|
||||
return personalDetails;
|
||||
}
|
||||
|
||||
private Section createShippingAddressSection() {
|
||||
Section shippingDetails = new Section();
|
||||
shippingDetails.addClassNames(Display.FLEX, FlexDirection.COLUMN, Margin.Bottom.XLARGE, Margin.Top.MEDIUM);
|
||||
|
||||
Paragraph stepTwo = new Paragraph("Checkout 2/3");
|
||||
stepTwo.addClassNames(Margin.NONE, FontSize.SMALL, TextColor.SECONDARY);
|
||||
|
||||
H3 header = new H3("Shipping address");
|
||||
header.addClassNames(Margin.Bottom.MEDIUM, Margin.Top.SMALL, FontSize.XXLARGE);
|
||||
|
||||
ComboBox<String> countrySelect = new ComboBox<>("Country");
|
||||
countrySelect.setRequiredIndicatorVisible(true);
|
||||
countrySelect.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
TextArea address = new TextArea("Street address");
|
||||
address.setMaxLength(200);
|
||||
address.setRequiredIndicatorVisible(true);
|
||||
address.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
Div subSection = new Div();
|
||||
subSection.addClassNames(Display.FLEX, FlexWrap.WRAP, Gap.MEDIUM);
|
||||
|
||||
TextField postalCode = new TextField("Postal Code");
|
||||
postalCode.setRequiredIndicatorVisible(true);
|
||||
postalCode.setPattern("[\\d \\p{L}]*");
|
||||
postalCode.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
TextField city = new TextField("City");
|
||||
city.setRequiredIndicatorVisible(true);
|
||||
city.addClassNames(Flex.GROW, Margin.Bottom.SMALL);
|
||||
|
||||
subSection.add(postalCode, city);
|
||||
|
||||
ComboBox<String> stateSelect = new ComboBox<>("State");
|
||||
stateSelect.setRequiredIndicatorVisible(true);
|
||||
|
||||
stateSelect.setItems(states);
|
||||
stateSelect.setVisible(false);
|
||||
countrySelect.setItems(countries);
|
||||
countrySelect
|
||||
.addValueChangeListener(e -> stateSelect.setVisible(countrySelect.getValue().equals("United States")));
|
||||
|
||||
Checkbox sameAddress = new Checkbox("Billing address is the same as shipping address");
|
||||
sameAddress.addClassNames(Margin.Top.SMALL);
|
||||
|
||||
Checkbox rememberAddress = new Checkbox("Remember address for next time");
|
||||
|
||||
shippingDetails.add(stepTwo, header, countrySelect, address, subSection, stateSelect, sameAddress,
|
||||
rememberAddress);
|
||||
return shippingDetails;
|
||||
}
|
||||
|
||||
private Component createPaymentInformationSection() {
|
||||
Section paymentInfo = new Section();
|
||||
paymentInfo.addClassNames(Display.FLEX, FlexDirection.COLUMN, Margin.Bottom.XLARGE, Margin.Top.MEDIUM);
|
||||
|
||||
Paragraph stepThree = new Paragraph("Checkout 3/3");
|
||||
stepThree.addClassNames(Margin.NONE, FontSize.SMALL, TextColor.SECONDARY);
|
||||
|
||||
H3 header = new H3("Personal details");
|
||||
header.addClassNames(Margin.Bottom.MEDIUM, Margin.Top.SMALL, FontSize.XXLARGE);
|
||||
|
||||
TextField cardHolder = new TextField("Cardholder name");
|
||||
cardHolder.setRequiredIndicatorVisible(true);
|
||||
cardHolder.setPattern("[\\p{L} \\-]+");
|
||||
cardHolder.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
Div subSectionOne = new Div();
|
||||
subSectionOne.addClassNames(Display.FLEX, FlexWrap.WRAP, Gap.MEDIUM);
|
||||
|
||||
TextField cardNumber = new TextField("Card Number");
|
||||
cardNumber.setRequiredIndicatorVisible(true);
|
||||
cardNumber.setPattern("[\\d ]{12,23}");
|
||||
cardNumber.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
TextField securityCode = new TextField("Security Code");
|
||||
securityCode.setRequiredIndicatorVisible(true);
|
||||
securityCode.setPattern("[0-9]{3,4}");
|
||||
securityCode.addClassNames(Flex.GROW, Margin.Bottom.SMALL);
|
||||
securityCode.setHelperText("What is this?");
|
||||
|
||||
subSectionOne.add(cardNumber, securityCode);
|
||||
|
||||
Div subSectionTwo = new Div();
|
||||
subSectionTwo.addClassNames(Display.FLEX, FlexWrap.WRAP, Gap.MEDIUM);
|
||||
|
||||
Select<String> expirationMonth = new Select<>();
|
||||
expirationMonth.setLabel("Expiration month");
|
||||
expirationMonth.setRequiredIndicatorVisible(true);
|
||||
expirationMonth.setItems("01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12");
|
||||
|
||||
Select<String> expirationYear = new Select<>();
|
||||
expirationYear.setLabel("Expiration year");
|
||||
expirationYear.setRequiredIndicatorVisible(true);
|
||||
expirationYear.setItems("22", "23", "24", "25", "26");
|
||||
|
||||
subSectionTwo.add(expirationMonth, expirationYear);
|
||||
|
||||
paymentInfo.add(stepThree, header, cardHolder, subSectionTwo);
|
||||
return paymentInfo;
|
||||
}
|
||||
|
||||
private Footer createFooter() {
|
||||
Footer footer = new Footer();
|
||||
footer.addClassNames(Display.FLEX, AlignItems.CENTER, JustifyContent.BETWEEN, Margin.Vertical.MEDIUM);
|
||||
|
||||
Button cancel = new Button("Cancel order");
|
||||
cancel.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
|
||||
|
||||
Button pay = new Button("Pay securely", new Icon(VaadinIcon.LOCK));
|
||||
pay.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS);
|
||||
|
||||
footer.add(cancel, pay);
|
||||
return footer;
|
||||
}
|
||||
|
||||
private Aside createAside() {
|
||||
Aside aside = new Aside();
|
||||
aside.addClassNames(Background.CONTRAST_5, BoxSizing.BORDER, Padding.LARGE, BorderRadius.LARGE,
|
||||
Position.STICKY);
|
||||
Header headerSection = new Header();
|
||||
headerSection.addClassNames(Display.FLEX, AlignItems.CENTER, JustifyContent.BETWEEN, Margin.Bottom.MEDIUM);
|
||||
H3 header = new H3("Order");
|
||||
header.addClassNames(Margin.NONE);
|
||||
Button edit = new Button("Edit");
|
||||
edit.addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE);
|
||||
headerSection.add(header, edit);
|
||||
|
||||
UnorderedList ul = new UnorderedList();
|
||||
ul.addClassNames(ListStyleType.NONE, Margin.NONE, Padding.NONE, Display.FLEX, FlexDirection.COLUMN, Gap.MEDIUM);
|
||||
|
||||
ul.add(createListItem("Vanilla cracker", "With wholemeal flour", "$7.00"));
|
||||
ul.add(createListItem("Vanilla blueberry cake", "With blueberry jam", "$8.00"));
|
||||
ul.add(createListItem("Vanilla pastry", "With wholemeal flour", "$5.00"));
|
||||
|
||||
aside.add(headerSection, ul);
|
||||
return aside;
|
||||
}
|
||||
|
||||
private ListItem createListItem(String primary, String secondary, String price) {
|
||||
ListItem item = new ListItem();
|
||||
item.addClassNames(Display.FLEX, JustifyContent.BETWEEN);
|
||||
|
||||
Div subSection = new Div();
|
||||
subSection.addClassNames(Display.FLEX, FlexDirection.COLUMN);
|
||||
|
||||
subSection.add(new Span(primary));
|
||||
Span secondarySpan = new Span(secondary);
|
||||
secondarySpan.addClassNames(FontSize.SMALL, TextColor.SECONDARY);
|
||||
subSection.add(secondarySpan);
|
||||
|
||||
Span priceSpan = new Span(price);
|
||||
|
||||
item.add(subSection, priceSpan);
|
||||
return item;
|
||||
}
|
||||
}
|
@@ -0,0 +1,227 @@
|
||||
package dev.mars3142.fhq.views.dashboard;
|
||||
|
||||
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.board.Board;
|
||||
import com.vaadin.flow.component.charts.Chart;
|
||||
import com.vaadin.flow.component.charts.model.*;
|
||||
import com.vaadin.flow.component.grid.ColumnTextAlign;
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
import com.vaadin.flow.component.grid.GridVariant;
|
||||
import com.vaadin.flow.component.html.H2;
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.component.html.Span;
|
||||
import com.vaadin.flow.component.icon.Icon;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.select.Select;
|
||||
import com.vaadin.flow.data.renderer.ComponentRenderer;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.router.RouteAlias;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.BoxSizing;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FontSize;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FontWeight;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Margin;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Padding;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.TextColor;
|
||||
import dev.mars3142.fhq.views.MainLayout;
|
||||
import dev.mars3142.fhq.views.dashboard.ServiceHealth.Status;
|
||||
|
||||
@PageTitle("Dashboard")
|
||||
@Route(value = "", layout = MainLayout.class)
|
||||
@RouteAlias(value = "", layout = MainLayout.class)
|
||||
public class DashboardView extends Main {
|
||||
|
||||
public DashboardView() {
|
||||
addClassName("dashboard-view");
|
||||
|
||||
Board board = new Board();
|
||||
board.addRow(createHighlight("Current users", "745", 33.7), createHighlight("View events", "54.6k", -112.45),
|
||||
createHighlight("Conversion rate", "18%", 3.9), createHighlight("Custom metric", "-123.45", 0.0));
|
||||
board.addRow(createViewEvents());
|
||||
board.addRow(createServiceHealth(), createResponseTimes());
|
||||
add(board);
|
||||
}
|
||||
|
||||
private Component createHighlight(String title, String value, Double percentage) {
|
||||
VaadinIcon icon = VaadinIcon.ARROW_UP;
|
||||
String prefix = "";
|
||||
String theme = "badge";
|
||||
|
||||
if (percentage == 0) {
|
||||
prefix = "±";
|
||||
} else if (percentage > 0) {
|
||||
prefix = "+";
|
||||
theme += " success";
|
||||
} else if (percentage < 0) {
|
||||
icon = VaadinIcon.ARROW_DOWN;
|
||||
theme += " error";
|
||||
}
|
||||
|
||||
H2 h2 = new H2(title);
|
||||
h2.addClassNames(FontWeight.NORMAL, Margin.NONE, TextColor.SECONDARY, FontSize.XSMALL);
|
||||
|
||||
Span span = new Span(value);
|
||||
span.addClassNames(FontWeight.SEMIBOLD, FontSize.XXXLARGE);
|
||||
|
||||
Icon i = icon.create();
|
||||
i.addClassNames(BoxSizing.BORDER, Padding.XSMALL);
|
||||
|
||||
Span badge = new Span(i, new Span(prefix + percentage.toString()));
|
||||
badge.getElement().getThemeList().add(theme);
|
||||
|
||||
VerticalLayout layout = new VerticalLayout(h2, span, badge);
|
||||
layout.addClassName(Padding.LARGE);
|
||||
layout.setPadding(false);
|
||||
layout.setSpacing(false);
|
||||
return layout;
|
||||
}
|
||||
|
||||
private Component createViewEvents() {
|
||||
// Header
|
||||
Select year = new Select();
|
||||
year.setItems("2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021");
|
||||
year.setValue("2021");
|
||||
year.setWidth("100px");
|
||||
|
||||
HorizontalLayout header = createHeader("View events", "City/month");
|
||||
header.add(year);
|
||||
|
||||
// Chart
|
||||
Chart chart = new Chart(ChartType.AREASPLINE);
|
||||
Configuration conf = chart.getConfiguration();
|
||||
conf.getChart().setStyledMode(true);
|
||||
|
||||
XAxis xAxis = new XAxis();
|
||||
xAxis.setCategories("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
|
||||
conf.addxAxis(xAxis);
|
||||
|
||||
conf.getyAxis().setTitle("Values");
|
||||
|
||||
PlotOptionsAreaspline plotOptions = new PlotOptionsAreaspline();
|
||||
plotOptions.setPointPlacement(PointPlacement.ON);
|
||||
plotOptions.setMarker(new Marker(false));
|
||||
conf.addPlotOptions(plotOptions);
|
||||
|
||||
conf.addSeries(new ListSeries("Berlin", 189, 191, 291, 396, 501, 403, 609, 712, 729, 942, 1044, 1247));
|
||||
conf.addSeries(new ListSeries("London", 138, 246, 248, 348, 352, 353, 463, 573, 778, 779, 885, 887));
|
||||
conf.addSeries(new ListSeries("New York", 65, 65, 166, 171, 293, 302, 308, 317, 427, 429, 535, 636));
|
||||
conf.addSeries(new ListSeries("Tokyo", 0, 11, 17, 123, 130, 142, 248, 349, 452, 454, 458, 462));
|
||||
|
||||
// Add it all together
|
||||
VerticalLayout viewEvents = new VerticalLayout(header, chart);
|
||||
viewEvents.addClassName(Padding.LARGE);
|
||||
viewEvents.setPadding(false);
|
||||
viewEvents.setSpacing(false);
|
||||
viewEvents.getElement().getThemeList().add("spacing-l");
|
||||
return viewEvents;
|
||||
}
|
||||
|
||||
private Component createServiceHealth() {
|
||||
// Header
|
||||
HorizontalLayout header = createHeader("Service health", "Input / output");
|
||||
|
||||
// Grid
|
||||
Grid<ServiceHealth> grid = new Grid();
|
||||
grid.addThemeVariants(GridVariant.LUMO_NO_BORDER);
|
||||
grid.setAllRowsVisible(true);
|
||||
|
||||
grid.addColumn(new ComponentRenderer<>(serviceHealth -> {
|
||||
Span status = new Span();
|
||||
String statusText = getStatusDisplayName(serviceHealth);
|
||||
status.getElement().setAttribute("aria-label", "Status: " + statusText);
|
||||
status.getElement().setAttribute("title", "Status: " + statusText);
|
||||
status.getElement().getThemeList().add(getStatusTheme(serviceHealth));
|
||||
return status;
|
||||
})).setHeader("").setFlexGrow(0).setAutoWidth(true);
|
||||
grid.addColumn(ServiceHealth::getCity).setHeader("City").setFlexGrow(1);
|
||||
grid.addColumn(ServiceHealth::getInput).setHeader("Input").setAutoWidth(true).setTextAlign(ColumnTextAlign.END);
|
||||
grid.addColumn(ServiceHealth::getOutput).setHeader("Output").setAutoWidth(true)
|
||||
.setTextAlign(ColumnTextAlign.END);
|
||||
|
||||
grid.setItems(new ServiceHealth(Status.EXCELLENT, "Münster", 324, 1540),
|
||||
new ServiceHealth(Status.OK, "Cluj-Napoca", 311, 1320),
|
||||
new ServiceHealth(Status.FAILING, "Ciudad Victoria", 300, 1219));
|
||||
|
||||
// Add it all together
|
||||
VerticalLayout serviceHealth = new VerticalLayout(header, grid);
|
||||
serviceHealth.addClassName(Padding.LARGE);
|
||||
serviceHealth.setPadding(false);
|
||||
serviceHealth.setSpacing(false);
|
||||
serviceHealth.getElement().getThemeList().add("spacing-l");
|
||||
return serviceHealth;
|
||||
}
|
||||
|
||||
private Component createResponseTimes() {
|
||||
HorizontalLayout header = createHeader("Response times", "Average across all systems");
|
||||
|
||||
// Chart
|
||||
Chart chart = new Chart(ChartType.PIE);
|
||||
Configuration conf = chart.getConfiguration();
|
||||
conf.getChart().setStyledMode(true);
|
||||
chart.setThemeName("gradient");
|
||||
|
||||
DataSeries series = new DataSeries();
|
||||
series.add(new DataSeriesItem("System 1", 12.5));
|
||||
series.add(new DataSeriesItem("System 2", 12.5));
|
||||
series.add(new DataSeriesItem("System 3", 12.5));
|
||||
series.add(new DataSeriesItem("System 4", 12.5));
|
||||
series.add(new DataSeriesItem("System 5", 12.5));
|
||||
series.add(new DataSeriesItem("System 6", 12.5));
|
||||
conf.addSeries(series);
|
||||
|
||||
// Add it all together
|
||||
VerticalLayout serviceHealth = new VerticalLayout(header, chart);
|
||||
serviceHealth.addClassName(Padding.LARGE);
|
||||
serviceHealth.setPadding(false);
|
||||
serviceHealth.setSpacing(false);
|
||||
serviceHealth.getElement().getThemeList().add("spacing-l");
|
||||
return serviceHealth;
|
||||
}
|
||||
|
||||
private HorizontalLayout createHeader(String title, String subtitle) {
|
||||
H2 h2 = new H2(title);
|
||||
h2.addClassNames(FontSize.XLARGE, Margin.NONE);
|
||||
|
||||
Span span = new Span(subtitle);
|
||||
span.addClassNames(TextColor.SECONDARY, FontSize.XSMALL);
|
||||
|
||||
VerticalLayout column = new VerticalLayout(h2, span);
|
||||
column.setPadding(false);
|
||||
column.setSpacing(false);
|
||||
|
||||
HorizontalLayout header = new HorizontalLayout(column);
|
||||
header.setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN);
|
||||
header.setSpacing(false);
|
||||
header.setWidthFull();
|
||||
return header;
|
||||
}
|
||||
|
||||
private String getStatusDisplayName(ServiceHealth serviceHealth) {
|
||||
Status status = serviceHealth.getStatus();
|
||||
if (status == Status.OK) {
|
||||
return "Ok";
|
||||
} else if (status == Status.FAILING) {
|
||||
return "Failing";
|
||||
} else if (status == Status.EXCELLENT) {
|
||||
return "Excellent";
|
||||
} else {
|
||||
return status.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private String getStatusTheme(ServiceHealth serviceHealth) {
|
||||
Status status = serviceHealth.getStatus();
|
||||
String theme = "badge primary small";
|
||||
if (status == Status.EXCELLENT) {
|
||||
theme += " success";
|
||||
} else if (status == Status.FAILING) {
|
||||
theme += " error";
|
||||
}
|
||||
return theme;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
package dev.mars3142.fhq.views.dashboard;
|
||||
|
||||
/**
|
||||
* Simple DTO class for the inbox list to demonstrate complex object data
|
||||
*/
|
||||
public class ServiceHealth {
|
||||
|
||||
private Status status;
|
||||
|
||||
private String city;
|
||||
|
||||
private int input;
|
||||
|
||||
private int output;
|
||||
|
||||
private String theme;
|
||||
|
||||
enum Status {
|
||||
EXCELLENT, OK, FAILING;
|
||||
}
|
||||
|
||||
public ServiceHealth() {
|
||||
|
||||
}
|
||||
|
||||
public ServiceHealth(Status status, String city, int input, int output) {
|
||||
this.status = status;
|
||||
this.city = city;
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Status status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public int getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public void setInput(int input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public int getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
public void setOutput(int output) {
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
}
|
44
src/main/java/dev/mars3142/fhq/views/myview/MyViewView.java
Normal file
44
src/main/java/dev/mars3142/fhq/views/myview/MyViewView.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package dev.mars3142.fhq.views.myview;
|
||||
|
||||
import com.vaadin.flow.component.Composite;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Gap;
|
||||
import dev.mars3142.fhq.views.MainLayout;
|
||||
|
||||
@PageTitle("My View")
|
||||
@Route(value = "my-view", layout = MainLayout.class)
|
||||
public class MyViewView extends Composite<VerticalLayout> {
|
||||
|
||||
public MyViewView() {
|
||||
HorizontalLayout layoutRow2 = new HorizontalLayout();
|
||||
HorizontalLayout layoutRow = new HorizontalLayout();
|
||||
VerticalLayout layoutColumn2 = new VerticalLayout();
|
||||
VerticalLayout layoutColumn3 = new VerticalLayout();
|
||||
VerticalLayout layoutColumn4 = new VerticalLayout();
|
||||
HorizontalLayout layoutRow3 = new HorizontalLayout();
|
||||
getContent().setWidth("100%");
|
||||
getContent().getStyle().set("flex-grow", "1");
|
||||
layoutRow2.addClassName(Gap.MEDIUM);
|
||||
layoutRow2.setWidth("100%");
|
||||
layoutRow2.setHeight("min-content");
|
||||
layoutRow.addClassName(Gap.MEDIUM);
|
||||
layoutRow.setWidth("100%");
|
||||
layoutRow.getStyle().set("flex-grow", "1");
|
||||
layoutColumn2.getStyle().set("flex-grow", "1");
|
||||
layoutColumn3.setWidth("100%");
|
||||
layoutColumn3.getStyle().set("flex-grow", "1");
|
||||
layoutColumn4.getStyle().set("flex-grow", "1");
|
||||
layoutRow3.addClassName(Gap.MEDIUM);
|
||||
layoutRow3.setWidth("100%");
|
||||
layoutRow3.setHeight("min-content");
|
||||
getContent().add(layoutRow2);
|
||||
getContent().add(layoutRow);
|
||||
layoutRow.add(layoutColumn2);
|
||||
layoutRow.add(layoutColumn3);
|
||||
layoutRow.add(layoutColumn4);
|
||||
getContent().add(layoutRow3);
|
||||
}
|
||||
}
|
BIN
src/main/resources/META-INF/resources/icons/icon.png
Normal file
BIN
src/main/resources/META-INF/resources/icons/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
15
src/main/resources/application.properties
Normal file
15
src/main/resources/application.properties
Normal file
@@ -0,0 +1,15 @@
|
||||
server.port=${PORT:8080}
|
||||
logging.level.org.atmosphere = warn
|
||||
spring.mustache.check-template-location = false
|
||||
|
||||
# Launch the default browser when starting the application in development mode
|
||||
vaadin.launch-browser=true
|
||||
# PostgreSQL configuration.
|
||||
spring.datasource.url = jdbc:postgresql://localhost:5432/vaadinstart
|
||||
spring.datasource.username = vaadinstart
|
||||
spring.datasource.password = vaadinstart
|
||||
spring.jpa.hibernate.ddl-auto = update
|
||||
# To improve the performance during development.
|
||||
# For more information https://vaadin.com/docs/latest/integrations/spring/configuration#special-configuration-parameters
|
||||
vaadin.allowed-packages = com.vaadin,org.vaadin,dev.hilla,dev.mars3142.fhq
|
||||
spring.jpa.defer-datasource-initialization = true
|
6
src/main/resources/banner.txt
Normal file
6
src/main/resources/banner.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
_____ _ _ _ ___
|
||||
| ___(_)_ __ _ __ _____ ____ _ _ __ ___ | | | |/ _ \
|
||||
| |_ | | '__| '_ ` _ \ \ /\ / / _` | '__/ _ \ | |_| | | | |
|
||||
| _| | | | | | | | | \ V V / (_| | | | __/ | _ | |_| |
|
||||
|_| |_|_| |_| |_| |_|\_/\_/ \__,_|_| \___| |_| |_|\__\_\
|
||||
|
Reference in New Issue
Block a user