Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ target
logs
attachments
*.patch
.env


9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM eclipse-temurin:17-jdk

WORKDIR /app

COPY target/*.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "app.jar"]
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,11 @@
- https://habr.com/ru/articles/259055/

Список выполненных задач:
...

1. Розібратися зі структурою проєкту (onboarding).
2. Видалити соціальні мережі: vk, yandex. Easy task
3. Винести чутливу інформацію до окремого проперті файлу.
6. Зробити рефакторинг методу com.javarush.jira.bugtracking.attachment.FileUtil#upload.
7. Додати новий функціонал: додавання тегів до завдання.
8. Додати підрахунок часу: скільки завдання перебувало у роботі та тестуванні.
9. Написати Dockerfile для основного сервера
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@
<optional>true</optional>
</dependency>

<dependency>
<groupId>me.paulschwarz</groupId>
<artifactId>spring-dotenv</artifactId>
<version>4.0.0</version>
</dependency>

</dependencies>

<build>
Expand Down
10 changes: 0 additions & 10 deletions resources/static/fontawesome/css/all.css
Original file line number Diff line number Diff line change
Expand Up @@ -8603,9 +8603,6 @@ readers do not read off random characters that represent icons */
content: "\f3e8";
}

.fa-vk:before {
content: "\f189";
}

.fa-untappd:before {
content: "\f405";
Expand Down Expand Up @@ -9955,10 +9952,6 @@ readers do not read off random characters that represent icons */
content: "\f3bc";
}

.fa-yandex:before {
content: "\f413";
}

.fa-readme:before {
content: "\f4d5";
}
Expand Down Expand Up @@ -10183,9 +10176,6 @@ readers do not read off random characters that represent icons */
content: "\f7c6";
}

.fa-yandex-international:before {
content: "\f414";
}

