Skip to content

Commit

Permalink
update templates, controller
Browse files Browse the repository at this point in the history
  • Loading branch information
NastasiyaT committed Oct 15, 2023
1 parent 57fba66 commit ac16374
Show file tree
Hide file tree
Showing 15 changed files with 324 additions and 10 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,7 @@ bin/
.vscode/

### Mac OS ###
.DS_Store
.DS_Store

### Jte ###
jte-classes/
2 changes: 2 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ dependencies {
implementation("io.javalin:javalin-rendering:5.6.0")
implementation("gg.jte:jte:3.0.1")
implementation("org.postgresql:postgresql:42.6.0")
implementation("org.apache.commons:commons-lang3:3.12.0")
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.1")

testImplementation("org.assertj:assertj-core:3.24.2")
testImplementation(platform("org.junit:junit-bom:5.9.2"))
Expand Down
6 changes: 5 additions & 1 deletion app/src/main/java/hexlet/code/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import gg.jte.ContentType;
import gg.jte.TemplateEngine;
import gg.jte.resolve.ResourceCodeResolver;
import hexlet.code.controller.UrlsController;
import hexlet.code.repository.BaseRepository;
import hexlet.code.util.NamedRoutes;
import io.javalin.Javalin;
Expand Down Expand Up @@ -77,7 +78,10 @@ public static Javalin getApp() throws IOException, SQLException {

app.before(ctx -> ctx.contentType("text/html; charset=utf-8"));

app.get(NamedRoutes.rootPath(), ctx -> ctx.render("mainpage.jte"));
app.get(NamedRoutes.rootPath(), UrlsController::build);
app.post(NamedRoutes.rootPath(), UrlsController::create);
app.get(NamedRoutes.urlsPath(), UrlsController::index);
app.get(NamedRoutes.urlPath("{id}"), UrlsController::show);

return app;
}
Expand Down
64 changes: 64 additions & 0 deletions app/src/main/java/hexlet/code/controller/UrlsController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package hexlet.code.controller;

import hexlet.code.dto.urls.UrlPage;
import hexlet.code.dto.urls.UrlsPage;
import hexlet.code.model.Url;
import hexlet.code.repository.UrlRepository;
import hexlet.code.util.NamedRoutes;
import io.javalin.http.Context;
import io.javalin.http.NotFoundResponse;
import org.apache.commons.lang3.StringUtils;

import java.net.MalformedURLException;
import java.net.URL;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

public class UrlsController {
private static final int ITEMS_PER_PAGE = 10;

public static void build(Context ctx) {
ctx.render("urls/build.jte");
}

public static void create(Context ctx) throws SQLException {

try {
var formUrl = new URL(ctx.formParamAsClass("name", String.class).get());
var name = formUrl.getProtocol() + "://" + formUrl.getAuthority();
var createdAt = new Timestamp(System.currentTimeMillis());
var url = new Url(name, createdAt);

if (UrlRepository.existsByName(name)) {
ctx.sessionAttribute("message", "Страница уже существует");
} else {
UrlRepository.save(url);
ctx.sessionAttribute("message", "Страница успешно добавлена");
}
ctx.redirect(NamedRoutes.urlsPath());
} catch (MalformedURLException e) {
ctx.sessionAttribute("message", "Некорректный URL");
ctx.redirect(NamedRoutes.rootPath());
}
}

public static void index(Context ctx) throws SQLException {
var urls = UrlRepository.getEntities();
var pageNumber = ctx.queryParamAsClass("page", Integer.class).getOrDefault(1);
var page = new UrlsPage(urls, pageNumber, ITEMS_PER_PAGE);
String message = ctx.consumeSessionAttribute("message");
page.setMessage(message);
ctx.render("urls/index.jte", Collections.singletonMap("page", page));
}

public static void show(Context ctx) throws SQLException {
var id = ctx.pathParamAsClass("id", Long.class).get();
var url = UrlRepository.find(id)
.orElseThrow(() -> new NotFoundResponse("Запись с таким ID не найдена"));
var page = new UrlPage(url);
ctx.render("urls/show.jte", Collections.singletonMap("page", page));
}
}
10 changes: 10 additions & 0 deletions app/src/main/java/hexlet/code/dto/BasePage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package hexlet.code.dto;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class BasePage {
private String message;
}
11 changes: 11 additions & 0 deletions app/src/main/java/hexlet/code/dto/urls/UrlPage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package hexlet.code.dto.urls;

import hexlet.code.model.Url;
import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
@Getter
public class UrlPage {
private Url url;
}
17 changes: 17 additions & 0 deletions app/src/main/java/hexlet/code/dto/urls/UrlsPage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package hexlet.code.dto.urls;

import hexlet.code.dto.BasePage;
import hexlet.code.model.Url;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

import java.util.List;

@AllArgsConstructor
@Getter
public class UrlsPage extends BasePage {
private List<Url> urls;
private int page;
private int itemsPerPage;
}
3 changes: 3 additions & 0 deletions app/src/main/java/hexlet/code/model/Url.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package hexlet.code.model;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

import java.sql.Timestamp;

@NoArgsConstructor
@Getter
@Setter
public class Url {
Expand Down
79 changes: 79 additions & 0 deletions app/src/main/java/hexlet/code/repository/UrlRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package hexlet.code.repository;

import hexlet.code.model.Url;

import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class UrlRepository extends BaseRepository {

public static void save(Url url) throws SQLException {
var sql = "INSERT INTO urls (name, created_at) VALUES (?, ?)";
try (var conn = dataSource.getConnection();
var preparedStatement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {

preparedStatement.setString(1, url.getName());
preparedStatement.setTimestamp(2, url.getCreatedAt());
preparedStatement.executeUpdate();

var generatedKeys = preparedStatement.getGeneratedKeys();
if (generatedKeys.next()) {
url.setId(generatedKeys.getLong(1));
} else {
throw new SQLException("Не сформирован ID");
}
}
}

public static Optional<Url> find(Long id) throws SQLException {
var sql = "SELECT * FROM urls WHERE id = ?";
try (var conn = dataSource.getConnection();
var stmt = conn.prepareStatement(sql)) {

stmt.setLong(1, id);
var resultSet = stmt.executeQuery();
if (resultSet.next()) {
var name = resultSet.getString("name");
var createdAt = resultSet.getTimestamp("created_at");
var url = new Url(name, createdAt);
url.setId(id);
return Optional.of(url);
}
return Optional.empty();
}
}

public static boolean existsByName(String name) throws SQLException {
var sql = "SELECT * FROM urls WHERE name = ?";
try (var conn = dataSource.getConnection();
var stmt = conn.prepareStatement(sql)) {

stmt.setString(1, name);
var resultSet = stmt.executeQuery();
return resultSet.next();
}
}

public static List<Url> getEntities() throws SQLException {
var sql = "SELECT * FROM urls";
try (var conn = dataSource.getConnection();
var stmt = conn.prepareStatement(sql)) {

var resultSet = stmt.executeQuery();
var result = new ArrayList<Url>();

while (resultSet.next()) {
var id = resultSet.getLong("id");
var name = resultSet.getString("name");
var createdAt = resultSet.getTimestamp("created_at");
var url = new Url(name, createdAt);
url.setId(id);
result.add(url);
}
return result;
}
}
}
16 changes: 16 additions & 0 deletions app/src/main/java/hexlet/code/util/NamedRoutes.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,20 @@ public final class NamedRoutes {
public static String rootPath() {
return "/";
}

public static String urlPath(Long id) {
return urlPath(String.valueOf(id));
}

public static String urlPath(String id) {
return "/urls/" + id;
}

public static String urlsPath() {
return "/urls";
}

public static String urlsPath(int page) {
return "urls?page=" + page;
}
}
16 changes: 13 additions & 3 deletions app/src/main/resources/templates/layout/page.jte
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,24 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WebApp</title>
<title>Анализатор страниц</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
</head>
<body>
<header>
<nav>
<a href="${NamedRoutes.rootPath()}">Main Page</a>
<nav class="navbar navbar-dark bg-dark border-bottom border-body">
<div class="container-fluid">
<span class="navbar-brand mb-0 h1">Анализатор страниц</span>
</div>
<ul class="nav justify-content-end nav-tabs">
<li class="nav-item">
<a class="nav-link" href="${NamedRoutes.rootPath()}">Главная</a>
</li>
<li class="nav-item">
<a class="nav-link" href="${NamedRoutes.urlsPath()}">Сайты</a>
</li>
</ul>
</nav>
</header>
${content}
Expand Down
5 changes: 0 additions & 5 deletions app/src/main/resources/templates/mainpage.jte

This file was deleted.

17 changes: 17 additions & 0 deletions app/src/main/resources/templates/urls/build.jte
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@import hexlet.code.util.NamedRoutes

@template.layout.page(
content = @`
<form action="${NamedRoutes.rootPath()}" method="post">
<h6>Введите адрес ссылки:</h6>
<div class="form-floating row row-cols-lg-auto g-3 align-items-center">
<label for="inputUrl" class="form-label">Ссылка</label>
<input type="url" class="form-control" id="inputUrl" name="name">
<div class="form-text">Пример: https://www.example.com</div>
</div>
<div>
<button type="submit" class="btn btn-primary">Проверить</button>
</div>
</form>
`
)
57 changes: 57 additions & 0 deletions app/src/main/resources/templates/urls/index.jte
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
@import hexlet.code.util.NamedRoutes
@import hexlet.code.model.Url
@import hexlet.code.dto.urls.UrlsPage
@param UrlsPage page

@template.layout.page(
content = @`
!{var message = page.getMessage();}
@if(message != null)
@if(message.contains("успешно"))
<div class="alert alert-success shadow-sm p-3 mb-5 bg-body rounded" role="alert">
${message}
<button type="button" class="btn-close position-absolute top-50 start-100 translate-middle" aria-label="Close"></button>
</div>
@elseif(message.contains("уже"))
<div class="alert alert-warning shadow-sm p-3 mb-5 bg-body rounded" role="alert">
${message}
<button type="button" class="btn-close position-absolute top-50 start-100 translate-middle" aria-label="Close"></button>
</div>
@endif
@endif

!{var pageCount = page.getUrls().size() / page.getItemsPerPage();}

<div class="btn-toolbar" role="toolbar" aria-label="Toolbar with button groups">
@for(int i = 1; i < pageCount; i++)
<button type="button" class="btn btn-primary"><a href="${NamedRoutes.urlsPath(i)}">i</a></button>
@endfor
</div>

!{var urls = page.getUrls();}
@if(!urls.isEmpty())
<table class="table table-light table-hover table-striped table-bordered border-success">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Название</th>
</tr>
</thead>
<tbody>
@for(Url item : urls)
<tr>
<th scope="row">${item.getId()}</th>
<td>${item.getName()}</td>
</tr>
@endfor
</tbody>
</table>
@else
<div class="alert alert-warning shadow-sm p-3 mb-5 bg-body rounded" role="alert">
Список пуст
<button type="button" class="btn-close position-absolute top-50 start-100 translate-middle" aria-label="Close"></button>
</div>
@endif

`
)
26 changes: 26 additions & 0 deletions app/src/main/resources/templates/urls/show.jte
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@import hexlet.code.dto.urls.UrlPage
@param UrlPage page

@template.layout.page(
content = @`
<div class="fw-bold">
<h1>Сайт ${page.getUrl().getName()}</h1>
</div>
<table class="table table-light table-hover border border-light border-2">
<tbody>
<tr>
<th scope="row">ID</th>
<td>${page.getUrl().getId()}</td>
</tr>
<tr>
<th scope="row">Название</th>
<td>${page.getUrl().getName()}</td>
</tr>
<tr>
<th scope="row">Дата добавления</th>
<td>${page.getUrl().getCreatedAt().toString()}</td>
</tr>
</tbody>
</table>
`
)

0 comments on commit ac16374

Please sign in to comment.