Социальная подкаст-платформа

Рассмотрение сервисов, позволяющих прослушивать подкасты. Разработка платформы, сочетающей в себе функции для удобного поиска подкастов и возможность их обсуждения с ведущими и другими слушателями. Оценка удобства работы с пользовательским интерфейсом.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 14.12.2019
Размер файла 2,7 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

package discasst.da;

import discasst.entity.Tweet;

import org.springframework.data.domain.Page;

import org.springframework.data.domain.Pageable;

import org.springframework.data.repository.PagingAndSortingRepository;

public interface TweetRepository extends PagingAndSortingRepository<Tweet, Long> {

Page<Tweet> findAllByPodcastIdOrderByIdDesc(long id, Pageable pageable);

Page<Tweet> findAllByPodcastIdInOrderByIdDesc(long[] podcastIds, Pageable pageable);

void deleteAllByPodcastId(long id);

}

Файл: Discasst\src\main\java\discasst\da\UserRepository.java

package discasst.da;

import discasst.entity.User;

import org.springframework.data.jpa.repository.Query;

import org.springframework.data.repository.CrudRepository;

import org.springframework.data.repository.query.Param;

import java.util.List;

public interface UserRepository extends CrudRepository<User, Long> {

User findByUsername(String username);

List<User> findAllByIdIn(long[] list);

List<User> findAllByCreationDate(String date);

@Query("select a from User a where a.creationDate like:monthAndYear")

List<User> findAllInThisMonth(@Param("monthAndYear") String monthAndYear);

}

Файл: Discasst\src\main\java\discasst\entity\CoauthorsEntity.java

package discasst.entity;

import lombok.Data;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

@Entity

@Data

public class CoauthorsEntity {

@Id

@GeneratedValue

private long id;

private long podcastId;

private long userId;

public CoauthorsEntity(long podcastId, long userId) {

this.podcastId = podcastId;

this.userId = userId;

}

}

Файл: Discasst\src\main\java\discasst\entity\Episode.java

package discasst.entity;

import lombok.Data;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import java.text.SimpleDateFormat;

import java.util.Date;

@Entity

@Data

public class Episode {

@Id

@GeneratedValue

private long id;

private long podcastId;

private String name;

@Column(columnDefinition = "TEXT")

private String description;

private String podsterLink;

private String date;

public long getPodcastId() {

return podcastId;

}

public Episode(long podcastId, String name,

String description, String podsterLink, Date date) {

this.podcastId = podcastId;

this.name = name;

this.description = description;

this.podsterLink = podsterLink;

this.date = new SimpleDateFormat("dd.MM.yy").format(date);

}

public void setDate(Date date) {

this.date = new SimpleDateFormat("dd.MM.yy").format(date);

}

}

Файл: Discasst\src\main\java\discasst\entity\Genre.java

package discasst.entity;

import lombok.Data;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

@Entity

@Data

public class Genre {

@Id

@GeneratedValue

private long id;

@Column(unique = true)

private String name;

public Genre(String name) {

this.name = name;

}

}

Файл: Discasst\src\main\java\discasst\entity\Podcast.java

package discasst.entity;

import lombok.Data;

import javax.persistence.*;

import java.text.SimpleDateFormat;

import java.util.Date;

@Entity

@Data

@Table(name = "podcast")

public class Podcast {

@Id

@GeneratedValue

private long id;

@Column(unique = true)

private String name;

private long authorId;

@Column(columnDefinition="TEXT")

private String description;

private String itunesLink = "";

private String vkLink = "";

private String twitterLink = "";

private String facebookLink = "";

private Integer episodeCount = 0;

private Integer subscribersCount = 0;

private long genreId;

private Integer rating = 0;

private String creationDate;

public Podcast(String name, String description, Integer rating, Integer genreId, int episodeCount) {

this.name = name;

this.description = description;

this.rating = rating;

this.genreId = genreId;

this.episodeCount = episodeCount;

}

public Podcast(String name, String description, String itunesLink, String vkLink, String twitterLink,

String facebookLink, Integer episodeCount, long genreId, Integer rating, Integer subscribersCount, long authorId) {

this.name = name;

this.description = description;

this.itunesLink = itunesLink;

this.vkLink = vkLink;

this.twitterLink = twitterLink;

this.facebookLink = facebookLink;

this.episodeCount = episodeCount;

this.genreId = genreId;

this.rating = rating;

this.subscribersCount = subscribersCount;

this.authorId = authorId;

}

public Integer getEpisodeCount() {

return episodeCount;

}

public void setEpisodeCount(Integer episodeCount) {

this.episodeCount = episodeCount;

}

public void setCreationDate(Date date) {

this.creationDate = new SimpleDateFormat("dd.MM.yy").format(date);

}

public long getAuthorId() {

return authorId;

}

public void ratingInc() {

this.rating++;

}

public void ratingDec() {

this.rating--;

}

public void subscribersCountDec() {

this.subscribersCount--;

}

public void subscribersCountInc() {

this.subscribersCount++;

}

}

