Browse Source

teachers-check done!

master
esoe 5 months ago
parent
commit
9b87e8bf35
  1. 6
      .vscode/launch.json
  2. 3
      .vscode/settings.json
  3. 10
      client-service-teachers/docker-compose.yaml
  4. 13
      client-service-teachers/src/main/java/ru/molokoin/clientserviceteachers/controllers/Hello.java
  5. 1
      client-service-teachers/src/main/resources/static/content/md/hello.md
  6. 1
      client-service-teachers/src/main/resources/static/teachers.md
  7. 14
      client-service-teachers/src/main/resources/templates/hello.html
  8. 0
      gates/.env
  9. 0
      gates/.gitignore
  10. 0
      gates/.mvn/wrapper/maven-wrapper.properties
  11. 2
      gates/README.md
  12. 20
      gates/docker-compose.yaml
  13. 5
      gates/dockerfile
  14. 0
      gates/mvnw
  15. 0
      gates/mvnw.cmd
  16. 70
      gates/pom.xml
  17. 13
      gates/src/main/java/ru/mlokoin/gates/GatesApplication.java
  18. 24
      gates/src/main/java/ru/mlokoin/gates/config/WebConfig.java
  19. 37
      gates/src/main/java/ru/mlokoin/gates/controller/BuildingController.java
  20. 170
      gates/src/main/java/ru/mlokoin/gates/controller/CretareaController.java
  21. 46
      gates/src/main/java/ru/mlokoin/gates/controller/EducationsController.java
  22. 279
      gates/src/main/java/ru/mlokoin/gates/controller/GatesController.java
  23. 13
      gates/src/main/java/ru/mlokoin/gates/controller/Hello.java
  24. 173
      gates/src/main/java/ru/mlokoin/gates/controller/ProgramController.java
  25. 268
      gates/src/main/java/ru/mlokoin/gates/controller/TeacherController.java
  26. 29
      gates/src/main/java/ru/mlokoin/gates/model/Building.java
  27. 35
      gates/src/main/java/ru/mlokoin/gates/model/BuildingWraper.java
  28. 45
      gates/src/main/java/ru/mlokoin/gates/model/Course.java
  29. 32
      gates/src/main/java/ru/mlokoin/gates/model/Document.java
  30. 38
      gates/src/main/java/ru/mlokoin/gates/model/EducatonEntry.java
  31. 38
      gates/src/main/java/ru/mlokoin/gates/model/Organization.java
  32. 45
      gates/src/main/java/ru/mlokoin/gates/model/Program.java
  33. 28
      gates/src/main/java/ru/mlokoin/gates/model/ProgramCretarea.java
  34. 34
      gates/src/main/java/ru/mlokoin/gates/model/ProgramCretareaWraper.java
  35. 39
      gates/src/main/java/ru/mlokoin/gates/model/ProgramWraper.java
  36. 55
      gates/src/main/java/ru/mlokoin/gates/model/Student.java
  37. 44
      gates/src/main/java/ru/mlokoin/gates/model/Teacher.java
  38. 31
      gates/src/main/java/ru/mlokoin/gates/model/TeacherWraper.java
  39. 21
      gates/src/main/java/ru/mlokoin/gates/model/XlsxCell.java
  40. 18
      gates/src/main/java/ru/mlokoin/gates/model/XlsxDocument.java
  41. 69
      gates/src/main/java/ru/mlokoin/gates/util/CustomMultipartFile.java
  42. 27
      gates/src/main/resources/application.yaml
  43. 2
      gates/src/main/resources/static/content/md/hello.md
  44. 53
      gates/src/main/resources/templates/buildings-check.html
  45. 61
      gates/src/main/resources/templates/cretareas-check.html
  46. 92
      gates/src/main/resources/templates/documents.html
  47. 14
      gates/src/main/resources/templates/hello.html
  48. 69
      gates/src/main/resources/templates/programs-check.html
  49. 28
      gates/src/main/resources/templates/storage-add.html
  50. 91
      gates/src/main/resources/templates/storage.html
  51. 67
      gates/src/main/resources/templates/teachers-check.html
  52. 73
      gates/src/main/resources/templates/view-as-educations.html
  53. 59
      gates/src/main/resources/templates/view-xlsx.html
  54. 13
      gates/src/test/java/ru/mlokoin/gates/GatesApplicationTests.java
  55. 2
      postgres-service/docker-compose.yaml
  56. 8
      resource-service-api/docker-compose.yaml
  57. 4
      resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/controllers/EducationEntryController.java
  58. 68
      resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/controllers/StorageController.java
  59. 37
      resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/entities/StorageEntry.java
  60. 12
      resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/repositories/StorageEntryFace.java
  61. 1
      storage-rs/.env
  62. 33
      storage-rs/.gitignore
  63. 18
      storage-rs/.mvn/wrapper/maven-wrapper.properties
  64. 25
      storage-rs/docker-compose.yaml
  65. 5
      storage-rs/dockerfile
  66. 250
      storage-rs/mvnw
  67. 146
      storage-rs/mvnw.cmd
  68. 16
      storage-rs/pom.xml
  69. 0
      storage-rs/src/main/docs/puml/erd-explorer-data.puml
  70. 5
      storage-rs/src/main/java/ru/molokoin/storagers/StorageRsApplication.java
  71. 2
      storage-rs/src/main/java/ru/molokoin/storagers/config/StorageConfiguration.java
  72. 12
      storage-rs/src/main/java/ru/molokoin/storagers/controller/HelloController.java
  73. 198
      storage-rs/src/main/java/ru/molokoin/storagers/controller/StorageController.java
  74. 157
      storage-rs/src/main/java/ru/molokoin/storagers/model/DocumentModel.java
  75. 186
      storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxCell.java
  76. 209
      storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxDocument.java
  77. 27
      storage-rs/src/main/java/ru/molokoin/storagers/service/StorageService.java
  78. 12
      storage-rs/src/main/java/ru/molokoin/storagers/service/StorageServiceFace.java
  79. 0
      storage-rs/src/main/resources/META-INF/additional-spring-configuration-metadata.json
  80. 2
      storage-rs/src/main/resources/application.yaml
  81. 2
      storage-rs/src/main/resources/static/content/md/hello.md
  82. 6
      storage-rs/src/main/resources/templates/documents.html
  83. 0
      storage-rs/src/main/resources/templates/hello.html
  84. 44
      storage-rs/src/main/resources/templates/view.html
  85. 2
      storage-rs/src/test/java/ru/molokoin/storagers/StorageRsApplicationTests.java
  86. 0
      storage-rs/uploads/1_ДИ.xlsx
  87. 0
      storage-rs/uploads/2_ДОПОГ.xlsx
  88. 0
      storage-rs/uploads/3_Трудовые отношения.xlsx
  89. 0
      storage-rs/uploads/4_Правила и нормы охраны труда.xlsx
  90. 0
      storage-rs/uploads/5_Общие нормативы и правила.xlsx
  91. 0
      storage-rs/uploads/6_Ремонт и диагностика.xlsx
  92. 0
      storage-rs/uploads/use_docker.pdf
  93. 0
      storage-rs/uploads/Заявление для МП.docx
  94. 0
      storage-rs/uploads/тесты.zip
  95. 1
      storage_rs/.env
  96. 21
      storage_rs/docker-compose.yaml
  97. 5
      storage_rs/dockerfile
  98. 5
      storage_rs/src/main/java/ru/molokoin/storage_rs/controller/ChohortController.java
  99. 95
      storage_rs/src/main/java/ru/molokoin/storage_rs/controller/StorageController.java
  100. 79
      storage_rs/src/main/java/ru/molokoin/storage_rs/model/Document.java
  101. Some files were not shown because too many files have changed in this diff Show More

6
.vscode/launch.json vendored

@ -40,11 +40,11 @@ @@ -40,11 +40,11 @@
},
{
"type": "java",
"name": "Spring Boot-StorageRsApplication<storage_rs>",
"name": "Spring Boot-StorageRsApplication<storageRS>",
"request": "launch",
"cwd": "${workspaceFolder}",
"mainClass": "ru.molokoin.storage_rs.StorageRsApplication",
"projectName": "storage_rs",
"mainClass": "ru.molokoin.storagers.StorageRsApplication",
"projectName": "storage-rs",
"args": "",
"envFile": "${workspaceFolder}/.env"
}

3
.vscode/settings.json vendored

@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@
{
"java.compile.nullAnalysis.mode": "automatic"
"java.compile.nullAnalysis.mode": "automatic",
"java.configuration.updateBuildConfiguration": "interactive"
}

10
client-service-teachers/docker-compose.yaml

@ -1,16 +1,20 @@ @@ -1,16 +1,20 @@
version: "3.7"
services:
client-service-teachers:
container_name: client-service-teachers
hostname: client-service-teachers
build:
context: ../client-service-teachers
dockerfile: dockerfile
image: "client-service-teachers"
command: ["java","-jar","/app/client-service-teachers-0.1.jar"]
ports:
- 80:8181
- 84:8181
restart: unless-stopped
networks:
- tech_network
networks:
default:
external:
tech_network:
name: tech_network
external: true
driver: bridge

13
client-service-teachers/src/main/java/ru/molokoin/clientserviceteachers/controllers/Hello.java

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
package ru.molokoin.clientserviceteachers.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class Hello {
@GetMapping("/hello")
public String hello(){
return "hello";
}
}

1
client-service-teachers/src/main/resources/static/content/md/hello.md

@ -0,0 +1 @@ @@ -0,0 +1 @@
# client-service-teacher

1
client-service-teachers/src/main/resources/static/teachers.md

@ -1 +0,0 @@ @@ -1 +0,0 @@
# teachers.md

14
client-service-teachers/src/main/resources/templates/hello.html

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>gates-hello</title>
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2/webcomponents-loader.min.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@1/src/zero-md.min.js"></script>
</head>
<body>
<zero-md th:src="@{/content/md/hello.md}"></zero-md>
</body>
</html>

0
storage_rs/src/main/resources/templates/view.html → gates/.env

0
storage_rs/.gitignore → gates/.gitignore vendored

0
storage_rs/.mvn/wrapper/maven-wrapper.properties → gates/.mvn/wrapper/maven-wrapper.properties vendored

2
gates/README.md

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
# GATES
Микросервис, предоставляющий пользовательский интерфейс для добавления документов из хранилища в базу данных

20
gates/docker-compose.yaml

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
version: "3.7"
services:
gates:
container_name: "gates"
hostname: "gates"
build:
context: ../gates
dockerfile: dockerfile
image: "gates"
command: ["java","-jar","/app/gates/gates-0.0.1.jar"]
ports:
- 83:8383
restart: unless-stopped
networks:
- tech_network
networks:
tech_network:
name: tech_network
external: true
driver: bridge

5
gates/dockerfile

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
FROM openjdk:17-jdk-alpine
RUN apk update
RUN apk upgrade
COPY target/gates-0.0.1.jar /app/gates/gates-0.0.1.jar
WORKDIR /app/gates

0
storage_rs/mvnw → gates/mvnw vendored

0
storage_rs/mvnw.cmd → gates/mvnw.cmd vendored

70
gates/pom.xml

@ -0,0 +1,70 @@ @@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>ru.mlokoin</groupId>
<artifactId>gates</artifactId>
<version>0.0.1</version>
<name>gates</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- <dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency> -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

13
gates/src/main/java/ru/mlokoin/gates/GatesApplication.java

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
package ru.mlokoin.gates;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GatesApplication {
public static void main(String[] args) {
SpringApplication.run(GatesApplication.class, args);
}
}

24
gates/src/main/java/ru/mlokoin/gates/config/WebConfig.java

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
package ru.mlokoin.gates.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class WebConfig {
@Bean
WebClient webClient() {
final int maxInMemorySize = 50 * 1024 * 1024; // 50MB
final ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(maxInMemorySize))
.build();
WebClient webClient = WebClient.builder()
.exchangeStrategies(exchangeStrategies)
// .baseUrl("http://resource-service-api:8181")
.build();
return webClient;
}
}

37
gates/src/main/java/ru/mlokoin/gates/controller/BuildingController.java

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
package ru.mlokoin.gates.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.reactive.function.client.WebClient;
import ru.mlokoin.gates.model.BuildingWraper;
@Controller
@RequestMapping(path = "/buildings")
public class BuildingController {
@Autowired
private WebClient client;
@GetMapping("/check/{id}")
public String checkBuildings(Model model, @PathVariable String id){
return "buildings-check";
// return "redirect:/document/view-as-educations/" + id;
}
@PostMapping(
path="/save/{id}",
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = {
MediaType.APPLICATION_JSON_VALUE
})
public String saveBuildings(@ModelAttribute("wrapBuildngs") BuildingWraper wraper, @PathVariable String id){
return "redirect:/buildings/check/" + id;
}
}

170
gates/src/main/java/ru/mlokoin/gates/controller/CretareaController.java

