Skip to content

Commit d2a2b7b

Browse files
Added corrections based on comments
1 parent 7d7ab97 commit d2a2b7b

File tree

11 files changed

+112
-53
lines changed

11 files changed

+112
-53
lines changed

app/.gitignore

Lines changed: 0 additions & 15 deletions
This file was deleted.

app/src/main/java/hexlet/code/controller/UrlChecksController.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212

1313
import java.sql.SQLException;
1414
import java.sql.Timestamp;
15+
import java.time.LocalDateTime;
1516

1617
public class UrlChecksController {
1718
public static void check(Context ctx) throws SQLException {
1819
var urlId = ctx.pathParamAsClass("id", Long.class).get();
1920

2021
var url = UrlRepository.findById(urlId)
21-
.orElseThrow(() -> new NotFoundResponse("URL not found"));
22+
.orElseThrow(() -> new NotFoundResponse("Некорректный адрес"));
2223
var name = url.getName();
2324

2425

@@ -37,15 +38,15 @@ public static void check(Context ctx) throws SQLException {
3738
String description = !responseBody.select("meta[name=description]").isEmpty()
3839
? responseBody.select("meta[name=description]").get(0).attr("content") : "";
3940

40-
var createdAt = new Timestamp(System.currentTimeMillis());
41+
var createdAt = LocalDateTime.now();
4142

4243
var urlCheck = new UrlCheck(statusCode, h1, title, description, createdAt);
4344
urlCheck.setUrlId(urlId);
4445
UrlCheckRepository.save(urlCheck);
4546
}
4647
ctx.redirect(NamedRoutes.urlPath(urlId));
4748
} catch (Exception e) {
48-
ctx.sessionAttribute("message", "The test failed");
49+
ctx.sessionAttribute("message", "Проверка не пройдена");
4950
ctx.redirect(NamedRoutes.urlPath(urlId));
5051
}
5152

app/src/main/java/hexlet/code/controller/UrlsController.java

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@
1616
import java.net.URISyntaxException;
1717
import java.sql.SQLException;
1818
import java.sql.Timestamp;
19+
import java.time.LocalDateTime;
1920
import java.util.Collections;
2021
import java.util.HashMap;
22+
import java.util.List;
2123
import java.util.Map;
24+
import java.util.stream.Collectors;
25+
import java.util.stream.IntStream;
2226

2327
public class UrlsController {
2428

@@ -30,23 +34,26 @@ public static void build(Context ctx) {
3034
}
3135

3236
public static void create(Context ctx) throws SQLException {
37+
String rawUrl = ctx.formParam("url");
38+
String name;
3339
try {
34-
var url = new Url();
35-
var name = normalizeUrl(ctx.formParamAsClass("url", String.class).get());
36-
37-
if (UrlRepository.existsByName(name)) {
38-
ctx.sessionAttribute("message", "URL already exists");
39-
} else {
40-
url.setName(name);
41-
url.setCreatedAt(new Timestamp(System.currentTimeMillis()));
42-
UrlRepository.save(url);
43-
ctx.sessionAttribute("message", "URL successfully created");
44-
}
45-
ctx.redirect(NamedRoutes.urlsPath());
40+
name = normalizeUrl(rawUrl);
4641
} catch (IllegalArgumentException | URISyntaxException | MalformedURLException e) {
4742
ctx.sessionAttribute("message", "Incorrect URL");
4843
ctx.redirect(NamedRoutes.rootPath());
44+
return;
45+
}
46+
47+
var url = new Url();
48+
if (UrlRepository.existsByName(name)) {
49+
ctx.sessionAttribute("message", "URL already exists");
50+
} else {
51+
url.setName(name);
52+
url.setCreatedAt(LocalDateTime.now());
53+
UrlRepository.save(url);
54+
ctx.sessionAttribute("message", "URL successfully created");
4955
}
56+
ctx.redirect(NamedRoutes.urlsPath());
5057
}
5158

5259
public static void index(Context ctx) throws SQLException {
@@ -61,11 +68,13 @@ public static void index(Context ctx) throws SQLException {
6168
} else if (!urls.isEmpty()) {
6269
urls = UrlRepository.getEntitiesPerPage(itemsPerPage, pageNumber);
6370

71+
List<Long> urlIds = urls.stream()
72+
.map(Url::getId)
73+
.collect(Collectors.toList());
74+
Map<Long, UrlCheck> latestChecks = UrlCheckRepository.findLatestChecksByUrlIds(urlIds);
6475
Map<Url, UrlCheck> urlsWithLatestChecks = new HashMap<>();
6576
for (Url item : urls) {
66-
var latestCheck = UrlCheckRepository.findLatestCheck(item.getId())
67-
.orElse(null);
68-
urlsWithLatestChecks.put(item, latestCheck);
77+
urlsWithLatestChecks.put(item, latestChecks.get(item.getId()));
6978
}
7079
page.setChecks(urlsWithLatestChecks);
7180
page.setPageNumber(pageNumber);
@@ -74,6 +83,13 @@ public static void index(Context ctx) throws SQLException {
7483

7584
String message = ctx.consumeSessionAttribute("message");
7685
page.setMessage(message);
86+
if (pageCount > 0) {
87+
List<Integer> pages = IntStream.rangeClosed(1, pageCount)
88+
.boxed()
89+
.collect(Collectors.toList());
90+
page.setPages(pages);
91+
}
92+
7793
ctx.render("urls/index.jte", Collections.singletonMap("page", page));
7894
}
7995

app/src/main/java/hexlet/code/dto/urls/UrlsPage.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ public class UrlsPage extends BasePage {
1717
private List<Url> urls;
1818
private Map<Url, UrlCheck> checks;
1919
private int pageNumber;
20+
private List<Integer> pages;
2021
}

app/src/main/java/hexlet/code/model/Url.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,25 @@
55
import lombok.NoArgsConstructor;
66
import lombok.Setter;
77

8-
import java.sql.Timestamp;
8+
import java.time.LocalDateTime;
99

10-
@AllArgsConstructor
1110
@NoArgsConstructor
1211
@Getter
1312
@Setter
1413
public class Url {
1514
private Long id;
1615
private String name;
17-
private Timestamp createdAt;
16+
private LocalDateTime createdAt;
17+
18+
public Url(String name) {
19+
this.name = name;
20+
}
21+
22+
public Url(Long id, String name, LocalDateTime createdAt) {
23+
this.id = id;
24+
this.name = name;
25+
this.createdAt = createdAt;
26+
}
1827

1928
}
2029

app/src/main/java/hexlet/code/model/UrlCheck.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import lombok.Getter;
44
import lombok.Setter;
55

6-
import java.sql.Timestamp;
6+
import java.time.LocalDateTime;
77

88
@Getter
99
@Setter
@@ -14,17 +14,17 @@ public class UrlCheck {
1414
private String h1;
1515
private String title;
1616
private String description;
17-
private Timestamp createdAt;
17+
private LocalDateTime createdAt;
1818

19-
public UrlCheck(int statusCode, String h1, String title, String description, Timestamp createdAt) {
19+
public UrlCheck(int statusCode, String h1, String title, String description, LocalDateTime createdAt) {
2020
this.statusCode = statusCode;
2121
this.h1 = h1;
2222
this.title = title;
2323
this.description = description;
2424
this.createdAt = createdAt;
2525
}
2626

27-
public UrlCheck(int statusCode, Timestamp createdAt) {
27+
public UrlCheck(int statusCode, LocalDateTime createdAt) {
2828
this.statusCode = statusCode;
2929
this.createdAt = createdAt;
3030
}

app/src/main/java/hexlet/code/repository/UrlCheckRepository.java

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,15 @@
44

55
import java.sql.SQLException;
66
import java.sql.Statement;
7+
import java.sql.Timestamp;
78
import java.util.ArrayList;
9+
import java.util.HashMap;
810
import java.util.List;
11+
import java.util.Map;
912
import java.util.Optional;
13+
import java.util.stream.Collectors;
14+
import java.time.LocalDateTime;
15+
1016

1117
public class UrlCheckRepository extends BaseRepository {
1218

@@ -15,12 +21,15 @@ public static void save(UrlCheck urlCheck) throws SQLException {
1521
+ "VALUES (?, ?, ?, ?, ?, ?)";
1622
try (var conn = dataSource.getConnection();
1723
var preparedStatement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
24+
if (urlCheck.getCreatedAt() == null) {
25+
urlCheck.setCreatedAt(LocalDateTime.now());
26+
}
1827
preparedStatement.setLong(1, urlCheck.getUrlId());
1928
preparedStatement.setInt(2, urlCheck.getStatusCode());
2029
preparedStatement.setString(3, urlCheck.getH1());
2130
preparedStatement.setString(4, urlCheck.getTitle());
2231
preparedStatement.setString(5, urlCheck.getDescription());
23-
preparedStatement.setTimestamp(6, urlCheck.getCreatedAt());
32+
preparedStatement.setTimestamp(6, Timestamp.valueOf(urlCheck.getCreatedAt()));
2433
preparedStatement.executeUpdate();
2534

2635
var generatedKeys = preparedStatement.getGeneratedKeys();
@@ -48,7 +57,7 @@ public static List<UrlCheck> find(Long urlId) throws SQLException {
4857
var h1 = resultSet.getString("h1");
4958
var title = resultSet.getString("title");
5059
var description = resultSet.getString("description");
51-
var createdAt = resultSet.getTimestamp("created_at");
60+
var createdAt = resultSet.getTimestamp("created_at").toLocalDateTime();
5261
var urlCheck = new UrlCheck(statusCode, h1, title, description, createdAt);
5362
urlCheck.setId(currentListId);
5463

@@ -69,11 +78,43 @@ public static Optional<UrlCheck> findLatestCheck(Long urlId) throws SQLException
6978

7079
if (resultSet.next()) {
7180
var statusCode = resultSet.getInt("status_code");
72-
var createdAt = resultSet.getTimestamp("created_at");
81+
var createdAt = resultSet.getTimestamp("created_at").toLocalDateTime();
7382
var check = new UrlCheck(statusCode, createdAt);
7483
return Optional.of(check);
7584
}
7685
return Optional.empty();
7786
}
7887
}
88+
89+
public static Map<Long, UrlCheck> findLatestChecksByUrlIds(List<Long> urlIds) throws SQLException {
90+
if (urlIds.isEmpty()) {
91+
return new HashMap<>();
92+
}
93+
String inClause = urlIds.stream().map(id -> "?").collect(Collectors.joining(", "));
94+
String sql = "SELECT DISTINCT ON (url_id) * FROM url_checks WHERE url_id IN (" + inClause + ") ORDER BY url_id, id DESC";
95+
try (var conn = dataSource.getConnection();
96+
var stmt = conn.prepareStatement(sql)) {
97+
int idx = 1;
98+
for (Long id : urlIds) {
99+
stmt.setLong(idx++, id);
100+
}
101+
var resultSet = stmt.executeQuery();
102+
var result = new HashMap<Long, UrlCheck>();
103+
while (resultSet.next()) {
104+
var id = resultSet.getLong("id");
105+
var urlId = resultSet.getLong("url_id");
106+
var statusCode = resultSet.getInt("status_code");
107+
var h1 = resultSet.getString("h1");
108+
var title = resultSet.getString("title");
109+
var description = resultSet.getString("description");
110+
var createdAt = resultSet.getTimestamp("created_at").toLocalDateTime();
111+
var check = new UrlCheck(statusCode, h1, title, description, createdAt);
112+
check.setId(id);
113+
check.setUrlId(urlId);
114+
check.setCreatedAt(createdAt);
115+
result.put(urlId, check);
116+
}
117+
return result;
118+
}
119+
}
79120
}

app/src/main/java/hexlet/code/repository/UrlRepository.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import java.util.ArrayList;
99
import java.util.List;
1010
import java.util.Optional;
11+
import java.time.LocalDateTime;
12+
import java.sql.Timestamp;
1113

1214
import static hexlet.code.repository.BaseRepository.dataSource;
1315

@@ -19,8 +21,11 @@ public static void save(Url url) throws SQLException {
1921
try (var conn = dataSource.getConnection();
2022
var stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
2123

24+
if (url.getCreatedAt() == null) {
25+
url.setCreatedAt(java.time.LocalDateTime.now());
26+
}
2227
stmt.setString(1, url.getName());
23-
stmt.setTimestamp(2, url.getCreatedAt());
28+
stmt.setTimestamp(2, Timestamp.valueOf(url.getCreatedAt()));
2429
stmt.executeUpdate();
2530

2631
var generatedKeys = stmt.getGeneratedKeys();
@@ -117,7 +122,7 @@ public static List<Url> getEntitiesPerPage(int itemsPerPage, int pageNumber) thr
117122
private static Url getUrl(ResultSet resultSet) throws SQLException {
118123
var id = resultSet.getLong("id");
119124
var name = resultSet.getString("name");
120-
var createdAt = resultSet.getTimestamp("created_at");
125+
var createdAt = resultSet.getTimestamp("created_at").toLocalDateTime();
121126
return new Url(id, name, createdAt);
122127
}
123128

app/src/main/resources/templates/urls/index.jte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
@import hexlet.code.util.NamedRoutes
33
@import hexlet.code.dto.urls.UrlsPage
44
@import org.apache.commons.lang3.StringUtils
5-
@import java.text.SimpleDateFormat
5+
@import java.time.format.DateTimeFormatter
66
@param UrlsPage page
77

88
@template.layout.page(
@@ -62,7 +62,7 @@ content = @`
6262

6363
!{var latestCheck = page.getChecks().get(item);}
6464
@if(latestCheck != null)
65-
<td>${new SimpleDateFormat("dd/MM/yy HH:mm").format(latestCheck.getCreatedAt())}</td>
65+
<td>${latestCheck.getCreatedAt().format(DateTimeFormatter.ofPattern("dd/MM/yy HH:mm"))}</td>
6666
<td>${latestCheck.getStatusCode()}</td>
6767
@else
6868
<td></td>
@@ -76,7 +76,7 @@ content = @`
7676

7777
<div class="btn-toolbar position-relative text-light py-6 d-flex justify-content-center" role="toolbar" aria-label="Toolbar with button groups">
7878
<div class="btn-group me-2" role="group" aria-label="First group">
79-
@for(int i = 1; i <= page.getPageNumber(); i++)
79+
@for(Integer i : page.getPages())
8080
<a class="btn btn-success opacity-75" href="${NamedRoutes.urlsPath(i)}" role="button">${i}</a>
8181
@endfor
8282
</div>

app/src/main/resources/templates/urls/show.jte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@import hexlet.code.dto.urls.UrlPage
22
@import hexlet.code.util.NamedRoutes
33
@import org.apache.commons.lang3.StringUtils
4-
@import java.text.SimpleDateFormat
4+
@import java.time.format.DateTimeFormatter
55
@param UrlPage page
66

77
@template.layout.page(
@@ -36,7 +36,7 @@ content = @`
3636
</tr>
3737
<tr>
3838
<th scope="row">Дата добавления</th>
39-
<td>${new SimpleDateFormat("dd/MM/yy HH:mm").format(page.getUrl().getCreatedAt())}</td>
39+
<td>${page.getUrl().getCreatedAt().format(DateTimeFormatter.ofPattern("dd/MM/yy HH:mm"))}</td>
4040
</tr>
4141
</tbody>
4242
</table>
@@ -72,7 +72,7 @@ content = @`
7272
<td>${check.getH1()}</td>
7373
<td>${check.getTitle()}</td>
7474
<td>${check.getDescription()}</td>
75-
<td>${new SimpleDateFormat("dd/MM/yy HH:mm").format(check.getCreatedAt())}</td>
75+
<td>${check.getCreatedAt().format(DateTimeFormatter.ofPattern("dd/MM/yy HH:mm"))}</td>
7676
</tr>
7777
@endfor
7878
</tbody>

0 commit comments

Comments
 (0)