esoe
5 months ago
102 changed files with 3862 additions and 502 deletions
@ -1,3 +1,4 @@
@@ -1,3 +1,4 @@
|
||||
{ |
||||
"java.compile.nullAnalysis.mode": "automatic" |
||||
"java.compile.nullAnalysis.mode": "automatic", |
||||
"java.configuration.updateBuildConfiguration": "interactive" |
||||
} |
@ -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: |
||||
name: tech_network |
||||
tech_network: |
||||
name: tech_network |
||||
external: true |
||||
driver: bridge |
@ -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"; |
||||
} |
||||
} |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
# client-service-teacher |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
# teachers.md |
@ -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,0 +1,2 @@
@@ -0,0 +1,2 @@
|
||||
# GATES |
||||
Микросервис, предоставляющий пользовательский интерфейс для добавления документов из хранилища в базу данных |
@ -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 |
@ -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,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> |
@ -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); |
||||
} |
||||
|
||||
} |
@ -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; |
||||
} |
||||
|
||||
|
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
@ -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"; |
||||
} |
||||
} |
@ -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"; |
||||
} |
||||
|
||||
/** |
||||
* Публикация "Реестра обученных" |
||||
* - просмотр |
||||
* - фильтры |
||||
* - запись в базу типа документа |
||||
* - настройка всех промежуточных состояний импорта |
||||
*/ |
||||
} |
@ -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"; |
||||
} |
||||
|
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
|
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
|
||||
|
||||
|
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
@ -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(); |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
|
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
@ -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
|
||||
} |
||||
|
||||
} |
@ -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 |
||||
|
||||
|
@ -0,0 +1,2 @@
@@ -0,0 +1,2 @@
|
||||
# gates |
||||
сервис для экспорта данных из файлов в базу |
@ -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> |
@ -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> |
@ -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> |
@ -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,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> |
@ -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> |
@ -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> |
@ -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> |
@ -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} > 1" th:each="cell : ${row}"> |
||||
<span th:text="${cell.content}"></span> |
||||
</td> |
||||
</tr> |
||||
</tbody> |
||||
</table> |
||||
</div> |
||||
</main> |
||||
</body> |
||||
</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} > 1" th:each="cell : ${row}"> |
||||
<span th:text="${cell.content}"></span> |
||||
</td> |
||||
</tr> |
||||
</tbody> |
||||
</table> |
||||
</div> |
||||
</main> |
||||
</body> |
||||
</html> |
@ -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() { |
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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); |
||||
} |
@ -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/ |
@ -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 |
@ -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 |
@ -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 |
@ -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 "$@" |
@ -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" |
@ -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; |
||||
|
@ -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); |
||||
} |
||||
} |
@ -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 + "]"; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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() { |
||||
} |
||||
|
||||
} |
@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
|
||||
spring: |
||||
application: |
||||
name: storage_rs |
||||
name: storage-rs |
||||
jpa: |
||||
hibernate: |
||||
ddl-auto: update |
@ -1,4 +1,4 @@
@@ -1,4 +1,4 @@
|
||||
# storage_rs |
||||
# storageRS |
||||
Сервис работы с файлами: |
||||
- загрузка файлов на сервер |
||||
- скачивание файлов с сервера |
@ -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} > 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> |
@ -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; |
@ -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 |
@ -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 |
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
package ru.molokoin.storage_rs.controller; |
||||
|
||||
public class ChohortController { |
||||
|
||||
} |
@ -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"; |
||||
} |
||||
|
||||
|
||||
} |
@ -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…
Reference in new issue