.fa-cc-amex:before {
content: "\f1f3";
Expand Down
9 changes: 1 addition & 8 deletions resources/view/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,7 @@ <h3 class="mb-3">Sign in</h3>
type="button">
<i class="fa-brands fa-google"></i>
</a>
<a class="btn btn-primary btn-lg me-2" href="/oauth2/authorization/vk" style="padding-left: 17px; padding-right: 17px;"
type="button">
<i class="fa-brands fa-vk"></i>
</a>
<a class="btn btn-danger btn-lg me-2" href="/oauth2/authorization/yandex" style="padding-left: 21px; padding-right: 21px;"
type="button">
<i class="fa-brands fa-yandex"></i>
</a>

<a class="btn btn-dark btn-lg me-2" href="/oauth2/authorization/github" type="button">
<i class="fa-brands fa-github"></i>
</a>
Expand Down
8 changes: 0 additions & 8 deletions resources/view/unauth/register.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,6 @@ <h3 class="mb-3">Registration</h3>
type="button">
<i class="fa-brands fa-google"></i>
</a>
<a class="btn btn-primary btn-lg me-2" href="/oauth2/authorization/vk" style="padding-left: 17px; padding-right: 17px;"
type="button">
<i class="fa-brands fa-vk"></i>
</a>
<a class="btn btn-danger btn-lg me-2" href="/oauth2/authorization/yandex" style="padding-left: 21px; padding-right: 21px;"
type="button">
<i class="fa-brands fa-yandex"></i>
</a>
<a class="btn btn-dark btn-lg me-2" href="/oauth2/authorization/github" type="button">
<i class="fa-brands fa-github"></i>
</a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
import org.springframework.core.io.UrlResource;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
Expand All @@ -24,15 +21,14 @@ public static void upload(MultipartFile multipartFile, String directoryPath, Str
if (multipartFile.isEmpty()) {
throw new IllegalRequestDataException("Select a file to upload.");
}
try {
Path dirPath = Paths.get(directoryPath);
Files.createDirectories(dirPath);

File dir = new File(directoryPath);
if (dir.exists() || dir.mkdirs()) {
File file = new File(directoryPath + fileName);
try (OutputStream outStream = new FileOutputStream(file)) {
outStream.write(multipartFile.getBytes());
} catch (IOException ex) {
throw new IllegalRequestDataException("Failed to upload file" + multipartFile.getOriginalFilename());
}
Path filePath = dirPath.resolve(fileName);
Files.write(filePath, multipartFile.getBytes());
} catch (IOException ex) {
throw new IllegalRequestDataException("Failed to upload file " + multipartFile.getOriginalFilename());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

@Transactional(readOnly = true)
public interface ActivityRepository extends BaseRepository<Activity> {
Expand All @@ -13,4 +14,6 @@ public interface ActivityRepository extends BaseRepository<Activity> {

@Query("SELECT a FROM Activity a JOIN FETCH a.author WHERE a.taskId =:taskId AND a.comment IS NOT NULL ORDER BY a.updated DESC")
List<Activity> findAllComments(long taskId);

Optional<Activity> findFirstByTaskIdAndStatusCodeOrderByUpdatedAsc (long taskId, String statusCode);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;

import static com.javarush.jira.bugtracking.task.TaskUtil.getLatestValue;
Expand All @@ -19,6 +21,10 @@ public class ActivityService {

private final Handlers.ActivityHandler handler;

public static final String IN_PROGRESS = "in_progress";
public static final String READY_FOR_REVIEW = "ready_for_review";
public static final String DONE = "done";

private static void checkBelong(HasAuthorId activity) {
if (activity.getAuthorId() != AuthUser.authId()) {
throw new DataConflictException("Activity " + activity.getId() + " doesn't belong to " + AuthUser.get());
Expand Down Expand Up @@ -73,4 +79,31 @@ private void updateTaskIfRequired(long taskId, String activityStatus, String act
}
}
}

public Duration getProgressDuration(Task task) {
LocalDateTime readyForReview = getActivityUpdatedTime(task.id(), READY_FOR_REVIEW);
LocalDateTime inProgress = getActivityUpdatedTime(task.id(), IN_PROGRESS);

if (readyForReview == null || inProgress == null) {
return Duration.ZERO;
}
return Duration.between(inProgress, readyForReview);
}

public Duration getTestingDuration(Task task) {
LocalDateTime done = getActivityUpdatedTime(task.id(), DONE);
LocalDateTime readyForReview = getActivityUpdatedTime(task.id(), READY_FOR_REVIEW);

if (readyForReview == null || done == null) {
return Duration.ZERO;
}
return Duration.between(readyForReview, done);
}

public LocalDateTime getActivityUpdatedTime(long taskId, String statusCode) {
return handler.getRepository()
.findFirstByTaskIdAndStatusCodeOrderByUpdatedAsc(taskId, statusCode)
.map(Activity::getUpdated)
.orElse(null);
}
}
3 changes: 2 additions & 1 deletion src/main/java/com/javarush/jira/bugtracking/task/Task.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

Expand Down Expand Up @@ -68,7 +69,7 @@ public class Task extends TitleEntity implements HasCode {
@ElementCollection(fetch = FetchType.LAZY)
@JoinColumn()
@OnDelete(action = OnDeleteAction.CASCADE)
private Set<@Size(min = 2, max = 32) String> tags = Set.of();
private Set<@Size(min = 2, max = 32) String> tags = new HashSet<>();

// history of comments and task fields changing
@OneToMany(mappedBy = "taskId", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,10 @@ public TaskTreeNode(TaskTo taskTo) {
this(taskTo, new LinkedList<>());
}
}

@PostMapping("/{id}/tag")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void addTag(@PathVariable long id, @RequestBody String tag) {
taskService.addTag(id, tag);
}
}
17 changes: 17 additions & 0 deletions src/main/java/com/javarush/jira/bugtracking/task/TaskService.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.javarush.jira.bugtracking.task.to.TaskToExt;
import com.javarush.jira.bugtracking.task.to.TaskToFull;
import com.javarush.jira.common.error.DataConflictException;
import com.javarush.jira.common.error.IllegalRequestDataException;
import com.javarush.jira.common.error.NotFoundException;
import com.javarush.jira.common.util.Util;
import com.javarush.jira.login.AuthUser;
Expand Down Expand Up @@ -140,4 +141,20 @@ private void checkAssignmentActionPossible(long id, String userType, boolean ass
throw new DataConflictException(String.format(assign ? CANNOT_ASSIGN : CANNOT_UN_ASSIGN, userType, task.getStatusCode()));
}
}

@Transactional
public void addTag(long id, String tag) {
if (tag == null || tag.isEmpty()) {
throw new IllegalRequestDataException("Tag must not be null or empty");
}
if (tag.length() > 32) {
throw new IllegalRequestDataException("Tag must not exceed 32 characters");
}
Task task = handler.getRepository().getExisted(id);
if (task.getTags().contains(tag)) {
throw new IllegalRequestDataException("Tag already exists for this task");
}
task.getTags().add(tag);
handler.getRepository().saveAndFlush(task);
}
}

This file was deleted.

This file was deleted.

Loading