Compare commits

..

14 Commits

Author SHA1 Message Date
d7d05132c8 Fix spring security config 2025-01-28 12:31:54 +04:00
f0c683cd39 jdk-21 + spring security 6 2025-01-28 10:52:34 +04:00
faa14b698c Изменил(а) на 'README.md' 2023-03-15 22:48:55 +04:00
2c44377ba2 Изменил(а) на 'README.md' 2023-03-15 22:48:10 +04:00
1469756a92 Изменил(а) на 'README.md' 2023-03-14 16:17:53 +04:00
e49ae3c8c2 Изменил(а) на 'README.md' 2023-03-14 16:16:25 +04:00
1fd1b7f38f fix mobile menu 2022-07-26 07:51:50 +04:00
b5aee9c7fc add rich text editor 2022-07-25 23:03:51 +04:00
4862f26258 fix performance issue 2022-04-12 08:43:10 +04:00
0f420be2d9 Merge remote-tracking branch 'origin/master' into master
# Conflicts:
#	src/main/resources/templates/default.html
2022-04-11 14:19:39 +04:00
feb399162f add background image 2022-04-11 14:18:50 +04:00
305f78777c Merge remote-tracking branch 'origin/master'
# Conflicts:
#	data/db.mv.db
#	src/main/resources/application.properties
2022-04-03 22:22:39 +04:00
32f28c48f9 add yandex metrika 2022-04-03 22:20:52 +04:00
Anton Romanov
beb5fd2e15 fix image upload 2022-03-18 12:14:55 +04:00
34 changed files with 288 additions and 340 deletions

View File

@ -1,2 +1,9 @@
# seminar # seminar
JDK: https://download.oracle.com/java/17/archive/jdk-17.0.6_windows-x64_bin.exe
IDE: IntelliJIDEA community version https://www.jetbrains.com/ru-ru/idea/download/#section=windows
To run: run project and open http://localhost:8080/
Demo: http://seminar.athene.tech

View File