Файл: Discasst\src\main\java\discasst\entity\RatingEntity.java

package discasst.entity;

import lombok.Data;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

@Entity

@Data

public class RatingEntity {

@Id

@GeneratedValue

private long id;

private long userId;

private long podcastId;

private boolean decision;

public RatingEntity(long userId, long podcastId, boolean decision) {

this.userId = userId;

this.podcastId = podcastId;

this.decision = decision;

}

public long getUserId() {

return userId;

}

public long getPodcastId() {

return podcastId;

}

public void setDecision(boolean decision) {

this.decision = decision;

}

public boolean isDecision() {

return decision;

}

}

Файл: Discasst\src\main\java\discasst\entity\Role.java

package discasst.entity;

import org.springframework.security.core.GrantedAuthority;

public enum Role implements GrantedAuthority {

ROLE_USER, ROLE_ADMIN;

@Override

public String getAuthority() {

return name();

}

}

Файл: Discasst\src\main\java\discasst\entity\SubscribeEntity.java

package discasst.entity;

import lombok.Data;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

@Entity

@Data

public class SubscribeEntity {

@Id

@GeneratedValue

private long id;

private long userId;

private long podcastId;

private boolean isSubscribed;

public SubscribeEntity(long userId, long podcastId, boolean sub) {

this.userId = userId;

this.podcastId = podcastId;

this.isSubscribed = sub;

}

public boolean isSubscribed() {

return isSubscribed;

}

public void setSubscribed(boolean subscribed) {

isSubscribed = subscribed;

}

}

Файл: Discasst\src\main\java\discasst\entity\Tweet.java

package discasst.entity;

import lombok.Data;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Random;

@Data

@Entity

public class Tweet {

@Id

@GeneratedValue

private long id;

private long podcastId;

private long authorId;

private String authorUsername;

private String text;

private String creationDate;

public Tweet(String text) {

Random r = new Random();

int v = r.nextInt(3);

this.podcastId = 21;

this.authorId = v == 0 ? 17: v == 1 ? 18: 19;

this.text = text;

this.creationDate = new SimpleDateFormat("dd.MM.yy HH:mm").format(new Date());

this.authorUsername = v == 0 ? "vedensky": v == 1 ? "istishev": "ilyaliya";

}

public long getAuthorId() {

return authorId;

}

public String getAuthorNickName() {

return authorUsername;

}

public String getText() {

return text;

}

public void setText(String text) {

this.text = text;

}

public void setCreationDate() {

this.creationDate = new SimpleDateFormat("dd.MM.yy HH:mm").format(new Date());

}

}

Файл: Discasst\src\main\java\discasst\entity\User.java

package discasst.entity;

import lombok.Data;

import org.springframework.security.core.GrantedAuthority;

import org.springframework.security.core.userdetails.UserDetails;

import javax.persistence.*;

import java.text.SimpleDateFormat;

import java.util.ArrayList;

import java.util.Collection;

import java.util.Date;

import java.util.List;

@Entity

@Data

public class User implements UserDetails {

@Id

@GeneratedValue

private long id;

@Transient

private List<Role> authorities = new ArrayList<Role>(){{add(Role.ROLE_USER);}};

private boolean accountNonExpired = true;

private boolean accountNonLocked = true;

private boolean credentialsNonExpired = true;

private boolean enabled = true;

@Column(unique = true)

private String username;

private String password;

private String email;

private String name;

private String creationDate;

public User(String username, String email, String password, String name) {

this.username = username;

this.email = email;

this.password = password;

this.name = name;

}

public void setName(String name) {

this.name = name;

}

@Override

public Collection<? extends GrantedAuthority> getAuthorities() {

return authorities;

}

@Override

public String getPassword() {

return password;

}

@Override

public String getUsername() {

return username;

}

@Override

public boolean isAccountNonExpired() {

return true;

}

@Override

public boolean isAccountNonLocked() {

return true;

}

@Override

public boolean isCredentialsNonExpired() {

return true;

}

@Override

public boolean isEnabled() {

return true;

}

public void setCreationDate(Date date) {

this.creationDate = new SimpleDateFormat("dd.MM.yy").format(date);

}

}

Файл: Discasst\src\main\java\discasst\loaders\DatabaseLoader.java

package discasst.loaders;

import discasst.da.*;

import discasst.entity.*;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.CommandLineRunner;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import org.springframework.stereotype.Component;

import java.util.Arrays;

import java.util.Date;

import java.util.List;

@Component

