Compare commits
5 Commits
05e6fe2447
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a568dcac00 | |||
| 255c972234 | |||
| 8035f05662 | |||
| a6bc64b7d1 | |||
| 5a9930161b |
@@ -33,12 +33,15 @@ Once the JAR file is built, you can run it using
|
|||||||
<tr><td> <code>index.html</code></td><td>HTML template</td></tr>
|
<tr><td> <code>index.html</code></td><td>HTML template</td></tr>
|
||||||
<tr><td> <code>index.ts</code></td><td>Frontend entrypoint, contains the client-side routing setup using <a href="https://vaadin.com/router">Vaadin Router</a></td></tr>
|
<tr><td> <code>index.ts</code></td><td>Frontend entrypoint, contains the client-side routing setup using <a href="https://vaadin.com/router">Vaadin Router</a></td></tr>
|
||||||
<tr><td> <code>main-layout.ts</code></td><td>Main layout Web Component, contains the navigation menu, uses <a href="https://vaadin.com/components/vaadin-app-layout">App Layout</a></td></tr>
|
<tr><td> <code>main-layout.ts</code></td><td>Main layout Web Component, contains the navigation menu, uses <a href="https://vaadin.com/components/vaadin-app-layout">App Layout</a></td></tr>
|
||||||
|
<tr><td> <code>server-layout.ts</code></td><td>Blank layout Web Component for server-side Java/Kotlin views</td></tr>
|
||||||
<tr><td> <code>views/</code></td><td>UI views Web Components (TypeScript)</td></tr>
|
<tr><td> <code>views/</code></td><td>UI views Web Components (TypeScript)</td></tr>
|
||||||
<tr><td> <code>themes/</code></td><td>Custom
|
<tr><td> <code>themes/</code></td><td>Custom
|
||||||
CSS styles</td></tr>
|
CSS styles</td></tr>
|
||||||
<tr><td><code>src/main/java/<groupId>/</code></td><td>Server-side
|
<tr><td><code>src/main/java/com/cubetiqs/fusion</code></td><td>Server-side
|
||||||
source directory, contains the server-side Java views</td></tr>
|
source directory, contains the server-side Java views</td></tr>
|
||||||
<tr><td> <code>Application.java</code></td><td>Server entry-point</td></tr>
|
<tr><td><code>src/main/kotlin/com/cubetiqs/fusion</code></td><td>Server-side
|
||||||
|
source directory, contains the server-side Kotlin views</td></tr>
|
||||||
|
<tr><td> <code>Application.kt</code></td><td>Server entry-point</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
## Deploying using Docker
|
## Deploying using Docker
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>Fusion Management</title>
|
<title>CUBETIQ Fusion</title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ const { serverSideRoutes } = new Flow({
|
|||||||
imports: () => import('../target/frontend/generated-flow-imports'),
|
imports: () => import('../target/frontend/generated-flow-imports'),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
console.log("serverSideRoutes", serverSideRoutes)
|
||||||
|
|
||||||
export type ViewRoute = Route & {
|
export type ViewRoute = Route & {
|
||||||
title?: string;
|
title?: string;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
@@ -67,15 +70,6 @@ export const views: ViewRoute[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
export const routes: ViewRoute[] = [
|
export const routes: ViewRoute[] = [
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: 'main-layout',
|
|
||||||
children: [
|
|
||||||
...views,
|
|
||||||
// for server-side, the next magic line sends all unmatched routes:
|
|
||||||
...serverSideRoutes, // IMPORTANT: this must be the last entry in the array
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: 'login',
|
path: 'login',
|
||||||
component: 'login-view',
|
component: 'login-view',
|
||||||
@@ -86,4 +80,18 @@ export const routes: ViewRoute[] = [
|
|||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: 'main-layout',
|
||||||
|
children: [
|
||||||
|
...views,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: 'server-layout',
|
||||||
|
children: [
|
||||||
|
...serverSideRoutes,
|
||||||
|
]
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
10
frontend/views/server-layout.ts
Normal file
10
frontend/views/server-layout.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { html } from 'lit';
|
||||||
|
import { customElement } from 'lit/decorators.js';
|
||||||
|
import {Layout} from "./view";
|
||||||
|
|
||||||
|
@customElement('server-layout')
|
||||||
|
export class AdminView extends Layout {
|
||||||
|
render() {
|
||||||
|
return html`<><slot></slot></>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
pom.xml
39
pom.xml
@@ -22,47 +22,31 @@
|
|||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
<!-- The order of definitions matters. Explicitly defining central here to make sure it has the highest priority. -->
|
|
||||||
|
|
||||||
<!-- Main Maven repository -->
|
|
||||||
<repository>
|
<repository>
|
||||||
<id>central</id>
|
<id>CUBETIQ Directory</id>
|
||||||
<url>https://repo.maven.apache.org/maven2</url>
|
<url>https://m.ctdn.net</url>
|
||||||
<snapshots>
|
<snapshots>
|
||||||
<enabled>false</enabled>
|
<enabled>false</enabled>
|
||||||
</snapshots>
|
</snapshots>
|
||||||
</repository>
|
</repository>
|
||||||
|
|
||||||
<repository>
|
<repository>
|
||||||
<id>vaadin-prereleases</id>
|
<id>CUBETIQ Directory Snapshots</id>
|
||||||
<url>
|
<url>https://m.ctdn.net/snapshots</url>
|
||||||
https://maven.vaadin.com/vaadin-prereleases/
|
|
||||||
</url>
|
|
||||||
</repository>
|
|
||||||
<!-- Repository used by many Vaadin add-ons -->
|
|
||||||
<repository>
|
|
||||||
<id>Vaadin Directory</id>
|
|
||||||
<url>https://maven.vaadin.com/vaadin-addons</url>
|
|
||||||
<snapshots>
|
<snapshots>
|
||||||
<enabled>false</enabled>
|
<enabled>true</enabled>
|
||||||
</snapshots>
|
</snapshots>
|
||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<pluginRepositories>
|
<pluginRepositories>
|
||||||
<!-- The order of definitions matters. Explicitly defining central here to make sure it has the highest priority. -->
|
|
||||||
<pluginRepository>
|
<pluginRepository>
|
||||||
<id>central</id>
|
<id>CUBETIQ Directory</id>
|
||||||
<url>https://repo.maven.apache.org/maven2</url>
|
<url>https://m.ctdn.net</url>
|
||||||
<snapshots>
|
<snapshots>
|
||||||
<enabled>false</enabled>
|
<enabled>false</enabled>
|
||||||
</snapshots>
|
</snapshots>
|
||||||
</pluginRepository>
|
</pluginRepository>
|
||||||
<pluginRepository>
|
|
||||||
<id>vaadin-prereleases</id>
|
|
||||||
<url>
|
|
||||||
https://maven.vaadin.com/vaadin-prereleases/
|
|
||||||
</url>
|
|
||||||
</pluginRepository>
|
|
||||||
</pluginRepositories>
|
</pluginRepositories>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
@@ -78,6 +62,12 @@
|
|||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.cubetiqs</groupId>
|
||||||
|
<artifactId>cui</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
<artifactId>kotlin-reflect</artifactId>
|
<artifactId>kotlin-reflect</artifactId>
|
||||||
@@ -89,7 +79,6 @@
|
|||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.vaadin</groupId>
|
<groupId>com.vaadin</groupId>
|
||||||
<!-- Replace artifactId with vaadin-core to use only free components -->
|
|
||||||
<artifactId>vaadin</artifactId>
|
<artifactId>vaadin</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import com.vaadin.flow.component.dependency.NpmPackage
|
|||||||
import com.vaadin.flow.component.page.AppShellConfigurator
|
import com.vaadin.flow.component.page.AppShellConfigurator
|
||||||
import com.vaadin.flow.server.PWA
|
import com.vaadin.flow.server.PWA
|
||||||
import com.vaadin.flow.theme.Theme
|
import com.vaadin.flow.theme.Theme
|
||||||
import org.springframework.boot.SpringApplication
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||||
|
import org.springframework.boot.runApplication
|
||||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
|
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@Theme(value = "fusionmanagement")
|
@Theme(value = "fusion")
|
||||||
@PWA(name = "Fusion Management", shortName = "Fusion Management", offlineResources = ["images/logo.png"])
|
@PWA(name = "CUBETIQ Fusion", shortName = "Fusion", offlineResources = ["images/logo.png"])
|
||||||
@NpmPackage.Container(
|
@NpmPackage.Container(
|
||||||
NpmPackage(value = "@fontsource/roboto", version = "4.5.0"),
|
NpmPackage(value = "@fontsource/roboto", version = "4.5.0"),
|
||||||
NpmPackage(value = "@adobe/lit-mobx", version = "2.0.0-rc.4"),
|
NpmPackage(value = "@adobe/lit-mobx", version = "2.0.0-rc.4"),
|
||||||
@@ -20,5 +20,5 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
|
|||||||
class Application : SpringBootServletInitializer(), AppShellConfigurator
|
class Application : SpringBootServletInitializer(), AppShellConfigurator
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
SpringApplication.run(Application::class.java, *args)
|
runApplication<Application>(*args)
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,170 @@
|
|||||||
package com.cubetiqs.fusion.frontend.views.test
|
package com.cubetiqs.fusion.frontend.views.test
|
||||||
|
|
||||||
import com.vaadin.flow.component.html.Div
|
import com.cubetiqs.cui.component.dialog.ConfirmDialog
|
||||||
|
import com.cubetiqs.cui.component.element.CDiv
|
||||||
|
import com.cubetiqs.cui.component.element.CSizeBox
|
||||||
|
import com.cubetiqs.cui.dsl.*
|
||||||
|
import com.cubetiqs.cui.inject.tinymce.TinyMceInjectable
|
||||||
|
import com.cubetiqs.cui.notification.Alert
|
||||||
|
import com.cubetiqs.cui.style.BoxShadow
|
||||||
|
import com.cubetiqs.cui.style.Height
|
||||||
|
import com.cubetiqs.cui.style.Padding
|
||||||
|
import com.vaadin.flow.component.AttachEvent
|
||||||
|
import com.vaadin.flow.component.button.ButtonVariant
|
||||||
|
import com.vaadin.flow.component.icon.VaadinIcon
|
||||||
|
import com.vaadin.flow.component.orderedlayout.FlexComponent
|
||||||
import com.vaadin.flow.router.Route
|
import com.vaadin.flow.router.Route
|
||||||
|
import com.vaadin.flow.server.auth.AnonymousAllowed
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
@Route("/views/test")
|
@Route("/test")
|
||||||
class TestView : Div() {
|
@AnonymousAllowed
|
||||||
init {
|
class TestView : CDiv(), TinyMceInjectable {
|
||||||
add("Hello World")
|
private val container = createDiv { }
|
||||||
|
|
||||||
|
private fun addAnswer() {
|
||||||
|
val editorId = "editor-${UUID.randomUUID()}"
|
||||||
|
val editor = createDiv {
|
||||||
|
setId(editorId)
|
||||||
|
addDiv {
|
||||||
|
|
||||||
|
setStyle(BoxShadow())
|
||||||
|
setStyle(Padding.All("10px"))
|
||||||
|
|
||||||
|
addHorizontalLayout {
|
||||||
|
addButton {
|
||||||
|
width = "10%"
|
||||||
|
var checked = false
|
||||||
|
addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE)
|
||||||
|
icon = createIcon(VaadinIcon.CHECK_CIRCLE_O) { }
|
||||||
|
|
||||||
|
addClickListener {
|
||||||
|
this.icon = if (checked) {
|
||||||
|
checked = false
|
||||||
|
createIcon(VaadinIcon.CHECK_CIRCLE_O) { }
|
||||||
|
} else {
|
||||||
|
checked = true
|
||||||
|
createIcon(VaadinIcon.CHECK_CIRCLE) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val editorContent = createTinyMceEditor {
|
||||||
|
width = "80%"
|
||||||
|
setId("$editorId-content")
|
||||||
|
enabledMathMode()
|
||||||
|
isInlineMode(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
add(editorContent)
|
||||||
|
|
||||||
|
addButton {
|
||||||
|
width = "10%"
|
||||||
|
addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE)
|
||||||
|
icon = createIcon(VaadinIcon.TRASH) {
|
||||||
|
color = "red"
|
||||||
|
}
|
||||||
|
|
||||||
|
addClickListener {
|
||||||
|
var isConfirm = false
|
||||||
|
val ct = editorContent.currentValue
|
||||||
|
if (ct.isNotBlank()) {
|
||||||
|
val confirm = ConfirmDialog(
|
||||||
|
"Are you sure?",
|
||||||
|
"Really want to delete the answering content...",
|
||||||
|
"Okay"
|
||||||
|
) {
|
||||||
|
removeElement(editorId)
|
||||||
|
}
|
||||||
|
|
||||||
|
add(confirm)
|
||||||
|
|
||||||
|
confirm.open()
|
||||||
|
|
||||||
|
isConfirm = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isConfirm) {
|
||||||
|
removeElement(editorId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add(CSizeBox(height = 10.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
container.add(editor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAttach(attachEvent: AttachEvent?) {
|
||||||
|
super.onAttach(attachEvent)
|
||||||
|
|
||||||
|
init()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun init() {
|
||||||
|
addBr(3)
|
||||||
|
|
||||||
|
addHorizontalLayout {
|
||||||
|
setWidthFull()
|
||||||
|
|
||||||
|
addDiv {
|
||||||
|
addDiv {
|
||||||
|
withStyle {
|
||||||
|
BoxShadow()
|
||||||
|
}
|
||||||
|
|
||||||
|
withStyle {
|
||||||
|
Padding.All("10px")
|
||||||
|
}
|
||||||
|
|
||||||
|
minHeight = "150px"
|
||||||
|
width = "500px"
|
||||||
|
addTinyMceEditor {
|
||||||
|
enabledMathMode()
|
||||||
|
isInlineMode(true)
|
||||||
|
getEditorElement().setStyle(Height.Min("150px"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addBr()
|
||||||
|
|
||||||
|
addDiv {
|
||||||
|
width = "500px"
|
||||||
|
setStyle(Padding.All("10px"))
|
||||||
|
|
||||||
|
addHorizontalLayout {
|
||||||
|
addButton {
|
||||||
|
text = "Add new answer"
|
||||||
|
|
||||||
|
addClickListener {
|
||||||
|
addAnswer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addSizedBox {
|
||||||
|
width = "10px"
|
||||||
|
}
|
||||||
|
|
||||||
|
addButton {
|
||||||
|
text = "See Answer Count"
|
||||||
|
|
||||||
|
addClickListener {
|
||||||
|
Alert.Companion.show("You clicked see answer...")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addBr(2)
|
||||||
|
|
||||||
|
add(container)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
justifyContentMode = FlexComponent.JustifyContentMode.CENTER
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.cubetiqs.fusion.frontend.views.user
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.grid.Grid
|
||||||
|
import com.vaadin.flow.component.html.Div
|
||||||
|
import com.vaadin.flow.router.PageTitle
|
||||||
|
import com.vaadin.flow.router.Route
|
||||||
|
import com.vaadin.flow.server.auth.AnonymousAllowed
|
||||||
|
|
||||||
|
@Route("/users")
|
||||||
|
@PageTitle("All Users")
|
||||||
|
@AnonymousAllowed
|
||||||
|
class UserView : Div() {
|
||||||
|
private fun generateUsers(): Collection<User> {
|
||||||
|
val users = mutableListOf<User>()
|
||||||
|
for (i in 1..1000000) {
|
||||||
|
users.add(User(i, "user-${"$i".padStart(6, '0')}", "MY USER - $i", "$i".padEnd(9, '0')))
|
||||||
|
}
|
||||||
|
|
||||||
|
return users
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
val grid = Grid(User::class.java)
|
||||||
|
grid.setItems(generateUsers())
|
||||||
|
add(grid)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class User(val id: Int, val username: String, val name: String, val phone: String)
|
||||||
|
}
|
||||||
2
src/main/resources/application-dev.yml
Normal file
2
src/main/resources/application-dev.yml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
server:
|
||||||
|
port: 8081
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
server:
|
|
||||||
port: ${PORT:8080}
|
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
level:
|
level:
|
||||||
org:
|
org:
|
||||||
atmosphere: warn
|
atmosphere: warn
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
|
profiles:
|
||||||
|
active: ${APP_PROFILE:dev}
|
||||||
mustache:
|
mustache:
|
||||||
check-template-location: false
|
check-template-location: false
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user