@ -0,0 +1,170 @@ @@ -0,0 +1,170 @@
package ru.mlokoin.gates.controller;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import ru.mlokoin.gates.model.ProgramCretarea;
import ru.mlokoin.gates.model.ProgramCretareaWraper;
import ru.mlokoin.gates.model.XlsxCell;
import ru.mlokoin.gates.model.XlsxDocument;
/**
* Контроллер, для работы с критериями
* - проверка соответствия критериев xlsx и базы данных
* - получение списка критериев, отсутствующих в базе
* - публикация новых критериев в базе
*
* Добавить возможности:
* - просмотра и редактирования критериев в базе
* - просмотра полного списка критериев в файле
* - настройка алиасов притериев
*/
@Controller
@RequestMapping(path = "/program-cretareas")
public class CretareaController {
@Autowired
private WebClient client;
/**
* Проверка критериев xlsx-файла:
* - получание списка уникальных критериев из файла
* - получение списка внесенных в базу критериев
* - вывод пользователю критериев, не найденых в базе
* - редактирование пользователем не найденых критериев
* - отправка в базу новых критериев
*
* @param model
* @param id
* @return
*/
@GetMapping("/check/{id}")
public String checkCretareas(Model model, @PathVariable String id) {
System.out.println("Проверка критериев, для внесения в базу ...");
System.out.println("Получение перечня критериев из xlsx-файла ...");
XlsxDocument xlsx = client.method(HttpMethod.GET)
.uri("http://storage-rs:8282/api/document/content/"
+ id + ".xlsx")
.retrieve()
.bodyToMono(new ParameterizedTypeReference <XlsxDocument>(){})
.block();
//список критериев из файла
ArrayList<ProgramCretarea> xlsx_cretareas = new ArrayList<>();//13 столбец
Map<Integer, List<XlsxCell>> map = xlsx.getData();
for (Map.Entry<Integer, List<XlsxCell>> entry : map.entrySet()) {
ProgramCretarea pc = new ProgramCretarea();
pc.setName_short(entry
.getValue()
.get(12)
.getContent());
xlsx_cretareas.add(pc);
}
xlsx_cretareas.remove(0);//Удалили из списка заголовок "Критериий"
Set<ProgramCretarea> xlsx_cretareaSet = Set.copyOf(xlsx_cretareas);
//список уникальных сокращенных наименований из файла
System.out.println("Список уникальных сокращенных наименований критериев из файла:");
Set<String> xlsx_ccs = new HashSet<>();
for (ProgramCretarea pc : xlsx_cretareaSet) {
System.out.println(pc.getName_short());
xlsx_ccs.add(pc.getName_short());
}
//Получение перечня критериев из базы
System.out.println("Получение списка критериев из базы ...");
List<ProgramCretarea> base_cretareas = client.method(HttpMethod.GET)
.uri("http://resource-service-api:8181/cretarea/list")
.retrieve()
.bodyToMono(new ParameterizedTypeReference <List<ProgramCretarea>>(){})
.block();
Set<ProgramCretarea> base_cretareaSet = Set.copyOf(base_cretareas);
//Список сокращенных наименований критериев из базы
System.out.println("Список уникальных сокращенных наименований критериев из базы:");
Set<String> base_ccs = new HashSet<>();
for (ProgramCretarea pc : base_cretareaSet) {
System.out.println(pc.getName_short());
base_ccs.add(pc.getName_short());
}
//Удаление критериев присутствующих в базе
xlsx_ccs.removeAll(base_ccs);
/**
* Если какието критерии файла отсутствуют в базе, вернуть страницу проверки критериев
*/
if (xlsx_ccs.size() != 0) {
//Подготовка списка, для передачи в представление
ArrayList<ProgramCretarea> list = new ArrayList<>();
for (String string : xlsx_ccs) {
ProgramCretarea pc = new ProgramCretarea();
pc.setName_short(string);
list.add(pc);
}
ProgramCretareaWraper pcwraper = new ProgramCretareaWraper(list);
model.addAttribute("wrapCretareas", pcwraper);
// model.addAttribute("cretareas", list);
model.addAttribute("id", id);
return "cretareas-check";
}
return "redirect:/document/view-as-educations/" + id;
}
/**
* Добавление всех критериев скопом
* @param wraper
* @param id
* @return
*/
@PostMapping(
path="/save/{id}",
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = {
MediaType.APPLICATION_JSON_VALUE
})
public String saveCretareas(@ModelAttribute("wrapCretareas") ProgramCretareaWraper wraper, @PathVariable String id){
/**
* Отправляем запросы на добавление новых критериев в базу
*/
System.out.println("Критерии для добавления в базу: "
+ wraper.getList().toString());
for (ProgramCretarea cretarea : wraper.getList()) {
//Проверка наличия полного наименования критерия
if (!cretarea.getName().equals("")) {
client.post()
.uri("http://resource-service-api:8181/cretarea/create")
.body(Mono.just(cretarea), ProgramCretarea.class)
.retrieve()
.toBodilessEntity()
.timeout(Duration.ofSeconds(1))
.block();
}
}
/**
* Возвращаем пользователя на страницу перечня новых критериев
* - если он не пустой
*/
return "redirect:/cretareas/check/" + id;
}
}

46
gates/src/main/java/ru/mlokoin/gates/controller/EducationsController.java

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
package ru.mlokoin.gates.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.reactive.function.client.WebClient;
import ru.mlokoin.gates.model.XlsxDocument;
@Controller
@RequestMapping(path = "/")
public class EducationsController {
@Autowired
private WebClient client;
/**
* Предоставление пользователю формы "view-as-educations"
* - просмотр xlsx-файла
* - проверки соответствия форме "Реестра обученных"
* - кнопки запуска механизмов проверок полей формы (критерии, программы, итд ...)
* @param model
* @param id
* @return
*/
@GetMapping("/document/view-as-educations/{id}")
public String viewAsEducations(Model model, @PathVariable String id) {
System.out.println("Просмотр содержимого файла ...");
XlsxDocument xlsx = client.method(HttpMethod.GET)
.uri("http://storage-rs:8282/api/document/content/"
+ id + ".xlsx")
.retrieve()
.bodyToMono(new ParameterizedTypeReference <XlsxDocument>(){})
.block();
model.addAttribute("filename", xlsx.getDocument().getName());
model.addAttribute("id", id);
model.addAttribute("xlsx", xlsx.getData());
model.addAttribute("headers", xlsx.getHeaders());
return "view-as-educations";
}
}

279
gates/src/main/java/ru/mlokoin/gates/controller/GatesController.java

@ -0,0 +1,279 @@ @@ -0,0 +1,279 @@
package ru.mlokoin.gates.controller;
import java.net.URI;
import java.net.URISyntaxException;
import java.time.Duration;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.MultipartBodyBuilder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import ru.mlokoin.gates.model.Document;
import ru.mlokoin.gates.model.XlsxDocument;
import ru.mlokoin.gates.util.CustomMultipartFile;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.bind.annotation.PostMapping;
/**
* Контроллер предоставления графического интерфейса
*/
@Controller
@RequestMapping(path = "/")
public class GatesController {
@Autowired
private WebClient client;
/**
* Получение списка файлов с сервера и доступа к инструментам извлечения данных
* - template : storage.html
* @param model
* @return
*/
@GetMapping("/storage")
public String getStorage(Model model){
List<Document> docs = client.method(HttpMethod.GET)
.uri("http://storage-rs:8282/api/list-uploads")
.retrieve()
.bodyToMono(new ParameterizedTypeReference <List<Document>>(){})
.block();
model.addAttribute("documents", docs);
return "storage";
}
/**
* Отправка файла в хранилище и сведений о нем в базу
* Возвращение ползователю обновленной страницы списка файлов
* - добавление метаданных файла в базу
* - получение id файла
* - отправка файла с новым именем в хранилище
*
* @param file
* @return
*/
@PostMapping("/storage/upload")
public String postMethodName(@RequestParam("file") MultipartFile file) {
Document doc = new Document();
doc.setName(file.getOriginalFilename());
doc.setSize(file.getSize());
/**
* Hfcibhtybt
*/
Optional<String> ext = Optional.ofNullable(file.getOriginalFilename())
.filter(f -> f.contains("."))
.map(f -> f.substring(file.getOriginalFilename().lastIndexOf(".") + 1));
doc.setExtension(ext.get());
doc.setExtension( ext.get());
// doc.setPath();
doc = client.post()
.uri("http://resource-service-api:8181/storage-entry/create")
.body(Mono.just(doc), Document.class)
.retrieve()
.bodyToMono(new ParameterizedTypeReference <Document>(){})
.timeout(Duration.ofSeconds(1))
.block();
MultipartBodyBuilder builder = new MultipartBodyBuilder();
Boolean ok;
MultipartFile out = new CustomMultipartFile(file, doc.getId()+"." + doc.getExtension());
builder.part("file", out.getResource());
ok = client.method(HttpMethod.POST)
.uri("http://storage-rs:8282/api/document/store")
.body(BodyInserters
.fromMultipartData(builder.build()))
.retrieve()
.bodyToMono(new ParameterizedTypeReference <Boolean>(){})
.block();
System.out.println("Файл добавлен в хранилище: " + ok);
System.out.println("ID: " + doc.getId());
System.out.println(doc.toString());
return "redirect:/storage";
}
/**
* Удаление файла из хранилища
* и возврат пользователю страницы работы с файлами
* !!! Добавить удаление записи из базы
* !!! Обернуть в транзакцию
*
* @param name
* @return
*/
@GetMapping("/storage/delete/{name}")
public String deleteFromStorage(@PathVariable String name) {
String filename = name;
String prefix = "http://storage-rs:8282/api/document/";
String postfix = "/delete";
URI uri;
try {
uri = new URI(prefix + filename + postfix);
client.method(HttpMethod.DELETE)
.uri(uri)
.retrieve()
.bodyToMono(new ParameterizedTypeReference <>(){})
.block();
} catch (URISyntaxException e) {
System.out.println("Не верный URI: " + e.getMessage());
}
return "redirect:/storage";
}
@GetMapping("/document/list")
public String getMethodName(Model model) {
List<Document> docs = client.method(HttpMethod.GET)
.uri("http://resource-service-api:8181/storage-entry/list")
.retrieve()
.bodyToMono(new ParameterizedTypeReference <List<Document>>(){})
.block();
model.addAttribute("documents", docs);
return "documents";
}
@GetMapping("/document/delete/{id}")
public String deleteFromDatabase(@PathVariable String id) {
System.out.println("gates# получение сведений о файле ... " + id);
/**
* Получеие сведений о файле из базы
*/
Document doc = client.method(HttpMethod.GET)
.uri("http://resource-service-api:8181/storage-entry/" + id)
.retrieve()
.bodyToMono(new ParameterizedTypeReference <Document>(){})
.block();
System.out.println("Документ для удаления: " + doc.toString());
System.out.println("Удаление из хранилища ...");
/**
* Удаление файла из хранилища
*/
client.delete()
.uri("http://storage-rs:8282/api/document/delete/"
+ id
+ "."
+ doc.getExtension())
.retrieve()
.bodyToMono(String.class)
.timeout(Duration.ofSeconds(1))
.block();
System.out.println("Удаление из базы ...");
/**
* Удаление записи о файле из базы
*/
client.delete()
.uri("http://resource-service-api:8181/storage-entry/delete/" + id)
.retrieve()
.bodyToMono(String.class)
.timeout(Duration.ofSeconds(1))
.block();
System.out.println("Файл успешно удален!");
return "redirect:/document/list";
}
/**
* Загрузка файла на сервер,
* - создание записи с метаданными файла в resource-service
* - передача его сервису storage-rs
* @param file
* @return
*/
@PostMapping("/document/upload")
public String upload(@RequestParam("file") MultipartFile file) {
Document doc = new Document();
doc.setName(file.getOriginalFilename());
doc.setSize(file.getSize());
/**
* Hfcibhtybt
*/
Optional<String> ext = Optional.ofNullable(file.getOriginalFilename())
.filter(f -> f.contains("."))
.map(f -> f.substring(file.getOriginalFilename().lastIndexOf(".") + 1));
doc.setExtension(ext.get());
doc.setExtension( ext.get());
// doc.setPath();
/**
* Добавление записи о файле в базу данных
*/
doc = client.post()
.uri("http://resource-service-api:8181/storage-entry/create")
.body(Mono.just(doc), Document.class)
.retrieve()
.bodyToMono(new ParameterizedTypeReference <Document>(){})
.timeout(Duration.ofSeconds(1))
.block();
/**
* Добавление файла в файловое хранилище
*/
MultipartBodyBuilder builder = new MultipartBodyBuilder();
Boolean ok;
MultipartFile out = new CustomMultipartFile(file, doc.getId()+"." + doc.getExtension());
builder.part("file", out.getResource());
ok = client.method(HttpMethod.POST)
.uri("http://storage-rs:8282/api/document/store")
.body(BodyInserters
.fromMultipartData(builder.build()))
.retrieve()
.bodyToMono(new ParameterizedTypeReference <Boolean>(){})
.block();
System.out.println("Файл добавлен в хранилище: " + ok);
System.out.println("ID: " + doc.getId());
System.out.println(doc.toString());
return "redirect:/document/list";
}
/**
* Просмотр содержимого файла:
* - предусмотреть возможность фильтрации
*/
@GetMapping("/document/view-xlsx/{id}")
public String view(Model model, @PathVariable String id) {
System.out.println("Просмотр содержимого файла ...");
XlsxDocument xlsx = client.method(HttpMethod.GET)
.uri("http://storage-rs:8282/api/document/content/"
+ id + ".xlsx")
.retrieve()
.bodyToMono(new ParameterizedTypeReference <XlsxDocument>(){})
.block();
model.addAttribute("filename", xlsx.getDocument().getName());
model.addAttribute("id", id);
model.addAttribute("xlsx", xlsx.getData());
model.addAttribute("headers", xlsx.getHeaders());
return "view-xlsx";
}
/**
* Публикация "Реестра обученных"
* - просмотр
* - фильтры
* - запись в базу типа документа
* - настройка всех промежуточных состояний импорта
*/
}

13
gates/src/main/java/ru/mlokoin/gates/controller/Hello.java

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
package ru.mlokoin.gates.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class Hello {
@GetMapping("/hello")
public String hello(){
return "hello";
}
}

173
gates/src/main/java/ru/mlokoin/gates/controller/ProgramController.java

