Merge branch '68-ping-conf' into 'dev'

Resolve "Ping конференции в списке конференций"

Closes #68

See merge request romanov73/ng-tracker!69
This commit is contained in:
Anton Romanov 2019-04-25 10:00:34 +00:00
commit 88ec35faa0
16 changed files with 354 additions and 10 deletions

View File

@ -56,6 +56,8 @@ public class ConferenceController {
@GetMapping("/dashboard") @GetMapping("/dashboard")
public void getDashboard(ModelMap modelMap) { public void getDashboard(ModelMap modelMap) {
modelMap.put("conferences", conferenceService.findAllActiveDto()); modelMap.put("conferences", conferenceService.findAllActiveDto());
conferenceService.setChartData(modelMap); // example
} }
@GetMapping("/conference") @GetMapping("/conference")
@ -132,6 +134,15 @@ public class ConferenceController {
return CONFERENCE_PAGE; return CONFERENCE_PAGE;
} }
@PostMapping(value = "/conference", params = "pingConference")
public String ping(@Valid ConferenceDto conferenceDto, Errors errors) throws IOException {
if (errors.hasErrors()) {
return CONFERENCE_PAGE;
}
conferenceService.ping(conferenceDto);
return CONFERENCE_PAGE;
}
@ModelAttribute("allParticipation") @ModelAttribute("allParticipation")
public List<ConferenceUser.Participation> getAllParticipation() { public List<ConferenceUser.Participation> getAllParticipation() {
return conferenceService.getAllParticipations(); return conferenceService.getAllParticipations();

View File

@ -35,7 +35,7 @@ public class Conference extends BaseEntity {
private String url; private String url;
private int ping; private int ping = 0;
@Column(name = "begin_date") @Column(name = "begin_date")
@Temporal(TemporalType.TIMESTAMP) @Temporal(TemporalType.TIMESTAMP)

View File

@ -1,6 +1,7 @@
package ru.ulstu.conference.repository; package ru.ulstu.conference.repository;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
import ru.ulstu.conference.model.Conference; import ru.ulstu.conference.model.Conference;
@ -19,4 +20,8 @@ public interface ConferenceRepository extends JpaRepository<Conference, Integer>
@Query("SELECT case when count(c) > 0 then true else false end FROM Conference c JOIN c.papers p WHERE p.id = :paperId") @Query("SELECT case when count(c) > 0 then true else false end FROM Conference c JOIN c.papers p WHERE p.id = :paperId")
boolean isPaperAttached(@Param("paperId") Integer paperId); boolean isPaperAttached(@Param("paperId") Integer paperId);
@Modifying
@Query("UPDATE Conference c SET c.ping = (c.ping + 1) WHERE c.id = :id")
int updatePingConference(@Param("id") Integer id);
} }

View File

@ -4,6 +4,7 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import ru.ulstu.conference.model.Conference; import ru.ulstu.conference.model.Conference;
import ru.ulstu.conference.model.ConferenceDto; import ru.ulstu.conference.model.ConferenceDto;
import ru.ulstu.conference.model.ConferenceFilterDto; import ru.ulstu.conference.model.ConferenceFilterDto;
@ -12,6 +13,7 @@ import ru.ulstu.conference.repository.ConferenceRepository;
import ru.ulstu.deadline.service.DeadlineService; import ru.ulstu.deadline.service.DeadlineService;
import ru.ulstu.paper.model.Paper; import ru.ulstu.paper.model.Paper;
import ru.ulstu.paper.service.PaperService; import ru.ulstu.paper.service.PaperService;
import ru.ulstu.ping.service.PingService;
import ru.ulstu.user.model.User; import ru.ulstu.user.model.User;
import ru.ulstu.user.service.UserService; import ru.ulstu.user.service.UserService;
@ -33,17 +35,20 @@ public class ConferenceService {
private final DeadlineService deadlineService; private final DeadlineService deadlineService;
private final PaperService paperService; private final PaperService paperService;
private final UserService userService; private final UserService userService;
private final PingService pingService;
public ConferenceService(ConferenceRepository conferenceRepository, public ConferenceService(ConferenceRepository conferenceRepository,
ConferenceUserService conferenceUserService, ConferenceUserService conferenceUserService,
DeadlineService deadlineService, DeadlineService deadlineService,
PaperService paperService, PaperService paperService,
UserService userService) { UserService userService,
PingService pingService) {
this.conferenceRepository = conferenceRepository; this.conferenceRepository = conferenceRepository;
this.conferenceUserService = conferenceUserService; this.conferenceUserService = conferenceUserService;
this.deadlineService = deadlineService; this.deadlineService = deadlineService;
this.paperService = paperService; this.paperService = paperService;
this.userService = userService; this.userService = userService;
this.pingService = pingService;
} }
public ConferenceDto getExistConferenceById(Integer id) { public ConferenceDto getExistConferenceById(Integer id) {
@ -151,7 +156,6 @@ public class ConferenceService {
conference.setTitle(conferenceDto.getTitle()); conference.setTitle(conferenceDto.getTitle());
conference.setDescription(conferenceDto.getDescription()); conference.setDescription(conferenceDto.getDescription());
conference.setUrl(conferenceDto.getUrl()); conference.setUrl(conferenceDto.getUrl());
conference.setPing(0);
conference.setBeginDate(conferenceDto.getBeginDate()); conference.setBeginDate(conferenceDto.getBeginDate());
conference.setEndDate(conferenceDto.getEndDate()); conference.setEndDate(conferenceDto.getEndDate());
conference.getPapers().clear(); conference.getPapers().clear();
@ -188,4 +192,36 @@ public class ConferenceService {
public boolean isAttachedToConference(Integer paperId) { public boolean isAttachedToConference(Integer paperId) {
return conferenceRepository.isPaperAttached(paperId); return conferenceRepository.isPaperAttached(paperId);
} }
@Transactional
public void ping(ConferenceDto conferenceDto) throws IOException {
pingService.addPing(findOne(conferenceDto.getId()));
conferenceRepository.updatePingConference(conferenceDto.getId());
}
public Conference findOne(Integer conferenceId) {
return conferenceRepository.findOne(conferenceId);
}
public void setChartData(ModelMap modelMap) {
//first, add the regional sales
Integer northeastSales = 17089;
Integer westSales = 10603;
Integer midwestSales = 5223;
Integer southSales = 10111;
modelMap.addAttribute("northeastSales", northeastSales);
modelMap.addAttribute("southSales", southSales);
modelMap.addAttribute("midwestSales", midwestSales);
modelMap.addAttribute("westSales", westSales);
//now add sales by lure type
List<Integer> inshoreSales = Arrays.asList(4074, 3455, 4112);
List<Integer> nearshoreSales = Arrays.asList(3222, 3011, 3788);
List<Integer> offshoreSales = Arrays.asList(7811, 7098, 6455);
modelMap.addAttribute("inshoreSales", inshoreSales);
modelMap.addAttribute("nearshoreSales", nearshoreSales);
modelMap.addAttribute("offshoreSales", offshoreSales);
}
} }

View File

@ -0,0 +1,73 @@
package ru.ulstu.ping.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.format.annotation.DateTimeFormat;
import ru.ulstu.conference.model.Conference;
import ru.ulstu.core.model.BaseEntity;
import ru.ulstu.user.model.User;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.util.Date;
@Entity
@Table(name = "ping")
public class Ping extends BaseEntity {
@Temporal(value = TemporalType.TIMESTAMP)
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date date;
@ManyToOne(optional = false)
@JoinColumn(name = "users_id")
private User user;
@ManyToOne(optional = false)
@JoinColumn(name = "conference_id")
private Conference conference;
public Ping() {
}
public Ping(Date date, User user) {
this.date = date;
this.user = user;
}
public Ping(@JsonProperty("id") Integer id,
@JsonProperty("date") Date date,
@JsonProperty("user") User user,
@JsonProperty("conference") Conference conference) {
setId(id);
this.date = date;
this.user = user;
this.conference = conference;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Conference getConference() {
return conference;
}
public void setConference(Conference conference) {
this.conference = conference;
}
}

View File

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

View File

@ -0,0 +1,30 @@
package ru.ulstu.ping.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.ulstu.conference.model.Conference;
import ru.ulstu.ping.model.Ping;
import ru.ulstu.ping.repository.PingRepository;
import ru.ulstu.user.service.UserService;
import java.io.IOException;
import java.util.Date;
@Service
public class PingService {
private final PingRepository pingRepository;
private final UserService userService;
public PingService(PingRepository pingRepository,
UserService userService) {
this.pingRepository = pingRepository;
this.userService = userService;
}
@Transactional
public void addPing(Conference conference) throws IOException {
Ping newPing = new Ping(new Date(), userService.getCurrentUser());
newPing.setConference(conference);
pingRepository.save(newPing);
}
}

View File

@ -0,0 +1,28 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="vova" id="20190424_000000-1">
<createTable tableName="ping">
<column name="id" type="integer">
<constraints nullable="false"/>
</column>
<column name="date" type="timestamp">
<constraints nullable="false"/>
</column>
<column name="users_id" type="integer">
<constraints nullable="false"/>
</column>
<column name="conference_id" type="integer"/>
<column name="version" type="integer"/>
</createTable>
<addPrimaryKey columnNames="id" constraintName="pk_ping" tableName="ping"/>
<addForeignKeyConstraint baseTableName="ping" baseColumnNames="users_id"
constraintName="fk_ping_users_id" referencedTableName="users"
referencedColumnNames="id"/>
<addForeignKeyConstraint baseTableName="ping" baseColumnNames="conference_id"
constraintName="fk_ping_conference_id" referencedTableName="conference"
referencedColumnNames="id"/>
</changeSet>
</databaseChangeLog>

View File

@ -33,4 +33,5 @@
<include file="db/changelog-20190419_000000-schema.xml"/> <include file="db/changelog-20190419_000000-schema.xml"/>
<include file="db/changelog-20190421_000000-schema.xml"/> <include file="db/changelog-20190421_000000-schema.xml"/>
<include file="db/changelog-20190422_000000-schema.xml"/> <include file="db/changelog-20190422_000000-schema.xml"/>
<include file="db/changelog-20190424_000000-schema.xml"/>
</databaseChangeLog> </databaseChangeLog>

View File

@ -91,6 +91,16 @@ body {
border-right: 1px solid #ced4da; border-right: 1px solid #ced4da;
} }
#ping-button[disabled=disabled] {
background-color: #ced4da;
border-color: #c2c5c7;
}
#ping-button[disabled=disabled]:hover {
background-color: #737475 !important;
border-color: #5d5e5f !important;
}
#take-part[disabled=disabled] { #take-part[disabled=disabled] {
background-color: #ced4da; background-color: #ced4da;
border-color: #c2c5c7; border-color: #c2c5c7;
@ -178,6 +188,22 @@ body {
float: right; float: right;
} }
.note-1 {
background-color: #bfffce;
}
.note-2 {
background-color: #eaffb4;
}
.note-3 {
background-color: #fff69f;
}
.note-4 {
background-color: #ff9973;
}
@media (max-width: 1199px) and (min-width: 768px){ @media (max-width: 1199px) and (min-width: 768px){
.paper-control { .paper-control {
display: block!important; display: block!important;

View File

@ -121,7 +121,11 @@
</div> </div>
</div> </div>
<div class="form-group d-flex justify-content-end"> <div class="form-group d-flex justify-content-between flex-wrap">
<!--<input type="hidden" th:value="*{ping}" th:name="ping"/>-->
<input id="ping-button" class="btn btn-primary"
type="submit" name="pingConference" value="Ping участникам"
th:disabled="*{id == null ? 'true' : 'false'}"/>
<input type="hidden" th:value="*{disabledTakePart}" th:name="disabledTakePart"/> <input type="hidden" th:value="*{disabledTakePart}" th:name="disabledTakePart"/>
<input id="take-part" class="btn btn-primary" <input id="take-part" class="btn btn-primary"
type="submit" name="takePart" value="Принять участие" type="submit" name="takePart" value="Принять участие"

View File

@ -4,6 +4,7 @@
layout:decorator="default" xmlns:th=""> layout:decorator="default" xmlns:th="">
<head> <head>
<link rel="stylesheet" type="text/css" href="../css/conference.css"/> <link rel="stylesheet" type="text/css" href="../css/conference.css"/>
<script src="https://code.highcharts.com/highcharts.js"></script>
</head> </head>
<body> <body>
<div layout:fragment="content"> <div layout:fragment="content">
@ -21,8 +22,127 @@
<div th:replace="conferences/fragments/confDashboardFragment :: confDashboard(conference=${conference})"/> <div th:replace="conferences/fragments/confDashboardFragment :: confDashboard(conference=${conference})"/>
</th:block> </th:block>
</div> </div>
<hr/>
<!--chart example-->
<nav>
<div class="nav nav-tabs" id="nav-tab" role="tablist">
<a class="nav-item nav-link active" id="nav-main-tab" data-toggle="tab"
href="#nav-stat1" role="tab" aria-controls="nav-stat1" aria-selected="true">Стат1</a>
<a class="nav-item nav-link" id="nav-latex-tab" data-toggle="tab"
href="#nav-stat2" role="tab" aria-controls="nav-stat2" aria-selected="false">Стат2</a>
</div>
</nav>
<div class="tab-content" id="nav-tabContent">
<div class="tab-pane fade show active" id="nav-stat1" role="tabpanel"
aria-labelledby="nav-main-tab">
<div id="salesByType" style="width:100%; height:400px;"></div>
</div>
<div class="tab-pane fade" id="nav-stat2" role="tabpanel"
aria-labelledby="nav-profile-tab">
<div id="salesByRegion" style="width:100%; height:400px;"></div>
</div>
</div>
<!--chart example-->
</div> </div>
</section> </section>
<script th:inline="javascript">
/*<![CDATA[*/
// chart example
$(function () {
Highcharts.setOptions({
lang: {
decimalPoint: '.',
thousandsSep: ','
}
});
drawSalesByTypeChart();
drawSalesByRegionChart();
});
function drawSalesByRegionChart() {
var salesByRegionChart = Highcharts.chart('salesByRegion', {
chart: {
type: 'pie',
margin: 40
},
title: {
text: 'Sales by Region'
},
tooltip: {
pointFormat: "${point.y:,.0f}"
},
plotOptions: {
pie: {
allowPointSelect: true,
depth: 35
}
},
series: [{
name: 'Regions',
colorByPoint:true,
data: [{
name: 'Northeast',
y: /*[[${northeastSales}]]*/ 0
},{
name: 'South',
y: /*[[${southSales}]]*/ 0
},{
name: 'Midwest',
y: /*[[${midwestSales}]]*/ 0
},{
name: 'West',
y: /*[[${westSales}]]*/ 0
}]
}]
});
}
function drawSalesByTypeChart() {
var salesByTypeChart = Highcharts.chart('salesByType', {
chart: {
type: 'column',
margin: 75
},
title: {
text: 'Sales by Lure Type'
},
xAxis: {
categories: ['May', 'June', 'July']
},
yAxis: {
title: {
text: 'Sales (US $)'
}
},
tooltip: {
pointFormat: "${point.y:,.0f}"
},
plotOptions: {
column: {
depth: 60,
stacking: true,
grouping: false,
groupZPadding: 10
}
},
series: [{
name: 'Inshore',
data: /*[[${inshoreSales}]]*/ []
}, {
name: 'Nearshore',
data: /*[[${nearshoreSales}]]*/ []
}, {
name: 'Offshore',
data: /*[[${offshoreSales}]]*/ []
}]
});
}
/*]]>*/
</script>
</div> </div>
</body> </body>
</html> </html>

View File

@ -4,12 +4,13 @@
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
</head> </head>
<body> <body>
<div th:fragment="confDashboard (conference)" class="col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3 dashboard-card"> <div th:fragment="confDashboard (conference)" th:class="@{'col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3 dashboard-card ' +
${conference.ping == 0 ? '' :
conference.ping &lt; 5 ? 'note-1' :
conference.ping &lt; 10 ? 'note-2' :
conference.ping &lt; 15 ? 'note-3' : 'note-4'} + ''}">
<div class="row"> <div class="row">
<div class="col-2"> <div class="col text-right">
</div>
<div class="col col-10 text-right">
<p th:if="${conference.url!=null and conference.url!=''}"><a target="_blank" th:href="${conference.url}"><i <p th:if="${conference.url!=null and conference.url!=''}"><a target="_blank" th:href="${conference.url}"><i
class="fa fa-external-link fa-1x" class="fa fa-external-link fa-1x"
aria-hidden="true"></i></a></p> aria-hidden="true"></i></a></p>

View File

@ -21,7 +21,7 @@
<div class="col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3"> <div class="col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3">
<a href="./conference?id=0" class="btn btn-light toolbar-button"> <a href="./conference?id=0" class="btn btn-light toolbar-button">
<i class="fa fa-plus-circle" aria-hidden="true"></i> <i class="fa fa-plus-circle" aria-hidden="true"></i>
Новая конференцию</a> Новая конференция</a>
</div> </div>
</div> </div>

View File

@ -107,6 +107,7 @@
} }
/*]]>*/ /*]]>*/
</script> </script>
<th:block layout:fragment="scripts"> <th:block layout:fragment="scripts">
</th:block> </th:block>

View File

@ -256,6 +256,7 @@
var lid = $("#leaderId option:selected").val(); var lid = $("#leaderId option:selected").val();
$("#authors [value='" + lid + "']").attr("disabled", "disabled"); $("#authors [value='" + lid + "']").attr("disabled", "disabled");
} }
</script> </script>
<script> <script>