#1 -- add some business logic

This commit is contained in:
Anton Romanov 2022-03-09 00:10:50 +04:00
parent d490fb8133
commit 5efcaa1a3c
13 changed files with 243 additions and 33 deletions

View File

@ -32,10 +32,11 @@ dependencies {
versionSwagger = '2.5.0' versionSwagger = '2.5.0'
} }
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web' implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-jetty' implementation group: 'org.springframework.boot', name: 'spring-boot-starter-jetty'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf' implementation group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf'
implementation group: 'org.slf4j', name: 'slf4j-api', version: versionSLF4J implementation group: 'org.springframework.boot', name: 'spring-boot-starter-validation'
implementation group: 'org.slf4j', name: 'slf4j-api', version: versionSLF4J
implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect' implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect'
implementation group: 'org.springframework.boot', name:'spring-boot-starter-data-jpa' implementation group: 'org.springframework.boot', name:'spring-boot-starter-data-jpa'
implementation group: 'com.h2database', name:'h2' implementation group: 'com.h2database', name:'h2'

Binary file not shown.

View File

@ -20,7 +20,8 @@ import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
public class MvcConfiguration implements WebMvcConfigurer { public class MvcConfiguration implements WebMvcConfigurer {
@Override @Override
public void addViewControllers(ViewControllerRegistry registry) { public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/{articlename:\\w+}"); registry.addViewController("/index");
registry.addViewController("/editNews");
} }
@Override @Override

View File

@ -9,28 +9,20 @@ package ru.ulstu.controller;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import ru.ulstu.model.News; import ru.ulstu.service.NewsService;
import java.util.GregorianCalendar;
import java.util.List;
@Controller @Controller
public class IndexController { public class IndexController {
private final NewsService newsService;
public IndexController(NewsService newsService) {
this.newsService = newsService;
}
@GetMapping("/") @GetMapping("/")
public String index(Model model) { public String index(Model model) {
model.addAttribute("news", List.of(new News("Открытие семинара", new GregorianCalendar(2022, 4, 1).getTime(), model.addAttribute("news", newsService.getAll());
"На кафере \"Информационные системы\" Ульяновского государственного технического университета состоится открытие постоянно действующего семинара \"Анализ данных и процессов\". Семинар планируется проводить ежемесячно."),
new News("Открытие семинара", new GregorianCalendar(2022, 4, 1).getTime(),
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec laoreet enim dolor, vitae imperdiet mi consectetur et. Etiam posuere massa sed arcu pulvinar, eu tincidunt nunc vehicula. Integer interdum magna et orci eleifend convallis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam interdum nulla eget lacus ultricies sagittis. Duis a lacus lacinia, pulvinar augue ultrices, vulputate arcu. Etiam facilisis justo nec ex tincidunt, sit amet tempus ante iaculis. Praesent non accumsan odio. Nunc faucibus mattis elit elementum lacinia. Sed orci augue, iaculis sed efficitur ac, faucibus nec orci. Vivamus sed tempor lectus. Mauris non nisi lobortis, varius tortor id, cursus orci. Sed gravida, est nec placerat ornare, mi metus mattis eros, vitae finibus lectus turpis ut felis. Mauris faucibus lorem orci, tempor bibendum leo varius et.\n" +
"\n" +
"Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Suspendisse ut vulputate enim, nec rutrum magna. Ut finibus dignissim arcu, gravida gravida eros vulputate a. Nulla dapibus eleifend egestas. Pellentesque malesuada venenatis fermentum. Proin suscipit mi enim, eu cursus neque luctus id. Sed nec sodales libero, vel finibus sem. Maecenas tincidunt sagittis risus a posuere. Donec quis velit lorem. Curabitur viverra libero quis nibh molestie, id suscipit lorem ultrices. Donec egestas lectus at justo tempus, et pulvinar magna dignissim. Donec eleifend pretium ante in maximus. Maecenas in malesuada ante. Donec euismod tincidunt tempus.\n" +
"\n" +
"Integer convallis euismod nibh non ornare. Sed sed sagittis enim, id tempus libero. Sed interdum dui ut orci ultrices efficitur. Aenean a tristique odio. Duis nec lacus sit amet metus fringilla posuere. Donec nisi felis, congue ut lorem in, efficitur dapibus leo. Sed vel urna porta, mollis nunc in, aliquam quam. Sed rhoncus justo nisi, vitae volutpat nibh feugiat at. Phasellus laoreet justo et elit aliquet, non tincidunt mauris sagittis. Nunc in quam velit. Aliquam lobortis turpis elit, ut aliquam dolor sagittis sed. Duis pellentesque eu turpis quis ullamcorper. Nullam in ullamcorper metus. Vestibulum sit amet tellus at nulla pretium commodo. Nulla eleifend lacus ex, ac sodales odio pellentesque in. Cras nec metus elit.\n" +
"\n" +
"Cras feugiat gravida magna, nec faucibus eros eleifend nec. Donec sodales ligula ut ante lacinia eleifend. Pellentesque bibendum nunc vel nulla luctus, ut vulputate turpis semper. Aenean quis massa bibendum, vehicula lorem et, fringilla arcu. Morbi nisi elit, pellentesque ac tincidunt quis, volutpat et felis. Duis ullamcorper velit mauris, sit amet egestas sem euismod ac. Proin sodales urna in libero scelerisque mollis.\n" +
"\n" +
"Curabitur sed massa tempus, ullamcorper nisl non, posuere mi. Integer nisl quam, venenatis ut dapibus vehicula, tempor nec metus. Suspendisse ultrices maximus lorem quis accumsan. Donec ac orci et dolor tincidunt pellentesque. In at tempor ligula. Nulla mi risus, malesuada tincidunt ante vel, rhoncus posuere massa. Pellentesque feugiat urna id arcu gravida euismod. Maecenas vulputate et lorem vitae molestie. Maecenas et nibh nec nisl facilisis faucibus. Vestibulum sed lacus elementum, interdum erat non, euismod odio. Proin ac lorem vel nibh efficitur egestas ac et nibh. Integer at enim.")));
return "index"; return "index";
} }
} }

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
*
*/
package ru.ulstu.controller;
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 ru.ulstu.model.News;
import ru.ulstu.service.NewsService;
@Controller
public class NewsController {
private final NewsService newsService;
public NewsController(NewsService newsService) {
this.newsService = newsService;
}
@GetMapping("/editNews/{newsId}")
public String editNews(@PathVariable(value = "newsId") Integer id, Model model) {
model.addAttribute("news", (id != null && id != 0) ? newsService.getById(id) : new News());
return "editNews";
}
@PostMapping("saveNews")
public String saveNews(@ModelAttribute News news) {
newsService.save(news);
return "redirect:/";
}
}

View File

@ -0,0 +1,83 @@
package ru.ulstu.model;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@MappedSuperclass
public abstract class BaseEntity implements Serializable, Comparable<BaseEntity> {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private Integer id;
@Version
private Integer version;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!getClass().isAssignableFrom(obj.getClass())) {
return false;
}
BaseEntity other = (BaseEntity) obj;
if (id == null) {
if (other.id != null) {
return false;
}
} else if (!id.equals(other.id)) {
return false;
}
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (id == null ? 0 : id.hashCode());
return result;
}
@Override
public String toString() {
return getClass().getSimpleName() + "{" +
"id=" + id +
", version=" + version +
'}';
}
@Override
public int compareTo(@NotNull BaseEntity o) {
return id != null ? id.compareTo(o.getId()) : -1;
}
public void reset() {
this.id = null;
this.version = null;
}
}