public class DatabaseLoader implements CommandLineRunner {

@Autowired

private UserRepository userRepository;

@Autowired

private PodcastRepository podcastRepository;

@Autowired

private GenreRepository genreRepository;

@Autowired

private EpisodeRepository episodeRepository;

@Autowired

private TweetRepository tweetRepository;

@Autowired

private CoauthorsRepository coauthorsRepository;

@Override

public void run(String... strings) {

List<String> genres = Arrays.asList("Обо всем", "Авто", "Аудиокниги", "Бизнес и карьера", "Интернет и технологии"

, "Кино и музыка", "Красота и здоровье", "Культура и искусство", "Наука и образование", "Политика"

, "Отношения", "Путешествия", "Спорт", "Видеоигры");

for (String name: genres) {

this.genreRepository.save(new Genre(name));

}

this.userRepository.save(new User("finch", "sal0212@mail.ru", new BCryptPasswordEncoder().encode("finch"), "FINCH"));

this.userRepository.save(new User("q", "qqq@mail.ru", new BCryptPasswordEncoder().encode("q"), "bigQ"));

this.userRepository.save(new User("vedensky", "vedensky@gmail.com", new BCryptPasswordEncoder().encode("vedensky"), "Борис Веденский"));

this.userRepository.save(new User("istishev", "istishev@mail.ru", new BCryptPasswordEncoder().encode("istishev"), "Валерий Истишев"));

this.userRepository.save(new User("ilyaliya", "ilyaliya@gmail.com", new BCryptPasswordEncoder().encode("ilyaliya"), "Илья Рябов"));

String podDesc = "Завтракаст один из самых популярных подкастов про игры, медиа, кино, сериалы и технологии в России. Его ведущими являются три очень разных человека маркетолог Тимур, технический директор Дима и видеопродюсер Максим. Их объединяет любовь к играм, книгам, сериалам, кино, новым технологиям, трендам в интернете и интересным событиям вокруг нас.";

this.podcastRepository.save(new Podcast("Завтракаст", podDesc, 404, 13, 0));

podDesc = "Раз в неделю Борис Веденский, Валерий Истишев и Илья Рябов соберутся, чтобы сжечь несколько ведьм, разоблачить пару заговоров, обсудить последние новости интернета, технологий, кино и видеоигр в неформальной обстановке.";

this.podcastRepository.save(new Podcast("Droider Cast", podDesc, "https://itunes.apple.com/ru/podcast/droider-cast/id1057019371?mt=2", "https://vk.com/droider_ru", "https://twitter.com/vedensky", "https://www.facebook.com/Droider", 12, 4, 509, 217, 17));

this.podcastRepository.save(new Podcast("Newочём", "Мы переводим и озвучиваем всё самое интересное, что появляется в зарубежном Интернете.", 342, 0, 0));

podDesc = "Рассказываем обо всём, что можно «взломать»: о здоровье, работе и технологиях, об образовании, спорте и отдыхе, об отношениях, финансах и мотивации. Помогаем решить проблемы или упростить ситуации, с которыми вы сталкиваетесь каждый день. Отвечаем на вопросы и призываем посмотреть на привычные вещи другими глазами.";

this.podcastRepository.save(new Podcast("Подкаст «Лайфхакера»", podDesc, 15, 0, 0));

podDesc = "Наше психологическое радио о простых и сложных переживаниях, о психологии эмоций, личной эффективности и личностном развитии, о саногенном мышлении, мы рассказываем на простых примерах, как пережить те или иные эмоции, как то: страх, гнев, стыд, обида или вина, либо вообще их угасить. Наши подкастырассказывают как контролируемое спокойствие влияет на результаты в бизнесе, спорте, развитии личности и личной жизни. Приятного прослушивания! ";

this.podcastRepository.save(new Podcast("Психология: мифы и реальность.", podDesc, 221, 8, 0));

podDesc = "Программа о том, как выучить английский язык быстро и без лишних усилий. Вы узнаете, как пополнить словарный запас, разобраться в правилах грамматики, поставить произношение. А самое главное -- освоить логику английского языка и научиться думать на нём.";

this.podcastRepository.save(new Podcast("Учим английский с Don't Speak", podDesc, 159, 8, 0));

podDesc = "Что может быть лучше душевной беседы? Только душевная беседа двух рыжих чуваков. Каждое воскресенье Константин Тростенюк и Денис Карамышев экспертно анализируют всё, что достойно экспертного анализа.";

this.podcastRepository.save(new Podcast("Душевный подкаст", podDesc, 407, 13, 0));

this.podcastRepository.save(new Podcast("Вечерние чтения", "Озвучиваю самое интересное из прочитанного за день.", 93, 2, 0));

podDesc = "Радио ENERGY, частота в Москве 104.2 FM, получила официальное разрешение на использование всемирно известного товарного знака NRJ / Energy, которым владеет французская медиагруппа «Эн Эр Жи» («NRJ Group»). Это стало возможным в результате переговоров, проходивших в 2006 году между представителями Группы и «ВКПМ». NRJ создает специальные проекты, самым известным из которых является ежегодная музыкальная премия NRJ Music Awards. Радиостанции с торговой маркой NRJ / Energy работают в Австрии, Бельгии, Болгарии, Германии, Дании, Норвегии, Финляндии, Швейцарии, Швеции, а также в Ливане и на Украине.\n\nСетевое издание ENERGYFM.RU, свидетельство о регистрации СМИ Эл № ФС77-50193 от 15.06.2012, выдано Федеральной службой по надзору в сфере связи, информационных технологий и массовых коммуникаций (Роскомнадзор).";

this.podcastRepository.save(new Podcast("NRJ RUSSIA", podDesc, 213, 5, 0));

this.podcastRepository.save(new Podcast("Предназначение. Дело Жизни", "Обсуждаются такие вопросы:\nПредназначение\nМотивация\nЭмоциональное выгорание\nЛень и прокрастинация\nCамоопределение\nКак найти себяПрофориентация\nПризвание\nКем быть в жизни\nДело Жизни\nПродуктивность\n\nВ эфире:\nИстории раскрытия и монетизации дела жизни. Короткие практики и медитации для самостоятельной работы. Методики и модели раскрытия предназначения. Записи выступлений и вебинаров Павла Кочкина. Ответы на вопросы подписчиков.", 277, 8, 0));

this.podcastRepository.save(new Podcast("Игровой Батискаф", "Лучшее со дна игровой индустрии в исполнении знатных водолазов.", 407, 13, 0));

this.episodeRepository.save(new Episode(21, "Droider Cast 1", "1 выпуск подкаста \"Droider Cast\"", "https://droidercast.podster.fm/50", new Date(2018, 9, 22)));

this.episodeRepository.save(new Episode(21, "Droider Cast 2", "2 выпуск подкаста \"Droider Cast\"", "https://droidercast.podster.fm/51", new Date(2018, 10, 12)));

this.episodeRepository.save(new Episode(21, "Droider Cast 3", "3 выпуск подкаста \"Droider Cast\"", "https://droidercast.podster.fm/52", new Date(2018, 10, 22)));

this.episodeRepository.save(new Episode(21, "Droider Cast 4", "4 выпуск подкаста \"Droider Cast\"", "https://droidercast.podster.fm/53", new Date(2018, 10, 27)));

this.episodeRepository.save(new Episode(21, "Droider Cast 5", "5 выпуск подкаста \"Droider Cast\"", "https://droidercast.podster.fm/53", new Date(2018, 11, 2)));

this.episodeRepository.save(new Episode(21, "Droider Cast 6", "6 выпуск подкаста \"Droider Cast\"", "https://droidercast.podster.fm/53", new Date(2018, 11, 12)));

this.episodeRepository.save(new Episode(21, "Droider Cast 7", "7 выпуск подкаста \"Droider Cast\"", "https://droidercast.podster.fm/53", new Date(2018, 11, 21)));

this.episodeRepository.save(new Episode(21, "Droider Cast 8", "8 выпуск подкаста \"Droider Cast\"", "https://droidercast.podster.fm/53", new Date(2018, 12, 2)));

this.episodeRepository.save(new Episode(21, "Droider Cast 9", "9 выпуск подкаста \"Droider Cast\"", "https://droidercast.podster.fm/53", new Date(2018, 12, 9)));

this.episodeRepository.save(new Episode(21, "Droider Cast 10", "10 выпуск подкаста \"Droider Cast\"", "https://droidercast.podster.fm/53", new Date(2018, 12, 16)));

this.episodeRepository.save(new Episode(21, "Droider Cast 11", "11 выпуск подкаста \"Droider Cast\"", "https://droidercast.podster.fm/53", new Date(2018, 12, 24)));

this.episodeRepository.save(new Episode(21, "Droider Cast 12", "12 выпуск подкаста \"Droider Cast\"", "https://droidercast.podster.fm/53", new Date(2019, 1, 5)));

for (int i = 1; i <= 25; i++) {

this.tweetRepository.save(new Tweet("Droider Cast Твит " + i + "!"));

}

this.coauthorsRepository.save(new CoauthorsEntity(21, 18));

this.coauthorsRepository.save(new CoauthorsEntity(21, 19));

}

}