@ -0,0 +1,173 @@ @@ -0,0 +1,173 @@
package ru.mlokoin.gates.controller;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import ru.mlokoin.gates.model.Program;
import ru.mlokoin.gates.model.ProgramCretarea;
import ru.mlokoin.gates.model.ProgramWraper;
import ru.mlokoin.gates.model.XlsxCell;
import ru.mlokoin.gates.model.XlsxDocument;
@Controller
@RequestMapping(path = "/programs")
public class ProgramController {
@Autowired
private WebClient client;
/**
* Проверка соответствия программ обучения из файла - содержащимся в базе
* @param model
* @param id
* @return
*/
@GetMapping("/check/{id}")
public String checkPrograms(Model model, @PathVariable String id) {
System.out.println("Проверка программ обучения, для внесения в базу ...");
System.out.println("Получение перечня программ из xlsx-файла ...");
//получение данных файла в переменную xlsx
XlsxDocument xlsx = client.method(HttpMethod.GET)
.uri("http://storage-rs:8282/api/document/content/"
+ id + ".xlsx")
.retrieve()
.bodyToMono(new ParameterizedTypeReference <XlsxDocument>(){})
.block();
//список программ из файла
ArrayList<Program> xlsx_programs = new ArrayList<>();//7 столбец
Map<Integer, List<XlsxCell>> map = xlsx.getData();
for (Map.Entry<Integer, List<XlsxCell>> entry : map.entrySet()) {
Program programm = new Program();
programm.setName(entry
.getValue()
.get(6)
.getContent());
xlsx_programs.add(programm);
}
xlsx_programs.remove(0);//Удалили из списка заголовок
Set<Program> xlsx_programSet = Set.copyOf(xlsx_programs);
//список уникальных наименований из файла
System.out.println("Список уникальных сокращенных наименований критериев из файла:");
Set<String> xlsx_stringSet = new HashSet<>();
for (Program pc : xlsx_programSet) {
System.out.println(pc.getName());
xlsx_stringSet.add(pc.getName());
}
//Получение перечня программ из базы
System.out.println("Получение списка программ из базы ...");
List<Program> base_programs = client.method(HttpMethod.GET)
.uri("http://resource-service-api:8181/program/list")
.retrieve()
.bodyToMono(new ParameterizedTypeReference <List<Program>>(){})
.block();
Set<Program> base_programSet = Set.copyOf(base_programs);
//Список наименований программ из базы
System.out.println("Список уникальных наименований программ из базы:");
Set<String> base_stringSet = new HashSet<>();
for (Program pc : base_programSet) {
System.out.println(pc.getName());
base_stringSet.add(pc.getName());
}
//Удаление программ присутствующих в базе
xlsx_stringSet.removeAll(base_stringSet);
if (xlsx_stringSet.size() != 0) {
//Подготовка списка, для передачи в представление
ArrayList<Program> list = new ArrayList<>();
for (String string : xlsx_stringSet) {
Program pc = new Program();
pc.setName(string);
list.add(pc);
}
/**
* Подготавлеваем обертку формы
*/
// передаем список новых программ
ProgramWraper pwraper = new ProgramWraper(list);
//подготавливаем список критериев
List<ProgramCretarea> base_cretareas = client.method(HttpMethod.GET)
.uri("http://resource-service-api:8181/cretarea/list")
.retrieve()
.bodyToMono(new ParameterizedTypeReference <List<ProgramCretarea>>(){})
.block();
//передаем список критериев в обертку формы, для селекта
pwraper.setCretareas(base_cretareas);
//передаем обертку в модель
model.addAttribute("wrapPrograms", pwraper);
model.addAttribute("id", id);
return "programs-check";
}
return "redirect:/document/view-as-educations/" + id;
}
/**
* Добавление новых программ обучения в базу
* @param wraper
* @param id
* @return
*/
@PostMapping(
path="/save/{id}",
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = {
MediaType.APPLICATION_JSON_VALUE
})
public String savePrograms(@ModelAttribute("wrapPrograms") ProgramWraper wraper, @PathVariable String id){
/**
* Отправляем запросы на добавление новых программ в базу
*/
System.out.println("Программы для добавления в базу: "
+ wraper.getPrograms().toString());
for (Program program : wraper.getPrograms()) {
//Проверка наличия полного наименования имени программы
if (!program.getName().equals("")) {
//проверка наличия длительности программы
if (program.getLenght() != null) {
//проверка наличия направления обучения
if (!program.getStudy_direction().equals("")){
//проверка наличия критерия
if (program.getCretarea() != null){
client.post()
.uri("http://resource-service-api:8181/program/create")
.body(Mono.just(program), Program.class)
.retrieve()
.toBodilessEntity()
.timeout(Duration.ofSeconds(1))
.block();
}
}
}
}
}
/**
* Возвращаем пользователя на страницу перечня новых критериев
* - если он не пустой
*/
return "redirect:/programs/check/" + id;
}
}

268
gates/src/main/java/ru/mlokoin/gates/controller/TeacherController.java

@ -0,0 +1,268 @@ @@ -0,0 +1,268 @@
package ru.mlokoin.gates.controller;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import ru.mlokoin.gates.model.ProgramCretarea;
import ru.mlokoin.gates.model.ProgramCretareaWraper;
import ru.mlokoin.gates.model.Teacher;
import ru.mlokoin.gates.model.TeacherWraper;
import ru.mlokoin.gates.model.XlsxCell;
import ru.mlokoin.gates.model.XlsxDocument;
@Controller
@RequestMapping(path = "/teachers")
public class TeacherController {
@Autowired
private WebClient client;
@GetMapping("/check/{id}")
public String checkTeachers(Model model, @PathVariable String id) {
List<String> errors = new ArrayList<>();//список ошибок
System.out.println("Проверка преподавателей, для внесения в базу ...");
System.out.println("Получение перечня преподавателей из xlsx-файла ...");
XlsxDocument xlsx = client.method(HttpMethod.GET)
.uri("http://storage-rs:8282/api/document/content/"
+ id + ".xlsx")
.retrieve()
.bodyToMono(new ParameterizedTypeReference <XlsxDocument>(){})
.block();
//список преподавателей из файла
// ArrayList<Teacher> xlsx_teachers = new ArrayList<>();//18 столбец
Map<Integer, List<XlsxCell>> map = xlsx.getData();
/**
* удалили строку заголовков
*/
map.remove(0);
System.out.println("Количество записей: " + map.size());
/**
* что делать с пустыми строками???
* - "- - -"
* - Указано два преподавателя (оставляем только первого)
* - Указан формат обучения "дистанционно" (удаляем)
* - Теоретически могут быть окончания "-угли, -оглы и т.д. ..." (писать через пробел чтобы отсутствовал сохранить исходное состояние)
*/
Set<String> xlsx_strings = new HashSet<>();//строки для браузера
Set<Teacher> xlsx_teachers = new HashSet<>();//объекты для обработки
for (Map.Entry<Integer, List<XlsxCell>> entry : map.entrySet()) {
/**
* получаем значение поля "Преподаватель"
* заменяем пустые поля на "- - -"
* добавляем запись в список уникальных значений
*/
String string = "";
try {
string = entry
.getValue()
.get(18)
.getContent();
} catch (Exception e) {
System.out.println("Не указан преподаватель: " + entry.getKey() + " :: " + e.getMessage());
string = "- - -";
}
/**
* Преобразование строки в объект Преподавателя
* - обработка возможных ошибок в файле
* - разбор строк происходит в основном переборе, чтобы можно было извлечь номер строки с ошибками для пользователя
*/
Teacher t = new Teacher();
String[] arr = string.split(" ");
for (int i = 0; i < arr.length; i++){
switch (i) {
case 0: {
if (arr.length > 1){
t.setSecond_name(arr[i]);//Фамилия
break;
}
t.setSecond_name("-");//Фамилия
t.setFirst_name("-");//Имя
t.setLast_name("-");//Отчество
errors.add("Возможна ошибка в строке документа: " + entry.getKey() + " :: В поле *Преподаватель* указано одно слово ... " + string);
break;
}
case 1: {
t.setFirst_name(arr[i]);//Имя
break;
}
case 2: {
t.setLast_name(arr[i]);//Отчество
break;
}
/**
* Обработка четвертого слова в строке
* Преподавателей, имеющих окончания в фамилии у нас нет.
* можно все что после 3-го слова откинуть ..
*
*/
case 3: {
// t.setLast_name(arr[(i-1)] + " " + arr[i]);//Окончание отчества - оглы, угли итд.
errors.add("Возможна ошибка в строке документа: " + entry.getKey() + " :: В поле *Преподаватель* указано больше трех слов ... " + string);
break;
}
default:
break;
}
}
xlsx_strings.add(string);
xlsx_teachers.add(t);
}
/**
* Промежуточные результаты в консоль
*/
System.out.println("Всего преподавателей(obj): " + xlsx_teachers.size());
System.out.println("Всего преподавателей(str): " + xlsx_strings.size());
for (Teacher teacher : xlsx_teachers) {
System.out.println("Преподаватель (obj): " + teacher.toString());
}
System.out.println(">> errors: " + errors.size());
for (String msg : errors) {
System.out.println("msg: " + msg);
}
/**
* Получение перечня преподавателей из базы
*/
System.out.println("Получение списка преподавателей из базы ...");
Set<Teacher> base_teachers = client.method(HttpMethod.GET)
.uri("http://resource-service-api:8181/teacher/list")
.retrieve()
.bodyToMono(new ParameterizedTypeReference <Set<Teacher>>(){})
.block();
/**
* Удаление преподавателей присутствующих в базе
* сравнение по объектам не проходит:
* - в объектах xlsx отсутствуют id, которые приходят с объектами из базы
* - менять Teacher.equals не хочется, он на lombok завязан
* - перевожу ФИО в строку и сравниваю строки!!!
*/
// xlsx_teachers.removeAll(base_teachers);
Set<String> xlsx_teachers_str = new HashSet<>();
Set<String> base_teachers_str = new HashSet<>();
for (Teacher t : xlsx_teachers) {
String s = t.getSecond_name() + " "
+ t.getFirst_name() + " "
+ t.getLast_name();
xlsx_teachers_str.add(s);
}
for (Teacher t : base_teachers) {
String s = t.getSecond_name() + " "
+ t.getFirst_name() + " "
+ t.getLast_name();
base_teachers_str.add(s);
}
xlsx_teachers_str.removeAll(base_teachers_str);
/**
* Если какието преподаватели отсутствуют в базе,
* вернуть страницу проверки преподавателей
*/
if (xlsx_teachers_str.size() != 0) {
/**
* Подготовка списка, для передачи в представление
* - опять преобразуем список из строкового в объектный
*/
ArrayList<Teacher> list = new ArrayList<>();
for (String string : xlsx_teachers_str) {
Teacher t = new Teacher();
String[] arr = string.split(" ");
for (int i = 0; i < arr.length; i++){
switch (i) {
case 0: {
t.setSecond_name(arr[i]);//Фамилия
break;
}
case 1: {
t.setFirst_name(arr[i]);//Имя
break;
}
case 2: {
t.setLast_name(arr[i]);//Отчество
break;
}
default:
break;
}
}
list.add(t);
}
//кладем список в обертку для формы
TeacherWraper teacherWraper = new TeacherWraper(list);
model.addAttribute("wrapTeachers", teacherWraper);
model.addAttribute("errors", errors);
model.addAttribute("id", id);
return "teachers-check";
}
return "redirect:/document/view-as-educations/" + id;
}
/**
* Добавление всех критериев скопом
* @param wraper
* @param id
* @return
*/
@PostMapping(
path="/save/{id}",
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = {
MediaType.APPLICATION_JSON_VALUE
})
public String saveTeachers(@ModelAttribute("wrapTeachers") TeacherWraper wraper, @PathVariable String id){
/**
* Отправляем запросы на добавление новых критериев в базу
*/
System.out.println("Преподаватели для добавления в базу: "
+ wraper.getList().toString());
for (Teacher teacher : wraper.getList()) {
//Проверка наличия флага для добавления в базу
//по полю табельного номера
if (teacher.getEmployee_id() != ""){
client.post()
.uri("http://resource-service-api:8181/teacher/create")
.body(Mono.just(teacher), Teacher.class)
.retrieve()
.toBodilessEntity()
.timeout(Duration.ofSeconds(1))
.block();
}
}
/**
* Возвращаем пользователя на страницу перечня новых критериев
* - если он не пустой
*/
return "redirect:/teachers/check/" + id;
}
}

29
gates/src/main/java/ru/mlokoin/gates/model/Building.java

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
package ru.mlokoin.gates.model;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Сущность объекта строительства
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Building implements Serializable{
private long id;
private String name_short;//Сокращенное наименование
private String name_full;//Полное наименование
private String code_short;//Краткий код
private String code_full;//Полный код
// подготовить конструкторы на все варианты внесения информации о преподавателях
public Building(String name_short, String name_full, String code_short, String code_full){
this.name_short = name_short;
this.name_full = name_full;
this.code_short = code_short;
this.code_full = code_full;
}
}

35
gates/src/main/java/ru/mlokoin/gates/model/BuildingWraper.java

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
package ru.mlokoin.gates.model;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
/**
* Обертка для списка объектов строительства, обеспечивающая работоспособность thymeleaf
* при отправке из формы перечня объектов строительства
*/
@Data
public class BuildingWraper {
List<Building> list;
public BuildingWraper(){
init();
}
public BuildingWraper(List<Building> list){
this.list = list;
}
public void init(){
this.list = new ArrayList<>();
}
public void add(Building building){
this.list.add(building);
}
public String toString(){
return this.list.toString();
}
}

45
gates/src/main/java/ru/mlokoin/gates/model/Course.java

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
package ru.mlokoin.gates.model;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Course {
private long id;//уникальный идентификатор курса
private String place;//место проведения занятий
private Date start_date;//дата начала курса
private Date protocol_date;//дата протокола
private String protocol_number;//номер протоколаssss
private String report_period;//отчетный период (наименование месяца)
private Teacher teacher;//сведения о преподаватле
private Program program;//сведения о программе обучения
private Building building;//сведения об объекте строительства
/**
* Конструктор без id
* @param place
* @param start_date
* @param protocol_date
* @param protocol_number
* @param report_period
* @param teacher
* @param program
* @param building
*/
public Course(String place, Date start_date, Date protocol_date, String protocol_number, String report_period,
Teacher teacher, Program program, Building building) {
this.place = place;
this.start_date = start_date;
this.protocol_date = protocol_date;
this.protocol_number = protocol_number;
this.report_period = report_period;
this.teacher = teacher;
this.program = program;
this.building = building;
}
}