@ -1,45 +1,42 @@
plugins { plugins {
id 'java' id 'java'
id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'org.springframework.boot' version '3.4.2'
id 'org.springframework.boot' version '2.6.4' id 'io.spring.dependency-management' version '1.1.7'
} }
jar { group = 'ru.ulstu'
archivesBaseName = 'seminar' version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
} }
repositories { repositories {
maven { maven {
url "http://repo.athene.tech/repository/maven-central/" url = uri("http://repo.athene.tech/repository/maven-central/")
allowInsecureProtocol(true) allowInsecureProtocol(true)
} }
} }
sourceCompatibility = 11
targetCompatibility = 11
dependencies { dependencies {
ext { implementation 'org.springframework.boot:spring-boot-starter'
versionSLF4J = '1.7.24' implementation 'org.springframework.boot:spring-boot-starter-web'
versionJetty = '9.3.16.v20170120'
versionJackson = '2.9.4'
versionSwagger = '2.5.0'
}
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.springframework.boot', name: 'spring-boot-starter-validation' implementation group: 'org.springframework.boot', name: 'spring-boot-starter-validation'
implementation group: 'org.springframework.boot', name:'spring-boot-starter-data-jpa' implementation group: 'org.springframework.boot', name:'spring-boot-starter-data-jpa'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-security' implementation group: 'org.springframework.boot', name: 'spring-boot-starter-security'
implementation group: 'org.slf4j', name: 'slf4j-api', version: versionSLF4J implementation group: 'org.slf4j', name: 'slf4j-api'
implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect', version: '3.1.0' implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect'
implementation group: 'org.thymeleaf.extras', name: 'thymeleaf-extras-springsecurity5' implementation group: 'org.thymeleaf.extras', name: 'thymeleaf-extras-springsecurity6'
implementation group: 'com.h2database', name:'h2' implementation group: 'com.h2database', name:'h2'
implementation group: 'javax.xml.bind', name: 'jaxb-api' implementation group: 'jakarta.xml.bind', name: 'jakarta.xml.bind-api', version: '4.0.2'
implementation group: 'org.javassist', name: 'javassist' implementation group: 'org.javassist', name: 'javassist', version: '3.30.2-GA'
implementation group: 'com.fasterxml.jackson.module', name: 'jackson-module-blackbird'
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.13.2'
implementation group: 'org.eclipse.jetty', name: 'jetty-servlet', version: versionJetty implementation group: 'org.eclipse.jetty', name: 'jetty-servlets', version: '11.0.24'
implementation group: 'org.webjars', name: 'jquery', version: '3.6.0' implementation group: 'org.webjars', name: 'jquery', version: '3.6.0'
implementation group: 'org.webjars', name: 'bootstrap', version: '4.3.0' implementation group: 'org.webjars', name: 'bootstrap', version: '4.3.0'
@ -49,7 +46,12 @@ dependencies {
implementation group: 'org.webjars', name: 'momentjs', version: '2.24.0' implementation group: 'org.webjars', name: 'momentjs', version: '2.24.0'
implementation group: 'org.webjars', name: 'bootstrap-glyphicons', version: 'bdd2cbfba0' implementation group: 'org.webjars', name: 'bootstrap-glyphicons', version: 'bdd2cbfba0'
testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test' testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
} }

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +1,7 @@
#Mon Dec 28 10:00:20 PST 2015
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip

View File

@ -2,85 +2,52 @@ package ru.ulstu.configuration;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanInitializationException; import org.springframework.context.annotation.Bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import ru.ulstu.model.UserRoleConstants; import ru.ulstu.model.UserRoleConstants;
import ru.ulstu.user.UserService;
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { public class SecurityConfiguration {
private final Logger log = LoggerFactory.getLogger(SecurityConfiguration.class); private final Logger log = LoggerFactory.getLogger(SecurityConfiguration.class);
private final String[] permittedUrls = new String[]{
"/login", "/index", "/news/**",
"/meetings/**", "/files/**", "/docs/**",
"/public/**", "/organizers", "/webjars/**",
"/h2-console/*", "/h2-console",
"/css/**", "/js/**", "/img/**",
"/templates/**", "/webjars/**"};
private final UserService userService; @Bean
private final BCryptPasswordEncoder bCryptPasswordEncoder; public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
private final AuthenticationSuccessHandler authenticationSuccessHandler;
private final LogoutSuccessHandler logoutSuccessHandler;
public SecurityConfiguration(UserService userService,
BCryptPasswordEncoder bCryptPasswordEncoder,
AuthenticationSuccessHandler authenticationSuccessHandler,
LogoutSuccessHandler logoutSuccessHandler) {
this.userService = userService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
this.authenticationSuccessHandler = authenticationSuccessHandler;
this.logoutSuccessHandler = logoutSuccessHandler;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.headers().frameOptions().disable();
log.debug("Security enabled"); log.debug("Security enabled");
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login", "/index", "/news/**", "/meetings/**", "/files/**", "/docs/**",
"/public/**", "/organizers", "/webjars/**", "/h2-console/*", "/h2-console").permitAll()
.antMatchers("/swagger-ui.html").hasAuthority(UserRoleConstants.ADMIN)
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/loginError")
.successHandler(authenticationSuccessHandler)
.permitAll()
.and()
.logout()
.logoutSuccessHandler(logoutSuccessHandler)
.logoutSuccessUrl(Constants.LOGOUT_URL)
.invalidateHttpSession(false)
.clearAuthentication(true)
.deleteCookies(Constants.COOKIES_NAME)
.permitAll();
}
@Override http
public void configure(WebSecurity web) { .headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
web.ignoring() .csrf(AbstractHttpConfigurer::disable)
.antMatchers("/css/**") .authorizeHttpRequests(auth ->
.antMatchers("/js/**") auth.requestMatchers("/").permitAll()
.antMatchers("/img/**") .requestMatchers(permittedUrls).permitAll()
.antMatchers("/templates/**") .requestMatchers("/swagger-ui.html").hasAuthority(UserRoleConstants.ADMIN)
.antMatchers("/webjars/**"); .anyRequest().authenticated())
} .formLogin(form ->
form.loginPage("/login")
@Autowired .failureUrl("/loginError")
public void configureGlobal(AuthenticationManagerBuilder auth) { .permitAll())
try { .logout(logout ->
auth.userDetailsService(userService).passwordEncoder(bCryptPasswordEncoder); logout
} catch (Exception e) { .logoutSuccessUrl(Constants.LOGOUT_URL)
throw new BeanInitializationException("Security configuration failed", e); .invalidateHttpSession(false)
} .clearAuthentication(true)
.deleteCookies(Constants.COOKIES_NAME)
.permitAll());
return http.build();
} }
} }

View File

@ -9,8 +9,8 @@ package ru.ulstu.configuration;
import nz.net.ultraq.thymeleaf.layoutdialect.LayoutDialect; import nz.net.ultraq.thymeleaf.layoutdialect.LayoutDialect;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect; import org.thymeleaf.extras.springsecurity6.dialect.SpringSecurityDialect;
import org.thymeleaf.spring5.SpringTemplateEngine; import org.thymeleaf.spring6.SpringTemplateEngine;
import org.thymeleaf.templateresolver.ITemplateResolver; import org.thymeleaf.templateresolver.ITemplateResolver;
@Configuration @Configuration

View File

@ -1,16 +1,16 @@
package ru.ulstu.meeting; package ru.ulstu.meeting;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.Lob;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Transient;
import jakarta.validation.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import ru.ulstu.model.BaseEntity; import ru.ulstu.model.BaseEntity;
import ru.ulstu.news.News; import ru.ulstu.news.News;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.OneToOne;
import javax.persistence.Transient;
import javax.validation.constraints.NotEmpty;
import java.util.Date; import java.util.Date;
@Entity @Entity

View File

@ -6,6 +6,7 @@
package ru.ulstu.meeting; package ru.ulstu.meeting;
import jakarta.validation.Valid;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.security.access.annotation.Secured; import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@ -20,7 +21,6 @@ import org.springframework.web.bind.annotation.RequestParam;
import ru.ulstu.model.OffsetablePageRequest; import ru.ulstu.model.OffsetablePageRequest;
import ru.ulstu.model.UserRoleConstants; import ru.ulstu.model.UserRoleConstants;
import javax.validation.Valid;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -70,8 +70,7 @@ public class MeetingController {
@PostMapping("saveMeeting") @PostMapping("saveMeeting")
@Secured({UserRoleConstants.ADMIN}) @Secured({UserRoleConstants.ADMIN})
public String saveNews(@Valid @ModelAttribute Meeting meeting, public String saveNews(@Valid @ModelAttribute Meeting meeting, BindingResult result) {
BindingResult result) {
if (result.hasErrors()) { if (result.hasErrors()) {
return "editMeeting"; return "editMeeting";
} }

View File

@ -1,14 +1,13 @@
package ru.ulstu.meeting; package ru.ulstu.meeting;
import jakarta.transaction.Transactional;
import jakarta.validation.constraints.NotNull;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.ulstu.news.News; import ru.ulstu.news.News;
import ru.ulstu.news.NewsService; import ru.ulstu.news.NewsService;
import javax.transaction.Transactional;
import javax.validation.constraints.NotNull;
@Service @Service
public class MeetingService { public class MeetingService {
private final MeetingRepository meetingRepository; private final MeetingRepository meetingRepository;

View File

@ -1,11 +1,12 @@
package ru.ulstu.model; package ru.ulstu.model;
import javax.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import javax.persistence.GenerationType; import jakarta.persistence.GenerationType;
import javax.persistence.Id; import jakarta.persistence.Id;
import javax.persistence.MappedSuperclass; import jakarta.persistence.MappedSuperclass;
import javax.persistence.Version; import jakarta.persistence.Version;
import javax.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import java.io.Serializable; import java.io.Serializable;
@MappedSuperclass @MappedSuperclass

View File

@ -1,16 +1,16 @@
package ru.ulstu.model; package ru.ulstu.model;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import ru.ulstu.configuration.Constants; import ru.ulstu.configuration.Constants;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;

View File

@ -1,11 +1,11 @@
package ru.ulstu.model; package ru.ulstu.model;
import javax.persistence.Column; import jakarta.persistence.Column;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.Id; import jakarta.persistence.Id;
import javax.persistence.Table; import jakarta.persistence.Table;
import javax.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.Size; import jakarta.validation.constraints.Size;
@Entity @Entity
@Table(name = "is_user_roles") @Table(name = "is_user_roles")

View File

@ -1,13 +1,14 @@
package ru.ulstu.model; package ru.ulstu.model;
import javax.persistence.Column; import jakarta.persistence.Column;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.JoinColumn; import jakarta.persistence.JoinColumn;
import javax.persistence.ManyToOne; import jakarta.persistence.ManyToOne;
import javax.persistence.Table; import jakarta.persistence.Table;
import javax.persistence.Temporal; import jakarta.persistence.Temporal;
import javax.persistence.TemporalType; import jakarta.persistence.TemporalType;
import javax.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import java.util.Date; import java.util.Date;
@Entity @Entity

View File

@ -1,15 +1,13 @@
package ru.ulstu.news; package ru.ulstu.news;
import jakarta.persistence.Entity;
import jakarta.persistence.Lob;
import jakarta.persistence.OneToOne;
import jakarta.validation.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.multipart.MultipartFile;
import ru.ulstu.meeting.Meeting; import ru.ulstu.meeting.Meeting;
import ru.ulstu.model.BaseEntity; import ru.ulstu.model.BaseEntity;
import javax.persistence.Entity;
import javax.persistence.Lob;
import javax.persistence.OneToOne;
import javax.persistence.Transient;
import javax.validation.constraints.NotEmpty;
import java.util.Date; import java.util.Date;
@Entity @Entity
@ -26,11 +24,6 @@ public class News extends BaseEntity {
@NotEmpty(message = "Текст новости не может быть пустым") @NotEmpty(message = "Текст новости не может быть пустым")
private String text; private String text;
private String imageFileName;
@Transient
private MultipartFile imageFile;
@OneToOne(mappedBy = "news") @OneToOne(mappedBy = "news")
private Meeting meeting; private Meeting meeting;
@ -67,22 +60,6 @@ public class News extends BaseEntity {
return text; return text;
} }
public String getImageFileName() {
return imageFileName;
}
public void setImageFileName(String imageFileName) {
this.imageFileName = imageFileName;
}
public MultipartFile getImageFile() {
return imageFile;
}
public void setImageFile(MultipartFile imageFile) {
this.imageFile = imageFile;
}
public Meeting getMeeting() { public Meeting getMeeting() {
return meeting; return meeting;
} }
@ -90,10 +67,4 @@ public class News extends BaseEntity {
public void setMeeting(Meeting meeting) { public void setMeeting(Meeting meeting) {
this.meeting = meeting; this.meeting = meeting;
} }
public String getPreview() {
return text != null && text.length() > MAX_NEWS_TEXT_PREVIEW_LENGTH
? text.substring(0, MAX_NEWS_TEXT_PREVIEW_LENGTH) + "..."
: text;
}
} }

View File

@ -6,6 +6,7 @@
package ru.ulstu.news; package ru.ulstu.news;
import jakarta.validation.Valid;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.security.access.annotation.Secured; import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@ -20,8 +21,6 @@ import org.springframework.web.bind.annotation.RequestParam;
import ru.ulstu.model.OffsetablePageRequest; import ru.ulstu.model.OffsetablePageRequest;
import ru.ulstu.model.UserRoleConstants; import ru.ulstu.model.UserRoleConstants;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -71,8 +70,7 @@ public class NewsController {
@PostMapping("saveNews") @PostMapping("saveNews")
@Secured({UserRoleConstants.ADMIN}) @Secured({UserRoleConstants.ADMIN})
public String saveNews(@Valid @ModelAttribute News news, public String saveNews(@Valid @ModelAttribute News news, BindingResult result) {
BindingResult result) throws IOException {
if (result.hasErrors()) { if (result.hasErrors()) {
return "editNews"; return "editNews";
} }

View File

@ -1,15 +1,12 @@
package ru.ulstu.news; package ru.ulstu.news;
import jakarta.transaction.Transactional;
import jakarta.validation.constraints.NotNull;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.ulstu.files.FileSystemStorageService;
import ru.ulstu.files.FileUtil;
import ru.ulstu.meeting.Meeting; import ru.ulstu.meeting.Meeting;
import javax.transaction.Transactional;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -37,17 +34,12 @@ public class NewsService {
return newsRepository.save(news); return newsRepository.save(news);
} }
public void save(News news) throws IOException { public void save(News news) {
String fileName = System.currentTimeMillis() + "";
news.setImageFileName(fileName);
if (news.getId() != null && (news.getId() != 0)) { if (news.getId() != null && (news.getId() != 0)) {
newsRepository.save(news); newsRepository.save(news);
} else { } else {
create(news); create(news);
} }
FileUtil.saveFile(FileSystemStorageService.UPLOAD_DIR, fileName, news.getImageFile());
} }
public News getById(@NotNull Integer id) { public News getById(@NotNull Integer id) {

View File

@ -1,9 +1,8 @@
package ru.ulstu.user; package ru.ulstu.user;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
public final class IpAddressResolver { public final class IpAddressResolver {
private static final String CLIENT_IP_HEADER = "Client-IP"; private static final String CLIENT_IP_HEADER = "Client-IP";
private static final String FORWARDED_FOR_HEADER = "X-Forwarded-For"; private static final String FORWARDED_FOR_HEADER = "X-Forwarded-For";

View File

@ -1,5 +1,9 @@
package ru.ulstu.user; package ru.ulstu.user;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -8,10 +12,6 @@ import org.springframework.security.web.authentication.SavedRequestAwareAuthenti
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.ulstu.configuration.Constants; import ru.ulstu.configuration.Constants;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException; import java.io.IOException;
@Component @Component

View File

@ -1,5 +1,9 @@
package ru.ulstu.user; package ru.ulstu.user;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -8,10 +12,6 @@ import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuc
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.ulstu.configuration.Constants; import ru.ulstu.configuration.Constants;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException; import java.io.IOException;
@Component @Component

View File

@ -1,15 +1,13 @@
#
# Copyright (C) 2021 Anton Romanov - All Rights Reserved
# You may use, distribute and modify this code, please write to: romanov73@gmail.com.
#
#
admin-password=admin admin-password=admin
spring.main.banner-mode=off spring.main.banner-mode=off
logging.level.tech.athene=DEBUG logging.level.tech.athene=DEBUG
server.port=8080 server.port=8080
spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false
spring.servlet.multipart.max-file-size=100000000 spring.servlet.multipart.max-file-size=2048MB
spring.servlet.multipart.max-request-size=100000000 spring.servlet.multipart.max-request-size=2048MB
server.tomcat.max-http-form-post-size=2048MB
#server.tomcat.max-swallow-size=2048MB
#server.max-http-header-size=2048MB
# go to http://localhost:8080/h2-console # go to http://localhost:8080/h2-console
spring.datasource.url=jdbc:h2:file:./data/db spring.datasource.url=jdbc:h2:file:./data/db
spring.datasource.driverClassName=org.h2.Driver spring.datasource.driverClassName=org.h2.Driver

View File

@ -1,7 +1,25 @@
@media (min-width: 1200px) { html, body {
.container { width: 100%;
max-width: 970px; height: 100%;
} }
.background {
background-image: url('/img/background.jpg');
background-repeat: no-repeat;
background-size: cover;
background-position: center;
opacity: 0.1;
height: 100%;
max-height: 768px;
width: 100%;
z-index: -100;
position: absolute;
}
.body-container {
position: relative;
margin: 0 auto;
min-height: 100%;
} }
.news { .news {
@ -50,6 +68,16 @@
border-radius: 2px; border-radius: 2px;
} }
footer { .clearfloat {
clear: both;
}
.empty {
height: 50px; height: 50px;
} }
footer {
height: 50px;
position: relative;
margin: -50px auto 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

View File

@ -1,9 +1,3 @@
<!--
~ 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"> <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}"> <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
<div class="container" layout:fragment="content"> <div class="container" layout:fragment="content">

View File

@ -7,70 +7,91 @@
<title th:text="#{messages.app-name}">app-name</title> <title th:text="#{messages.app-name}">app-name</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script type="text/javascript" src="/webjars/jquery/3.6.0/jquery.min.js"></script> <script type="text/javascript" src="/webjars/jquery/3.6.0/jquery.min.js"></script>
<script type="text/javascript" src="/webjars/momentjs/2.24.0/moment.js"></script>
<script type="text/javascript" src="/webjars/momentjs/2.24.0/locale/ru.js"></script>
<script type="text/javascript" src="/webjars/bootstrap/4.3.0/js/bootstrap.bundle.min.js"></script> <script type="text/javascript" src="/webjars/bootstrap/4.3.0/js/bootstrap.bundle.min.js"></script>
<script type="text/javascript" src="/webjars/bootstrap-select/1.13.8/js/bootstrap-select.min.js"></script>
<script type="text/javascript"
src="/webjars/bootstrap-datetimepicker/2.4.4/js/bootstrap-datetimepicker.js"></script>
<link rel="stylesheet" href="/webjars/bootstrap/4.3.0/css/bootstrap.min.css"/> <link rel="stylesheet" href="/webjars/bootstrap/4.3.0/css/bootstrap.min.css"/>
<link rel="stylesheet" href="/webjars/bootstrap-select/1.13.8/css/bootstrap-select.min.css"/>
<link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/> <link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/>
<link rel="stylesheet" href="/webjars/bootstrap-glyphicons/bdd2cbfba0/css/bootstrap-glyphicons.css"/>
<link rel="stylesheet" href="/webjars/bootstrap-datetimepicker/2.4.4/css/bootstrap-datetimepicker.css"/>
<link rel="stylesheet" href="/css/main.css"/> <link rel="stylesheet" href="/css/main.css"/>
</head> </head>
<body> <body>
<nav class="navbar navbar-expand-md navbar-light bg-white"> <div class="body-container">
<a class="navbar-brand" href="/"> <div class="background"></div>
<img src="/img/logo.svg" width="50px"> <nav class="navbar navbar-expand-md navbar-light bg-white">
<div class="navbar-text" th:text="#{messages.logo-title}" style="font-size: 16px"></div> <a class="navbar-brand" href="/">
</a> <img src="/img/logo.svg" width="50px">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" <div class="navbar-text" th:text="#{messages.logo-title}" style="font-size: 16px"></div>
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> </a>
<span class="navbar-toggler-icon"></span> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
</button> aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<div class="collapse navbar-collapse" id="navbarSupportedContent"> <span class="navbar-toggler-icon"></span>
<ul class="navbar-nav mr-auto"> </button>
<li class="nav-item"> <div class="collapse navbar-collapse" id="navbarSupportedContent">
<a class="nav-link" href="/news/news">Новости</a> <ul class="navbar-nav mr-auto">
</li> <li class="nav-item">
<li class="nav-item"> <a class="nav-link" href="/news/news">Новости</a>
<a class="nav-link" href="/meetings/meetings">Заседания</a> </li>
</li> <li class="nav-item">
<li class="nav-item"> <a class="nav-link" href="/meetings/meetings">Заседания</a>
<a class="nav-link" href="/organizers">Организаторы</a> </li>
</li> <li class="nav-item">
<li class="nav-item"> <a class="nav-link" href="/organizers">Организаторы</a>
<a class="nav-link" href="/docs">Документы</a> </li>
</li> <li class="nav-item">
<li class="nav-item"> <a class="nav-link" href="/docs">Документы</a>
<a class="nav-link" href="/reports">Отчеты</a> </li>
</li> <li class="nav-item">
<li class="nav-item"> <a class="nav-link" href="/reports">Отчеты</a>
<a class="nav-link" href="/admin">Администратору</a> </li>
</li> <li class="nav-item">
<li> <a class="nav-link" href="/admin">Администратору</a>
<div sec:authorize="isAuthenticated()"> </li>
<a class="nav-link" href="/logout">Выход</a> <li>
</div> <div sec:authorize="isAuthenticated()">
<a class="nav-link" href="/logout">Выход</a>
</div>
</li> </li>
</ul>
</div>
</nav>
<div class="wrapper">
<div id="content">
<div class="container-fluid">
<ul id="messages" class="feedback-panel">
<div class="alert alert-danger" role="alert" th:if="${error}" th:text="${error}">
</div>
</ul> </ul>
</div> </div>
<div layout:fragment="content"> </nav>
<div class="wrapper">
<div id="content">
<div class="container-fluid">
<ul id="messages" class="feedback-panel">
<div class="alert alert-danger" role="alert" th:if="${error}" th:text="${error}">
</div>
</ul>
</div>
<div layout:fragment="content">
</div>
</div> </div>
<div class="clearfloat"></div>
<div class="empty"></div>
</div> </div>
<footer></footer> <footer></footer>
<!-- Yandex.Metrika counter -->
<script type="text/javascript">
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(88139282, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript>
<div><img src="https://mc.yandex.ru/watch/88139282" style="position:absolute; left:-9999px;" alt=""/></div>
</noscript>
<!-- /Yandex.Metrika counter -->
</div> </div>
<footer>
2022
</footer>
</body> </body>
</html> </html>

View File

@ -1,20 +1,14 @@
<!--
~ 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"> <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}"> <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
<div class="container" layout:fragment="content"> <div class="container" layout:fragment="content">
<ul class="list-group"> <ul class="list-group">
<li class="list-group-item"> <li class="list-group-item">
<a class="link-secondary" href="/docs/polozh.docx"> <a class="link-dark" href="/docs/polozh.docx">
Положение Положение
</a> </a>
</li> </li>
<li class="list-group-item"> <li class="list-group-item">
<a class="link-secondary" href="/docs/plan2022.docx"> <a class="link-dark" href="/docs/plan2022.docx">
План заседаний на 2022 год. План заседаний на 2022 год.
</a> </a>
</li> </li>

View File

@ -30,6 +30,17 @@
<button type="submit" class="btn btn-outline-dark">Сохранить</button> <button type="submit" class="btn btn-outline-dark">Сохранить</button>
<a href="javascript:history.back()" class="btn btn-outline-dark">Отмена</a> <a href="javascript:history.back()" class="btn btn-outline-dark">Отмена</a>
</form> </form>
<script type="text/javascript" src="/webjars/momentjs/2.24.0/moment.js"></script>
<script type="text/javascript" src="/webjars/momentjs/2.24.0/locale/ru.js"></script>
<script type="text/javascript" src="/webjars/bootstrap-select/1.13.8/js/bootstrap-select.min.js"></script>
<script type="text/javascript"
src="/webjars/bootstrap-datetimepicker/2.4.4/js/bootstrap-datetimepicker.js"></script>
<script type="text/javascript" src="/webjars/summernote/0.8.10/summernote-bs4.js"></script>
<link rel="stylesheet" href="/webjars/bootstrap-select/1.13.8/css/bootstrap-select.min.css"/>
<link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/>
<link rel="stylesheet" href="/webjars/bootstrap-glyphicons/bdd2cbfba0/css/bootstrap-glyphicons.css"/>
<link rel="stylesheet" href="/webjars/bootstrap-datetimepicker/2.4.4/css/bootstrap-datetimepicker.css"/>
<link rel="stylesheet" href="/webjars/summernote/0.8.10/summernote-bs4.css"/>
<script> <script>
$(function () { $(function () {
$("#date").datetimepicker({ $("#date").datetimepicker({
@ -37,6 +48,9 @@
locale: 'ru' locale: 'ru'
}); });
}); });
$('#text').summernote({
height: 300
});
</script> </script>
</div> </div>
</html> </html>

View File

@ -1,9 +1,3 @@
<!--
~ 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"> <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<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"
@ -27,16 +21,26 @@
<p th:if="${#fields.hasErrors('text')}" th:class="${#fields.hasErrors('text')}? error"> <p th:if="${#fields.hasErrors('text')}" th:class="${#fields.hasErrors('text')}? error">
Не может быть пустым</p> Не может быть пустым</p>
</div> </div>
<div class="form-group">
<label for="image">Изображение</label>
<input type="file" name="imageFile" class="form-control" th:field="*{imageFile}" id="image"
placeholder="Фото новости"/>
<p th:if="${#fields.hasErrors('imageFile')}" th:class="${#fields.hasErrors('imageFile')} ? error">
Ошибка</p>
</div>
<button type="submit" class="btn btn-outline-dark">Сохранить</button> <button type="submit" class="btn btn-outline-dark">Сохранить</button>
<a href="javascript:history.back()" class="btn btn-outline-dark">Отмена</a> <a href="javascript:history.back()" class="btn btn-outline-dark">Отмена</a>
</form> </form>
<script type="text/javascript" src="/webjars/momentjs/2.24.0/moment.js"></script>
<script type="text/javascript" src="/webjars/momentjs/2.24.0/locale/ru.js"></script>
<script type="text/javascript" src="/webjars/bootstrap-select/1.13.8/js/bootstrap-select.min.js"></script>
<script type="text/javascript"
src="/webjars/bootstrap-datetimepicker/2.4.4/js/bootstrap-datetimepicker.js"></script>
<script type="text/javascript" src="/webjars/summernote/0.8.10/summernote-bs4.js"></script>
<link rel="stylesheet" href="/webjars/bootstrap-select/1.13.8/css/bootstrap-select.min.css"/>
<link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/>
<link rel="stylesheet" href="/webjars/bootstrap-glyphicons/bdd2cbfba0/css/bootstrap-glyphicons.css"/>
<link rel="stylesheet" href="/webjars/bootstrap-datetimepicker/2.4.4/css/bootstrap-datetimepicker.css"/>
<link rel="stylesheet" href="/webjars/summernote/0.8.10/summernote-bs4.css"/>
<script>
$('#text').summernote({
height: 300
});
</script>
</div> </div>
</html> </html>

View File

@ -1,19 +1,10 @@
<!--
~ 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"> <!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" <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
layout:decorate="~{default}"> layout:decorate="~{default}">
<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">
<div class="col-md-4"> <div class="col-md-12">
<img class="news-image" th:src="@{'/files/' + ${n.imageFileName}}"/>
</div>
<div class="col-md-8">
<div class="row"> <div class="row">
<div class="col-md-10"> <div class="col-md-10">
<a th:if="${n.meeting == null}" th:href="@{'/news/news/' + ${n.id}}" class="link-dark"><h5 <a th:if="${n.meeting == null}" th:href="@{'/news/news/' + ${n.id}}" class="link-dark"><h5
@ -22,13 +13,13 @@
class="link-dark"><h5 th:text="${n.title}"/></a> class="link-dark"><h5 th:text="${n.title}"/></a>
</div> </div>
</div> </div>
<div th:if="${n.meeting == null}" th:text="${n.preview}" class="news-item"></div> <div th:if="${n.meeting == null}" th:utext="${n.text}" class="news-item"></div>
<div th:if="${n.meeting != null}" th:text="${'Тема заседания: ' + n.meeting.title}" <div th:if="${n.meeting != null}" th:text="${'Тема заседания: ' + n.meeting.title}"
class="news-item"></div> class="news-item"></div>
<div th:if="${n.meeting != null}" <div th:if="${n.meeting != null}"
th:text="${'Дата: ' + #calendars.format(n.meeting.date, 'dd.MM.yyyy HH:mm')}" th:text="${'Дата: ' + #calendars.format(n.meeting.date, 'dd.MM.yyyy HH:mm')}"
class="news-item"></div> class="news-item"></div>
<div th:if="${n.meeting != null}" th:text="${n.meeting.text}" class="news-item"></div> <div th:if="${n.meeting != null}" th:utext="${n.meeting.text}" class="news-item"></div>
</div> </div>
</div> </div>
<div th:text="${'Опубликовано: ' + #calendars.format(n.date, 'dd.MM.yyyy HH:mm')}" <div th:text="${'Опубликовано: ' + #calendars.format(n.date, 'dd.MM.yyyy HH:mm')}"

View File

@ -7,6 +7,7 @@
<div class="row"> <div class="row">
<div class="col-md-10"> <div class="col-md-10">
<a th:href="@{'/meetings/meetings/' + ${m.id}}" class="link-dark"><h5 th:text="${m.title}"/></a> <a th:href="@{'/meetings/meetings/' + ${m.id}}" class="link-dark"><h5 th:text="${m.title}"/></a>
<div th:text="${'Дата заседания: ' + #calendars.format(m.date, 'dd.MM.yyyy HH:mm')}"></div>
</div> </div>
<div sec:authorize="hasRole('ROLE_ADMIN')" class="col-md-2" style="text-align: right"> <div sec:authorize="hasRole('ROLE_ADMIN')" class="col-md-2" style="text-align: right">
<a th:href="@{'/meetings/editMeeting/' + ${m.id}}" class="link-dark"> <a th:href="@{'/meetings/editMeeting/' + ${m.id}}" class="link-dark">
@ -29,6 +30,5 @@
th:text=${pageNumber} th:text=${pageNumber}
th:class="${pageNumber == meetings.number+1} ? active"></a> th:class="${pageNumber == meetings.number+1} ? active"></a>
</div> </div>
</div> </div>
</html> </html>

View File

@ -1,9 +1,3 @@
<!--
~ 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"> <!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" <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"
@ -11,10 +5,7 @@
<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">
<div class="col-md-4"> <div class="col-md-12">
<img class="news-image" th:src="@{'/files/' + ${n.imageFileName}}"/>
</div>
<div class="col-md-8">
<div class="row"> <div class="row">
<div class="col-md-10"> <div class="col-md-10">
<a th:if="${n.meeting == null}" th:href="@{'/news/news/' + ${n.id}}" class="link-dark"><h5 <a th:if="${n.meeting == null}" th:href="@{'/news/news/' + ${n.id}}" class="link-dark"><h5
@ -32,13 +23,13 @@
</a> </a>
</div> </div>
</div> </div>
<div th:if="${n.meeting == null}" th:text="${n.preview}" class="news-item"></div> <div th:if="${n.meeting == null}" th:utext="${n.text}" class="news-item"></div>
<div th:if="${n.meeting != null}" th:text="${'Тема заседания: ' + n.meeting.title}" <div th:if="${n.meeting != null}" th:text="${'Тема заседания: ' + n.meeting.title}"
class="news-item"></div> class="news-item"></div>
<div th:if="${n.meeting != null}" <div th:if="${n.meeting != null}"
th:text="${'Дата: ' + #calendars.format(n.meeting.date, 'dd.MM.yyyy HH:mm')}" th:text="${'Дата: ' + #calendars.format(n.meeting.date, 'dd.MM.yyyy HH:mm')}"
class="news-item"></div> class="news-item"></div>
<div th:if="${n.meeting != null}" th:text="${n.meeting.text}" class="news-item"></div> <div th:if="${n.meeting != null}" th:utext="${n.meeting.text}" class="news-item"></div>
</div> </div>
</div> </div>
<div th:text="${'Опубликовано: ' + #calendars.format(n.date, 'dd.MM.yyyy HH:mm')}" <div th:text="${'Опубликовано: ' + #calendars.format(n.date, 'dd.MM.yyyy HH:mm')}"

View File

@ -1,9 +1,3 @@
<!--
~ 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"> <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}"> <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
<div class="container" layout:fragment="content"> <div class="container" layout:fragment="content">

View File

@ -1,21 +1,12 @@
<!--
~ 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"> <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<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}">
<div class="container" layout:fragment="content"> <div class="container" layout:fragment="content">
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-12">
<img class="news-image" src="/img/logo.svg"/>
</div>
<div class="col-md-8">
<h5 th:text="${meeting.title}"/> <h5 th:text="${meeting.title}"/>
<div th:text="${meeting.text}" class="news-item"></div> <div th:utext="${meeting.text}" class="news-item"></div>
</div> </div>
</div> </div>
<a href="javascript:history.back()" class="btn btn-outline-dark" style="text-align: right">Назад</a> <a href="javascript:history.back()" class="btn btn-outline-dark" style="text-align: right">Назад</a>

View File

@ -1,21 +1,12 @@
<!--
~ 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"> <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<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}">
<div class="container" layout:fragment="content"> <div class="container" layout:fragment="content">
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-12">
<img class="news-image" th:src="@{'/files/' + ${news.imageFileName}}"/>
</div>
<div class="col-md-8">
<h5 th:text="${news.title}"/> <h5 th:text="${news.title}"/>
<div th:text="${news.text}" class="news-item"></div> <div th:utext="${news.text}" class="news-item"></div>
</div> </div>
</div> </div>
<div th:text="${'Опубликовано: ' + #calendars.format(news.date, 'dd.MM.yyyy HH:mm')}" <div th:text="${'Опубликовано: ' + #calendars.format(news.date, 'dd.MM.yyyy HH:mm')}"