Файл: Discasst\src\main\java\discasst\service\PodcastService.java

package discasst.service;

import com.google.gson.Gson;

import discasst.da.*;

import discasst.entity.CoauthorsEntity;

import discasst.entity.Episode;

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.security.core.userdetails.UsernameNotFoundException;

import org.springframework.stereotype.Service;

import org.springframework.web.bind.annotation.*;

import javax.transaction.Transactional;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.List;

@Service

@RestController

public class PodcastService {

@Autowired

private GenreRepository genreRepository;

@Autowired

private PodcastRepository podcastRepository;

@Autowired

private EpisodeRepository episodeRepository;

@Autowired

private CoauthorsRepository coauthorsRepository;

@Autowired

private SubscribeRepository subscribeRepository;

@Autowired

private TweetRepository tweetRepository;

@Autowired

private RatingRepository ratingRepository;

@RequestMapping(value = "/getGenres", method = RequestMethod.GET)

public List<Genre> getGenres() {

List<Genre> genres = genreRepository.findAll();

if (genres != null) return genres;

else throw new UsernameNotFoundException("Genres not found!");

}

@RequestMapping(value = "/createPodcast")

public @ResponseBody

void createPodcast(@RequestBody String podcast) {

Gson g = new Gson();

Podcast pod = g.fromJson(podcast, Podcast.class);

pod.setCreationDate(new Date());

podcastRepository.save(pod);

}

@Transactional

@RequestMapping(value = "/removePodcast", method = RequestMethod.POST)

public @ResponseBody

void removePodcast(@RequestParam(value = "id") long id) {

episodeRepository.deleteAllByPodcastId(id);

coauthorsRepository.deleteAllByPodcastId(id);

tweetRepository.deleteAllByPodcastId(id);

subscribeRepository.deleteAllByPodcastId(id);

ratingRepository.deleteAllByPodcastId(id);

podcastRepository.deleteById(id);

}

@RequestMapping(value = "/getPodcastsByUserId")

public @ResponseBody

List<Podcast> getPodcastsByUserId(@RequestParam(value = "id") long id) {

return podcastRepository.findAllByAuthorId(id);

}

@RequestMapping(value = "/getPodcastsByUserIdInCoauthors")

public @ResponseBody

List<Podcast> getPodcastsByUserIdInCoauthors(@RequestParam(value = "id") long id) {

long[] ids = coauthorsRepository.findAllByUserId(id);

return podcastRepository.findAllByIdIn(ids);

}

@RequestMapping(value = "/createEpisode")

public @ResponseBody

void createEpisode(@RequestBody String episode) {

Gson g = new Gson();

Episode newEpisode = g.fromJson(episode, Episode.class);

newEpisode.setDate(new Date());

episodeRepository.save(newEpisode);

Podcast pod = podcastRepository.findById(newEpisode.getPodcastId());

pod.setEpisodeCount(pod.getEpisodeCount() + 1);

podcastRepository.save(pod);

}

@RequestMapping(value = "/getEpisodesByPodcastIdInPage")

public @ResponseBody

Page<Episode> getAllEpisodesByPodcastIdInPage(

@RequestParam(value = "id") long id, Pageable pageable) {

return episodeRepository.findAllByPodcastIdOrderByIdDesc(id, pageable);

}

@Transactional

@RequestMapping(value = "/getEpisodesInFeedByUserIdInPage")

public @ResponseBody

Page<Episode> getEpisodesInFeedByUserIdInPage(@RequestParam(value = "id") long id, Pageable pageable) {

long[] subs = subscribeRepository.findAllByUserId(id);

return episodeRepository.findAllByPodcastIdInOrderByIdDesc(subs, pageable);

}

@RequestMapping(value = "/getEpisodesCountToday")

public @ResponseBody

int getEpisodesCountToday() throws ParseException {

String today = new SimpleDateFormat("dd.MM.yy").format(new Date());

return episodeRepository.findAllByDate(today).size();

}

@RequestMapping(value = "/getEpisodesCountThisMounth")

public @ResponseBody

int getEpisodesCountThisMounth() throws ParseException {

String today = new SimpleDateFormat("MM.yy").format(new Date());

return episodeRepository.findAllInThisMonth("%" + today + "%").size();

}

@RequestMapping(value = "/getPodcastsCountToday")

public @ResponseBody

int getPodcastsCountToday() throws ParseException {

String today = new SimpleDateFormat("dd.MM.yy").format(new Date());

return podcastRepository.findAllByCreationDate(today).size();

}

@RequestMapping(value = "/getPodcastsCountThisMounth")

public @ResponseBody

int getPodcastsCountThisMounth() throws ParseException {

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>

)

}

}