View File

@ -1,12 +1,22 @@
package ru.ulstu.model; package ru.ulstu.model;
import javax.persistence.Entity;
import javax.persistence.Lob;
import java.util.Date; import java.util.Date;
public class News { @Entity
public class News extends BaseEntity {
private final static int MAX_NEWS_TEXT_PREVIEW_LENGTH = 800; private final static int MAX_NEWS_TEXT_PREVIEW_LENGTH = 800;
private final String title;
private final Date date; private String title;
private final String text;
private Date date;
@Lob
private String text;
public News() {
}
public News(String title, Date date, String text) { public News(String title, Date date, String text) {
this.title = title; this.title = title;
@ -22,12 +32,24 @@ public class News {
return date; return date;
} }
public void setDate(Date date) {
this.date = date;
}
public void setTitle(String title) {
this.title = title;
}
public void setText(String text) {
this.text = text;
}
public String getText() { public String getText() {
return text; return text;
} }
public String getPreview() { public String getPreview() {
return text.length() > MAX_NEWS_TEXT_PREVIEW_LENGTH return text != null && text.length() > MAX_NEWS_TEXT_PREVIEW_LENGTH
? text.substring(0, MAX_NEWS_TEXT_PREVIEW_LENGTH) + "..." ? text.substring(0, MAX_NEWS_TEXT_PREVIEW_LENGTH) + "..."
: text; : text;
} }

View File

@ -0,0 +1,7 @@
package ru.ulstu.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import ru.ulstu.model.News;
public interface NewsRepository extends JpaRepository<News, Integer> {
}

View File

@ -0,0 +1,45 @@
package ru.ulstu.service;
import org.springframework.stereotype.Service;
import ru.ulstu.model.News;
import ru.ulstu.repository.NewsRepository;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
@Service
public class NewsService {
private final NewsRepository newsRepository;
public NewsService(NewsRepository newsRepository) {
this.newsRepository = newsRepository;
}
public void create(String title, String text) {
newsRepository.save(new News(title, new Date(), text));
}
public void create(News news) {
news.setDate(new Date());
newsRepository.save(news);
}
public void save(News news) {
if (news.getId() != null && (news.getId() != 0)) {
newsRepository.save(news);
} else {
create(news);
}
}
public News getById(@NotNull Integer id) {
return newsRepository
.findById(id)
.orElseThrow(() -> new RuntimeException("Новость не найдена"));
}
public List<News> getAll() {
return newsRepository.findAll();
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 299 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -22,7 +22,7 @@
<body> <body>
<nav class="navbar navbar-expand-md navbar-light bg-white"> <nav class="navbar navbar-expand-md navbar-light bg-white">
<a class="navbar-brand" href="/"> <a class="navbar-brand" href="/">
<img src="img/logo.svg" width="50px"> <img src="/img/logo.svg" width="50px">
<div class="navbar-text" th:text="#{messages.logo-title}" style="font-size: 16px"></div> <div class="navbar-text" th:text="#{messages.logo-title}" style="font-size: 16px"></div>
</a> </a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
@ -32,13 +32,13 @@
<div class="collapse navbar-collapse" id="navbarSupportedContent"> <div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto"> <ul class="navbar-nav mr-auto">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="news">Новости</a> <a class="nav-link" href="/news">Новости</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="news">Заседания</a> <a class="nav-link" href="/news">Заседания</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="news">Отчеты</a> <a class="nav-link" href="/news">Отчеты</a>
</li> </li>
</ul> </ul>
</div> </div>

View File

@ -0,0 +1,26 @@
<!--
~ Copyright (C) 2021 Anton Romanov - All Rights Reserved
~ You may use, distribute and modify this code, please write to: romanov73@gmail.com.
~
-->
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
layout:decorate="~{default}">
<div class="container" layout:fragment="content">
<h3>Редактирование новости:</h3>
<form action="#" th:action="@{/saveNews}" th:object="${news}" method="post">
<p style="color:red" th:text="${error}"></p>
<div class="form-group">
<label for="title">Заголовок</label>
<input type="text" class="form-control" id="title" th:field="*{title}" placeholder="Заголовок новости">
</div>
<div class="form-group">
<label for="text">Текст новости</label>
<textarea class="form-control" id="text" th:field="*{text}" placeholder="Текст новости"></textarea>
</div>
<button type="submit" class="btn btn-primary">Сохранить</button>
</form>
</div>
</html>

View File

@ -8,10 +8,6 @@
<html <html
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
layout:decorate="~{default}"> layout:decorate="~{default}">
<head>
<title>Time series smoothing</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
</head>
<div class="container" layout:fragment="content"> <div class="container" layout:fragment="content">
<div th:each="n : ${news}" class="news"> <div th:each="n : ${news}" class="news">
<div class="row"> <div class="row">