Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
d7d05132c8 | |||
f0c683cd39 | |||
faa14b698c | |||
2c44377ba2 | |||
1469756a92 | |||
e49ae3c8c2 | |||
1fd1b7f38f | |||
b5aee9c7fc | |||
4862f26258 | |||
0f420be2d9 | |||
feb399162f | |||
305f78777c | |||
32f28c48f9 | |||
|
beb5fd2e15 |
@ -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
|
50
build.gradle
50
build.gradle
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BIN
data/db.mv.db
BIN
data/db.mv.db
Binary file not shown.
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
5
gradle/wrapper/gradle-wrapper.properties
vendored
@ -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
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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";
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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";
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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";
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
}
|
BIN
src/main/resources/public/img/background.jpg
Normal file
BIN
src/main/resources/public/img/background.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 135 KiB |
@ -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">
|
||||||
|
@ -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>
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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')}"
|
||||||
|
@ -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>
|
||||||
|
@ -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')}"
|
||||||
|
@ -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">
|
||||||
|
@ -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>
|
||||||
|
@ -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')}"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user