feat: 숏폼 복사 시 작업 완료 처리
This commit is contained in:
parent
80e462acbf
commit
ea08b6d6b7
@ -50,6 +50,11 @@ public class ShortformController {
|
|||||||
return ApiResponse.ok(shortformService.reset(id));
|
return ApiResponse.ok(shortformService.reset(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/jobs/{id}/complete")
|
||||||
|
public ApiResponse<JobDetail> complete(@PathVariable Long id) {
|
||||||
|
return ApiResponse.ok(shortformService.completeCopyWorkflow(id));
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/jobs/{id}/subtitles/retry")
|
@PostMapping("/jobs/{id}/subtitles/retry")
|
||||||
public ApiResponse<Long> retrySubtitles(@PathVariable Long id) {
|
public ApiResponse<Long> retrySubtitles(@PathVariable Long id) {
|
||||||
shortformService.retrySubtitle(id);
|
shortformService.retrySubtitle(id);
|
||||||
|
|||||||
@ -154,6 +154,14 @@ public class ShortformJob {
|
|||||||
this.completedAt = LocalDateTime.now();
|
this.completedAt = LocalDateTime.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** URL 또는 자막을 외부 작업 도구로 복사한 큐 작업을 완료 처리한다. */
|
||||||
|
public void completeCopyWorkflow() {
|
||||||
|
this.status = ShortformJobStatus.DONE;
|
||||||
|
if (this.completedAt == null) {
|
||||||
|
this.completedAt = LocalDateTime.now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 결과를 비우고 다시 대기 상태로 되돌린다. 등록 정보(URL·videoId·등록시각)는 유지하므로
|
* 결과를 비우고 다시 대기 상태로 되돌린다. 등록 정보(URL·videoId·등록시각)는 유지하므로
|
||||||
* 삭제 후 재등록할 필요가 없고, 큐 스킬이 PENDING 만 집어가므로 그대로 다시 실행된다.
|
* 삭제 후 재등록할 필요가 없고, 큐 스킬이 PENDING 만 집어가므로 그대로 다시 실행된다.
|
||||||
|
|||||||
@ -133,6 +133,14 @@ public class ShortformService {
|
|||||||
.orElseThrow(() -> new IllegalArgumentException("작업이 없습니다: " + jobId));
|
.orElseThrow(() -> new IllegalArgumentException("작업이 없습니다: " + jobId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public JobDetail completeCopyWorkflow(Long jobId) {
|
||||||
|
ShortformJob job = jobRepository.findById(jobId)
|
||||||
|
.orElseThrow(() -> new IllegalArgumentException("작업이 없습니다: " + jobId));
|
||||||
|
job.completeCopyWorkflow();
|
||||||
|
return JobDetail.from(job);
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void delete(Long jobId) {
|
public void delete(Long jobId) {
|
||||||
jobRepository.deleteById(jobId);
|
jobRepository.deleteById(jobId);
|
||||||
|
|||||||
@ -182,8 +182,7 @@
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
await navigator.clipboard.writeText(decodeURIComponent(btn.dataset.copy));
|
await navigator.clipboard.writeText(decodeURIComponent(btn.dataset.copy));
|
||||||
if (btn.hasAttribute('data-complete-on-copy')) {
|
if (btn.hasAttribute('data-complete-on-copy')) {
|
||||||
btn.textContent = '완료';
|
await completeCopiedJob(id, el, btn);
|
||||||
btn.disabled = true;
|
|
||||||
} else {
|
} else {
|
||||||
btn.textContent = '복사됨!';
|
btn.textContent = '복사됨!';
|
||||||
setTimeout(() => btn.textContent = label, 1200);
|
setTimeout(() => btn.textContent = label, 1200);
|
||||||
@ -195,8 +194,7 @@
|
|||||||
subtitleButton.onclick = async (e) => {
|
subtitleButton.onclick = async (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
await navigator.clipboard.writeText(detail.subtitleVtt);
|
await navigator.clipboard.writeText(detail.subtitleVtt);
|
||||||
subtitleButton.textContent = '완료';
|
await completeCopiedJob(id, el, subtitleButton);
|
||||||
subtitleButton.disabled = true;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,6 +203,17 @@
|
|||||||
return (s || '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
return (s || '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function completeCopiedJob(id, card, button) {
|
||||||
|
await api('/api/shortform/jobs/' + id + '/complete', { method: 'POST' });
|
||||||
|
button.textContent = '완료';
|
||||||
|
button.disabled = true;
|
||||||
|
const badge = card.querySelector('.sf-badge');
|
||||||
|
if (badge) {
|
||||||
|
badge.className = 'sf-badge DONE';
|
||||||
|
badge.textContent = 'DONE';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function clipHtml(c) {
|
function clipHtml(c) {
|
||||||
return `<div class="sf-clip">
|
return `<div class="sf-clip">
|
||||||
<div class="sf-clip-head">
|
<div class="sf-clip-head">
|
||||||
@ -301,8 +310,7 @@
|
|||||||
button.onclick = async (e) => {
|
button.onclick = async (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
await navigator.clipboard.writeText(detail.subtitleVtt);
|
await navigator.clipboard.writeText(detail.subtitleVtt);
|
||||||
button.textContent = '완료';
|
await completeCopiedJob(id, card, button);
|
||||||
button.disabled = true;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -69,4 +69,14 @@ class ShortformJobResetTest {
|
|||||||
assertThat(job.getTitle()).isEqualTo("새 클립");
|
assertThat(job.getTitle()).isEqualTo("새 클립");
|
||||||
assertThat(job.getRawOutput()).isEqualTo("새 Output");
|
assertThat(job.getRawOutput()).isEqualTo("새 Output");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 복사_워크플로를_완료하면_DONE으로_변경된다() {
|
||||||
|
ShortformJob job = ShortformJob.create("https://youtu.be/abc12345678", "abc12345678");
|
||||||
|
|
||||||
|
job.completeCopyWorkflow();
|
||||||
|
|
||||||
|
assertThat(job.getStatus()).isEqualTo(ShortformJobStatus.DONE);
|
||||||
|
assertThat(job.getCompletedAt()).isNotNull();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user