Compare commits
No commits in common. "95af96868d048349be35e15ede8db30c6859a9e2" and "4c47281c779945af193711d3750660c5a5a188cb" have entirely different histories.
95af96868d
...
4c47281c77
@ -31,8 +31,6 @@ dependencies {
|
|||||||
|
|
||||||
api 'net.minestom:minestom-snapshots:8209a1d1e9' // stableVersion: 1_21_4-6490538291
|
api 'net.minestom:minestom-snapshots:8209a1d1e9' // stableVersion: 1_21_4-6490538291
|
||||||
|
|
||||||
api 'de.articdive:jnoise-pipeline:4.1.0'
|
|
||||||
|
|
||||||
api 'org.slf4j:slf4j-api:2.0.16'
|
api 'org.slf4j:slf4j-api:2.0.16'
|
||||||
api 'org.apache.logging.log4j:log4j-slf4j2-impl:2.24.0'
|
api 'org.apache.logging.log4j:log4j-slf4j2-impl:2.24.0'
|
||||||
api 'org.apache.logging.log4j:log4j-api:2.24.0'
|
api 'org.apache.logging.log4j:log4j-api:2.24.0'
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import net.kyori.adventure.sound.Sound;
|
|||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.TextColor;
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
import net.kyori.adventure.text.format.TextDecoration;
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
import net.minestom.server.MinecraftServer;
|
|
||||||
import net.minestom.server.entity.Player;
|
import net.minestom.server.entity.Player;
|
||||||
import net.minestom.server.sound.SoundEvent;
|
import net.minestom.server.sound.SoundEvent;
|
||||||
|
|
||||||
@ -33,26 +32,4 @@ public class DebugMessage {
|
|||||||
.append(Component.text(message, TextColor.color(0xFF6A6B)))
|
.append(Component.text(message, TextColor.color(0xFF6A6B)))
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void broadcast(String message) {
|
|
||||||
if (!Debug.isEnabled()) return;
|
|
||||||
|
|
||||||
for (var player: MinecraftServer.getConnectionManager().getOnlinePlayers()) {
|
|
||||||
player.sendMessage(Component.text()
|
|
||||||
.append(Component.text("[DEBUG] ", TextColor.color(0xFFC909), TextDecoration.BOLD))
|
|
||||||
.append(Component.text(message, TextColor.color(0xFFD297)))
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void broadcastError(String message) {
|
|
||||||
if (!Debug.isEnabled()) return;
|
|
||||||
for (var player: MinecraftServer.getConnectionManager().getOnlinePlayers()) {
|
|
||||||
player.sendMessage(Component.text()
|
|
||||||
.append(Component.text("[DEBUG] ", TextColor.color(0xFFC909), TextDecoration.BOLD))
|
|
||||||
.append(Component.text("Error: ", TextColor.color(0xFF3F3F)))
|
|
||||||
.append(Component.text(message, TextColor.color(0xFF6A6B)))
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ public class DialogDialogActionHandler implements DialogActionHandler {
|
|||||||
public void handle(DialogButtonClick click, Params params) {
|
public void handle(DialogButtonClick click, Params params) {
|
||||||
var player = click.player();
|
var player = click.player();
|
||||||
|
|
||||||
if (!params.contains("dialogId")) {
|
if (params.contains("dialogId")) {
|
||||||
DebugMessage.sendError(player, "Отсутствует обязательный параметр dialogId для команды dialog");
|
DebugMessage.sendError(player, "Отсутствует обязательный параметр dialogId для команды dialog");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ public class ScriptDialogActionHandler implements DialogActionHandler {
|
|||||||
public void handle(DialogButtonClick click, Params params) {
|
public void handle(DialogButtonClick click, Params params) {
|
||||||
var player = click.player();
|
var player = click.player();
|
||||||
|
|
||||||
if (!params.contains("scriptId")) {
|
if (params.contains("scriptId")) {
|
||||||
DebugMessage.sendError(player, "Отсутствует обязательный параметр scriptId для команды script");
|
DebugMessage.sendError(player, "Отсутствует обязательный параметр scriptId для команды script");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -27,7 +27,6 @@ public class ScriptDialogActionHandler implements DialogActionHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
click.renderer().close(false);
|
|
||||||
ScriptService.ofPlayer(player).start(script.get(), params);
|
ScriptService.ofPlayer(player).start(script.get(), params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@ public class PlayerEventMetrics {
|
|||||||
CompletableFuture.runAsync(() -> {
|
CompletableFuture.runAsync(() -> {
|
||||||
log.debug("Sending event '{}' for player '{}'({}) with data '{}'", eventName, player.getUsername(), player.getUuid(), GSON.toJson(details));
|
log.debug("Sending event '{}' for player '{}'({}) with data '{}'", eventName, player.getUsername(), player.getUuid(), GSON.toJson(details));
|
||||||
try (var con = sql2o.open()) {
|
try (var con = sql2o.open()) {
|
||||||
con.createQuery("insert into msb3.events_buffer (uuid, player_name, timestamp, event_type, details) values (:uuid, :player_name, now(), :event_type, :details)", false)
|
con.createQuery("insert into events (uuid, player_name, timestamp, event_type, details) values (:uuid, :player_name, now(), :event_type, :details)", false)
|
||||||
.addParameter("uuid", player.getUuid())
|
.addParameter("uuid", player.getUuid())
|
||||||
.addParameter("player_name", player.getUsername())
|
.addParameter("player_name", player.getUsername())
|
||||||
.addParameter("event_type", eventName)
|
.addParameter("event_type", eventName)
|
||||||
|
|||||||
@ -21,8 +21,8 @@ public class NavigatorContext extends PlayerContext implements Navigator {
|
|||||||
private final static Component EMPTY = Component.text(" ");
|
private final static Component EMPTY = Component.text(" ");
|
||||||
|
|
||||||
private BossBar bossBar;
|
private BossBar bossBar;
|
||||||
private volatile Point target;
|
private Point target;
|
||||||
private volatile String text;
|
private String text;
|
||||||
private MinecraftFont.Text cachedText;
|
private MinecraftFont.Text cachedText;
|
||||||
private boolean prevTargetEmpty = true;
|
private boolean prevTargetEmpty = true;
|
||||||
private boolean enabled = true;
|
private boolean enabled = true;
|
||||||
@ -71,7 +71,6 @@ public class NavigatorContext extends PlayerContext implements Navigator {
|
|||||||
prevTargetEmpty = this.target == null;
|
prevTargetEmpty = this.target == null;
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.text = text;
|
this.text = text;
|
||||||
cachedText = null;
|
|
||||||
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.util;
|
|
||||||
|
|
||||||
import lombok.experimental.UtilityClass;
|
|
||||||
import net.minestom.server.instance.InstanceContainer;
|
|
||||||
|
|
||||||
@UtilityClass
|
|
||||||
public class ChunkPreloader {
|
|
||||||
|
|
||||||
public void preload(InstanceContainer instance, int startChunkX, int startChunkZ, int endChunkX, int endChunkZ) {
|
|
||||||
record Point(int x, int z) {}
|
|
||||||
|
|
||||||
var min = new Point(Math.min(startChunkX, endChunkX), Math.min(startChunkZ, endChunkZ));
|
|
||||||
var max = new Point(Math.max(startChunkX, endChunkX), Math.max(startChunkZ, endChunkZ));
|
|
||||||
|
|
||||||
for (int chunkX = min.x; chunkX <= max.x; chunkX++) {
|
|
||||||
for (int chunkZ = min.z; chunkZ <= max.z; chunkZ++) {
|
|
||||||
instance.loadChunk(chunkX, chunkZ).join();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -9,6 +9,3 @@ create table if not exists msb3.events
|
|||||||
details Nullable(String)
|
details Nullable(String)
|
||||||
) engine = ReplacingMergeTree partition by toYYYYMM(timestamp)
|
) engine = ReplacingMergeTree partition by toYYYYMM(timestamp)
|
||||||
primary key (uuid, event_type, timestamp);
|
primary key (uuid, event_type, timestamp);
|
||||||
|
|
||||||
create table msb3.events_buffer as msb3.events
|
|
||||||
engine = Buffer(msb3, events, 1, 10, 100, 50, 200, 500, 100000);
|
|
||||||
|
|||||||
@ -1,5 +1,13 @@
|
|||||||
<yandex>
|
<yandex>
|
||||||
<users>
|
<users>
|
||||||
|
<default>
|
||||||
|
<networks replace="replace">
|
||||||
|
<ip>::/1</ip>
|
||||||
|
<ip>127.0.0.1</ip>
|
||||||
|
</networks>
|
||||||
|
<profile>default</profile>
|
||||||
|
<quota>default</quota>
|
||||||
|
</default>
|
||||||
<msb3>
|
<msb3>
|
||||||
<password>example</password>
|
<password>example</password>
|
||||||
<profile>default</profile>
|
<profile>default</profile>
|
||||||
|
|||||||
3
editor/.gitignore
vendored
Normal file
3
editor/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
**/frontend/generated/
|
||||||
|
.vaadin-node-tasks.lock
|
||||||
39
editor/build.gradle
Normal file
39
editor/build.gradle
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
plugins {
|
||||||
|
id 'org.springframework.boot' version '3.4.1'
|
||||||
|
id 'io.spring.dependency-management' version '1.1.7'
|
||||||
|
id 'com.vaadin' version '24.6.1'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
compileOnly {
|
||||||
|
extendsFrom annotationProcessor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ext {
|
||||||
|
set('vaadinVersion', "24.6.1")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
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'
|
||||||
|
|
||||||
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||||
|
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencyManagement {
|
||||||
|
imports {
|
||||||
|
mavenBom "com.vaadin:vaadin-bom:${vaadinVersion}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourcesJar.dependsOn({
|
||||||
|
vaadinPrepareFrontend
|
||||||
|
})
|
||||||
23
editor/database/00-init.sql
Normal file
23
editor/database/00-init.sql
Normal 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)
|
||||||
|
);
|
||||||
|
|
||||||
1
editor/database/01-init-insert.sql
Normal file
1
editor/database/01-init-insert.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
-- Default inserts
|
||||||
2
editor/database/Dockerfile
Normal file
2
editor/database/Dockerfile
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
FROM postgres:latest
|
||||||
|
COPY *.sql /docker-entrypoint-initdb.d/
|
||||||
13
editor/docker-compose.yml
Normal file
13
editor/docker-compose.yml
Normal 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' ]
|
||||||
20
editor/src/main/frontend/index.html
Normal file
20
editor/src/main/frontend/index.html
Normal 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>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package ru.dragonestia.editor;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class EditorApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(EditorApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,158 @@
|
|||||||
|
package ru.dragonestia.editor.component;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.Unit;
|
||||||
|
import com.vaadin.flow.component.button.Button;
|
||||||
|
import com.vaadin.flow.component.button.ButtonVariant;
|
||||||
|
import com.vaadin.flow.component.details.Details;
|
||||||
|
import com.vaadin.flow.component.html.H2;
|
||||||
|
import com.vaadin.flow.component.html.H3;
|
||||||
|
import com.vaadin.flow.component.html.Hr;
|
||||||
|
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||||
|
import com.vaadin.flow.component.notification.Notification;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
|
import com.vaadin.flow.component.textfield.Autocomplete;
|
||||||
|
import com.vaadin.flow.component.textfield.TextArea;
|
||||||
|
import com.vaadin.flow.component.textfield.TextField;
|
||||||
|
import ru.dragonestia.editor.model.DialogueContext;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class DialogEditor extends VerticalLayout {
|
||||||
|
|
||||||
|
private final DialogueContext ctx;
|
||||||
|
private final TextArea fieldComment;
|
||||||
|
private final TextArea fieldText;
|
||||||
|
private final Button buttonNewAnswer;
|
||||||
|
private final AnswersLayout layoutAnswers;
|
||||||
|
private final ArrayList<AnswerComponent> answers = new ArrayList<>();
|
||||||
|
|
||||||
|
public DialogEditor(DialogueContext ctx) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
|
||||||
|
add(new H2("Редактор диалога"));
|
||||||
|
|
||||||
|
var commentDetail = new Details("Комментарий");
|
||||||
|
commentDetail.setWidth("100%");
|
||||||
|
commentDetail.add(fieldComment = createFieldComment());
|
||||||
|
commentDetail.setOpened(!(ctx.getComment() == null || ctx.getComment().isEmpty()));
|
||||||
|
add(commentDetail);
|
||||||
|
|
||||||
|
add(new Hr());
|
||||||
|
|
||||||
|
add(fieldText = createFieldText());
|
||||||
|
|
||||||
|
add(new H3("Ответы диалога"));
|
||||||
|
add(buttonNewAnswer = createButtonNewAnswer());
|
||||||
|
add(layoutAnswers = new AnswersLayout());
|
||||||
|
updateAnswers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextArea createFieldComment() {
|
||||||
|
var field = new TextArea("Комментарий");
|
||||||
|
field.setAutocomplete(Autocomplete.OFF);
|
||||||
|
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.setAutocomplete(Autocomplete.OFF);
|
||||||
|
field.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
field.setMinHeight(10, Unit.REM);
|
||||||
|
if (ctx.getText() != null) field.setValue(ctx.getText());
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Button createButtonNewAnswer() {
|
||||||
|
var button = new Button("Добавить новый ответ", e -> {
|
||||||
|
if (answers.size() >= 4) {
|
||||||
|
Notification.show("Ответов у диалога не может быть больше 4");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var component = new AnswerComponent();
|
||||||
|
|
||||||
|
component.onDelete = answer -> {
|
||||||
|
answers.removeIf(target -> target.uuid.equals(answer.uuid));
|
||||||
|
updateAnswers();
|
||||||
|
};
|
||||||
|
|
||||||
|
answers.add(component);
|
||||||
|
updateAnswers();
|
||||||
|
});
|
||||||
|
button.addThemeVariants(ButtonVariant.LUMO_SUCCESS, ButtonVariant.LUMO_PRIMARY);
|
||||||
|
button.setPrefixComponent(VaadinIcon.PLUS.create());
|
||||||
|
button.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateAnswers() {
|
||||||
|
layoutAnswers.removeAll();
|
||||||
|
for (var component: answers) {
|
||||||
|
layoutAnswers.add(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AnswersLayout extends VerticalLayout {
|
||||||
|
|
||||||
|
private AnswersLayout() {
|
||||||
|
getStyle().set("border", "2px solid #1C6EA4");
|
||||||
|
getStyle().set("border-radius", "26px");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AnswerComponent extends VerticalLayout {
|
||||||
|
|
||||||
|
private final UUID uuid = UUID.randomUUID();
|
||||||
|
private final TextField fieldText;
|
||||||
|
private final TextArea fieldComment;
|
||||||
|
|
||||||
|
private Consumer<AnswerComponent> onDelete;
|
||||||
|
|
||||||
|
private AnswerComponent() {
|
||||||
|
add(fieldText = createFieldText());
|
||||||
|
|
||||||
|
var commentDetail = new Details("Комментарий");
|
||||||
|
commentDetail.setWidth("100%");
|
||||||
|
commentDetail.add(fieldComment = createFieldComment());
|
||||||
|
add(commentDetail);
|
||||||
|
add(createButtonDelete());
|
||||||
|
|
||||||
|
getStyle().set("background-color", "#EEEEEE");
|
||||||
|
getStyle().set("border-radius", "26px");
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextField createFieldText() {
|
||||||
|
var field = new TextField("Текст");
|
||||||
|
field.setAutocomplete(Autocomplete.OFF);
|
||||||
|
field.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextArea createFieldComment() {
|
||||||
|
var field = new TextArea("Комментарий");
|
||||||
|
field.setAutocomplete(Autocomplete.OFF);
|
||||||
|
field.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
field.setMinHeight(10, Unit.REM);
|
||||||
|
field.setHelperText("Здесь можно описать какой-нибудь комментарий по поводу ответа диалога. Эта информация имеет роль заметки для разработчиков");
|
||||||
|
field.setPlaceholder("Какая-то заметка для разработчика");
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Button createButtonDelete() {
|
||||||
|
var button = new Button("Удалить ответ", e -> {
|
||||||
|
if (onDelete != null) onDelete.accept(this);
|
||||||
|
});
|
||||||
|
button.addThemeVariants(ButtonVariant.LUMO_ERROR, ButtonVariant.LUMO_PRIMARY);
|
||||||
|
button.setPrefixComponent(VaadinIcon.TRASH.create());
|
||||||
|
button.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package ru.dragonestia.editor.controller;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import ru.dragonestia.editor.controller.mapper.DialogueMapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class DialogueController {
|
||||||
|
|
||||||
|
@GetMapping("/api/dialogues")
|
||||||
|
List<DialogueMapper> allDialogues() {
|
||||||
|
return List.of(); // TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
package ru.dragonestia.editor.controller.mapper;
|
||||||
|
|
||||||
|
import ru.dragonestia.editor.model.DialogueContext;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public record DialogueMapper(
|
||||||
|
String groupId,
|
||||||
|
String id,
|
||||||
|
String text,
|
||||||
|
List<Answer> answers
|
||||||
|
) {
|
||||||
|
|
||||||
|
public static DialogueMapper fromEntity(DialogueContext context) {
|
||||||
|
var buttons = new ArrayList<Answer>();
|
||||||
|
for (var button: context.getAnswers()) {
|
||||||
|
var actionData = new HashMap<String, String>();
|
||||||
|
for (var actionParam: button.getAction().getFields()) {
|
||||||
|
actionData.put(actionParam.getIdentifier(), actionParam.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
var conditions = new ArrayList<Condition>();
|
||||||
|
for (var condition: button.getConditions()) {
|
||||||
|
var conditionData = new HashMap<String, String>();
|
||||||
|
for (var param: condition.getFields()) {
|
||||||
|
conditionData.put(param.getIdentifier(), param.getValue());
|
||||||
|
}
|
||||||
|
conditions.add(new Condition(condition.getIdentifier(), conditionData));
|
||||||
|
}
|
||||||
|
|
||||||
|
buttons.add(new Answer(button.getIdentifier(), button.getText(), button.getAction().getIdentifier(), actionData, conditions));
|
||||||
|
}
|
||||||
|
return new DialogueMapper(context.getGroupId(), context.getGroupId(), context.getText(), buttons);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Answer(
|
||||||
|
String id,
|
||||||
|
String text,
|
||||||
|
String actionId,
|
||||||
|
Map<String, String> actionData,
|
||||||
|
List<Condition> conditions
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public record Condition(
|
||||||
|
String id,
|
||||||
|
Map<String, String> data
|
||||||
|
) {}
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
package ru.dragonestia.editor.model;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class DialogueAction {
|
||||||
|
|
||||||
|
private String identifier;
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private List<Field> fields = new ArrayList<>();
|
||||||
|
private boolean builtIn;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class Field {
|
||||||
|
|
||||||
|
private String identifier;
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private FieldType type;
|
||||||
|
private String defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package ru.dragonestia.editor.model;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class DialogueCondition {
|
||||||
|
|
||||||
|
private String identifier;
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private ArrayList<Field> fields = new ArrayList<>();
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class Field {
|
||||||
|
|
||||||
|
private String identifier;
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private FieldType type;
|
||||||
|
private String defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
package ru.dragonestia.editor.model;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class DialogueContext {
|
||||||
|
|
||||||
|
private String groupId;
|
||||||
|
private String id;
|
||||||
|
private String text;
|
||||||
|
private String comment;
|
||||||
|
private ArrayList<Answer> answers = new ArrayList<>();
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class Answer {
|
||||||
|
|
||||||
|
private String identifier;
|
||||||
|
private String text;
|
||||||
|
private String comment;
|
||||||
|
private Action action;
|
||||||
|
private ArrayList<Condition> conditions = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class Action {
|
||||||
|
|
||||||
|
private String identifier;
|
||||||
|
private String name;
|
||||||
|
private ArrayList<Field> fields = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class Condition {
|
||||||
|
|
||||||
|
private String identifier;
|
||||||
|
private String name;
|
||||||
|
private ArrayList<Field> fields = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class Field {
|
||||||
|
|
||||||
|
private String identifier;
|
||||||
|
private String name;
|
||||||
|
private FieldType type;
|
||||||
|
private String value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package ru.dragonestia.editor.model;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum FieldType {
|
||||||
|
STRING("Строка", input -> true),
|
||||||
|
TEXT("Текст", input -> true),
|
||||||
|
INTEGER("Целое число", input -> {
|
||||||
|
try {
|
||||||
|
Integer.parseInt(input);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
BOOLEAN("Булево значение", input -> switch (input.toLowerCase()) {
|
||||||
|
case "true", "false" -> true;
|
||||||
|
default -> false;
|
||||||
|
}),
|
||||||
|
DOUBLE("Число с плавающей точкой", input -> {
|
||||||
|
try {
|
||||||
|
Double.parseDouble(input);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final Predicate<String> validator;
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,97 @@
|
|||||||
|
package ru.dragonestia.editor.page;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.Unit;
|
||||||
|
import com.vaadin.flow.component.button.Button;
|
||||||
|
import com.vaadin.flow.component.button.ButtonVariant;
|
||||||
|
import com.vaadin.flow.component.grid.Grid;
|
||||||
|
import com.vaadin.flow.component.html.H2;
|
||||||
|
import com.vaadin.flow.component.html.Paragraph;
|
||||||
|
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||||
|
import com.vaadin.flow.component.textfield.TextField;
|
||||||
|
import com.vaadin.flow.data.value.ValueChangeMode;
|
||||||
|
import ru.dragonestia.editor.page.browser.BrowserPage;
|
||||||
|
import ru.dragonestia.editor.page.browser.TabContainer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DialogueGroupPage extends TabContainer {
|
||||||
|
|
||||||
|
private final String groupIdentifier;
|
||||||
|
private final TextField fieldSearch;
|
||||||
|
private final Grid<DialogueEntry> grid;
|
||||||
|
|
||||||
|
public DialogueGroupPage(BrowserPage browser, String groupIdentifier) {
|
||||||
|
super(browser, "Группа: " + groupIdentifier);
|
||||||
|
this.groupIdentifier = groupIdentifier;
|
||||||
|
|
||||||
|
add(new H2(groupIdentifier));
|
||||||
|
add(new Paragraph(
|
||||||
|
"Здесь содержатся диалоги, которые связаны с данной группой. " +
|
||||||
|
"Нажмите на диалог в таблице чтобы редактировать или удалить его. " +
|
||||||
|
"Если хотите создать новый диалог, то нажмите кнопку для создания ниже. "
|
||||||
|
));
|
||||||
|
|
||||||
|
var buttonsLayout = new HorizontalLayout();
|
||||||
|
buttonsLayout.setWidth("100%");
|
||||||
|
add(buttonsLayout);
|
||||||
|
buttonsLayout.add(createButtonNewDialogue());
|
||||||
|
buttonsLayout.add(createButtonUpdateDialogues());
|
||||||
|
|
||||||
|
add(fieldSearch = createFieldSearch());
|
||||||
|
add(grid = createGrid());
|
||||||
|
// TODO: init grid data
|
||||||
|
grid.setItems(List.of(
|
||||||
|
new DialogueEntry("test1", ""),
|
||||||
|
new DialogueEntry("test2", "а ывп выпыв пку пукфпкаырп ыварукып куруке авыфп авып"),
|
||||||
|
new DialogueEntry("fsdfdsfds", "111"),
|
||||||
|
new DialogueEntry("hello", "Приветственный диалог с игроком")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Button createButtonUpdateDialogues() {
|
||||||
|
var button = new Button("Обновить список диалогов", VaadinIcon.REFRESH.create(), event -> {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Button createButtonNewDialogue() {
|
||||||
|
var button = new Button("Создать новый диалог", VaadinIcon.PLUS.create(), e -> {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextField createFieldSearch() {
|
||||||
|
var field = new TextField();
|
||||||
|
field.setPlaceholder("Поиск группы по идентификатору");
|
||||||
|
field.setPrefixComponent(VaadinIcon.SEARCH.create());
|
||||||
|
field.setValueChangeMode(ValueChangeMode.EAGER);
|
||||||
|
field.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
field.addValueChangeListener(e -> {
|
||||||
|
var input = e.getValue().trim().toLowerCase();
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Grid<DialogueEntry> createGrid() {
|
||||||
|
var grid = new Grid<DialogueEntry>();
|
||||||
|
grid.addColumn(DialogueEntry::identifier).setHeader("Идентификатор").setWidth("15%").setFlexGrow(0);
|
||||||
|
grid.addColumn(DialogueEntry::comment).setHeader("Комментарий");
|
||||||
|
grid.addItemClickListener(e -> {
|
||||||
|
var dialogueIdentifier = e.getItem().identifier();
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
browser.openTab(new DialoguePage(browser, groupIdentifier, "test_id"));
|
||||||
|
});
|
||||||
|
return grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public record DialogueEntry(String identifier, String comment) {}
|
||||||
|
}
|
||||||
@ -0,0 +1,325 @@
|
|||||||
|
package ru.dragonestia.editor.page;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.Text;
|
||||||
|
import com.vaadin.flow.component.Unit;
|
||||||
|
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.dialog.Dialog;
|
||||||
|
import com.vaadin.flow.component.html.H3;
|
||||||
|
import com.vaadin.flow.component.html.ListItem;
|
||||||
|
import com.vaadin.flow.component.html.Paragraph;
|
||||||
|
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.Scroller;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
|
import com.vaadin.flow.component.textfield.IntegerField;
|
||||||
|
import com.vaadin.flow.component.textfield.NumberField;
|
||||||
|
import com.vaadin.flow.component.textfield.TextArea;
|
||||||
|
import com.vaadin.flow.component.textfield.TextField;
|
||||||
|
import com.vaadin.flow.data.value.ValueChangeMode;
|
||||||
|
import ru.dragonestia.editor.model.DialogueAction;
|
||||||
|
import ru.dragonestia.editor.model.DialogueContext;
|
||||||
|
import ru.dragonestia.editor.model.FieldType;
|
||||||
|
import ru.dragonestia.editor.page.browser.BrowserPage;
|
||||||
|
import ru.dragonestia.editor.page.browser.TabContainer;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class DialoguePage extends TabContainer {
|
||||||
|
|
||||||
|
private final static Random random = new Random();
|
||||||
|
|
||||||
|
private final String groupIdentifier;
|
||||||
|
private final String dialogueIdentifier;
|
||||||
|
private final TextArea fieldText;
|
||||||
|
private final TextArea fieldComment;
|
||||||
|
private final Button buttonNewAnswer;
|
||||||
|
private final VerticalLayout layoutAnswers;
|
||||||
|
private final List<Answer> answers = new ArrayList<>();
|
||||||
|
|
||||||
|
private DialogueContext dialogueContext = new DialogueContext();
|
||||||
|
|
||||||
|
public DialoguePage(BrowserPage browser, String groupIdentifier, String dialogueIdentifier) {
|
||||||
|
super(browser, "Диалог: %s/%s".formatted(groupIdentifier, dialogueIdentifier));
|
||||||
|
this.groupIdentifier = groupIdentifier;
|
||||||
|
this.dialogueIdentifier = dialogueIdentifier;
|
||||||
|
|
||||||
|
var layout = new HorizontalLayout();
|
||||||
|
layout.setPadding(false);
|
||||||
|
layout.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
add(layout);
|
||||||
|
var leftLayout = new VerticalLayout();
|
||||||
|
leftLayout.setWidth(45, Unit.PERCENTAGE);
|
||||||
|
leftLayout.setPadding(false);
|
||||||
|
layout.add(leftLayout);
|
||||||
|
var rightLayout = new VerticalLayout();
|
||||||
|
rightLayout.setPadding(false);
|
||||||
|
layout.add(rightLayout);
|
||||||
|
|
||||||
|
leftLayout.add(createFieldIdentifier());
|
||||||
|
leftLayout.add(fieldText = createFieldText());
|
||||||
|
leftLayout.add(createTextHelping());
|
||||||
|
|
||||||
|
var controlLayout = new HorizontalLayout();
|
||||||
|
controlLayout.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
controlLayout.setPadding(false);
|
||||||
|
leftLayout.add(controlLayout);
|
||||||
|
controlLayout.add(createButtonSave());
|
||||||
|
controlLayout.add(createButtonDelete());
|
||||||
|
|
||||||
|
leftLayout.add(fieldComment = createFieldComment());
|
||||||
|
|
||||||
|
rightLayout.add(new H3("Ответы диалогов"));
|
||||||
|
rightLayout.add(buttonNewAnswer = createButtonNewAnswer());
|
||||||
|
|
||||||
|
layoutAnswers = new VerticalLayout();
|
||||||
|
layoutAnswers.setPadding(false);
|
||||||
|
rightLayout.add(layoutAnswers);
|
||||||
|
updateAnswers();
|
||||||
|
|
||||||
|
//add(new DialogEditor(new DialogueContext()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextField createFieldIdentifier() {
|
||||||
|
var field = new TextField("Идентификатор группы/идентификатор диалога");
|
||||||
|
field.setHelperText("Идентификатор диалога изменять нельзя");
|
||||||
|
field.setValue("%s/%s".formatted(groupIdentifier, dialogueIdentifier));
|
||||||
|
field.setReadOnly(true);
|
||||||
|
field.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextArea createFieldText() {
|
||||||
|
var field = new TextArea("Текст диалога");
|
||||||
|
field.setHeight(20, Unit.REM);
|
||||||
|
field.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
private VerticalLayout createTextHelping() {
|
||||||
|
var layout = new VerticalLayout();
|
||||||
|
layout.setPadding(false);
|
||||||
|
layout.add(new Text("Здесь описаны подсказки с плейсхолдерами для диалога:")); // TODO
|
||||||
|
layout.add(new ListItem("Плейсхолдер 1"));
|
||||||
|
layout.add(new ListItem("Плейсхолдер 2"));
|
||||||
|
layout.add(new ListItem("Плейсхолдер 3"));
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextArea createFieldComment() {
|
||||||
|
var field = new TextArea("Комментарий");
|
||||||
|
field.setHelperText("Комментарием может являться любая пометка с кратким описанием диалога. Этот комментарий видно в списке диалогов на сайте.");
|
||||||
|
field.setMinHeight(10, Unit.REM);
|
||||||
|
field.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Button createButtonNewAnswer() {
|
||||||
|
var button = new Button("Добавить ответ диалога", VaadinIcon.PLUS.create());
|
||||||
|
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS);
|
||||||
|
button.addClickListener(e -> {
|
||||||
|
var answer = new Answer();
|
||||||
|
answer.deletion = () -> deleteAnswer(answer);
|
||||||
|
answers.add(answer);
|
||||||
|
updateAnswers();
|
||||||
|
});
|
||||||
|
button.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Button createButtonSave() {
|
||||||
|
var button = new Button("Сохранить", VaadinIcon.DATABASE.create(), e -> {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS);
|
||||||
|
button.setWidth(49, Unit.PERCENTAGE);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Button createButtonDelete() {
|
||||||
|
var button = new Button("Удалить", VaadinIcon.TRASH.create(), e -> sendDeletionConfirm());
|
||||||
|
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_ERROR);
|
||||||
|
button.setWidth(49, Unit.PERCENTAGE);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendDeletionConfirm() {
|
||||||
|
var dialog = new Dialog("Удаление диалога");
|
||||||
|
dialog.setWidth(30, Unit.REM);
|
||||||
|
dialog.getFooter().add(new Button("Отмена", e -> dialog.close()));
|
||||||
|
|
||||||
|
var randomNumber = Integer.toString(random.nextInt(100, 999));
|
||||||
|
|
||||||
|
var layout = new VerticalLayout();
|
||||||
|
dialog.add(layout);
|
||||||
|
layout.add(new Paragraph("Подтвердите что вы хотите удалить диалог. Введите код ниже в поле для ввода чтобы подтвердить удаление."));
|
||||||
|
|
||||||
|
var codeLayout = new H3(randomNumber);
|
||||||
|
layout.add(codeLayout);
|
||||||
|
|
||||||
|
var buttonConfirm = new Button("Подтвердить удаление", e -> {
|
||||||
|
// TODO
|
||||||
|
dialog.close();
|
||||||
|
});
|
||||||
|
buttonConfirm.setEnabled(false);
|
||||||
|
buttonConfirm.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_ERROR);
|
||||||
|
buttonConfirm.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
|
||||||
|
var fieldConfirmation = new TextField();
|
||||||
|
fieldConfirmation.setPlaceholder("Введите код, написанный выше");
|
||||||
|
fieldConfirmation.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
fieldConfirmation.setValueChangeMode(ValueChangeMode.EAGER);
|
||||||
|
fieldConfirmation.addValueChangeListener(e -> {
|
||||||
|
buttonConfirm.setEnabled(randomNumber.equals(e.getValue()));
|
||||||
|
});
|
||||||
|
layout.add(fieldConfirmation);
|
||||||
|
|
||||||
|
layout.add(buttonConfirm);
|
||||||
|
|
||||||
|
dialog.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateAnswers() {
|
||||||
|
buttonNewAnswer.setEnabled(answers.size() < 4);
|
||||||
|
|
||||||
|
layoutAnswers.removeAll();
|
||||||
|
for (var answer: answers) {
|
||||||
|
layoutAnswers.add(answer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteAnswer(Answer answer) {
|
||||||
|
answers.removeIf(target -> answer.uuid.equals(target.uuid));
|
||||||
|
updateAnswers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Answer extends HorizontalLayout {
|
||||||
|
|
||||||
|
private final UUID uuid = UUID.randomUUID();
|
||||||
|
private Runnable deletion;
|
||||||
|
private final VerticalLayout layoutAction;
|
||||||
|
|
||||||
|
public Answer() {
|
||||||
|
var layoutLeft = new VerticalLayout();
|
||||||
|
add(layoutLeft);
|
||||||
|
var layoutRight = new VerticalLayout();
|
||||||
|
add(layoutRight);
|
||||||
|
layoutAction = new VerticalLayout();
|
||||||
|
layoutAction.setPadding(false);
|
||||||
|
|
||||||
|
layoutLeft.add(createFieldText());
|
||||||
|
layoutLeft.add(createSelectAction());
|
||||||
|
layoutLeft.add(layoutAction);
|
||||||
|
|
||||||
|
layoutRight.add(createButtonDeleteAnswer());
|
||||||
|
layoutRight.add(createFieldIdentifier());
|
||||||
|
layoutRight.add(createFieldComment());
|
||||||
|
|
||||||
|
setWidth(100, Unit.PERCENTAGE);
|
||||||
|
getStyle().set("background-color", "#EEEEEE");
|
||||||
|
getStyle().set("border-radius", "26px");
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextField createFieldText() {
|
||||||
|
var field = new TextField("Текст кнопки");
|
||||||
|
field.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Button createButtonDeleteAnswer() {
|
||||||
|
var button = new Button("Удалить ответ", VaadinIcon.TRASH.create(), e -> {
|
||||||
|
if (deletion == null) return;
|
||||||
|
deletion.run();
|
||||||
|
});
|
||||||
|
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_ERROR);
|
||||||
|
button.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextField createFieldIdentifier() {
|
||||||
|
var field = new TextField("Идентификатор кнопки");
|
||||||
|
field.setHelperText("Может быть пустым. Этот параметр нужен чтобы запоминать какие кнопки нажимал игрок чтобы потом делать различные проверки на это.");
|
||||||
|
field.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextArea createFieldComment() {
|
||||||
|
var field = new TextArea("Комментарий");
|
||||||
|
field.setHelperText("Комментарием может являться любая пометка с кратким описанием ответа диалога.");
|
||||||
|
field.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
field.setHeight(10, Unit.REM);
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ComboBox<DialogueAction> createSelectAction() {
|
||||||
|
var comboBox = new ComboBox<DialogueAction>("Действие ответа диалога");
|
||||||
|
comboBox.setHelperText("Выполняется, когда игрок нажимает на кнопку выбора ответа внутри диалога");
|
||||||
|
comboBox.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
comboBox.setItemLabelGenerator(action -> "%s [%s]".formatted(action.getName(), action.getIdentifier()));
|
||||||
|
|
||||||
|
var items = List.of(
|
||||||
|
new DialogueAction("close", "Закрыть диалог", "Просто закрывает диалог", new ArrayList<>(), true),
|
||||||
|
new DialogueAction("dialogue", "Перейти к диалогу", "Перейти к другому диалогу", List.of(
|
||||||
|
new DialogueAction.Field("groupId", "Id-группы диалога", "", FieldType.STRING, ""),
|
||||||
|
new DialogueAction.Field("dialogueId", "Id диалога", "", FieldType.STRING, "")
|
||||||
|
), true),
|
||||||
|
new DialogueAction("test_params", "Тест всех полей", "", List.of(
|
||||||
|
new DialogueAction.Field("param1", "Строка", "", FieldType.STRING, ""),
|
||||||
|
new DialogueAction.Field("param2", "Текст", "", FieldType.TEXT, ""),
|
||||||
|
new DialogueAction.Field("param3", "Булево значение", "", FieldType.BOOLEAN, ""),
|
||||||
|
new DialogueAction.Field("param4", "Целое число", "", FieldType.INTEGER, ""),
|
||||||
|
new DialogueAction.Field("param5", "Число с плавающей точкой", "", FieldType.DOUBLE, "")
|
||||||
|
), true)
|
||||||
|
);
|
||||||
|
comboBox.setItems(items);
|
||||||
|
comboBox.setValue(items.getFirst());
|
||||||
|
comboBox.addValueChangeListener(e -> {
|
||||||
|
updateAction(e.getValue(), new HashMap<>());
|
||||||
|
});
|
||||||
|
return comboBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateAction(DialogueAction action, Map<String, String> params) {
|
||||||
|
layoutAction.removeAll();
|
||||||
|
var fieldMapper = new HashMap<String, Supplier<String>>();
|
||||||
|
for (var param: action.getFields()) {
|
||||||
|
var component = switch (param.getType()) {
|
||||||
|
case STRING -> {
|
||||||
|
var field = new TextField(param.getName());
|
||||||
|
field.setValue(param.getDefaultValue());
|
||||||
|
fieldMapper.put(param.getIdentifier(), field::getValue);
|
||||||
|
yield field;
|
||||||
|
}
|
||||||
|
case TEXT -> {
|
||||||
|
var field = new TextArea(param.getName());
|
||||||
|
field.setValue(param.getDefaultValue());
|
||||||
|
fieldMapper.put(param.getIdentifier(), field::getValue);
|
||||||
|
yield field;
|
||||||
|
}
|
||||||
|
case BOOLEAN -> {
|
||||||
|
var field = new Checkbox(param.getName());
|
||||||
|
field.setValue(Boolean.parseBoolean(param.getDefaultValue()));
|
||||||
|
fieldMapper.put(param.getIdentifier(), () -> Boolean.toString(field.getValue()));
|
||||||
|
yield field;
|
||||||
|
}
|
||||||
|
case INTEGER -> {
|
||||||
|
var field = new IntegerField(param.getName());
|
||||||
|
fieldMapper.put(param.getIdentifier(), () -> Integer.toString(field.getValue()));
|
||||||
|
yield field;
|
||||||
|
}
|
||||||
|
case DOUBLE -> {
|
||||||
|
var field = new NumberField(param.getName());
|
||||||
|
fieldMapper.put(param.getIdentifier(), () -> Double.toString(field.getValue()));
|
||||||
|
yield field;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
component.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
layoutAction.add(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
166
editor/src/main/java/ru/dragonestia/editor/page/HomePage.java
Normal file
166
editor/src/main/java/ru/dragonestia/editor/page/HomePage.java
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
package ru.dragonestia.editor.page;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.Html;
|
||||||
|
import com.vaadin.flow.component.Unit;
|
||||||
|
import com.vaadin.flow.component.button.Button;
|
||||||
|
import com.vaadin.flow.component.button.ButtonVariant;
|
||||||
|
import com.vaadin.flow.component.dialog.Dialog;
|
||||||
|
import com.vaadin.flow.component.grid.Grid;
|
||||||
|
import com.vaadin.flow.component.html.*;
|
||||||
|
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||||
|
import com.vaadin.flow.component.notification.Notification;
|
||||||
|
import com.vaadin.flow.component.notification.NotificationVariant;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
|
import com.vaadin.flow.component.textfield.TextField;
|
||||||
|
import com.vaadin.flow.data.value.ValueChangeMode;
|
||||||
|
import ru.dragonestia.editor.page.browser.BrowserPage;
|
||||||
|
import ru.dragonestia.editor.page.browser.TabContainer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
public class HomePage extends TabContainer {
|
||||||
|
|
||||||
|
public HomePage(BrowserPage browser) {
|
||||||
|
super(browser, "Домашняя страница");
|
||||||
|
|
||||||
|
add(new H3("Диалоги"));
|
||||||
|
addLink("Управление группами диалогов", this::findOrCreateDialog);
|
||||||
|
addLink("Список всех групп диалогов", this::listAllDialogueGroups);
|
||||||
|
add(new H3("Действия ответов диалога"));
|
||||||
|
addLink("Создание/редактирование действий ответов диалога", this::findOrCreateDialogAction);
|
||||||
|
addLink("Список всех действий ответов диалога", this::listAllDialogueActions);
|
||||||
|
add(new H3("Условия ответов диалога"));
|
||||||
|
addLink("Создание/редактирование условий ответов диалога", this::findOrCreateDialogCondition);
|
||||||
|
addLink("Список всех ответов диалога", this::listAllDialogueConditions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addLink(String label, BiConsumer<VerticalLayout, Runnable> content) {
|
||||||
|
var component = new Span(new Html("<a href='#'>" + label + "</a>"));
|
||||||
|
component.addClickListener(event -> {
|
||||||
|
var dialog = new Dialog();
|
||||||
|
dialog.setMinHeight(30, Unit.PERCENTAGE);
|
||||||
|
dialog.setWidth(40, Unit.PERCENTAGE);
|
||||||
|
|
||||||
|
dialog.getHeader().add(new H2(label));
|
||||||
|
|
||||||
|
var layout = new VerticalLayout();
|
||||||
|
layout.setPadding(false);
|
||||||
|
content.accept(layout, dialog::close);
|
||||||
|
dialog.add(layout);
|
||||||
|
|
||||||
|
var closeButton = new Button("Close");
|
||||||
|
closeButton.addThemeVariants();
|
||||||
|
closeButton.addClickListener(e -> dialog.close());
|
||||||
|
dialog.getFooter().add(closeButton);
|
||||||
|
|
||||||
|
dialog.open();
|
||||||
|
});
|
||||||
|
add(new ListItem(component));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findOrCreateDialog(VerticalLayout layout, Runnable closeWindow) {
|
||||||
|
layout.add(new Paragraph(
|
||||||
|
"Введите идентификатор группы диалога чтобы перейти к созданию или редактированию группы диалога. " +
|
||||||
|
"Группы диалогов нужны чтобы упростить группировку диалогов. "
|
||||||
|
));
|
||||||
|
|
||||||
|
var fieldIdentifier = new TextField("Идентификатор группы");
|
||||||
|
fieldIdentifier.setHelperText("Идентификатор может содержать только символы английского алфавита, цифры и символ нижнего подчеркивания");
|
||||||
|
fieldIdentifier.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
layout.add(fieldIdentifier);
|
||||||
|
|
||||||
|
var buttons = new HorizontalLayout();
|
||||||
|
buttons.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
buttons.setJustifyContentMode(JustifyContentMode.CENTER);
|
||||||
|
layout.add(buttons);
|
||||||
|
|
||||||
|
var buttonCheckGroup = new Button("Проверить существование группы", e -> {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
buttonCheckGroup.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||||
|
buttonCheckGroup.setWidth(49, Unit.PERCENTAGE);
|
||||||
|
buttons.add(buttonCheckGroup);
|
||||||
|
|
||||||
|
var createOrFind = new Button("Создать/редактировать", e -> {
|
||||||
|
var groupIdentifier = fieldIdentifier.getValue().trim().toLowerCase();
|
||||||
|
|
||||||
|
if (groupIdentifier.isEmpty()) return;
|
||||||
|
if (!groupIdentifier.matches("^[aA-zZ\\d_]+$")) {
|
||||||
|
Notification.show("Идентификатор группы содержит недопустимые символы.")
|
||||||
|
.addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
browser.openTab(new DialogueGroupPage(browser, groupIdentifier));
|
||||||
|
closeWindow.run();
|
||||||
|
});
|
||||||
|
createOrFind.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS);
|
||||||
|
createOrFind.setWidth(49, Unit.PERCENTAGE);
|
||||||
|
buttons.add(createOrFind);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void listAllDialogueGroups(VerticalLayout layout, Runnable closeWindow) {
|
||||||
|
var buttonRefresh = new Button("Обновить список", VaadinIcon.REFRESH.create());
|
||||||
|
layout.add(buttonRefresh);
|
||||||
|
|
||||||
|
var fieldSearch = new TextField();
|
||||||
|
fieldSearch.setPlaceholder("Поиск группы по идентификатору");
|
||||||
|
fieldSearch.setPrefixComponent(VaadinIcon.SEARCH.create());
|
||||||
|
fieldSearch.setValueChangeMode(ValueChangeMode.EAGER);
|
||||||
|
fieldSearch.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
layout.add(fieldSearch);
|
||||||
|
|
||||||
|
var grid = new Grid<DialogGroupEntry>();
|
||||||
|
var data = new ArrayList<DialogGroupEntry>();
|
||||||
|
// TODO: initial data loading
|
||||||
|
grid.setItems(data);
|
||||||
|
grid.addColumn(DialogGroupEntry::id).setHeader("Id группы").setWidth("25%").setFlexGrow(0);
|
||||||
|
grid.addColumn(DialogGroupEntry::dialoguesInside).setHeader("Кол-во диалогов").setWidth("20%").setFlexGrow(0);
|
||||||
|
grid.addComponentColumn(obj -> new Paragraph(obj.comment())).setHeader("Комментарий");
|
||||||
|
grid.addItemClickListener(e -> {
|
||||||
|
var item = e.getItem();
|
||||||
|
// TODO: open dialogue group
|
||||||
|
|
||||||
|
closeWindow.run();
|
||||||
|
});
|
||||||
|
layout.add(grid);
|
||||||
|
|
||||||
|
fieldSearch.addValueChangeListener(e -> {
|
||||||
|
var input = e.getValue().trim().toLowerCase();
|
||||||
|
var newList = new ArrayList<>(data);
|
||||||
|
newList.removeIf(entry -> !entry.id().toLowerCase().startsWith(input));
|
||||||
|
grid.setItems(newList);
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonRefresh.addClickListener(e -> {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
layout.add(new Paragraph(
|
||||||
|
"В этом списке отображаются группы, которые имеют хоть какое-то количество диалогов внутри. " +
|
||||||
|
"Нажмите на строчку с диалогом чтобы заглянуть внутрь. "
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findOrCreateDialogAction(VerticalLayout layout, Runnable closeWindow) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void listAllDialogueActions(VerticalLayout layout, Runnable closeWindow) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findOrCreateDialogCondition(VerticalLayout layout, Runnable closeWindow) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void listAllDialogueConditions(VerticalLayout layout, Runnable closeWindow) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private record DialogGroupEntry(String id, int dialoguesInside, String comment) {}
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
package ru.dragonestia.editor.page.browser;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.Component;
|
||||||
|
import com.vaadin.flow.component.Unit;
|
||||||
|
import com.vaadin.flow.component.button.Button;
|
||||||
|
import com.vaadin.flow.component.html.Span;
|
||||||
|
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
|
import com.vaadin.flow.component.tabs.Tab;
|
||||||
|
import com.vaadin.flow.component.tabs.TabSheet;
|
||||||
|
import com.vaadin.flow.router.Route;
|
||||||
|
import ru.dragonestia.editor.page.HomePage;
|
||||||
|
|
||||||
|
@Route("/")
|
||||||
|
public class BrowserPage extends VerticalLayout {
|
||||||
|
|
||||||
|
private final TabSheet tabs;
|
||||||
|
|
||||||
|
public BrowserPage() {
|
||||||
|
tabs = new TabSheet();
|
||||||
|
tabs.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
//tabs.setSuffixComponent(createNewTabButton());
|
||||||
|
add(tabs);
|
||||||
|
|
||||||
|
openHomePage();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component createNewTabButton() {
|
||||||
|
return new Button(VaadinIcon.PLUS.create(), event -> openHomePage());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openHomePage() {
|
||||||
|
var tab = new Tab(new Span(VaadinIcon.HOME.create()));
|
||||||
|
var style = tab.getStyle();
|
||||||
|
style.setPaddingTop("0rem");
|
||||||
|
style.setPaddingBottom("0rem");
|
||||||
|
|
||||||
|
tabs.add(tab, new HomePage(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openTab(TabContainer container) {
|
||||||
|
var tab = new Tab();
|
||||||
|
var style = tab.getStyle();
|
||||||
|
style.setPaddingTop("0rem");
|
||||||
|
style.setPaddingBottom("0rem");
|
||||||
|
tab.setLabel(container.getTitle());
|
||||||
|
container.setTab(tab);
|
||||||
|
|
||||||
|
var closeTabButton = new Span(VaadinIcon.CLOSE_SMALL.create());
|
||||||
|
closeTabButton.getStyle().setMarginLeft("1rem");
|
||||||
|
closeTabButton.addClickListener(event -> tabs.remove(tab));
|
||||||
|
tab.add(closeTabButton);
|
||||||
|
|
||||||
|
tabs.add(tab, container);
|
||||||
|
tabs.setSelectedTab(tab);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
package ru.dragonestia.editor.page.browser;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
|
import com.vaadin.flow.component.tabs.Tab;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public abstract class TabContainer extends VerticalLayout {
|
||||||
|
|
||||||
|
protected final BrowserPage browser;
|
||||||
|
private String title;
|
||||||
|
private Tab tab;
|
||||||
|
|
||||||
|
public TabContainer(BrowserPage browser, String title) {
|
||||||
|
this.browser = browser;
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
tab.setLabel(title);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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> {}
|
||||||
@ -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> {}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package ru.dragonestia.editor.service;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class DialoguePackageService {
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
editor/src/main/resources/application.yaml
Normal file
21
editor/src/main/resources/application.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
spring:
|
||||||
|
application:
|
||||||
|
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
|
||||||
|
|
||||||
|
mvc:
|
||||||
|
static-path-pattern: '/static/**'
|
||||||
|
|
||||||
|
server:
|
||||||
|
port: 8080
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="design-properties" content="{"RULERS_VISIBLE":true,"GUIDELINES_VISIBLE":false,"SNAP_TO_OBJECTS":true,"SNAP_TO_GRID":true,"SNAPPING_DISTANCE":10,"GENERATE_GETTERS":false,"JAVA_SOURCES_ROOT":"../../src/main/java","THEME":"valo"}">
|
||||||
|
<meta name="vaadin-version" content="8.1.5">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<vaadin-vertical-layout size-full></vaadin-vertical-layout>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -1,2 +1,2 @@
|
|||||||
MSB3_MAVEN_REPOSITORY=http://git.dragonestia.ru/api/packages/MSB/maven
|
MSB3_MAVEN_REPOSITORY=http://git.dragonestia.ru/api/packages/MSB/maven
|
||||||
MSB3_VERSION=3.0.2
|
MSB3_VERSION=3.0.0
|
||||||
@ -1,3 +1,4 @@
|
|||||||
rootProject.name = 'msb3'
|
rootProject.name = 'msb3'
|
||||||
|
|
||||||
include 'resource-compiler', 'api'
|
include 'resource-compiler', 'api', 'editor'
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user