Merge branch 'refs/heads/master' into feat/ai
# Conflicts: # gradle.properties
This commit is contained in:
commit
d8f52142e6
40
README.md
40
README.md
@ -1,2 +1,42 @@
|
|||||||
msb3
|
msb3
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
## О проекте
|
||||||
|
**MinestomServerBase** (msb3) - это надстройка над Minestom, содержащая готовые модули,
|
||||||
|
упрощающие разработку мини-игр.
|
||||||
|
|
||||||
|
## Использование
|
||||||
|
|
||||||
|
Указать репозиторий:
|
||||||
|
```groovy
|
||||||
|
maven {
|
||||||
|
name = "Gitea"
|
||||||
|
url = uri("https://git.dragonestia.ru/api/packages/Dragonestia/maven")
|
||||||
|
|
||||||
|
credentials(HttpHeaderCredentials) {
|
||||||
|
name = "Authorization"
|
||||||
|
value = "token ${dragonestiaGiteaToken}"
|
||||||
|
}
|
||||||
|
|
||||||
|
authentication {
|
||||||
|
header(HttpHeaderAuthentication)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Указать зависимость:
|
||||||
|
```groovy
|
||||||
|
dependencies {
|
||||||
|
implementation 'ru.dragonestia.msb3:msb-api:ВЕРСИЯ'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Последнюю версию можно найти тут: [ТЫК](https://git.dragonestia.ru/Dragonestia/-/packages/maven/ru.dragonestia.msb3:msb-api/)
|
||||||
|
|
||||||
|
## Полезные ссылки
|
||||||
|
- [Документация Minestom](https://minestom.net/docs/introduction)
|
||||||
|
- [Kyori Adventure](https://docs.advntr.dev/index) - форматирование текста
|
||||||
|
- [Unnamed Creative](https://unnamed.team/docs/creative) - управление ресурс-паками
|
||||||
|
- [SpongePowered Configurate](https://github.com/SpongePowered/Configurate/wiki) - файлы конфигурации
|
||||||
|
- [SQL2O](https://github.com/aaberg/sql2o/wiki) - работа с базами данных
|
||||||
|
- [JNoise](https://github.com/Articdive/JNoise/wiki) - процедурная генерация шумов
|
||||||
|
|||||||
3
editor/.gitignore
vendored
3
editor/.gitignore
vendored
@ -1,3 +0,0 @@
|
|||||||
node_modules
|
|
||||||
**/frontend/generated/
|
|
||||||
.vaadin-node-tasks.lock
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
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
|
|
||||||
})
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
-- 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 +0,0 @@
|
|||||||
-- Default inserts
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
FROM postgres:latest
|
|
||||||
COPY *.sql /docker-entrypoint-initdb.d/
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
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' ]
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,158 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
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
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,97 +0,0 @@
|
|||||||
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) {}
|
|
||||||
}
|
|
||||||
@ -1,325 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,166 +0,0 @@
|
|||||||
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) {}
|
|
||||||
}
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
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> {}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
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> {}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
package ru.dragonestia.editor.service;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class DialoguePackageService {
|
|
||||||
}
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
<!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,4 +1,3 @@
|
|||||||
rootProject.name = 'msb3'
|
rootProject.name = 'msb3'
|
||||||
|
|
||||||
include 'resource-compiler', 'api', 'editor'
|
include 'resource-compiler', 'api'
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user