const el = document.getElementById('root');

ReactDOM.render(<App/>, el);

Файл: Discasst\src\main\resources\static\app\components\Helper.js

export function getCookie(name) {

var matches = document.cookie.match(new RegExp(

"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"

));

return matches ? decodeURIComponent(matches[1]): undefined;

}

export function getFullCSRFParam() {

const token = getCookie('XSRF-TOKEN');

return `_csrf=${token}`;

}

export function saveCookie(cookieName, value) {

document.cookie = `${cookieName}=${value}; path=/`;

}

export function deleteCookie(cookieName) {

document.cookie = `${cookieName}=${""}; path=/; expires=-1`;

}

export function saveAllCookie(username, id, email, creationDate, name, bio) {

saveCookie("username", username);

saveCookie("userId", id);

saveCookie("userEmail", email);

saveCookie("userCreationDate", creationDate);

saveCookie("name", name);

saveCookie("bio", bio);

}

export function deleteAllCookie() {

deleteCookie("username");

deleteCookie("userId");

deleteCookie("userEmail");

deleteCookie("userCreationDate");

deleteCookie("name");

deleteCookie("bio");

deleteCookie("XSRF-TOKEN");

}

export function isUserSignedIn() {

let username = getCookie("username");

return (username !== "" && username !== undefined);

}

export const getGenres = () =>

fetch("/getAllGenres").then(response => response.json());

Файл: Discasst\src\main\resources\static\app\components\Navbar.js

const React = require('react');

import {deleteAllCookie, getCookie, getFullCSRFParam} from "./Helper";

