String today = new SimpleDateFormat("MM.yy").format(new Date());
return podcastRepository.findAllInThisMonth("%" + today + "%").size();
}
@Transactional
@RequestMapping(value = "/addCoauthors")
public @ResponseBody
void addCoauthors(@RequestBody String authorsIdsJSON, @RequestParam(value = "podcastId") long podcastId) {
Gson g = new Gson();
int[] authorsIds = g.fromJson(authorsIdsJSON, int[].class);
coauthorsRepository.deleteAllByPodcastId(podcastId);
for (int i: authorsIds) {
coauthorsRepository.save(new CoauthorsEntity(podcastId, i));
}
}
@RequestMapping(value = "/getCoauthors")
public @ResponseBody
List<CoauthorsEntity> getCoauthors(@RequestParam(value = "podcastId") long podcastId) {
return coauthorsRepository.findAllByPodcastId(podcastId);
}
}
Файл: Discasst\src\main\java\discasst\service\RatingService.java
package discasst.service;
import com.google.gson.Gson;
import discasst.da.PodcastRepository;
import discasst.da.RatingRepository;
import discasst.entity.Podcast;
import discasst.entity.RatingEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;
import javax.transaction.Transactional;
@Service
@RestController
public class RatingService {
@Autowired
private PodcastRepository podcastRepository;
@Autowired
private RatingRepository ratingRepository;
@Transactional
@RequestMapping(value = "/vote", method = RequestMethod.POST)
public @ResponseBody
void vote(@RequestBody String rateStr) {
Gson g = new Gson();
RatingEntity newrate = g.fromJson(rateStr, RatingEntity.class);
RatingEntity oldrate = ratingRepository.findByPodcastIdAndUserId(newrate.getPodcastId(), newrate.getUserId());
Podcast podcast = podcastRepository.findById(newrate.getPodcastId());
//если пользователь уже голосовал
if (oldrate != null) {
//если оценка отличается
if (oldrate.isDecision() != newrate.isDecision()) {
//если оценка положительная
if (newrate.isDecision()) {
podcast.ratingInc();
podcast.ratingInc();
oldrate.setDecision(true);
} else {
podcast.ratingDec();
podcast.ratingDec();
oldrate.setDecision(false);
}
ratingRepository.save(oldrate);
}
} else {
ratingRepository.save(newrate);
if (newrate.isDecision()) {
podcast.ratingInc();
} else {
podcast.ratingDec();
}
}
podcastRepository.save(podcast);
}
@RequestMapping(value = "/getMyVote", method = RequestMethod.GET)
public @ResponseBody
int getMyVote(@RequestParam(value = "userId") long userId, @RequestParam(value = "podcastId") long podcastId) {
RatingEntity oldrate = ratingRepository.findByPodcastIdAndUserId(podcastId, userId);
//если пользователь уже голосовал
if (oldrate != null) {
//если оценка положительная
if (oldrate.isDecision()) {
return 1;
} else {
return -1;
}
} else {
return 0;
}
}
}
Файл: Discasst\src\main\java\discasst\service\RequestService.java
package discasst.service;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Класс для бинда первого входа на сайт (первая загрузка сайта не через реакт роутер)
*/
@Controller
public class RequestService {
@RequestMapping(value = "/signin")
public String signinPage() {
return "MainHTML";
}
@RequestMapping(value = "/register")
public String registerPage() {
return "MainHTML";
}
@RequestMapping(value = "/search")
public String searchPage() {
return "MainHTML";
}
@RequestMapping(value = "/feed")
public String feed() {
return "MainHTML";
}
@RequestMapping(value = "/statistics")
public String statisticsPage() {
return "MainHTML";
}
@RequestMapping(value = "/")
public String mainPage() {
return "MainHTML";
}
@RequestMapping(value = "/user/{username}")
public String userProfilePage() {
return "MainHTML";
}
@RequestMapping(value = "/podcast/{podcastId}")
public String podcastPage() {
return "MainHTML";
}
@RequestMapping(value = "/createNewPodcast")
public String createNewPodcastPage() {
return "MainHTML";
}
@RequestMapping(value = "/createNewEpisode/{podcastId}")
public String createNewEpisodePage() {
return "MainHTML";
}
@RequestMapping(value = "/addCoauthors/{podcastId}")
public String addCoauthorsPage() {
return "MainHTML";
}
}
Файл: Discasst\src\main\java\discasst\service\SearchService.java
package discasst.service;
import com.google.gson.Gson;
import discasst.da.GenreRepository;
import discasst.da.PodcastRepository;
import discasst.entity.Genre;
import discasst.entity.Podcast;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Service
@RestController
public class SearchService {
@Autowired
private PodcastRepository podcastRepository;
@Autowired
private GenreRepository genreRepository;
@RequestMapping(value = "/getPodcastsInPage", method = RequestMethod.POST)
public Page<Podcast> getPodcastsInPage(@RequestBody String json, Pageable pageable) {
Gson g = new Gson();
FilterAndGenres filterAndGenres = g.fromJson(json, FilterAndGenres.class);
if (filterAndGenres.byRating) {
return podcastRepository.findByNameContainsIgnoreCaseAndGenreIdNotInOrderByRatingDesc(filterAndGenres.filter, filterAndGenres.genres, pageable);
} else {
return podcastRepository.findByNameContainsIgnoreCaseAndGenreIdNotInOrderByIdDesc(filterAndGenres.filter, filterAndGenres.genres, pageable);
}
}
@RequestMapping(value = "/getPodcastById", method = RequestMethod.GET)
public Podcast getPodcastById(@RequestParam(value = "id", required = true) long id) {
return podcastRepository.findById(id);
}
@RequestMapping(value = "/getAllGenres", method = RequestMethod.GET)
public List<Genre> getAllGenres() {
return genreRepository.findAll();
}
class FilterAndGenres {
public String filter = "";
public long[] genres;
public boolean byRating;
}
}
Файл: Discasst\src\main\java\discasst\service\SubscribeService.java
package discasst.service;
import discasst.da.PodcastRepository;
import discasst.da.SubscribeRepository;
import discasst.entity.Podcast;
import discasst.entity.SubscribeEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;
import javax.transaction.Transactional;
@Service
@RestController
public class SubscribeService {
@Autowired
private SubscribeRepository subscribeRepository;
@Autowired
private PodcastRepository podcastRepository;
@Transactional
@RequestMapping(value = "/subscribe", method = RequestMethod.GET)
public @ResponseBody
void subscribe(@RequestParam(value = "userId") long userId, @RequestParam(value = "podcastId") long podcastId) {
SubscribeEntity subs = subscribeRepository.findByPodcastIdAndUserId(podcastId, userId);
Podcast podcast = podcastRepository.findById(podcastId);
//если запись с таким пользователем и подкастом существует
if (subs != null) {
subs.setSubscribed(!subs.isSubscribed());
subscribeRepository.save(subs);
if (subs.isSubscribed()) {
podcast.subscribersCountInc();
} else {
podcast.subscribersCountDec();
}
} else {
subscribeRepository.save(new SubscribeEntity(userId, podcastId, true));
podcast.subscribersCountInc();
}
podcastRepository.save(podcast);
}
@RequestMapping(value = "/getMySubscribe", method = RequestMethod.GET)
public @ResponseBody
boolean getMyVote(@RequestParam(value = "userId") long userId, @RequestParam(value = "podcastId") long podcastId) {
SubscribeEntity subs = subscribeRepository.findByPodcastIdAndUserId(podcastId, userId);
//если запись с таким пользователем и подкастом существует
if (subs != null) {
return subs.isSubscribed();
} else {
return false;
}
}
}
Файл: Discasst\src\main\java\discasst\service\TweetService.java
package discasst.service;
import com.google.gson.Gson;
import discasst.da.SubscribeRepository;
import discasst.da.TweetRepository;
import discasst.entity.Tweet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;
@Service
@RestController
public class TweetService {
@Autowired
private TweetRepository tweetRepository;
@Autowired
private SubscribeRepository subscribeRepository;
@RequestMapping(value = "/addTweet", method = RequestMethod.POST, headers = {"Content-type=application/json"})
public void create(@RequestBody String tweetJson) {
Gson g = new Gson();
Tweet newTwit = g.fromJson(tweetJson, Tweet.class);
newTwit.setCreationDate();
newTwit.setCreationDate();
this.tweetRepository.save(newTwit);
System.out.println("new tweet added:" + newTwit.getText());
}
@RequestMapping(value = "/deleteTweet", method = RequestMethod.POST)
public void deleteById(@RequestParam(value = "tweetId") Long tweetId) {
this.tweetRepository.deleteById(tweetId);
}
public Tweet getById(int id) {
return null;
}
@RequestMapping(value = "/getAllTwitsByPodcastId")
public Page<Tweet> getAllTwitsByUserId(@RequestParam(value = "id") Long id, Pageable pageable) {
return tweetRepository.findAllByPodcastIdOrderByIdDesc(id, pageable);
}
@RequestMapping(value = "/getAllTwitsByUserIdFeed")
public Page<Tweet> getAllTwitsByUserIdFeed(@RequestParam(value = "id") Long id, Pageable pageable) {
long[] subs = subscribeRepository.findAllByUserId(id);
return tweetRepository.findAllByPodcastIdInOrderByIdDesc(subs, pageable);
}
}
Файл: Discasst\src\main\java\discasst\service\UserService.java
package discasst.service;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import discasst.da.UserRepository;
import discasst.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@Service
@RestController
public class UserService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = userRepository.findByUsername(s);
if (user != null) return user;
else throw new UsernameNotFoundException("User " + s + " not found!");
}
@RequestMapping(value = "/getUserInfo", method = RequestMethod.GET)
public User getUserInfo(@RequestParam(value = "username", required = true) String username) {
User user = userRepository.findByUsername(username);
if (user != null) return user;
else throw new UsernameNotFoundException("User " + username + " not found!");
}
@RequestMapping(value = "/addUser", method = RequestMethod.POST)
public void addUser(@RequestParam(value = "username", required = true) String username,
@RequestParam(value = "name", required = true) String name,
@RequestParam(value = "email", required = true) String email,
@RequestParam(value = "password", required = true) String password,
HttpServletRequest request, HttpServletResponse response) {
User newUser = new User(username, email, new BCryptPasswordEncoder().encode(password), name);
try {
newUser.setCreationDate(new Date());
userRepository.save(newUser);
System.out.println("new user added: " + username);
response.setHeader("newUserStatus", "ok");
} catch (Exception e) {
System.out.println("error on adding new user: " + e.getMessage());
if (e.getCause().getCause().getMessage().contains("Нарушение уникального индекса или первичного ключа"))
response.setHeader("newUserStatus", "usernameError");
else response.setHeader("newUserStatus", "unknownError");
}
}
@RequestMapping(value = "/updateProfile", method = RequestMethod.POST)
public void updateProfile(@RequestParam(value = "name", required = true) String name,
@RequestParam(value = "username", required = true) String username,
HttpServletRequest request, HttpServletResponse response) {
try {
User updatedUser = userRepository.findByUsername(username);
updatedUser.setName(name);
userRepository.save(updatedUser);
System.out.println("profile updated: " + name);
response.setHeader("updateProfileStatus", "ok");
} catch (Exception e) {
System.out.println("profile update error: " + e.getMessage());
response.setHeader("updateProfileStatus", "error");
}
}
@RequestMapping(value = "/getUsersCountToday")
public @ResponseBody
int getUsersCountToday() throws ParseException {
String today = new SimpleDateFormat("dd.MM.yy").format(new Date());
return userRepository.findAllByCreationDate(today).size();
}
@RequestMapping(value = "/getUsersCountThisMounth")
public @ResponseBody
int getUsersCountThisMounth() throws ParseException {
String today = new SimpleDateFormat("MM.yy").format(new Date());
return userRepository.findAllInThisMonth("%" + today + "%").size();
}
@RequestMapping(value = "/getCoauthorsByIdList", method = RequestMethod.POST)
public @ResponseBody
List<User> getCoauthorsByIdList(@RequestBody String coauthorsIdsJSON) {
Gson g = new Gson();
JsonElement json = new JsonPrimitive(coauthorsIdsJSON);
long[] coauthorsIds = g.fromJson(coauthorsIdsJSON, Ids.class).ids;
return userRepository.findAllByIdIn(coauthorsIds);
}
@RequestMapping(value = "/loginCheck", method = RequestMethod.POST)
public @ResponseBody
int loginCheck() {
return 200;
}
public class Ids {
long[] ids;
}
}
Исходный код клиентской части проекта:
Файл: Discasst\src\main\resources\templates\MainHTML.html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8"/>
<title>Discasst</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="/css/discasst.css">
</head>
<body style="background-color: #e6ecf0">
<div id="root"></div>
<script src="/generated/bundle.js" type="text/javascript"></script>
</body>
</html>
Файл: Discasst\src\main\resources\static\css\discasst.css
body {
height: 100%;
}
.hr10 {
height: 10px;
visibility: hidden
}
.hr100 {
height: 100px;
visibility: hidden
}
.hr15 {
height: 15px;
visibility: hidden
}
.hr30 {
height: 30px;
visibility: hidden
}
.hr60 {
height: 60px;
visibility: hidden
}
.btn:focus,.btn:active:focus,.btn.active:focus,
.btn.focus,.btn:active.focus,.btn.active.focus {
outline: none;
box-shadow: none;
}
.icon-button {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
outline: none;
border: 0;
background: transparent;
}
/* navbar */
.navbar-nav.navbar-center {
position: absolute;
left: 50%;
transform: translatex(-50%);
}
a:hover {
cursor: pointer;
}
/* searchPanel */
.search-list.btn:focus {
outline: 0
}
.search-list.list-group-item:focus {
outline: 0
}
/* signin */
.form-control-signin-css {
position: relative;
box-sizing: border-box;
height: auto;
padding: 10px;
font-size: 16px;
}
#signinUser {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
#signinPass {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
Файл: Discasst\src\main\resources\static\package.json
{
"name": "discasst",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack -d --watch"
},
"author": "",
"license": "ISC",
"dependencies": {
"bootstrap": "^4.1.1",
"css-loader": "^1.0.1",
"jquery": "^3.3.1",
"react": "^16.4.1",
"react-bootstrap": "^0.32.4",
"react-dom": "^16.4.1",
"react-router-dom": "^4.3.1",
"reactstrap": "^6.3.1",
"requirejs": "^2.3.5",
"rest": "^2.0.0",
"rest-js": "^1.1.3",
"style-loader": "^0.23.1",
"react-disqus-comments": "^1.4.0"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-plugin-transform-regenerator": "^6.26.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"webpack": "^4.16.3",
"webpack-cli": "^3.1.0"
}
}
Файл: Discasst\src\main\resources\static\app\app.js
import SigninPage from "./components/login/SigninPage";
import RegisterPage from "./components/login/RegisterPage"
import SearchPage from "./components/searchPage/SearchPage"
import UserProfilePage from "./components/userPage/UserProfilePage"
import PodcastPage from "./components/podcastPage/PodcastPage";
import CreateNewPodcastPage from "./components/userPage/CreateNewPodcastPage";
import CreateNewEpisodePage from "./components/userPage/CreateNewEpisodePage";
import StatisticsPage from "./components/statistics/StatisticsPage";
import AddCoauthorsPage from "./components/userPage/AddCoauthorsPage";
import FeedPage from "./components/feedPage/FeedPage";
import {BrowserRouter, Route, Switch} from 'react-router-dom';
const React = require('react');
const ReactDOM = require('react-dom');
export default class App extends React.Component {
render() {
return (
<BrowserRouter>
<Switch>
<Route exact path='/' component={SearchPage}/>
<Route path='/signin' component={SigninPage}/>
<Route path='/register' component={RegisterPage}/>
<Route path='/search' component={SearchPage}/>
<Route path='/feed' component={FeedPage}/>
<Route path='/statistics' component={StatisticsPage}/>
<Route path='/createNewPodcast' component={CreateNewPodcastPage}/>
<Route path='/podcast/:podcastId' component={PodcastPage}/>
<Route path='/createNewEpisode/:podcastId' component={CreateNewEpisodePage}/>
<Route path='/user/:username' component={UserProfilePage}/>
<Route path='/addCoauthors/:podcastId' component={AddCoauthorsPage}/>
</Switch>
</BrowserRouter>
)