Compare commits

...

7 Commits

21 changed files with 294 additions and 49 deletions

View File

@@ -33,12 +33,15 @@ Once the JAR file is built, you can run it using
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;<code>index.html</code></td><td>HTML template</td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;<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>&nbsp;&nbsp;&nbsp;&nbsp;<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>&nbsp;&nbsp;&nbsp;&nbsp;<code>server-layout.ts</code></td><td>Blank layout Web Component for server-side Java/Kotlin views</td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;<code>views/</code></td><td>UI views Web Components (TypeScript)</td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;<code>themes/</code></td><td>Custom
CSS styles</td></tr>
<tr><td><code>src/main/java/&lt;groupId&gt;/</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>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;<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>&nbsp;&nbsp;&nbsp;&nbsp;<code>Application.kt</code></td><td>Server entry-point</td></tr>
</table>
## Deploying using Docker

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Fusion Management</title>
<title>CUBETIQ Fusion</title>
<style>
body {
margin: 0;

View File

@@ -1,9 +1,17 @@
import { Flow } from "@vaadin/flow-frontend";
import { Route } from '@vaadin/router';
import Role from './generated/com/cubetiqs/fusion/data/Role';
import { appStore } from './stores/app-store';
import './views/home/home-view';
import './views/main-layout';
const { serverSideRoutes } = new Flow({
imports: () => import('../target/frontend/generated-flow-imports'),
});
console.log("serverSideRoutes", serverSideRoutes)
export type ViewRoute = Route & {
title?: string;
icon?: string;
@@ -62,11 +70,6 @@ export const views: ViewRoute[] = [
},
];
export const routes: ViewRoute[] = [
{
path: '',
component: 'main-layout',
children: [...views],
},
{
path: 'login',
component: 'login-view',
@@ -77,4 +80,18 @@ export const routes: ViewRoute[] = [
return;
},
},
{
path: '',
component: 'main-layout',
children: [
...views,
],
},
{
path: '',
component: 'server-layout',
children: [
...serverSideRoutes,
]
}
];

View File

@@ -30,7 +30,7 @@ export class LoginView extends View {
action="login"
no-forgot-password
.i18n=${Object.assign(
{ header: { title: 'Fusion Management', description: 'Login using user/user or admin/admin' } },
{ header: { title: 'Fusion', description: 'Login using user/user or admin/admin' } },
loginI18nDefault
)}
>

View 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></>`;
}
}

View File

@@ -90,6 +90,8 @@
},
"vaadin": {
"dependencies": {
"@adobe/lit-mobx": "2.0.0-rc.4",
"@fontsource/roboto": "4.5.0",
"@polymer/iron-icon": "3.0.1",
"@polymer/iron-list": "3.1.0",
"@polymer/polymer": "3.2.0",
@@ -139,7 +141,9 @@
"@vaadin/vaadin-upload": "21.0.0-alpha13",
"@vaadin/vaadin-virtual-list": "21.0.0-alpha13",
"construct-style-sheets-polyfill": "2.4.16",
"lit": "2.0.0-rc.1"
"line-awesome": "1.3.0",
"lit": "2.0.0-rc.1",
"mobx": "^6.1.5"
},
"devDependencies": {
"@types/validator": "13.1.0",

43
pom.xml
View File

@@ -22,47 +22,31 @@
</parent>
<repositories>
<!-- The order of definitions matters. Explicitly defining central here to make sure it has the highest priority. -->
<!-- Main Maven repository -->
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
<id>CUBETIQ Directory</id>
<url>https://m.ctdn.net</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>vaadin-prereleases</id>
<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>
<id>CUBETIQ Directory Snapshots</id>
<url>https://m.ctdn.net/snapshots</url>
<snapshots>
<enabled>false</enabled>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<!-- The order of definitions matters. Explicitly defining central here to make sure it has the highest priority. -->
<pluginRepository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
<id>CUBETIQ Directory</id>
<url>https://m.ctdn.net</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>vaadin-prereleases</id>
<url>
https://maven.vaadin.com/vaadin-prereleases/
</url>
</pluginRepository>
</pluginRepositories>
<dependencyManagement>
@@ -78,6 +62,12 @@
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.cubetiqs</groupId>
<artifactId>cui</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
@@ -89,7 +79,6 @@
<dependency>
<groupId>com.vaadin</groupId>
<!-- Replace artifactId with vaadin-core to use only free components -->
<artifactId>vaadin</artifactId>
</dependency>
<dependency>
@@ -106,7 +95,6 @@
<artifactId>a-vaadin-helper</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>org.vaadin.artur.exampledata</groupId>
<artifactId>exampledata</artifactId>
@@ -118,11 +106,11 @@
<artifactId>h2</artifactId>
</dependency>
<!-- Spring and Frameworks-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
@@ -133,6 +121,7 @@
<optional>true</optional>
</dependency>
<!-- Test Framework-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>

View File

@@ -33,6 +33,9 @@ public class SecurityConfiguration extends VaadinWebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
web.ignoring().antMatchers("/images/logo.png");
web.ignoring()
.antMatchers(
"/images/logo.png"
);
}
}

View File

@@ -1,17 +1,24 @@
package com.cubetiqs.fusion
import org.springframework.boot.autoconfigure.SpringBootApplication
import com.vaadin.flow.server.PWA
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
import com.vaadin.flow.component.dependency.NpmPackage
import com.vaadin.flow.component.page.AppShellConfigurator
import com.vaadin.flow.server.PWA
import com.vaadin.flow.theme.Theme
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
@SpringBootApplication
@Theme(value = "fusionmanagement")
@PWA(name = "Fusion Management", shortName = "Fusion Management", offlineResources = ["images/logo.png"])
@Theme(value = "fusion")
@PWA(name = "CUBETIQ Fusion", shortName = "Fusion", offlineResources = ["images/logo.png"])
@NpmPackage.Container(
NpmPackage(value = "@fontsource/roboto", version = "4.5.0"),
NpmPackage(value = "@adobe/lit-mobx", version = "2.0.0-rc.4"),
NpmPackage(value = "mobx", version = "^6.1.5"),
NpmPackage(value = "line-awesome", version = "1.3.0"),
)
class Application : SpringBootServletInitializer(), AppShellConfigurator
fun main(args: Array<String>) {
SpringApplication.run(Application::class.java, *args)
runApplication<Application>(*args)
}

View File

@@ -0,0 +1,6 @@
package com.cubetiqs.fusion.config
import org.springframework.context.annotation.Configuration
@Configuration
class DefaultConfig

View File

@@ -0,0 +1,5 @@
package com.cubetiqs.fusion.frontend
import com.vaadin.flow.component.UI
class MainView : UI()

View File

@@ -0,0 +1,170 @@
package com.cubetiqs.fusion.frontend.views.test
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.server.auth.AnonymousAllowed
import java.util.*
@Route("/test")
@AnonymousAllowed
class TestView : CDiv(), TinyMceInjectable {
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
}
}
}

View File

@@ -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)
}

View File

@@ -0,0 +1,2 @@
server:
port: 8081

View File

@@ -1,11 +1,11 @@
server:
port: ${PORT:8080}
logging:
level:
org.atmosphere: warn
org:
atmosphere: warn
spring:
profiles:
active: ${APP_PROFILE:dev}
mustache:
check-template-location: false