export default class Navbar extends React.Component {

constructor(props) {

super(props);

this.state = {

isSignedIn: false

};

}

componentDidMount() {

this.isUserLogIn();

}

loginout = () => {

if (this.state.isSignedIn) {

deleteAllCookie();

this.props.history.push(`/signin?logout`);

}

else {

this.props.history.push(`/signin`);

}

};

toStats = () => {

this.props.history.push(`/statistics`);

};

toMyProfile = () => {

this.props.history.push(`/user/${getCookie("username")}`);

};

toFeed = () => {

this.props.history.push(`/feed`);

};

toNotifications = () => {

this.props.history.push(`/notifications`);

};

toHome = () => {

this.props.history.push(`/`);

};

toSignIn = () => {

this.props.history.push(`/signin`);

};

isUserLogIn() {

let username = getCookie("username");

if (username === "" || username === undefined) return false;

fetch(`/loginCheck?${getFullCSRFParam()}`, {

method: 'POST'

}).then((response) => {

if (response.status === 200 && !response.redirected) this.setState({isSignedIn: true});

});

}

onFilterSubmit = () => {

const filter = document.getElementById("topSearch").value;

this.props.history.push({

pathname: '/search',

state: {filterValue: filter}

})

};

render() {

return (

<div>

<nav className="navbar navbar-default" style={{backgroundColor: '#ffffff'}} role="navigation">

<div className="container-fluid centered">

<div className="navbar-header">

<a onClick={() => {

this.toHome()

}} className="navbar-brand" style={{height: '64px', display: 'flex', alignItems: 'center'}}>

<img src="/images/discasst.png" height='36'></img>

</a>

</div>

<div>

<ul className="nav navbar-nav"

style={{height: '64px', display: 'flex', alignItems: 'center'}}>

<li><a onClick={() => {

!this.state.isSignedIn ? this.toSignIn(): this.toFeed()

}}>

<span className="glyphicon glyphicon-align-justify"></span> Feed</a>

</li>

<li><a onClick={() => {

!this.state.isSignedIn ? this.toSignIn(): this.toMyProfile()

}}>

<span className="glyphicon glyphicon-user"></span> My Profile</a>

</li>

<li><a onClick={() => {

this.toStats()

}}>

<span className="glyphicon glyphicon-stats"></span></a>

</li>

</ul>

{!this.props.isSearchOff && <ul className="nav navbar-nav navbar-center">

<li>

<a>

<form onSubmit={this.onFilterSubmit}>

<div className="input-group" style={{width: '300px'}}>

<input id="topSearch" type="text" className="form-control"/>

<span className="input-group-btn">

<button className="btn btn-info" type="button"

onClick={this.onFilterSubmit}

>

<span className="glyphicon glyphicon-search"></span>

</button>

</span>

</div>

</form>

</a>

</li>

</ul>}

<ul className="nav navbar-nav navbar-right">

<li>

<a><button className="btn btn-info" type="button" onClick={this.loginout}>

<span

className="glyphicon glyphicon-log-out"></span> {this.state.isSignedIn ? "Sign Out": "Sign In"}

</button></a>

</li>

</ul>

</div>

</div>

</nav>

</div>

)

}

}

Файл: Discasst\src\main\resources\static\app\components\feedPage\FeedPage.js

import Navbar from '../Navbar';

import PodcastPageContent from "../podcastPage/PodcastPageContent";

const React = require('react');

export default class FeedPage extends React.Component {

constructor(props) {

super(props);

this.state = {};

}

render() {

return (

<div>

<Navbar history={this.props.history}/>

<div className="container-fluid">

<div style={{display: "flex",}}>

<div style={{width: "25%"}}>

</div>

<div style={{width: "50%", textAlign: "center"}}>

<PodcastPageContent

history={this.props.history}

feed={true}

/>

</div>

<div style={{width: "25%"}}>

</div>

</div>

</div>

</div>

)

}

}

Файл: Discasst\src\main\resources\static\app\components\login\RegisterPage.js

const React = require('react');

import {getFullCSRFParam} from "../Helper";

var errorEnum = {

NONE: "",

UNKNOWN: "Unknown error. Try again.",

USERNAME_TAKEN: "This login is already taken.",

LONG_USERNAME: "Login is too long (max length: 16).",

LONG_NAME: "Name is too long (max length: 16).",

WRONG_NAME: "Wrong name (allowed characters: a-Z, а-Я, 0-9, ' ').",

WRONG_USERNAME: "Wrong login (allowed characters: a-Z, 0-9, _).",

WRONG_EMAIL: "Wrong email (exemple: abc-42@xyz.com).",

WRONG_PASS: "Wrong password (allowed characters: a-Z, а-Я, 0-9).",

WRONG_PASS_LENGTH: "Password length must be 4-20 characters.",

WRONG_PASS_REPEAT: "Passwords don't match.",

};