32
gates/src/main/java/ru/mlokoin/gates/model/Document.java

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
package ru.mlokoin.gates.model;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Document implements Serializable{
private Long id;
private String name;//наименование файла в файловой системе ({id}.{extension})
private String path;//путь в файловой системе (root/{id}.{extension})
private String extension;//расширение файла
private Long size;//размер файла
/**
* без id
* @param name
* @param path
* @param extension
* @param size
*/
public Document(String name, String path, String extension, long size) {
this.name = name;
this.path = path;
this.extension = extension;
this.size = size;
}
}

38
gates/src/main/java/ru/mlokoin/gates/model/EducatonEntry.java

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
package ru.mlokoin.gates.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class EducatonEntry {
private long id;
private String sertificate_number;//номер удостоверения
private String frdo_number;//ФРДО номер по реестру
private String eisot_number;//ЕИСОТ номер по реестру
private String ones;//единички (вспомогатльный столбец)
private Course course;//сведения о курсе
private Student student;//сведения о студенте
/**
* Конструктор без id
* @param sertificate_number
* @param frdo_number
* @param eisot_number
* @param ones
* @param course
* @param student
*/
public EducatonEntry(String sertificate_number, String frdo_number, String eisot_number, String ones,
Course course, Student student) {
this.sertificate_number = sertificate_number;
this.frdo_number = frdo_number;
this.eisot_number = eisot_number;
this.ones = ones;
this.course = course;
this.student = student;
}
}

38
gates/src/main/java/ru/mlokoin/gates/model/Organization.java

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
package ru.mlokoin.gates.model;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Сущность организации
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Organization implements Serializable{
private long id;
private String ownership;//Форма собственности ПСК
private String name_short;//Сокращенное наименование
private String name_full;//Полное наименование
private String type;//вид ПСК - производственная/сервисная
private String inn;//ИНН организации
/**
* Конструктор без id
* @param ownership
* @param name_short
* @param name_full
* @param type
* @param inn
*/
public Organization(String ownership, String name_short, String name_full, String type, String inn) {
this.ownership = ownership;
this.name_short = name_short;
this.name_full = name_full;
this.type = type;
this.inn = inn;
}
}

45
gates/src/main/java/ru/mlokoin/gates/model/Program.java

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
package ru.mlokoin.gates.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Program {
private long id;
private String name;//Наименование
private Integer lenght;//длительность программы в часах
/**
* Направление обучения:
* - Обязательное обучение
* - Производственное обучение
* - Обучение вновь внедряемым процедурам
* - Обучение водителей
*/
private String study_direction;
private Integer price;//рублей
private ProgramCretarea cretarea;
/**
* конструктор со всеми полями сущности, за исключением id
* Подготовить все варианты конструкторов
* @param name
* @param lenght
* @param study_direction
* @param price
* @param cretarea
*/
public Program(String name, Integer lenght, String study_direction, Integer price, ProgramCretarea cretarea) {
this.name = name;
this.lenght = lenght;
this.study_direction = study_direction;
this.price = price;
this.cretarea = cretarea;
}
}

28
gates/src/main/java/ru/mlokoin/gates/model/ProgramCretarea.java

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
package ru.mlokoin.gates.model;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class ProgramCretarea implements Serializable{
private long id;
private String name;//Наименование
private String name_short;//Наименование : сокращенно
/**
* подготовить конструкторы на все варианты внесения информации о преподавателях
*
* @param name
* @param name_short
*/
public ProgramCretarea(String name, String name_short) {
this.name = name;
this.name_short = name_short;
}
}

34
gates/src/main/java/ru/mlokoin/gates/model/ProgramCretareaWraper.java

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
package ru.mlokoin.gates.model;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
/**
* Обертка для списка критериев, обеспечивающая работоспособность thymeleaf
* при отправке из формы списка критериев
*/
@Data
public class ProgramCretareaWraper {
List<ProgramCretarea> list;
public ProgramCretareaWraper(){
init();
}
public ProgramCretareaWraper(List<ProgramCretarea> list){
this.list = list;
}
public void init(){
this.list = new ArrayList<>();
}
public void add(ProgramCretarea cretarea){
this.list.add(cretarea);
}
public String toString(){
return this.list.toString();
}
}

39
gates/src/main/java/ru/mlokoin/gates/model/ProgramWraper.java

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
package ru.mlokoin.gates.model;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
/**
* Обертка для списка программ обучения - для thymeleaf
*/
@Data
public class ProgramWraper {
List<Program> programs;
List<ProgramCretarea> cretareas;
public ProgramWraper(){
init();
}
public ProgramWraper(ArrayList<Program> list) {
this.programs = list;
}
public void init(){
this.programs = new ArrayList<>();
}
public void addProgram(Program program){
this.programs.add(program);
}
public void addCretarea(ProgramCretarea cretarea){
this.cretareas.add(cretarea);
}
public String toString(){
return this.programs.toString();
}
}

55
gates/src/main/java/ru/mlokoin/gates/model/Student.java

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
package ru.mlokoin.gates.model;
import java.io.Serializable;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Student implements Serializable{
private long id;
private String first_name;//Имя
private String second_name;//Отчество
private String last_name;//Фамилия
private String profession;//Профессия
private String category;//Категория (ИТР или рабочий)
private String direction;//Структурное подразделение
private String snils;//СНИЛС
private Date berth;//Дата рождения
private String sitizenship;//Гражданство
private String sex;//Пол (Муж/Жен)
private Organization organization;//Организация - работодатель
/**
* Конструктор со всеми полями сущности кроме id
* @param first_name
* @param second_name
* @param last_name
* @param profession
* @param category
* @param direction
* @param snils
* @param berth
* @param sitizenship
* @param sex
* @param organization
*/
public Student(String first_name, String second_name, String last_name, String profession, String category,
String direction, String snils, Date berth, String sitizenship, String sex, Organization organization) {
this.first_name = first_name;
this.second_name = second_name;
this.last_name = last_name;
this.profession = profession;
this.category = category;
this.direction = direction;
this.snils = snils;
this.berth = berth;
this.sitizenship = sitizenship;
this.sex = sex;
this.organization = organization;
}
}

44
gates/src/main/java/ru/mlokoin/gates/model/Teacher.java

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
package ru.mlokoin.gates.model;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Сущьность преподавателя
* добавить данные:
* - телефоны (список)
* - эл почты (список)
* - программы которые преподает
* - график работы
* - основное место работы (офис, наимеование ОП)
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Teacher implements Serializable{
private long id;
private String first_name;//Имя
private String second_name;//Фамилия
private String last_name;//Отчество
private String employee_id;
private String snils;
// подготовить конструкторы на все варианты внесения информации о преподавателях
public Teacher(String first_name, String second_name, String last_name){
this.first_name = first_name;
this.second_name = second_name;
this.last_name = last_name;
}
//конструктор - все аргуметы кроме id
public Teacher(String first_name, String second_name, String last_name, String employee_id, String snils){
this.first_name = first_name;
this.second_name = second_name;
this.last_name = last_name;
this.employee_id = employee_id;
this.snils = snils;
}
}

31
gates/src/main/java/ru/mlokoin/gates/model/TeacherWraper.java

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
package ru.mlokoin.gates.model;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
@Data
public class TeacherWraper {
List<Teacher> list;
public TeacherWraper(){
init();
}
public TeacherWraper(List<Teacher> list){
this.list = list;
}
public void init(){
this.list = new ArrayList<>();
}
public void add(Teacher teacher){
this.list.add(teacher);
}
public String toString(){
return this.list.toString();
}
}

21
gates/src/main/java/ru/mlokoin/gates/model/XlsxCell.java

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
package ru.mlokoin.gates.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class XlsxCell {
private String content; //содержимое ячейки
private String textColor; //цвет шрифта
private String bgColor; // цвет заливки ячейки
private String textSize; //8-12-14-24 размеры шрифта
private int textWeight; //жирность: bold (900), normal(500),
private String type;// STRING, NUMERIC, BOOLEAN, FORMULA
public XlsxCell(String content){
this.content = content;
}
}

18
gates/src/main/java/ru/mlokoin/gates/model/XlsxDocument.java

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
package ru.mlokoin.gates.model;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class XlsxDocument implements Serializable{
private Map<Integer, List<XlsxCell>> data;
private Document document;
private List<XlsxCell> headers;
}

69
gates/src/main/java/ru/mlokoin/gates/util/CustomMultipartFile.java

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
package ru.mlokoin.gates.util;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.web.multipart.MultipartFile;
public class CustomMultipartFile implements MultipartFile{
private MultipartFile file;
private String name;
/**
* @param file
* @param name
*/
public CustomMultipartFile(MultipartFile file, String name) {
this.file = file;
this.name = name;
}
@NonNull
@Override
public byte[] getBytes() throws IOException {
return file.getBytes();
}
@Override
@Nullable
public String getContentType() {
return file.getContentType();
}
@NonNull
@Override
public InputStream getInputStream() throws IOException {
return file.getInputStream();
}
@NonNull
@Override
public String getName() {
return file.getName();
}
@Override
@Nullable
public String getOriginalFilename() {
return this.name;
}
@Override
public long getSize() {
return file.getSize();
}
@Override
public boolean isEmpty() {
return file.isEmpty();
}
@Override
public void transferTo(File dest) throws IOException, IllegalStateException {
//NO REALIZATION
}
}

27
gates/src/main/resources/application.yaml

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
spring:
application:
name: gates
jpa:
hibernate:
ddl-auto: update
database-platform: org.hibernate.dialect.PostgreSQLDialect
datasource:
url: "jdbc:postgresql://postgres-service:5432/tech-services"
username: tech-services
password: password
servlet:
multipart:
max-file-size: 50MB
max-request-size: 50MB
mvc:
hiddenmethod:
filter:
enabled: true
format:
date: yyyy-MM-dd
date-time: yyyy-MM-dd HH:mm:ss
time: HH:mm:ss
server:
port: 8383

2
gates/src/main/resources/static/content/md/hello.md

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
# gates
сервис для экспорта данных из файлов в базу

53
gates/src/main/resources/templates/buildings-check.html

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>check-buildings</title>
<!-- Скрипт обработки thymeleaf компонентов -->
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2/webcomponents-loader.min.js"></script>
<!-- скрипт просмотра *.MD документов -->
<!-- <script type="module" src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@1/src/zero-md.min.js"></script> -->
</head>
<body>
<header>
<h2>check-buildings</h2>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</header>
<main>
<div class="main-wraper">
<h2>Объекты строительства, отсутствующие в базе:</h2>
<!-- <form th:action="@{/program-cretareas/save/{id}(id=${id})}"
th:method="post"
th:object="${wrapCretareas}">
<table rules="all">
<thead>
<th>
<span>КРАТКО</span>
</th>
<th>
<span>ПОЛНО</span>
</th>
</thead>
<tbody>
<tr th:each="dc, dcStat : *{getList()}" >
<td>
<input type="text" th:field="*{list[__${dcStat.index}__].name_short}"/>
</td>
<td>
<input type="text" th:field="*{list[__${dcStat.index}__].name}"/>
</td>
</tr>
</tbody>
</table>
<input type="submit" value="POST-ALL"/>
</form> -->
</div>
</main>
</body>
</html>

61
gates/src/main/resources/templates/cretareas-check.html

@ -0,0 +1,61 @@ @@ -0,0 +1,61 @@
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>check-cretareas</title>
<!-- Скрипт обработки thymeleaf компонентов -->
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2/webcomponents-loader.min.js"></script>
<!-- скрипт просмотра *.MD документов -->
<!-- <script type="module" src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@1/src/zero-md.min.js"></script> -->
</head>
<body>
<header>
<h2>check-cretareas</h2>
<ul>
<li>POST NEW CRETAREAS привязать к пути на контроллере</li>
<li>Отправка формы, для передачи сервису ресурсов данных о новых критериях ...</li>
<li>Для новых критериев сделать пустой объект списка критериев, который будет отправляться после заполнения ...</li>
<li>Критерии добавлять в базу по одному, вдруг какие-то критерии окажутся опечатками и нужно будет редактировать исходный файл ...</li>
<li>Кнопка возврата к странице экспорта документа</li>
<li></li>
<li></li>
<li></li>
</ul>
</header>
<main>
<div class="main-wraper">
<h2>Критерии, отсутствующие в базе:</h2>
<form th:action="@{/program-cretareas/save/{id}(id=${id})}"
th:method="post"
th:object="${wrapCretareas}">
<table rules="all">
<thead>
<th>
<span>КРАТКО</span>
</th>
<th>
<span>ПОЛНО</span>
</th>
<!-- <th>
<span>ОТПРАВИТЬ</span>
</th> -->
</thead>
<tbody>
<tr th:each="dc, dcStat : *{getList()}" >
<td>
<input type="text" th:field="*{list[__${dcStat.index}__].name_short}"/>
</td>
<td>
<input type="text" th:field="*{list[__${dcStat.index}__].name}"/>
</td>
</tr>
</tbody>
</table>
<input type="submit" value="POST-ALL"/>
</form>
</div>
</main>
</body>
</html>

92
gates/src/main/resources/templates/documents.html

