Skip to content

Commit 1137ee7

Browse files
committed
added chart filters into admin dashboard
1 parent 586a4ae commit 1137ee7

17 files changed

Lines changed: 234 additions & 32 deletions

File tree

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,14 @@ SpringBlog is powered by many powerful frameworks and third-party projects:
2121
- [Prism](http://prismjs.com) - syntax highlighter
2222
- [HighCharts](https://www.highcharts.com/) - charts JS-library
2323
- [TelegramBots](https://github.com/rubenlagus/TelegramBots) - telegram bot API for sending announcements of posts into Telegram Channel
24+
- [Date Range Picker](http://www.daterangepicker.com) - A JavaScript component for choosing date ranges. Designed to work with the Bootstrap CSS framework.
2425

2526
## Changelog
2627

28+
#### 2017-12-25
29+
30+
* Added chart filters into admin dashboard using [Date Range Picker](http://www.daterangepicker.com)
31+
2732
#### 2017-12-22 - SpringBlog version 2.8.0 is released
2833

2934
* __SpringBoot updated upto 1.4.9__

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ apply plugin: 'org.springframework.boot'
66
sourceCompatibility = 1.8
77
targetCompatibility = 1.8
88

9-
version = '2.8.0'
9+
version = '2.8.1'
1010

1111
repositories {
1212
mavenCentral()

src/main/java/com/raysmond/blog/admin/controllers/AdminController.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.raysmond.blog.models.dto.VisitStatDTO;
55
import com.raysmond.blog.models.dto.VisitsStatsChartDTO;
66
import com.raysmond.blog.services.AppSetting;
7+
import com.raysmond.blog.services.PostService;
78
import com.raysmond.blog.services.StatisticsService;
89
import com.raysmond.blog.support.web.MessageHelper;
910
import com.raysmond.blog.utils.DTOUtil;
@@ -32,9 +33,13 @@ public class AdminController {
3233
@Autowired
3334
private AppSetting appSetting;
3435

36+
@Autowired
37+
private PostService postService;
38+
3539

3640
@RequestMapping("")
37-
public String index() {
41+
public String index(Model model) {
42+
model.addAttribute("posts", postService.getPostsIdTitleList());
3843
return "admin/home/index";
3944
}
4045

src/main/java/com/raysmond/blog/admin/controllers/NotificatorController.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ public class NotificatorController {
4040
try {
4141
notificator.announcePost(post);
4242
return new PostAnnouncementDTO(false);
43+
} catch (IllegalArgumentException iae) {
44+
iae.printStackTrace();
45+
return new PostAnnouncementDTO(true, iae.getMessage());
4346
} catch (TelegramApiException e) {
4447
e.printStackTrace();
4548
return new PostAnnouncementDTO(true, "Error occures");
Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package com.raysmond.blog.admin.controllers;
22

3+
import com.raysmond.blog.models.dto.PostsIdListDTO;
34
import com.raysmond.blog.models.dto.VisitsStatsChartDTO;
45
import com.raysmond.blog.services.StatisticsService;
56
import org.springframework.beans.factory.annotation.Autowired;
7+
import org.springframework.format.annotation.DateTimeFormat;
68
import org.springframework.http.MediaType;
79
import org.springframework.stereotype.Controller;
810
import org.springframework.ui.Model;
9-
import org.springframework.web.bind.annotation.RequestMapping;
10-
import org.springframework.web.bind.annotation.ResponseBody;
11+
import org.springframework.web.bind.annotation.*;
12+
13+
import java.util.Date;
1114

1215
/**
1316
* Created by bvn13 on 20.12.2017.
@@ -20,12 +23,20 @@ public class StatisticsController {
2023
private StatisticsService statisticsService;
2124

2225

23-
@RequestMapping(value = "/visits", produces = MediaType.APPLICATION_JSON_VALUE)
26+
@GetMapping(value = "/visits", produces = MediaType.APPLICATION_JSON_VALUE)
2427
public @ResponseBody VisitsStatsChartDTO getVisitsChart() {
25-
26-
VisitsStatsChartDTO chart = statisticsService.getVisitsStatsChartData();
28+
VisitsStatsChartDTO chart = statisticsService.getFullVisitsStatsChartData();
2729
return chart;
30+
}
2831

32+
@PostMapping(value = "/visits", produces = MediaType.APPLICATION_JSON_VALUE)
33+
public @ResponseBody VisitsStatsChartDTO getVisitsChartByPeriodAndPostsIdList(
34+
@RequestParam @DateTimeFormat(pattern="dd-MM-yyyy") Date start,
35+
@RequestParam @DateTimeFormat(pattern="dd-MM-yyyy") Date end,
36+
@RequestBody PostsIdListDTO postsDto)
37+
{
38+
VisitsStatsChartDTO chart = statisticsService.getChartDataByPeriodAndPostsList(start, end, postsDto.getIds());
39+
return chart;
2940
}
3041

3142
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.raysmond.blog.models.dto;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Data;
5+
6+
/**
7+
* Created by bvn13 on 25.12.2017.
8+
*/
9+
@Data
10+
@AllArgsConstructor
11+
public class PostIdTitleDTO {
12+
private Long id;
13+
private String title;
14+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.raysmond.blog.models.dto;
2+
3+
import lombok.Data;
4+
5+
import java.util.List;
6+
7+
/**
8+
* Created by bvn13 on 25.12.2017.
9+
*/
10+
@Data
11+
public class PostsIdListDTO {
12+
private List<Integer> ids;
13+
}

src/main/java/com/raysmond/blog/notificators/Notificator.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ public class Notificator {
2020
private TelegramBotManager telegramBot;
2121

2222

23-
public void announcePost(Post post) throws TelegramApiException {
23+
public void announcePost(Post post) throws IllegalArgumentException, TelegramApiException {
24+
if (post == null || post.getAnnouncement().isEmpty()) {
25+
throw new IllegalArgumentException("Nothing to announce");
26+
}
2427
String postUrl = appSetting.getMainUriStripped()+"/posts/"+(post.getPermalink().isEmpty() ? post.getId() : post.getPermalink());
2528
String message = String.format(
2629
"*%s*\r\n\n" +

src/main/java/com/raysmond/blog/services/PostService.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.raysmond.blog.models.Post;
66
import com.raysmond.blog.models.SeoPostData;
77
import com.raysmond.blog.models.Tag;
8+
import com.raysmond.blog.models.dto.PostIdTitleDTO;
89
import com.raysmond.blog.models.support.PostFormat;
910
import com.raysmond.blog.models.support.PostStatus;
1011
import com.raysmond.blog.models.support.PostType;
@@ -221,6 +222,10 @@ public List<Post> getAllPublishedPosts() {
221222
return this.postRepository.findAllByPostTypeAndPostStatus(PostType.POST, PostStatus.PUBLISHED);
222223
}
223224

225+
public List<Post> getAllPosts() {
226+
return this.postRepository.findAll();
227+
}
228+
224229
public Post createAboutPage() {
225230
logger.debug("Create default about page");
226231

@@ -315,4 +320,18 @@ private void saveSeoData(Post post) {
315320
}
316321
}
317322

323+
public List<PostIdTitleDTO> getPostsIdTitleList() {
324+
List<PostIdTitleDTO> result = new ArrayList<>();
325+
this.getAllPosts().forEach(p -> {
326+
result.add(new PostIdTitleDTO(p.getId(), p.getTitle()));
327+
});
328+
Collections.sort(result, new Comparator<PostIdTitleDTO>() {
329+
@Override
330+
public int compare(PostIdTitleDTO o1, PostIdTitleDTO o2) {
331+
return Long.compare(o2.getId(), o1.getId());
332+
}
333+
});
334+
return result;
335+
}
336+
318337
}

src/main/java/com/raysmond/blog/services/StatisticsService.java

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,35 @@ public List<Object> getVisitsStats() {
4444
return result;
4545
}
4646

47-
public VisitsStatsChartDTO getVisitsStatsChartData() {
47+
public List<Object> getVisitsStatsByPeriodAndPostsList(Date periodStart, Date periodEnd, List<Integer> postsIdList) {
4848

49+
Session session = (Session) this.entityManager.getDelegate();
50+
SQLQuery query = session.createSQLQuery(
51+
"select data.dt, data.post_id, data.title, data.count from (" +
52+
"select date_trunc('day', v.createdat) as dt, v.post_id, p.title, count(distinct v.clientip) as count " +
53+
"from visits as v " +
54+
"left join seo_robots_agents as ra " +
55+
"on case when ra.isregexp then lower(nullif(v.useragent,'')) ~* lower(ra.useragent) " +
56+
"else lower(nullif(v.useragent,'')) like concat('%',lower(ra.useragent),'%') end " +
57+
"inner join posts as p " +
58+
"on v.post_id = p.id " +
59+
"where v.isadmin = false " +
60+
"and ra.id isnull " +
61+
"group by date_trunc('day', v.createdat), v.post_id, p.title " +
62+
") as data " +
63+
"where data.dt >= :periodStart and data.dt <= :periodEnd and data.post_id in (:postsIdList)"
64+
);
65+
66+
query.setParameter("periodStart", periodStart);
67+
query.setParameter("periodEnd", periodEnd);
68+
query.setParameterList("postsIdList", postsIdList);
69+
70+
List<Object> result = query.list();
71+
72+
return result;
73+
}
74+
75+
private VisitsStatsChartDTO convertDataToChart(List<Object> list) {
4976
VisitsStatsChartDTO chart = new VisitsStatsChartDTO();
5077
chart.getChart().setType("line");
5178
chart.getTitle().setText("Visits Statistics");
@@ -59,7 +86,6 @@ public VisitsStatsChartDTO getVisitsStatsChartData() {
5986
Map<String, Map<Date, Long>> data = new HashMap<>();
6087

6188

62-
List<Object> list = getVisitsStats();
6389
for (Object vs : list) {
6490
Object[] vsa = (Object[]) vs;
6591

@@ -104,4 +130,14 @@ public VisitsStatsChartDTO getVisitsStatsChartData() {
104130
return chart;
105131
}
106132

133+
public VisitsStatsChartDTO getFullVisitsStatsChartData() {
134+
List<Object> list = getVisitsStats();
135+
return convertDataToChart(list);
136+
}
137+
138+
public VisitsStatsChartDTO getChartDataByPeriodAndPostsList(Date periodStart, Date periodEnd, List<Integer> postsIdList) {
139+
List<Object> list = getVisitsStatsByPeriodAndPostsList(periodStart, periodEnd, postsIdList);
140+
return convertDataToChart(list);
141+
}
142+
107143
}

0 commit comments

Comments
 (0)