export default class RegisterPage extends React.Component {

constructor(props) {

super(props);

this.state = {

password: '',

username: '',

name: '',

email: '',

success: false,

error: errorEnum.NONE

};

}

componentDidMount() {

$('form').submit(false);

}

onChangeUsername(event) {

this.setState({username: event.target.value});

}

onChangePass(event) {

this.setState({password: event.target.value});

}

onChangeName(event) {

this.setState({name: event.target.value});

}

onChangeEmail(event) {

this.setState({email: event.target.value});

}

register() {

if (!this.fullCheckPass()) return;

fetch(`/addUser?` +

`username=${this.state.username}` + `&` +

`password=${this.state.password}` + `&` +

`name=${this.state.name}` + `&` +

`email=${this.state.email}` + `&` +

getFullCSRFParam(), {

method: 'POST'

}).then((response) => {

let status = response.headers.get("newUserStatus");

if (status === "ok") {

this.setState({success: true, error: errorEnum.NONE});

setTimeout(() => {

this.props.history.push(`/signin`);

}, 1500)

}

else if (status === "usernameError") {

this.setState({success: false, error: errorEnum.USERNAME_TAKEN});

document.getElementById("login").focus();

}

else this.setState({success: false, error: errorEnum.UNKNOWN});

});

}

fullCheckPass() {

this.setState({error: errorEnum.NONE});

if (!this.validUsername()) return false;

if (!this.validName()) return false;

if (!this.validPassword()) return false;

if (!this.validEmail()) return false;

return true;

}

validUsername() {

var usernameRegex = /^[a-zA-Z0-9_]+$/;

var login = this.state.username;

if (login.length > 16) {

this.setState({error: errorEnum.LONG_USERNAME});

document.getElementById("login").focus();

return false;

}

var res = login.match(usernameRegex);

if (res === null) {

this.setState({error: errorEnum.WRONG_USERNAME});

document.getElementById("login").focus();

return false;

}

return true;

}

validPassword() {

var passRegex = /^[a-zA-Zа-яА-Я0-9]+$/;

var pass = this.state.password;

if (pass.length > 20 || pass.length < 4) {

this.setState({error: errorEnum.WRONG_PASS_LENGTH});

document.getElementById("pass").focus();

return false;

}

var res = pass.match(passRegex);

if (res === null) {

this.setState({error: errorEnum.WRONG_PASS});

document.getElementById("pass").focus();

return false;

}

return true;

}

validName() {

var nameRegex = /^[a-zA-Zа-яА-Я0-9 ]+$/;

var name = this.state.name;

if (name.length > 16) {

this.setState({error: errorEnum.LONG_NAME});

document.getElementById("name").focus();

return false;

}

var res = name.match(nameRegex);

if (res === null) {

this.setState({error: errorEnum.WRONG_NAME});

document.getElementById("name").focus();

return false;

}

return true;

}

validEmail() {

var emailRegex = /^[a-z0-9-\\.]+@[a-z-]+.[a-z]+$/;

var email = this.state.email;

var res = email.match(emailRegex);

if (res === null) {

this.setState({error: errorEnum.WRONG_EMAIL});

document.getElementById("email").focus();

return false;

}

return true;

}

render() {

const tss = this.state.success;

const tse = this.state.error;

return (

<div className="center-block main-center" style={{maxWidth: 500}}>

<hr className="hr100"/>

<div className="panel panel-info">

<div className="panel-body center-block" style={{maxWidth: 400}}>

<form onSubmit={this.register.bind(this)} className="form-signin">

<hr className="hr10"/>

<div className="input-group">

<span className="input-group-addon">Login</span>

<input id="login" className="form-control" required autoFocus

onChange={this.onChangeUsername.bind(this)}/>

</div>

<hr className="hr15"/>

<div className="input-group">

<span className="input-group-addon">Password</span>

<input id="pass" type="password" className="form-control" required

onChange={this.onChangePass.bind(this)}/>

</div>

<hr className="hr15"/>

<...


Подобные документы

  • Обзор существующих технологий разработки программного обеспечения. Описание платформы NET Framework. Принцип работы платформы: компиляция исходного кода; процесс загрузки и исполнения кода; IL-код и верификация. Новые возможности платформы NET Framework.

    реферат [30,7 K], добавлен 01.03.2011

  • Последовательность разработки информационного обеспечения очного и дистанционного обучения через просмотры и прослушивание подкастов. Создание веб-сайта или модуля существующей системы. Описание интерфейсов системы. Настройка прав доступа к подкастам.

    дипломная работа [2,3 M], добавлен 19.11.2010

  • Знакомство с особенностями и этапами разработки приложения для платформы Android. Рассмотрение функций персонажа: бег, прыжок, взаимодействие с объектами. Анализ блок-схемы алгоритма генерации платформ. Способы настройки функционала рабочей области.

    дипломная работа [3,4 M], добавлен 19.01.2017

  • Основы работы с многооконным графическим пользовательским интерфейсом операционной системы Windows95/NT. Основы работы с прикладными программами Windows и DOS. Разработка простого приложения для Windows при помощи средства разработки приложений DELPHI.

    контрольная работа [281,0 K], добавлен 15.01.2009

  • Облачные технологии - использование приложения, расположенного на удаленных серверах, посредством удобного пользовательского интерфейса. История и перспективы их развития. Платформы обслуживания "облаков". Положительные и отрицательные стороны сервисов.

    презентация [770,2 K], добавлен 14.03.2017

  • Отличительные черты смартфонов и коммуникаторов от обычных мобильных телефонов, их дополнительные возможности. Назначение и конфигурация платформы J2ME, ее функции. Порядок проектирования приложения для мобильного телефона на основе платформы J2ME.

    дипломная работа [3,6 M], добавлен 05.09.2009

  • Анализ хозяйственной деятельности организации и ее состояния. Особенности работы мобильной платформы. Реквизитный состав документов. Программная реализация и оценка эффективности приложения. Безопасность работы с приложением и безопасность данных.

    дипломная работа [1,0 M], добавлен 13.06.2014

  • Рассмотрение поисковых систем интернета как программно-аппаратного комплекса с веб-интерфейсом, предоставляющего возможность поиска информации. Виды поисковых систем: Archie, Wandex, Aliweb, WebCrawler, AltaVista, Yahoo!, Google, Яндекс, Bing и Rambler.

    реферат [24,3 K], добавлен 10.05.2013

  • База знаний интеллектуальной справочной системы по алгебре дробей со стандартными набором информационно-поисковых операций, пользовательским интерфейсом. Тестирование на стандартных вопросах и шаблонах поиска. Интеграция со смежными предметными областями.

    курсовая работа [12,3 M], добавлен 06.05.2011

  • Описание языков программирования Java и JavaFX. Среда разработки NetBeans и класс численных методов. Архитектура и принцип работы апплета с понятным пользовательским интерфейсом. Разработка алгоритма программы на примере модели межвидовой конкуренции.

    курсовая работа [1023,2 K], добавлен 19.09.2012

  • Понятие и функциональные особенности Java Card как версии Java-платформы для устройств с крайне ограниченными вычислительными ресурсами, оценка ее возможностей и необходимых ресурсов. Анализ степени безопасности платформы, взаимодействие компонентов.

    презентация [1,0 M], добавлен 19.05.2014

  • Описание платформы Deductor, ее назначение. Организационная структура аналитической платформы Deductor, состав модулей. Принципы работы программы, импорт и экспорт данных. Визуализация информации, сценарная последовательность и мастер обработки.

    курсовая работа [3,7 M], добавлен 19.04.2014

  • Рассмотрение и анализ моделей и алгоритмов семантического поиска в мультиагентной системе поддержки пользователей. Ознакомление с интерфейсом чата с ботом. Изучение и характеристика экспериментальных оценок релевантности и пертинентности запросов.

    дипломная работа [3,0 M], добавлен 13.10.2017

  • Изучение информационной базы клиента "Управление торговлей". Выбор и изучение платформы для построения сайта. Выбор технологии и среды разработки. Разработка основных алгоритмов решения задач и хранения данных. Проектирование интерфейса пользователя.

    дипломная работа [1,1 M], добавлен 20.05.2017

  • Разработка базы данных средней сложности с типовым пользовательским интерфейсом, а в частности, разработка базы данных СНАБЖЕНИЕ МАГАЗИНОВ на основе реляционной системы управления базами данных Microsoft Access, входящей в комплект Microsoft Office.

    курсовая работа [2,1 M], добавлен 02.12.2012

  • Разработка компьютерного приложения "Кипящая жидкость" с применением навыков программирования на языке Java. Проектирование алгоритма для решения поставленной задачи, его предметная область. Создание приложения с графическим пользовательским интерфейсом.

    отчет по практике [3,0 M], добавлен 29.10.2015

  • Возможности среды программирования delphi при разработке приложения с визуальным интерфейсом. Разработка спецификации программного обеспечения и на ее основе кода программного продукта. Отладка программы "трассировкой", ее тестирование и оптимизация.

    курсовая работа [501,4 K], добавлен 07.12.2016

  • Возможность поиска информации в режиме продвинутого диалога на естественном языке. Системы с интеллектуальным интерфейсом. Экспертные, самообучающиеся и адаптивные системы. Интеллектуальные базы данных. Системы контекстной и когнитивной помощи.

    презентация [224,2 K], добавлен 16.10.2013

  • Средства поиска информации в сети Интернет. Основные требования и методика поиска информации. Структура и характеристика поисковых сервисов. Глобальные поисковые машины WWW (World Wide Web). Планирование поиска и сбора информации в сети Интернет.

    реферат [32,2 K], добавлен 02.11.2010

  • Создание информационной системы работы такси с целью обеспечения диспетчерам более быстрого и удобного поиска необходимой информации. Создание таблиц и связей для работы с базами данных в среде Microsoft Access 2007. разработка запросов и отчетов.

    курсовая работа [3,1 M], добавлен 06.05.2013

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.