@ -0,0 +1,92 @@ @@ -0,0 +1,92 @@
<!-- Шаблон для представления данных из базы данных
- список файлов на сервере и сведения о них
- инструменты управления файлами на сервере
-->
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>documents</title>
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2/webcomponents-loader.min.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@1/src/zero-md.min.js"></script>
</head>
<body>
<header>
<h1>documents</h1>
menu : auth : documents
<br>
</header>
<main>
<div class="main-wraper">
<!--
-->
<h2>Добавление пакетов:</h2>
<form method="post" th:action="@{/document/upload}" enctype="multipart/form-data">
<div>
<input type="file" name="file">
</div>
<button type="submit">Upload File</button>
</form>
<h2>Перечень файлов:</h2>
<form th:action="@{/documents}" method="get"></form>
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<!-- <th>path</th> -->
<th>extension</th>
<th>size(bytes)</th>
<th>
</th>
</tr>
</thead>
<tbody>
<tr th:each="doc: ${documents}">
<td>
<input type="text" id="id" name="id" th:value="${doc.id}" readonly />
</td>
<td>
<input type="text" id="name" name="name" th:value="${doc.name}" readonly />
</td>
<!-- <td>
<input type="text" id="path" name="path" th:value="${doc.path}" readonly />
</td> -->
<td>
<input type="text" id="extension" name="extension" th:value="${doc.extension}" readonly />
</td>
<td>
<input type="text" id="size" name="size" th:value="${doc.size}" readonly />
</td>
<td>
<form th:action="@{/document/delete/{id}(id=${doc.id})}" th:method="get">
<!-- <input type="headen" th:field="${doc.name}" name="docName"> -->
<input type="submit" value="X"/>
</form>
</td>
<td>
<form th:action="@{/document/view-xlsx/{id}(id=${doc.id})}" th:method="get">
<input type="submit" value="VIEW"/>
</form>
</td>
<!-- <td>
<form th:action="@{/export-as-educations/{name}(name=${doc.name})}" th:method="get">
<input type="submit" value="EXPORT-AS-EDUCATIONS"/>
</form>
</td> -->
</tr>
</tbody>
</table>
</table>
</div>
</main>
</body>
</html>

14
gates/src/main/resources/templates/hello.html

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>gates-hello</title>
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2/webcomponents-loader.min.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@1/src/zero-md.min.js"></script>
</head>
<body>
<zero-md th:src="@{/content/md/hello.md}"></zero-md>
</body>
</html>

69
gates/src/main/resources/templates/programs-check.html

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>check-programs</title>
<!-- Скрипт обработки thymeleaf компонентов -->
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2/webcomponents-loader.min.js"></script>
<!-- скрипт просмотра *.MD документов -->
<!-- <script type="module" src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@1/src/zero-md.min.js"></script> -->
</head>
<body>
<header>
<h2>check-programs</h2>
<ul>
<li>Наименование программы не должно содержать знаков переноса строки.
При внесении в базу они заменяются пробелами и не проходят проверку при сравнении с наименованием в xlsx</li>
<li></li>
<li></li>
</ul>
</header>
<main>
<form th:action="@{/programs/save/{id}(id=${id})}"
th:method="post"
th:object="${wrapPrograms}">
<table rules="all">
<thead>
<th><span>Наименование программы (name)</span></th>
<th><span>Продолжительность, часов (lenght)</span></th>
<th><span>Направление обучения (study_direction)</span></th>
<th><span>Стоимость (price)</span></th>
<th><span>Критерий (cretarea_id)</span></th>
</thead>
<tbody>
<tr th:each="p, pStat : *{getPrograms()}" >
<td>
<input type="text" th:field="*{programs[__${pStat.index}__].name}">
</td>
<td>
<input type="text" th:field="*{programs[__${pStat.index}__].lenght}"/>
</td>
<td>
<select th:field="*{programs[__${pStat.index}__].study_direction}">
<option value="0" disabled >выберите нарпавление обучения</option>
<option value="1" >Обучение вновь внедряемым процедурам</option>
<option value="2" >Обучение водителей</option>
<option value="3" >Обязательное обучение</option>
<option value="4" >Производственное обучение</option>
<option value="4" >Профессиональная переподготовка</option>
</select>
</td>
<td>
<input type="text" th:field="*{programs[__${pStat.index}__].price}"/>
</td>
<td>
<select th:field="*{programs[__${pStat.index}__].cretarea.id}">
<option value="0" disabled >выберите критерий</option>
<option th:each="option : *{cretareas}" th:value="${option.id}" th:text="${option.name_short}"></option>
</select>
</td>
</tr>
</tbody>
</table>
<input type="submit" value="POST-ALL"/>
</form>
</main>
</body>
</html>

28
gates/src/main/resources/templates/storage-add.html

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>gates-uploads</title>
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2/webcomponents-loader.min.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@1/src/zero-md.min.js"></script>
</head>
<body>
<header>
<h1>gates-uploads</h1>
<br>
</header>
<main>
<div class="main-wraper">
<h2>Загрузка файла на сервер</h2>
<form method="post" th:action="@{/upload}" enctype="multipart/form-data">
<div>
<input type="file" name="file">
</div>
<button type="submit">Upload File</button>
</form>
</div>
</main>
</body>
</html>

91
gates/src/main/resources/templates/storage.html

@ -0,0 +1,91 @@ @@ -0,0 +1,91 @@
<!-- Шаблон для представления данных из файлового хранилища
- Список файлов на сервере
-
-->
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>Uploads</title>
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2/webcomponents-loader.min.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@1/src/zero-md.min.js"></script>
</head>
<body>
<header>
<h1>Gates</h1>
menu : auth : Storage
<br>
</header>
<main>
<div class="main-wraper">
<!--
-->
<h2>Добавление пакетов:</h2>\
<h2>Перечень файлов:</h2>
<form th:action="@{/storage}" method="get"></form>
<form method="post" th:action="@{/storage/upload}" enctype="multipart/form-data">
<div>
<input type="file" name="file">
</div>
<button type="submit">Upload File</button>
</form>
<table>
<thead>
<tr>
<th>name</th>
<th>path</th>
<th>extension</th>
<th>size(bytes)</th>
<th>
</th>
</tr>
</thead>
<tbody>
<tr th:each="doc: ${documents}">
<td>
<input type="text" id="name" name="name" th:value="${doc.name}" readonly />
</td>
<td>
<input type="text" id="path" name="path" th:value="${doc.path}" readonly />
</td>
<td>
<input type="text" id="extension" name="extension" th:value="${doc.extension}" readonly />
</td>
<td>
<input type="text" id="size" name="size" th:value="${doc.size}" readonly />
</td>
<td>
<form th:action="@{/storage/delete/{name}(name=${doc.name})}" th:method="get">
<!-- <input type="headen" th:field="${doc.name}" name="docName"> -->
<input type="submit" value="X"/>
</form>
</td>
<!-- <td>
<form th:action="@{/view/{name}(name=${doc.name})}" th:method="get">
<input type="submit" value="VIEW"/>
</form>
</td> -->
<!-- <td>
<form th:action="@{/export-as-educations/{name}(name=${doc.name})}" th:method="get">
<input type="submit" value="EXPORT-AS-EDUCATIONS"/>
</form>
</td> -->
</tr>
</tbody>
</table>
</table>
</div>
</main>
</body>
</html>

67
gates/src/main/resources/templates/teachers-check.html

@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>check-teachers</title>
<!-- Скрипт обработки thymeleaf компонентов -->
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2/webcomponents-loader.min.js"></script>
<!-- скрипт просмотра *.MD документов -->
<!-- <script type="module" src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@1/src/zero-md.min.js"></script> -->
</head>
<body>
<header>
<h2>check-teachers</h2>
<ul>
<li>Преподаватели добавляются в базу если указан табельный номер.</li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</header>
<main>
<form th:action="@{/teachers/save/{id}(id=${id})}"
th:method="post"
th:object="${wrapTeachers}">
<table rules="all">
<thead>
<th>Имя (first_name)</th>
<th>Фамилия (second_name)</th>
<th>Отчество (last_name)</th>
<th>Табельный номер (employee_id)</th>
<th>СНИЛС (snils)</th>
</thead>
<tbody>
<tr th:each="t, tStat : *{getList()}">
<td>
<input type="text" th:field="*{list[__${tStat.index}__].first_name}">
</td>
<td>
<input type="text" th:field="*{list[__${tStat.index}__].second_name}">
</td>
<td>
<input type="text" th:field="*{list[__${tStat.index}__].last_name}">
</td>
<td>
<input type="text" th:field="*{list[__${tStat.index}__].employee_id}">
</td>
<td>
<input type="text" th:field="*{list[__${tStat.index}__].snils}">
</td>
</tr>
</tbody>
</table>
<input type="submit" value="POST-ALL"/>
</form>
<div>
<h2>errors (потенциальные ошибки в исходном документе):
<span th:text="${#lists.size(errors)}"></span>
</h2>
<ul th:each="e: ${errors}">
<li th:text="${e}"></li>
</ul>
</div>
</main>
</body>
</html>

73
gates/src/main/resources/templates/view-as-educations.html

@ -0,0 +1,73 @@ @@ -0,0 +1,73 @@
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>view-as-educations</title>
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2/webcomponents-loader.min.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@1/src/zero-md.min.js"></script>
</head>
<body>
<header>
<h2>view-as-educations (предусмотреть): </h2>
<ul>
<li>Добавиь на страницу обработки ошибок и результатов отработки проверок</li>
<li>Удалить перед загрузкой xlsx-файла все знаки переноса строки (при отправке в базу автоматически меняются на пробелы)</li>
<li>Предусмотреть автоматический погон проверок</li>
<li>Разделить контроллеры по характеру взаимодействия с базой</li>
<li></li>
<li></li>
<li></li>
</ul>
<br><br>
<h2>CONTROLS:</h2>
<form th:action="@{/program-cretareas/check/{id}(id=${id})}" th:method="get">
<input type="submit" value="CHECK-CRETAREAS"/>
</form>
<form th:action="@{/programs/check/{id}(id=${id})}" th:method="get">
<input type="submit" value="CHECK-PROGRAMS"/>
</form>
<form th:action="@{/teachers/check/{id}(id=${id})}" th:method="get">
<input type="submit" value="CHECK-TEACHERS"/>
</form>
<form th:action="@{#}" th:method="get">
<input type="submit" value="CHECK-BUILDINGS"/>
</form>
<form th:action="@{#}" th:method="get">
<input type="submit" value="CHECK-PSK"/>
</form>
<form th:action="@{#}" th:method="get">
<input type="submit" value="CHECK-COURSES"/>
</form>
<form th:action="@{#}" th:method="get">
<input type="submit" value="CHECK-STUDENTS"/>
</form>
<form th:action="@{#}" th:method="get">
<input type="submit" value="POST-AS-EDUCATIONS"/>
</form>
</header>
<main>
<div class="main-wraper">
<table rules="all">
<caption th:text="${filename}"></caption>
<thead>
<tr>
<th th:each="header : ${headers}">
<span th:text="${header.content}"></span>
</th>
</tr>
</thead>
<tbody>
<tr th:each="row: ${xlsx.values()}">
<td th:if="${rowStat.count} &gt; 1" th:each="cell : ${row}">
<span th:text="${cell.content}"></span>
</td>
</tr>
</tbody>
</table>
</div>
</main>
</body>
</html>

59
gates/src/main/resources/templates/view-xlsx.html

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>View-xlsx</title>
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2/webcomponents-loader.min.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@1/src/zero-md.min.js"></script>
</head>
<body>
<header>
<h2>View-xlsx (предусмотреть): </h2>
<ul>
<li></li>
</ul>
<br><br>
<h2>ЭКСПОРТИРОВАТЬ ФАЙЛ КАК:</h2>
<ul>
<li>
<form th:action="@{/document/view-as-educations/{id}(id=${id})}" th:method="get">
<input type="submit" value="РЕЕСТР ОБУЧЕННЫХ (educations)"/>
</form>
</li>
<li>
<form th:action="@{#}" th:method="get">
<input type="submit" value="ЗАЯВКА НА ОБУЧЕНИЕ"/>
</form>
</li>
<li>
<form th:action="@{#}" th:method="get">
<input type="submit" value="СПИСОЧНЫЙ СОСТАВ"/>
</form>
</li>
</ul>
</header>
<main>
<div class="main-wraper">
<table rules="all">
<caption th:text="${filename}"></caption>
<thead>
<tr>
<th th:each="header : ${headers}">
<span th:text="${header.content}"></span>
</th>
</tr>
</thead>
<tbody>
<tr th:each="row: ${xlsx.values()}">
<td th:if="${rowStat.count} &gt; 1" th:each="cell : ${row}">
<span th:text="${cell.content}"></span>
</td>
</tr>
</tbody>
</table>
</div>
</main>
</body>
</html>

13
gates/src/test/java/ru/mlokoin/gates/GatesApplicationTests.java

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
package ru.mlokoin.gates;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class GatesApplicationTests {
@Test
void contextLoads() {
}
}

2
postgres-service/docker-compose.yaml

@ -24,8 +24,8 @@ volumes: @@ -24,8 +24,8 @@ volumes:
external: true
networks:
default:
external:
name: tech_network
external: true
driver: bridge
# docker volume create db_tech-services

8
resource-service-api/docker-compose.yaml

@ -1,6 +1,8 @@ @@ -1,6 +1,8 @@
version: "3.7"
services:
resource-service-api:
container_name: resource-service-api
hostname: resource-service-api
build:
context: ../resource-service-api
dockerfile: dockerfile
@ -9,8 +11,10 @@ services: @@ -9,8 +11,10 @@ services:
ports:
- 81:8181
restart: unless-stopped
networks:
- tech_network
networks:
default:
external:
tech_network:
name: tech_network
external: true
driver: bridge

4
resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/controllers/EducationEntryController.java

