feat: updated subproject 'editor'

This commit is contained in:
Andrey Terentev 2025-01-15 02:11:59 +07:00
parent a7279b9891
commit 795b9bb640
20 changed files with 375 additions and 38 deletions

39
editor/.gitignore vendored
View File

@ -1,38 +1,3 @@
node_modules node_modules
HELP.md **/frontend/generated/
.gradle .vaadin-node-tasks.lock
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/

View File

@ -16,8 +16,11 @@ ext {
} }
dependencies { dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework:spring-aspects'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'org.postgresql:postgresql'
implementation 'com.vaadin:vaadin-spring-boot-starter' implementation 'com.vaadin:vaadin-spring-boot-starter'

View File

@ -0,0 +1,23 @@
-- Table definitions
create domain dialogue_package_id as
varchar(32) not null;
create domain dialogue_id as
varchar(64) not null;
create table dialogue_packages (
id dialogue_package_id primary key,
comment text not null
);
create table dialogues (
id dialogue_id primary key,
package dialogue_package_id,
comment text not null,
ctx json not null,
foreign key (package) references dialogue_packages (id)
);

View File

@ -0,0 +1 @@
-- Default inserts

View File

@ -0,0 +1,2 @@
FROM postgres:latest
COPY *.sql /docker-entrypoint-initdb.d/

13
editor/docker-compose.yml Normal file
View File

@ -0,0 +1,13 @@
version: "3"
services:
postgres:
image: msb3_postgresql
build:
context: ./database
restart: always
environment:
POSTGRES_DB: 'postgres'
POSTGRES_USER: 'postgres'
POSTGRES_PASSWORD: 'some_password'
ports: [ '5432:5432' ]

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
body, #outlet {
height: 100vh;
width: 100%;
margin: 0;
}
</style>
<title>MSB3 Control Panel</title>
</head>
<body>
<div id="outlet"></div>
</body>
</html>

View File

@ -0,0 +1,49 @@
package ru.dragonestia.editor.component;
import com.vaadin.flow.component.Unit;
import com.vaadin.flow.component.details.Details;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.html.Hr;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextArea;
import ru.dragonestia.editor.model.DialogueContext;
public class DialogEditor extends VerticalLayout {
private final DialogueContext ctx;
public DialogEditor(DialogueContext ctx) {
this.ctx = ctx;
add(new H2("Редактор диалога"));
var commentDetail = new Details("Комментарий");
commentDetail.setWidth("100%");
commentDetail.add(createFieldComment());
commentDetail.setOpened(!(ctx.getComment() == null || ctx.getComment().isEmpty()));
add(commentDetail);
add(new Hr());
add(createFieldText());
}
private TextArea createFieldComment() {
var field = new TextArea("Комментарий");
field.setWidth(100, Unit.PERCENTAGE);
field.setMinHeight(10, Unit.REM);
field.setHelperText("Здесь можно описать какой-нибудь комментарий по поводу диалога. Эта информация имеет роль заметки для разработчиков");
field.setPlaceholder("Какая-то заметка для разработчика");
if (ctx.getComment() != null) field.setValue(ctx.getComment());
return field;
}
private TextArea createFieldText() {
var field = new TextArea("Текст диалога");
field.setRequired(true);
field.setWidth(100, Unit.PERCENTAGE);
field.setMinHeight(10, Unit.REM);
if (ctx.getText() != null) field.setValue(ctx.getText());
return field;
}
}

View File

@ -0,0 +1,32 @@
package ru.dragonestia.editor.model;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import ru.dragonestia.editor.model.converter.DialogueContextConverter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "dialogues")
public class Dialogue {
@Id
@Column(name = "id", columnDefinition = "dialogue_id")
private String id;
@JoinColumn(name = "package")
@ManyToOne(fetch = FetchType.EAGER)
private DialoguePackage dialoguePackage;
@Column(name = "comment")
private String comment;
@Convert(converter = DialogueContextConverter.class)
@Column(name = "ctx", columnDefinition = "json")
private DialogueContext ctx;
}

View File

@ -0,0 +1,13 @@
package ru.dragonestia.editor.model;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class DialogueContext {
private String id;
private String text;
private String comment;
}

View File

@ -0,0 +1,26 @@
package ru.dragonestia.editor.model;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "dialogue_packages")
public class DialoguePackage {
@Id
@Column(name = "id", columnDefinition = "dialogue_package_id")
private String id;
@Column(name = "comment")
private String comment;
}

View File