@ -45,7 +45,7 @@ public class EducationEntryController { @@ -45,7 +45,7 @@ public class EducationEntryController {
@PutMapping(path = "/education/update/{id}",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> updateProgram(@PathVariable Integer id, @RequestBody EducationEntry educationEntry) {
public ResponseEntity<?> updateEducationEntry(@PathVariable Integer id, @RequestBody EducationEntry educationEntry) {
EducationEntry ee = repo.findEducationEntryById(id);
ee.setSertificate_number(educationEntry.getSertificate_number());
ee.setFrdo_number(educationEntry.getFrdo_number());
@ -58,7 +58,7 @@ public class EducationEntryController { @@ -58,7 +58,7 @@ public class EducationEntryController {
}
@DeleteMapping("/education/delete/{id}")
public ResponseEntity<String> deleteProgram(@PathVariable Long id){
public ResponseEntity<String> deleteEducationEntry(@PathVariable Long id){
EducationEntry ee = repo.findEducationEntryById(id);
System.out.println(ee.toString());
repo.delete(ee);

68
resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/controllers/StorageController.java

@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
package ru.molokoin.resourceserviceapi.controllers;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import ru.molokoin.resourceserviceapi.entities.StorageEntry;
import ru.molokoin.resourceserviceapi.repositories.StorageEntryFace;
/**
* Контроллер для работы с таблицей, хранящей сведения о файлах в файловом хранилище
*/
@RestController
@RequestMapping(path = "/", consumes = {"*/*"})
public class StorageController {
@Autowired
private StorageEntryFace repo;
@GetMapping("/storage-entry/list")
public ResponseEntity<List<StorageEntry>> getStorageEntries(){
return new ResponseEntity<>(repo.findAll(), HttpStatus.OK);
}
@GetMapping("/storage-entry/{id}")
public ResponseEntity<?> getStorageEntryByID(@PathVariable Integer id){
return new ResponseEntity<>(repo.findStorageEntryById(id), HttpStatus.OK);
}
@PostMapping(path = "/storage-entry/create",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> saveStorageEntry(@RequestBody StorageEntry storageEntry) {
repo.save(storageEntry);
return new ResponseEntity<>(storageEntry, HttpStatus.CREATED);
}
@PutMapping(path = "/storage-entry/update/{id}",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> updateStorageEntry(@PathVariable Integer id, @RequestBody StorageEntry storageEntry) {
StorageEntry se = repo.findStorageEntryById(id);
se.setName(storageEntry.getName());
se.setPath(storageEntry.getPath());
se.setExtension(storageEntry.getExtension());
se.setSize(storageEntry.getSize());
repo.save(se);
return new ResponseEntity<>(repo.findStorageEntryById(id), HttpStatus.CREATED);
}
@DeleteMapping("/storage-entry/delete/{id}")
public ResponseEntity<String> deleteStorageEntry(@PathVariable Long id){
StorageEntry se = repo.findStorageEntryById(id);
repo.delete(se);
return new ResponseEntity<>("Запись id#" + id + " удалена ... ", HttpStatus.OK);
}
}

37
resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/entities/StorageEntry.java

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
package ru.molokoin.resourceserviceapi.entities;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Data
public class StorageEntry {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long id;
private String name;//наименование файла в файловой системе ({id}.{extension})
private String path;//путь в файловой системе (root/{id}.{extension})
private String extension;//расширение файла
private Long size;//размер файла
/**
* Конструктор без id
* @param name
* @param path
* @param extension
* @param size
*/
public StorageEntry(String name, String path, String extension, Long size) {
this.name = name;
this.path = path;
this.extension = extension;
this.size = size;
}
}

12
resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/repositories/StorageEntryFace.java

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
package ru.molokoin.resourceserviceapi.repositories;
import java.util.List;
import org.springframework.data.repository.ListCrudRepository;
import ru.molokoin.resourceserviceapi.entities.StorageEntry;
public interface StorageEntryFace extends ListCrudRepository<StorageEntry, Long>{
List<StorageEntry> findAll();
StorageEntry findStorageEntryById(long id);
}

1
storage-rs/.env

@ -0,0 +1 @@ @@ -0,0 +1 @@
DATA='/app/storage-rs/uploads'

33
storage-rs/.gitignore vendored

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

18
storage-rs/.mvn/wrapper/maven-wrapper.properties vendored

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
wrapperVersion=3.3.1
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip

25
storage-rs/docker-compose.yaml

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
version: "3.7"
services:
storage-rs:
container_name: storage-rs
hostname: storage-rs
build:
context: ../storage-rs
dockerfile: dockerfile
image: "storage-rs"
command: ["java","-jar","/app/storage-rs/storage-rs-0.0.1.jar"]
ports:
- 82:8282
restart: unless-stopped
volumes:
- tech_storage_rs:${DATA}
networks:
- tech_network
volumes:
tech_storage_rs:
external: true
networks:
tech_network:
name: tech_network
external: true
driver: bridge

5
storage-rs/dockerfile

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
FROM openjdk:17-jdk-alpine
RUN apk update
RUN apk upgrade
COPY target/storage-rs-0.0.1.jar /app/storage-rs/storage-rs-0.0.1.jar
WORKDIR /app/storage-rs

250
storage-rs/mvnw vendored

@ -0,0 +1,250 @@ @@ -0,0 +1,250 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.3.1
#
# Optional ENV vars
# -----------------
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
# MVNW_REPOURL - repo url base for downloading maven distribution
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
# ----------------------------------------------------------------------------
set -euf
[ "${MVNW_VERBOSE-}" != debug ] || set -x
# OS specific support.
native_path() { printf %s\\n "$1"; }
case "$(uname)" in
CYGWIN* | MINGW*)
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
native_path() { cygpath --path --windows "$1"; }
;;
esac
# set JAVACMD and JAVACCMD
set_java_home() {
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
if [ -n "${JAVA_HOME-}" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACCMD="$JAVA_HOME/jre/sh/javac"
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACCMD="$JAVA_HOME/bin/javac"
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
return 1
fi
fi
else
JAVACMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v java
)" || :
JAVACCMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v javac
)" || :
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
return 1
fi
fi
}
# hash string like Java String::hashCode
hash_string() {
str="${1:-}" h=0
while [ -n "$str" ]; do
char="${str%"${str#?}"}"
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
str="${str#?}"
done
printf %x\\n $h
}
verbose() { :; }
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
die() {
printf %s\\n "$1" >&2
exit 1
}
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
while IFS="=" read -r key value; do
case "${key-}" in
distributionUrl) distributionUrl="${value-}" ;;
distributionSha256Sum) distributionSha256Sum="${value-}" ;;
esac
done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
case "${distributionUrl##*/}" in
maven-mvnd-*bin.*)
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
*)
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
distributionPlatform=linux-amd64
;;
esac
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
;;
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
esac
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
distributionUrlName="${distributionUrl##*/}"
distributionUrlNameMain="${distributionUrlName%.*}"
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
MAVEN_HOME="$HOME/.m2/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
exec_maven() {
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
}
if [ -d "$MAVEN_HOME" ]; then
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
exec_maven "$@"
fi
case "${distributionUrl-}" in
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
esac
# prepare tmp dir
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
trap clean HUP INT TERM EXIT
else
die "cannot create temp dir"
fi
mkdir -p -- "${MAVEN_HOME%/*}"
# Download and Install Apache Maven
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
verbose "Downloading from: $distributionUrl"
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
# select .zip or .tar.gz
if ! command -v unzip >/dev/null; then
distributionUrl="${distributionUrl%.zip}.tar.gz"
distributionUrlName="${distributionUrl##*/}"
fi
# verbose opt
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
# normalize http auth
case "${MVNW_PASSWORD:+has-password}" in
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
esac
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
verbose "Found wget ... using wget"
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
verbose "Found curl ... using curl"
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
elif set_java_home; then
verbose "Falling back to use Java to download"
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
cat >"$javaSource" <<-END
public class Downloader extends java.net.Authenticator
{
protected java.net.PasswordAuthentication getPasswordAuthentication()
{
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
}
public static void main( String[] args ) throws Exception
{
setDefault( new Downloader() );
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
}
}
END
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
verbose " - Compiling Downloader.java ..."
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
verbose " - Running Downloader.java ..."
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
fi
# If specified, validate the SHA-256 sum of the Maven distribution zip file
if [ -n "${distributionSha256Sum-}" ]; then
distributionSha256Result=false
if [ "$MVN_CMD" = mvnd.sh ]; then
echo "Checksum validation is not supported for maven-mvnd." >&2
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
elif command -v sha256sum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
elif command -v shasum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
fi
if [ $distributionSha256Result = false ]; then
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
exit 1
fi
fi
# unzip and move
if command -v unzip >/dev/null; then
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
else
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
fi
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
clean || :
exec_maven "$@"

146
storage-rs/mvnw.cmd vendored

@ -0,0 +1,146 @@ @@ -0,0 +1,146 @@
<# : batch portion
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.3.1
@REM
@REM Optional ENV vars
@REM MVNW_REPOURL - repo url base for downloading maven distribution
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
@REM ----------------------------------------------------------------------------
@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
@SET __MVNW_CMD__=
@SET __MVNW_ERROR__=
@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
@SET PSModulePath=
@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
)
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
@SET __MVNW_PSMODULEP_SAVE=
@SET __MVNW_ARG0_NAME__=
@SET MVNW_USERNAME=
@SET MVNW_PASSWORD=
@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
@echo Cannot start maven from wrapper >&2 && exit /b 1
@GOTO :EOF
: end batch / begin powershell #>
$ErrorActionPreference = "Stop"
if ($env:MVNW_VERBOSE -eq "true") {
$VerbosePreference = "Continue"
}
# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
if (!$distributionUrl) {
Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
}
switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
"maven-mvnd-*" {
$USE_MVND = $true
$distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
$MVN_CMD = "mvnd.cmd"
break
}
default {
$USE_MVND = $false
$MVN_CMD = $script -replace '^mvnw','mvn'
break
}
}
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
if ($env:MVNW_REPOURL) {
$MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
}
$distributionUrlName = $distributionUrl -replace '^.*/',''
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
exit $?
}
if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
}
# prepare tmp dir
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
trap {
if ($TMP_DOWNLOAD_DIR.Exists) {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
}
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
# Download and Install Apache Maven
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
Write-Verbose "Downloading from: $distributionUrl"
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
$webclient = New-Object System.Net.WebClient
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
# If specified, validate the SHA-256 sum of the Maven distribution zip file
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
if ($distributionSha256Sum) {
if ($USE_MVND) {
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
}
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
}
}
# unzip and move
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
try {
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
} catch {
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
Write-Error "fail to move MAVEN_HOME"
}
} finally {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"

16
storage_rs/pom.xml → storage-rs/pom.xml

@ -9,19 +9,19 @@ @@ -9,19 +9,19 @@
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>ru.molokoin</groupId>
<artifactId>storage_rs</artifactId>
<artifactId>storage-rs</artifactId>
<version>0.0.1</version>
<name>storage_rs</name>
<name>storage-rs</name>
<description>file-explorer api</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<!-- <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependency> -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
@ -32,11 +32,11 @@ @@ -32,11 +32,11 @@
<artifactId>poi-ooxml</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependency> -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
@ -45,7 +45,7 @@ @@ -45,7 +45,7 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
@ -53,7 +53,7 @@ @@ -53,7 +53,7 @@
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
</dependency> -->
<dependency>
<groupId>org.springframework.boot</groupId>

0
storage_rs/src/main/docs/puml/erd-explorer-data.puml → storage-rs/src/main/docs/puml/erd-explorer-data.puml

5
storage_rs/src/main/java/ru/molokoin/storage_rs/StorageRsApplication.java → storage-rs/src/main/java/ru/molokoin/storagers/StorageRsApplication.java

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
package ru.molokoin.storage_rs;
package ru.molokoin.storagers;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import ru.molokoin.storage_rs.config.StorageConfiguration;
import ru.molokoin.storagers.config.StorageConfiguration;
@SpringBootApplication
@EnableConfigurationProperties(StorageConfiguration.class)
@ -13,5 +13,4 @@ public class StorageRsApplication { @@ -13,5 +13,4 @@ public class StorageRsApplication {
public static void main(String[] args) {
SpringApplication.run(StorageRsApplication.class, args);
}
}

2
storage_rs/src/main/java/ru/molokoin/storage_rs/config/StorageConfiguration.java → storage-rs/src/main/java/ru/molokoin/storagers/config/StorageConfiguration.java

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
package ru.molokoin.storage_rs.config;
package ru.molokoin.storagers.config;
import org.springframework.boot.context.properties.ConfigurationProperties;

12
storage_rs/src/main/java/ru/molokoin/storage_rs/controller/HelloController.java → storage-rs/src/main/java/ru/molokoin/storagers/controller/HelloController.java

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
package ru.molokoin.storage_rs.controller;
package ru.molokoin.storagers.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import ru.molokoin.storage_rs.model.Document;
import ru.molokoin.storage_rs.service.StorageServiceFace;
import ru.molokoin.storagers.model.DocumentModel;
import ru.molokoin.storagers.service.StorageServiceFace;
/**
* контроллер, для отрабтки тестов,
@ -30,12 +30,12 @@ public class HelloController { @@ -30,12 +30,12 @@ public class HelloController {
@GetMapping("/hello")
public String hello(){
System.out.println("storage_rs/hello-controller# " + "передача пользователю шаблона hello.html");
System.out.println("storage_rs/hello-controller#(из config): " + storage.root());
System.out.println("storageRS/hello-controller# " + "передача пользователю шаблона hello.html");
System.out.println("storageRS/hello-controller#(из config): " + storage.root());
System.out.println("Загружено документов: " + storage.list().size());
System.out.println("Перечень загруженных документов:");
int i = 1;
for (Document doc : storage.list()) {
for (DocumentModel doc : storage.list()) {
System.out.println("Document#" + i + ": " + doc.getPath() + "(size#" + doc.getSize() + ")");
i++;
}

198
storage-rs/src/main/java/ru/molokoin/storagers/controller/StorageController.java

@ -0,0 +1,198 @@ @@ -0,0 +1,198 @@
package ru.molokoin.storagers.controller;
import java.util.Arrays;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import ru.molokoin.storagers.model.DocumentModel;
import ru.molokoin.storagers.model.XlsxDocument;
import ru.molokoin.storagers.service.StorageServiceFace;
/**
* Контроллер для работы с файловой системой контейнера
* - получение
* - хранение
* - передача
* файлов пользователя/сторонего сервиса
*/
@Controller
@RequestMapping(path = "/", consumes = {"*/*"})
public class StorageController {
/**
* Подключаем сервис доступа к базе даных
*/
// private DocumentFace database;
/**
* получаем в переменную root
* значение свойства storage.location
* из файла application.yaml
*/
private StorageServiceFace storage;
/**
* Конструктор контроллера, дня инициализации объекта хранилища
* - передается интерфейс
* @param storage
*/
public StorageController(StorageServiceFace storage){
this.storage = storage;
}
/**
* Загружаем файл пользователя и возвращаем список файлов на сервере
*
* @return
*/
@PostMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file){
if (file.isEmpty() != true){
//добавляем перед именем файла идентификатор
String filename = storage.list().size() + "." + file.getOriginalFilename() + "";
storage.store(file, filename);
}else {
System.out.println("Попытка загрузить пустой файл!!!");
}
return "redirect:/uploads";
}
public String prefix(String input){
String[] tokens = input.split("\\.");
List<String> list = Arrays.asList(tokens);
return list.get(0);
}
public String ext(String filename){
String[] tokens = filename.split("\\.");
List<String> list = Arrays.asList(tokens);
int i = list.size();
return list.get(i - 1);
}
/**
* Возвращаем пользователю список файлов с сервера
* @param model
* @return
*/
@GetMapping("/uploads")
public String list(Model model){
model.addAttribute("documents", storage.list());
return "documents";
}
/**
* Удаление файла по имени из хранилища
* @param name
* @return
*/
@GetMapping("/delete/{name}")
public String deleteByName(@PathVariable String name) {
storage.delete(name);
return "redirect:/uploads";
}
/**
* id содержится в имени файла
* - по id найти имя файла и вызвать метод удаления по имени
* @param id
* @return
*/
// @GetMapping("/delete/by-id/{id}")
// public String deleteById(@PathVariable Long id) {
// storage.delete(id);
// return "redirect:/uploads";
// }
/**
* Просмотр содержимого xlsx-файла
* @param name
* @return
*/
@GetMapping("/view/{name}")
public String view(Model model, @PathVariable String name) {
DocumentModel doc = storage.find(name);
XlsxDocument xlsx = new XlsxDocument(doc);
model.addAttribute("filename", xlsx.getDocument().getName());
model.addAttribute("xlsx", xlsx.getData());
model.addAttribute("headers", xlsx.getHeaders());
return "view";
}
/**
* Экспорт данных из xlsx файла в базу данных
* - получение данных из xlsx
* - формирование запросов к сервису ресурсов, для публикации данных в базе
*
* @param name
* @return
*/
@GetMapping("/export-as-educations/{name}")
public String exportAsEducations(@PathVariable String name){
return "redirect:/uploads";
}
/**
* API
*/
/**
* Получение списка загруженных на сервер файлов в json формате
* @return
*/
@GetMapping("/api/list-uploads")
public ResponseEntity<List<DocumentModel>> getUploads(){
return new ResponseEntity<>(storage.list(), HttpStatus.OK);
}
/**
* Получение метаданных о файле
* @param filename
* @return
*/
@GetMapping("/api/document/{filename}")
public ResponseEntity<?> getDocumentByName(@PathVariable String filename){
return new ResponseEntity<>(storage.find(filename), HttpStatus.OK);
}
/**
* Получение содержимого файла в json формате
* @param filename
* @return
*/
@GetMapping("/api/document/content/{filename}")
public ResponseEntity<?> getDocumentContentByName(@PathVariable String filename){
DocumentModel doc = storage.find(filename);
XlsxDocument xlsx = new XlsxDocument(doc);
return new ResponseEntity<>(xlsx, HttpStatus.OK);
}
/**
* Удаление файла по имени
*/
@DeleteMapping("/api/document/delete/{filename}")
public ResponseEntity<Boolean> deleteProgram(@PathVariable String filename){
return new ResponseEntity<>(storage.delete(filename), HttpStatus.OK);
}
/**
* Загрузка файла на сервер
* @param file
* @return
*/
@PostMapping("/api/document/store")
public ResponseEntity<Boolean> store(@RequestParam("file") MultipartFile file){
return new ResponseEntity<>(storage.store(file, file.getOriginalFilename()), HttpStatus.OK);
}
}

157
storage-rs/src/main/java/ru/molokoin/storagers/model/DocumentModel.java

@ -0,0 +1,157 @@ @@ -0,0 +1,157 @@
package ru.molokoin.storagers.model;
// import lombok.AllArgsConstructor;
// import lombok.Data;
// import lombok.Getter;
// import lombok.NoArgsConstructor;
// import lombok.Setter;
// @Getter
// @Setter
// @AllArgsConstructor
// @NoArgsConstructor
public class DocumentModel {
private Long id;
private String name;//наименование файла в файловой системе ({id}.{extension})
private String path;//путь в файловой системе (root/{id}.{extension})
private String extension;//расширение файла
private Long size;//размер файла
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the path
*/
public String getPath() {
return path;
}
/**
* @param path the path to set
*/
public void setPath(String path) {
this.path = path;
}
/**
* @return the extension
*/
public String getExtension() {
return extension;
}
/**
* @param extension the extension to set
*/
public void setExtension(String extension) {
this.extension = extension;
}
/**
* @return the size
*/
public Long getSize() {
return size;
}
/**
* @param size the size to set
*/
public void setSize(Long size) {
this.size = size;
}
/**
*
*/
public DocumentModel() {
}
/**
* @param name
* @param path
* @param extension
* @param size
*/
public DocumentModel(String name, String path, String extension, Long size) {
this.name = name;
this.path = path;
this.extension = extension;
this.size = size;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((path == null) ? 0 : path.hashCode());
result = prime * result + ((extension == null) ? 0 : extension.hashCode());
result = prime * result + ((size == null) ? 0 : size.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DocumentModel other = (DocumentModel) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (path == null) {
if (other.path != null)
return false;
} else if (!path.equals(other.path))
return false;
if (extension == null) {
if (other.extension != null)
return false;
} else if (!extension.equals(other.extension))
return false;
if (size == null) {
if (other.size != null)
return false;
} else if (!size.equals(other.size))
return false;
return true;
}
/**
* @return the id
*/
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @param id
* @param name
* @param path
* @param extension
* @param size
*/
public DocumentModel(Long id, String name, String path, String extension, Long size) {
this.id = id;
this.name = name;
this.path = path;
this.extension = extension;
this.size = size;
}
@Override
public String toString() {
return "DocumentModel [id=" + id + ", name=" + name + ", path=" + path + ", extension=" + extension + ", size="
+ size + "]";
}
}

186
storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxCell.java

@ -0,0 +1,186 @@ @@ -0,0 +1,186 @@
package ru.molokoin.storagers.model;
// import lombok.AllArgsConstructor;
// import lombok.Data;
// import lombok.NoArgsConstructor;
// @Data
// @AllArgsConstructor
// @NoArgsConstructor
public class XlsxCell {
private String content; //содержимое ячейки
private String textColor; //цвет шрифта
private String bgColor; // цвет заливки ячейки
private String textSize; //8-12-14-24 размеры шрифта
private int textWeight; //жирность: bold (900), normal(500),
private String type;// STRING, NUMERIC, BOOLEAN, FORMULA
public XlsxCell(String content){
this.content = content;
}
/**
* @return the content
*/
public String getContent() {
return content;
}
/**
* @param content the content to set
*/
public void setContent(String content) {
this.content = content;
}
/**
* @return the textColor
*/
public String getTextColor() {
return textColor;
}
/**
* @param textColor the textColor to set
*/
public void setTextColor(String textColor) {
this.textColor = textColor;
}
/**
* @return the bgColor
*/
public String getBgColor() {
return bgColor;
}
/**
* @param bgColor the bgColor to set
*/
public void setBgColor(String bgColor) {
this.bgColor = bgColor;
}
/**
* @return the textSize
*/
public String getTextSize() {
return textSize;
}
/**
* @param textSize the textSize to set
*/
public void setTextSize(String textSize) {
this.textSize = textSize;
}
/**
* @return the textWeight
*/
public int getTextWeight() {
return textWeight;
}
/**
* @param textWeight the textWeight to set
*/
public void setTextWeight(int textWeight) {
this.textWeight = textWeight;
}
/**
* @return the type
*/
public String getType() {
return type;
}
/**
* @param type the type to set
*/
public void setType(String type) {
this.type = type;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((content == null) ? 0 : content.hashCode());
result = prime * result + ((textColor == null) ? 0 : textColor.hashCode());
result = prime * result + ((bgColor == null) ? 0 : bgColor.hashCode());
result = prime * result + ((textSize == null) ? 0 : textSize.hashCode());
result = prime * result + textWeight;
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
XlsxCell other = (XlsxCell) obj;
if (content == null) {
if (other.content != null)
return false;
} else if (!content.equals(other.content))
return false;
if (textColor == null) {
if (other.textColor != null)
return false;
} else if (!textColor.equals(other.textColor))
return false;
if (bgColor == null) {
if (other.bgColor != null)
return false;
} else if (!bgColor.equals(other.bgColor))
return false;
if (textSize == null) {
if (other.textSize != null)
return false;
} else if (!textSize.equals(other.textSize))
return false;
if (textWeight != other.textWeight)
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
return true;
}
@Override
public String toString() {
return "XlsxCell [content=" + content + ", textColor=" + textColor + ", bgColor=" + bgColor + ", textSize="
+ textSize + ", textWeight=" + textWeight + ", type=" + type + "]";
}
/**
*
*/
public XlsxCell() {
}
/**
* @param content
* @param textColor
* @param bgColor
* @param textSize
* @param textWeight
* @param type
*/
public XlsxCell(String content, String textColor, String bgColor, String textSize, int textWeight, String type) {
this.content = content;
this.textColor = textColor;
this.bgColor = bgColor;
this.textSize = textSize;
this.textWeight = textWeight;
this.type = type;
}
}

209
storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxDocument.java

@ -0,0 +1,209 @@ @@ -0,0 +1,209 @@
package ru.molokoin.storagers.model;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
// import lombok.AllArgsConstructor;
// import lombok.Data;
// import lombok.NoArgsConstructor;
// @Data
// @AllArgsConstructor
// @NoArgsConstructor
public class XlsxDocument implements Serializable{
private Map<Integer, List<XlsxCell>> data;
private DocumentModel document;
private List<XlsxCell> headers;//верхняя строка формы
public XlsxDocument(DocumentModel document){
this.document = document;
this.data = init(document);
this.headers = data.get(0);
}
private Map<Integer, List<XlsxCell>> init(DocumentModel document) {
FileInputStream file;
Workbook workbook;
try {
file = new FileInputStream(new File(document.getPath()));
workbook = new XSSFWorkbook(file);
Sheet sheet = workbook.getSheetAt(0);
data = new HashMap<>();
Integer i = 0;
//перебор строк
int rowStart = sheet.getFirstRowNum();
int rowEnd = sheet.getLastRowNum();
for (int rowNum = rowStart; rowNum < rowEnd; rowNum++){
Row r = sheet.getRow(rowNum);
if (r != null) {
//перебор ячеек в строке
List<XlsxCell> xlsxCells = new ArrayList<>();
XlsxCell xlsxCell = null;
int lastColumn = r.getLastCellNum();
for (int cn = 0; cn < lastColumn; cn++){
Cell cell = r.getCell(cn);
if (cell == null) {
//обработка нулевой ячейки
xlsxCell = new XlsxCell("");
xlsxCell.setType("NULL");
} else {
//обработка ячейки
switch (cell.getCellType()) {
case STRING: {
xlsxCell = new XlsxCell(cell.getStringCellValue() + "");
xlsxCell.setType("STRING");
} break;
case NUMERIC: {
xlsxCell = new XlsxCell(cell.getNumericCellValue() + "");
xlsxCell.setType("NUMERIC");
} break;
case BOOLEAN: {
xlsxCell = new XlsxCell(cell.getBooleanCellValue() + "");
xlsxCell.setType("BOOLEAN");
} break;
case FORMULA: {
xlsxCell = new XlsxCell(cell.getCellFormula() + "");
xlsxCell = new XlsxCell("FORMULA");
xlsxCell.setType("FORMULA");
} break;
case BLANK: {
xlsxCell = new XlsxCell("");
xlsxCell.setType("BLANK");
} break;
case ERROR: {
xlsxCell = new XlsxCell("");
xlsxCell.setType("ERROR");
} break;
case _NONE: {
xlsxCell = new XlsxCell("");
xlsxCell.setType("_NONE");
} break;
}
}
xlsxCells.add(xlsxCell);
}
data.put(rowNum, xlsxCells);
}
}
}catch (IOException e) {
System.out.println("Не читается файл: " + e.getMessage());
}
return data;
}
/**
* @return the data
*/
public Map<Integer, List<XlsxCell>> getData() {
return data;
}
/**
* @param data the data to set
*/
public void setData(Map<Integer, List<XlsxCell>> data) {
this.data = data;
}
/**
* @return the document
*/
public DocumentModel getDocument() {
return document;
}
/**
* @param document the document to set
*/
public void setDocument(DocumentModel document) {
this.document = document;
}
/**
* @return the headers
*/
public List<XlsxCell> getHeaders() {
return headers;
}
/**
* @param headers the headers to set
*/
public void setHeaders(List<XlsxCell> headers) {
this.headers = headers;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((data == null) ? 0 : data.hashCode());
result = prime * result + ((document == null) ? 0 : document.hashCode());
result = prime * result + ((headers == null) ? 0 : headers.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
XlsxDocument other = (XlsxDocument) obj;
if (data == null) {
if (other.data != null)
return false;
} else if (!data.equals(other.data))
return false;
if (document == null) {
if (other.document != null)
return false;
} else if (!document.equals(other.document))
return false;
if (headers == null) {
if (other.headers != null)
return false;
} else if (!headers.equals(other.headers))
return false;
return true;
}
@Override
public String toString() {
return "XlsxDocument [data=" + data + ", document=" + document + ", headers=" + headers + "]";
}
/**
* @param data
* @param document
* @param headers
*/
public XlsxDocument(Map<Integer, List<XlsxCell>> data, DocumentModel document, List<XlsxCell> headers) {
this.data = data;
this.document = document;
this.headers = headers;
}
/**
*
*/
public XlsxDocument() {
}
}

27
storage_rs/src/main/java/ru/molokoin/storage_rs/service/StorageService.java → storage-rs/src/main/java/ru/molokoin/storagers/service/StorageService.java

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
package ru.molokoin.storage_rs.service;
package ru.molokoin.storagers.service;
import java.io.File;
import java.io.IOException;
@ -17,9 +17,9 @@ import org.springframework.stereotype.Service; @@ -17,9 +17,9 @@ import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import jakarta.annotation.PostConstruct;
import ru.molokoin.storagers.config.StorageConfiguration;
import ru.molokoin.storagers.model.DocumentModel;
import ru.molokoin.storage_rs.config.StorageConfiguration;
import ru.molokoin.storage_rs.model.Document;
@Service
public class StorageService implements StorageServiceFace{
@ -57,8 +57,8 @@ public class StorageService implements StorageServiceFace{ @@ -57,8 +57,8 @@ public class StorageService implements StorageServiceFace{
}
@Override
public List<Document> list() {
List<Document> docs = new ArrayList<>();
public List<DocumentModel> list() {
List<DocumentModel> docs = new ArrayList<>();
/**
* Получаем список файлов в директории root
*/
@ -68,7 +68,7 @@ public class StorageService implements StorageServiceFace{ @@ -68,7 +68,7 @@ public class StorageService implements StorageServiceFace{
* извлекаем сведения о каждом файле для формирвоания сущности document
*/
for (String file : new ArrayList<>(Arrays.asList(files))) {
Document doc = new Document();
DocumentModel doc = new DocumentModel();
doc.setPath(root() + "/" + file);
@ -89,10 +89,17 @@ public class StorageService implements StorageServiceFace{ @@ -89,10 +89,17 @@ public class StorageService implements StorageServiceFace{
/**
* Получаем расширение файла
*/
try {
Optional<String> ext = Optional.ofNullable(file)
.filter(f -> f.contains("."))
.map(f -> f.substring(file.lastIndexOf(".") + 1));
doc.setExtension(ext.get());
} catch (Exception e) {
System.out.println("У файла отсутствует расширение: " + e.getMessage());
}
// doc.setId(null);
docs.add(doc);
}
return docs;
@ -101,7 +108,7 @@ public class StorageService implements StorageServiceFace{ @@ -101,7 +108,7 @@ public class StorageService implements StorageServiceFace{
/**
* Найти документ по имени
*/
public Document find(String name){
public DocumentModel find(String name){
return list().stream().filter(doc -> name.equals(doc.getName()))
.findAny()
.orElse(null);
@ -140,9 +147,10 @@ public class StorageService implements StorageServiceFace{ @@ -140,9 +147,10 @@ public class StorageService implements StorageServiceFace{
}
@Override
public void store(MultipartFile file) {
public Boolean store(MultipartFile file, String name_new) {
try {
Files.copy(file.getInputStream(), root().resolve(file.getOriginalFilename()));
Files.copy(file.getInputStream(), root().resolve(name_new));
return true;
} catch (Exception e) {
if (e instanceof FileAlreadyExistsException) {
throw new RuntimeException("A file of that name already exists.");
@ -156,5 +164,4 @@ public class StorageService implements StorageServiceFace{ @@ -156,5 +164,4 @@ public class StorageService implements StorageServiceFace{
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'store'");
}
}

12
storage_rs/src/main/java/ru/molokoin/storage_rs/service/StorageServiceFace.java → storage-rs/src/main/java/ru/molokoin/storagers/service/StorageServiceFace.java

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
package ru.molokoin.storage_rs.service;
package ru.molokoin.storagers.service;
import java.io.IOException;
import java.nio.file.Path;
@ -7,7 +7,7 @@ import java.util.List; @@ -7,7 +7,7 @@ import java.util.List;
import org.springframework.core.io.Resource;
import org.springframework.web.multipart.MultipartFile;
import ru.molokoin.storage_rs.model.Document;
import ru.molokoin.storagers.model.DocumentModel;
public interface StorageServiceFace {
/**
@ -31,14 +31,14 @@ public interface StorageServiceFace { @@ -31,14 +31,14 @@ public interface StorageServiceFace {
* получить список размещенных на хосте и не зарегистрированных в базе файлов
* @return
*/
public List<Document> list();
public List<DocumentModel> list();
/**
* Поиск документа из списка по имени
* @param name
* @return
*/
public Document find(String name);
public DocumentModel find(String name);
/**
* Удаление всех файлов, очистка хранилища
@ -62,8 +62,9 @@ public interface StorageServiceFace { @@ -62,8 +62,9 @@ public interface StorageServiceFace {
/**
* Сохранение файла в хранилище
* @param resource
* @return
*/
public void store(MultipartFile file);
public Boolean store(MultipartFile file, String name_new);
/**
* Сохранение группы ресурсов в хранилище
@ -71,5 +72,4 @@ public interface StorageServiceFace { @@ -71,5 +72,4 @@ public interface StorageServiceFace {
* @return
*/
public boolean store(List<Resource> resources);
}

0
storage_rs/src/main/resources/META-INF/additional-spring-configuration-metadata.json → storage-rs/src/main/resources/META-INF/additional-spring-configuration-metadata.json

2
storage_rs/src/main/resources/application.yaml → storage-rs/src/main/resources/application.yaml

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
spring:
application:
name: storage_rs
name: storage-rs
jpa:
hibernate:
ddl-auto: update

2
storage_rs/src/main/resources/static/content/md/hello.md → storage-rs/src/main/resources/static/content/md/hello.md

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
# storage_rs
# storageRS
Сервис работы с файлами:
- загрузка файлов на сервер
- скачивание файлов с сервера

6
storage_rs/src/main/resources/templates/documents.html → storage-rs/src/main/resources/templates/documents.html

@ -61,6 +61,12 @@ xmlns:th="http://www.thymeleaf.org"> @@ -61,6 +61,12 @@ xmlns:th="http://www.thymeleaf.org">
<input type="submit" value="VIEW"/>
</form>
</td>
<td>
<form th:action="@{/export-as-educations/{name}(name=${doc.name})}" th:method="get">
<input type="submit" value="EXPORT-AS-EDUCATIONS"/>
</form>
</td>
</tr>
</tbody>
</table>

0
storage_rs/src/main/resources/templates/hello.html → storage-rs/src/main/resources/templates/hello.html

44
storage-rs/src/main/resources/templates/view.html

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>Uploads</title>
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2/webcomponents-loader.min.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@1/src/zero-md.min.js"></script>
</head>
<body>
<header>
<h1>View</h1>
menu : auth : View
<br>
</header>
<main>
<div class="main-wraper">
<table>
<caption th:text="${filename}"></caption>
<thead>
<tr>
<th th:each="header : ${headers}">
<span th:text="${header.content}"></span>
</th>
</tr>
</thead>
<tbody>
<tr th:each="row: ${xlsx.values()}">
<td>
<span th:text="${rowStat.count}"></span>
</td>
<td th:if="${rowStat.count} &gt; 1" th:each="cell : ${row}">
<!-- <span th:text="${cellStat.count}"></span>
<br><br> -->
<span th:text="${cell.content}"></span>
</td>
</tr>
</tbody>
</table>
</div>
</main>
</body>
</html>

2
storage_rs/src/test/java/ru/molokoin/storage_rs/StorageRsApplicationTests.java → storage-rs/src/test/java/ru/molokoin/storagers/StorageRsApplicationTests.java

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
package ru.molokoin.storage_rs;
package ru.molokoin.storagers;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

0
storage_rs/uploads/1_ДИ.xlsx → storage-rs/uploads/1_ДИ.xlsx

0
storage_rs/uploads/2_ДОПОГ.xlsx → storage-rs/uploads/2_ДОПОГ.xlsx

0
storage_rs/uploads/3_Трудовые отношения.xlsx → storage-rs/uploads/3_Трудовые отношения.xlsx

0
storage_rs/uploads/4_Правила и нормы охраны труда.xlsx → storage-rs/uploads/4_Правила и нормы охраны труда.xlsx

0
storage_rs/uploads/5_Общие нормативы и правила.xlsx → storage-rs/uploads/5_Общие нормативы и правила.xlsx

0
storage_rs/uploads/6_Ремонт и диагностика.xlsx → storage-rs/uploads/6_Ремонт и диагностика.xlsx

0
storage_rs/uploads/use_docker.pdf → storage-rs/uploads/use_docker.pdf

0
storage_rs/uploads/Заявление для МП.docx → storage-rs/uploads/Заявление для МП.docx

0
storage_rs/uploads/тесты.zip → storage-rs/uploads/тесты.zip

1
storage_rs/.env

@ -1 +0,0 @@ @@ -1 +0,0 @@
DATA='/app/storage_rs/uploads'

21
storage_rs/docker-compose.yaml

@ -1,21 +0,0 @@ @@ -1,21 +0,0 @@
version: "3.7"
services:
storage_rs:
build:
context: ../storage_rs
dockerfile: dockerfile
image: "storage_rs"
command: ["java","-jar","/app/storage_rs/storage_rs-0.0.1.jar"]
ports:
- 82:8282
restart: unless-stopped
volumes:
- tech_storage_rs:${DATA}
volumes:
tech_storage_rs:
external: true
networks:
default:
external:
name: tech_network
driver: bridge

5
storage_rs/dockerfile

@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
FROM openjdk:17-jdk-alpine
RUN apk update
RUN apk upgrade
COPY target/storage_rs-0.0.1.jar /app/storage_rs/storage_rs-0.0.1.jar
WORKDIR /app/storage_rs

5
storage_rs/src/main/java/ru/molokoin/storage_rs/controller/ChohortController.java

@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
package ru.molokoin.storage_rs.controller;
public class ChohortController {
}

95
storage_rs/src/main/java/ru/molokoin/storage_rs/controller/StorageController.java

@ -1,95 +0,0 @@ @@ -1,95 +0,0 @@
package ru.molokoin.storage_rs.controller;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import ru.molokoin.storage_rs.model.Document;
import ru.molokoin.storage_rs.model.XlsxCell;
import ru.molokoin.storage_rs.model.XlsxDocument;
import ru.molokoin.storage_rs.service.StorageServiceFace;
/**
* Контроллер для работы с файловой системой контейнера
* - получение
* - хранение
* - передача
* файлов пользователя/сторонего сервиса
*/
@Controller
@RequestMapping(path = "/", consumes = {"*/*"})
public class StorageController {
/**
* получаем в переменную root
* значение свойства storage.location
* из файла application.yaml
*/
private StorageServiceFace storage;
/**
* Конструктор контроллера, дня инициализации объекта хранилища
* - передается интерфейс
* @param storage
*/
public StorageController(StorageServiceFace storage){
this.storage = storage;
}
/**
* Загружаем файл пользователя и возвращаем список файлов на сервере
* @return
*/
@PostMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file){
storage.store(file);
return "redirect:/uploads";
}
/**
* Возвращаем пользователю список файлов с сервера
* @param model
* @return
*/
@GetMapping("/uploads")
public String list(Model model){
model.addAttribute("documents", storage.list());
return "documents";
}
/**
* Удаление файла из хранилища
* @param name
* @return
*/
@GetMapping("/delete/{name}")
public String delete(@PathVariable String name) {
storage.delete(name);
return "redirect:/uploads";
}
/**
* Удаление файла из хранилища
* @param name
* @return
*/
@GetMapping("/view/{name}")
public String view(@PathVariable String name) {
Document doc = storage.find(name);
XlsxDocument xlsx = new XlsxDocument(doc);
for (List<XlsxCell> row : xlsx.getData().values()) {
for (XlsxCell xlsxCell : row) {
System.out.println(xlsxCell.getContent());
}
}
return "redirect:/uploads";
}
}

79
storage_rs/src/main/java/ru/molokoin/storage_rs/model/Document.java

@ -1,79 +0,0 @@ @@ -1,79 +0,0 @@
package ru.molokoin.storage_rs.model;
public class Document {
private String name;//наименование файла в файловой системе ({id}.{extension})
private String path;//путь в файловой системе (root/{id}.{extension})
private String extension;//расширение файла
private Long size;//размер файла
/**
*
*/
public Document() {
}
/**
* @param name
* @param path
* @param extension
* @param size
*/
public Document(String name, String path, String extension, long size) {
this.name = name;
this.path = path;
this.extension = extension;
this.size = size;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the path
*/
public String getPath() {
return path;
}
/**
* @param path the path to set
*/
public void setPath(String path) {
this.path = path;
}
/**
* @return the extension
*/
public String getExtension() {
return extension;
}
/**
* @param extension the extension to set
*/
public void setExtension(String extension) {
this.extension = extension;
}
/**
* @return the size
*/
public long getSize() {
return size;
}
/**
* @param size the size to set
*/
public void setSize(Long size) {
this.size = size;
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save