@ -0,0 +1,20 @@
package ru.dragonestia.editor.model.converter;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
import ru.dragonestia.editor.model.DialogueContext;
import ru.dragonestia.editor.util.JsonUtils;
@Converter
public class DialogueContextConverter implements AttributeConverter<DialogueContext, String> {
@Override
public String convertToDatabaseColumn(DialogueContext ctx) {
return JsonUtils.toJson(ctx);
}
@Override
public DialogueContext convertToEntityAttribute(String json) {
return JsonUtils.fromJson(json);
}
}

View File

@ -0,0 +1,81 @@
package ru.dragonestia.editor.page;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.BeforeLeaveEvent;
import com.vaadin.flow.router.BeforeLeaveObserver;
import java.util.Optional;
public class Page extends VerticalLayout implements BeforeEnterObserver, BeforeLeaveObserver {
protected void init(QueryParams params) {}
protected void destroy() {}
@Override
public final void beforeEnter(BeforeEnterEvent event) {
init(key -> event.getRouteParameters().get(key));
}
@Override
public final void beforeLeave(BeforeLeaveEvent event) {
destroy();
}
public interface QueryParams {
Optional<String> String(String key);
default Optional<Integer> Integer(String key) {
return String(key).map(str -> {
try {
return Integer.parseInt(str);
} catch (Exception ex) {
return null;
}
});
}
default Optional<Long> Long(String key) {
return String(key).map(str -> {
try {
return Long.parseLong(str);
} catch (Exception ex) {
return null;
}
});
}
default Optional<Float> Float(String key) {
return String(key).map(str -> {
try {
return Float.parseFloat(str);
} catch (Exception ex) {
return null;
}
});
}
default Optional<Double> Double(String key) {
return String(key).map(str -> {
try {
return Double.parseDouble(str);
} catch (Exception ex) {
return null;
}
});
}
default Optional<Boolean> Boolean(String key) {
return String(key).map(str -> {
try {
return Boolean.parseBoolean(str);
} catch (Exception ex) {
return null;
}
});
}
}
}

View File

@ -0,0 +1,15 @@
package ru.dragonestia.editor.page;
import com.vaadin.flow.router.Route;
import ru.dragonestia.editor.component.DialogEditor;
import ru.dragonestia.editor.model.DialogueContext;
@Route("/")
public class TestPage extends Page {
@Override
protected void init(QueryParams params) {
var ctx = new DialogueContext();
add(new DialogEditor(ctx));
}
}

View File

@ -0,0 +1,6 @@
package ru.dragonestia.editor.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import ru.dragonestia.editor.model.DialoguePackage;
public interface DialoguePackageRepository extends JpaRepository<DialoguePackage, String> {}

View File

@ -0,0 +1,6 @@
package ru.dragonestia.editor.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import ru.dragonestia.editor.model.Dialogue;
public interface DialogueRepository extends JpaRepository<Dialogue, String> {}

View File

@ -0,0 +1,9 @@
package ru.dragonestia.editor.service;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class DialoguePackageService {
}

View File

@ -0,0 +1,30 @@
package ru.dragonestia.editor.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
import lombok.experimental.UtilityClass;
@UtilityClass
public class JsonUtils {
private final ObjectMapper mapper = new ObjectMapper();
private final ObjectWriter writer = mapper.writer();
private final ObjectReader reader = mapper.reader();
public String toJson(Object object) {
try {
return writer.writeValueAsString(object);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public <T> T fromJson(String json) {
try {
return reader.readValue(json);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}

View File

@ -2,5 +2,17 @@ spring:
application: application:
name: 'editor' name: 'editor'
datasource:
url: ${BFF_POSTGRES_URL:jdbc:postgresql://localhost:5432/postgres}
username: ${BFF_POSTGRES_USERNAME:postgres}
password: ${BFF_POSTGRES_PASSWORD:some_password}
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
hibernate:
ddl-auto: validate
server: server:
port: 8080 port: 8080

View File

@ -0,0 +1,11 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="design-properties" content="{&quot;RULERS_VISIBLE&quot;:true,&quot;GUIDELINES_VISIBLE&quot;:false,&quot;SNAP_TO_OBJECTS&quot;:true,&quot;SNAP_TO_GRID&quot;:true,&quot;SNAPPING_DISTANCE&quot;:10,&quot;GENERATE_GETTERS&quot;:false,&quot;JAVA_SOURCES_ROOT&quot;:&quot;../../src/main/java&quot;,&quot;THEME&quot;:&quot;valo&quot;}">
<meta name="vaadin-version" content="8.1.5">
</head>
<body>
<vaadin-vertical-layout size-full></vaadin-vertical-layout>
</body>
</html>