Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
7baa5bf
chore: Development Presentation target 추가
opficdev Sep 13, 2026
6c9c6a2
feat: 개발 기록 조회 상태와 DI 연결
opficdev Sep 13, 2026
b5846ac
feat: 개발 기록 초안과 최초 확정 상태 구성
opficdev Sep 13, 2026
c99a753
refactor: Markdown 공용 표시 경계 확장
opficdev Sep 13, 2026
0fa8641
ui: 개발 기록 타임라인 구성
opficdev Sep 13, 2026
540ef2f
ui: 개발 기록 작성과 상세 화면 구성
opficdev Sep 13, 2026
4e86674
test: 개발 기록 상태 흐름 검증
opficdev Sep 13, 2026
b5bf0c2
fix: 개발 기록 target 컴파일 오류 수정
opficdev Sep 13, 2026
2df25af
refactor: 개발 기록 DI 준비 책임 분리
opficdev Sep 13, 2026
d7eb789
fix: 기록 기준 버전 계약 명시
opficdev Sep 13, 2026
2346115
fix: 개발 기록 확정 재시도 안정화
opficdev Sep 13, 2026
db34014
fix: 개발 기록 상세 실패 상태 분리
opficdev Sep 13, 2026
34c930a
fix: 개발 기록 요청 중 편집 잠금
opficdev Sep 13, 2026
0c954ba
test: 개발 기록 실패 상태 검증 정리
opficdev Sep 13, 2026
b8a5ac4
ui: 개발 기록 화면 제목 축약
opficdev Sep 13, 2026
ffb9f98
ui: 개발 기록 버전 순번 표시
opficdev Sep 13, 2026
c226c45
ui: 개발 기록 타임라인 제목 위계 정리
opficdev Sep 13, 2026
7513d4a
ui: 불필요 제목 제거
opficdev Sep 13, 2026
7889ba6
ui: 마크다운 프리뷰 상하 패딩 추가
opficdev Sep 13, 2026
a8a1344
ui: Button 컨벤션 적용
opficdev Sep 13, 2026
61a3414
ui: 설계하지 않은 접근성 제어 제거
opficdev Sep 13, 2026
1ba773a
ui: 상단 안전 영역 배경 모디파이어 추가
opficdev Sep 13, 2026
8b786d2
ui: 파일 리네이밍 + 일부 수정
opficdev Sep 13, 2026
916f768
ui: 기록 상세 View 이름과 제목 위계 정리
opficdev Sep 14, 2026
f86e748
ui: 버튼 위치 이동
opficdev Sep 14, 2026
0d43dad
ui: 기록 편집 View 명칭과 스타일 정리
opficdev Sep 14, 2026
9313954
ui: 기록 편집 안내 문구 정리
opficdev Sep 14, 2026
e309e78
refactor: RecordPresentation 명칭 정리
opficdev Sep 14, 2026
cd07273
refactor: 기록 화면 Feature 명칭 통일
opficdev Sep 14, 2026
7f42dea
fix: 기록 초안 개정 충돌 검증
opficdev Sep 14, 2026
8aef5d6
fix: 기록 생성 재시도 식별자 유지
opficdev Sep 14, 2026
b0c6d58
fix: 기록 확정 재시도 식별자 유지
opficdev Sep 14, 2026
33d06da
fix: 기록 현재 버전 조회 병렬화
opficdev Sep 14, 2026
b345aec
fix: 기록 조회 실패 재시도 제공
opficdev Sep 14, 2026
32ec12c
fix: 기록 저장 중 편집 화면 닫기 차단
opficdev Sep 14, 2026
94c716f
fix: 기록 확정 단계부터 재시도
opficdev Sep 14, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ extension AppGraph {
func preparePresentationDependencies() {
prepareDependencies { dependencies in
prepareEntryDependencies(&dependencies)
prepareDevelopmentDependencies(&dependencies)
prepareTodoDependencies(&dependencies)
prepareHomeDependencies(&dependencies)
prepareTodayDependencies(&dependencies)
Expand All @@ -21,6 +22,39 @@ extension AppGraph {
}

private extension AppGraph {
func prepareDevelopmentDependencies(_ dependencies: inout DependencyValues) {
DevelopmentDependencyPreparation.prepareGoal(
&dependencies,
fetchGoalUseCase: developmentGraphSet
.developmentGoalUseCaseGraph
.fetchDevelopmentGoalUseCase
)
DevelopmentDependencyPreparation.prepareQuery(
&dependencies,
fetchRecordsUseCase: developmentGraphSet
.developmentRecordQueryUseCaseGraph
.fetchDevelopmentRecordsUseCase,
fetchRecordHistoryUseCase: developmentGraphSet
.developmentRecordQueryUseCaseGraph
.fetchDevelopmentRecordHistoryUseCase,
fetchRecordVersionUseCase: developmentGraphSet
.developmentRecordQueryUseCaseGraph
.fetchDevelopmentRecordVersionUseCase
)
DevelopmentDependencyPreparation.prepareMutation(
&dependencies,
createRecordUseCase: developmentGraphSet
.developmentRecordMutationUseCaseGraph
.createDevelopmentRecordUseCase,
saveRecordDraftUseCase: developmentGraphSet
.developmentRecordMutationUseCaseGraph
.saveDevelopmentRecordDraftUseCase,
confirmRecordUseCase: developmentGraphSet
.developmentRecordMutationUseCaseGraph
.confirmDevelopmentRecordUseCase
)
}

func prepareEntryDependencies(_ dependencies: inout DependencyValues) {
PresentationDependencyPreparation.prepareRoot(
&dependencies,
Expand Down
16 changes: 14 additions & 2 deletions Application/Data/Sources/DTO/DevelopmentRecordDTO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,21 @@ public struct DevelopmentRecordDraftRequest: Encodable {
public let title: String
public let markdownContent: String
public let baseVersionId: String?
public let revisionId: String?
public let expectedRevisionId: String?

public init(
title: String,
markdownContent: String,
baseVersionId: String?
baseVersionId: String?,
revisionId: String? = nil,
expectedRevisionId: String? = nil
) {
self.title = title
self.markdownContent = markdownContent
self.baseVersionId = baseVersionId
self.revisionId = revisionId
self.expectedRevisionId = expectedRevisionId
}
}

Expand All @@ -35,15 +41,18 @@ public struct DevelopmentRecordConfirmationRequest {
public let versionId: String
public let kind: String
public let sourceVersionId: String?
public let draftRevisionId: String?

public init(
versionId: String,
kind: String,
sourceVersionId: String?
sourceVersionId: String?,
draftRevisionId: String? = nil
) {
self.versionId = versionId
self.kind = kind
self.sourceVersionId = sourceVersionId
self.draftRevisionId = draftRevisionId
}
}

Expand All @@ -61,17 +70,20 @@ public struct DevelopmentRecordDraftResponse {
public let title: String
public let markdownContent: String
public let baseVersionId: String?
public let revisionId: String?
public let updatedAt: Date

public init(
title: String,
markdownContent: String,
baseVersionId: String?,
revisionId: String? = nil,
updatedAt: Date
) {
self.title = title
self.markdownContent = markdownContent
self.baseVersionId = baseVersionId
self.revisionId = revisionId
self.updatedAt = updatedAt
}
}
Expand Down
10 changes: 8 additions & 2 deletions Application/Data/Sources/Mapper/DevelopmentRecordMapping.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@
import Domain

public extension DevelopmentRecordDraftRequest {
static func fromDomain(_ draft: DevelopmentRecord.Draft) -> Self {
static func fromDomain(
_ draft: DevelopmentRecord.Draft,
expectedRevisionId: String? = nil
) -> Self {
Self(
title: draft.title,
markdownContent: draft.markdownContent,
baseVersionId: draft.baseVersionId
baseVersionId: draft.baseVersionId,
revisionId: draft.revisionId,
expectedRevisionId: expectedRevisionId
)
}
}
Expand All @@ -23,6 +28,7 @@ public extension DevelopmentRecordDraftResponse {
title: title,
markdownContent: markdownContent,
baseVersionId: baseVersionId,
revisionId: revisionId,
updatedAt: updatedAt
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ public protocol DevelopmentRecordService {
) async throws -> DevelopmentRecordResponse
func fetchRecords(goalId: String) async throws -> [DevelopmentRecordResponse]
func fetchRecord(goalId: String, recordId: String) async throws -> DevelopmentRecordResponse
func fetchVersion(
goalId: String,
recordId: String,
versionId: String
) async throws -> DevelopmentRecordVersionResponse
func fetchVersions(
goalId: String,
recordId: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ final class DevelopmentRecordRepositoryImpl: DevelopmentRecordRepository {
}
}

func fetchVersion(
goalId: String,
recordId: String,
versionId: String
) async throws -> DevelopmentRecord.Version {
do {
return try await service.fetchVersion(
goalId: goalId,
recordId: recordId,
versionId: versionId
).toDomain()
} catch {
throw error.toDomain()
}
}

func fetchVersions(
goalId: String,
recordId: String
Expand All @@ -61,13 +77,14 @@ final class DevelopmentRecordRepositoryImpl: DevelopmentRecordRepository {
func saveDraft(
goalId: String,
recordId: String,
expectedRevisionId: String?,
draft: DevelopmentRecord.Draft
) async throws -> DevelopmentRecord {
do {
let response = try await service.saveDraft(
goalId: goalId,
recordId: recordId,
request: .fromDomain(draft)
request: .fromDomain(draft, expectedRevisionId: expectedRevisionId)
)
return try response.toDomain()
} catch {
Expand All @@ -80,7 +97,8 @@ final class DevelopmentRecordRepositoryImpl: DevelopmentRecordRepository {
recordId: String,
versionId: String,
kind: DevelopmentRecord.Version.Kind,
sourceVersionId: String?
sourceVersionId: String?,
draftRevisionId: String?
) async throws -> DevelopmentRecord.Version {
do {
let response = try await service.confirmDraft(
Expand All @@ -89,7 +107,8 @@ final class DevelopmentRecordRepositoryImpl: DevelopmentRecordRepository {
request: .init(
versionId: versionId,
kind: kind.storageValue,
sourceVersionId: sourceVersionId
sourceVersionId: sourceVersionId,
draftRevisionId: draftRevisionId
)
)
return try response.toDomain()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct DevelopmentRecordMappingTests {
title: "기록",
markdownContent: "본문",
baseVersionId: "version-1",
revisionId: "revision-1",
updatedAt: .distantPast
)

Expand All @@ -25,6 +26,7 @@ struct DevelopmentRecordMappingTests {
#expect(request.title == "기록")
#expect(request.markdownContent == "본문")
#expect(request.baseVersionId == "version-1")
#expect(request.revisionId == "revision-1")
}

@Test("저장 버전 종류는 Domain 종류로 변환한다")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,16 @@ struct DevelopmentRecordRepositoryImplTests {
recordId: "record-1",
versionId: "version-2",
kind: .correction,
sourceVersionId: "version-1"
sourceVersionId: "version-1",
draftRevisionId: "revision-1"
)

let request = try #require(await service.confirmationRequest())
#expect(version.kind == .correction)
#expect(request.versionId == "version-2")
#expect(request.kind == "correction")
#expect(request.sourceVersionId == "version-1")
#expect(request.draftRevisionId == "revision-1")
}
}

Expand Down Expand Up @@ -100,6 +102,14 @@ private actor DevelopmentRecordServiceSpy: DevelopmentRecordService {
[version]
}

func fetchVersion(
goalId: String,
recordId: String,
versionId: String
) async throws -> DevelopmentRecordVersionResponse {
version
}

func saveDraft(
goalId: String,
recordId: String,
Expand Down
6 changes: 6 additions & 0 deletions Application/Domain/Sources/Entity/DevelopmentRecord.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ public struct DevelopmentRecord: Hashable {
public let title: String
public let markdownContent: String
public let baseVersionId: String?
public let revisionId: String?
public let updatedAt: Date

public init(
title: String,
markdownContent: String,
baseVersionId: String?,
revisionId: String? = nil,
updatedAt: Date
) throws {
guard title.containsMeaningfulCharacter else {
Expand All @@ -26,10 +28,14 @@ public struct DevelopmentRecord: Hashable {
guard baseVersionId?.containsMeaningfulCharacter != false else {
throw DomainLayerError.invalidDevelopmentRecordVersion
}
guard revisionId?.containsMeaningfulCharacter != false else {
throw DomainLayerError.invalidDevelopmentRecordVersion
}

self.title = title
self.markdownContent = markdownContent
self.baseVersionId = baseVersionId
self.revisionId = revisionId
self.updatedAt = updatedAt
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,9 @@ public final class DevelopmentRecordQueryUseCaseGraph {
private func makeFetchDevelopmentRecordHistoryUseCase() -> FetchDevelopmentRecordHistoryUseCase {
FetchDevelopmentRecordHistoryUseCaseImpl(input.repository)
}

@Provide
private func makeFetchDevelopmentRecordVersionUseCase() -> FetchDevelopmentRecordVersionUseCase {
FetchDevelopmentRecordVersionUseCaseImpl(input.repository)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,25 @@ public protocol DevelopmentRecordRepository {
) async throws -> DevelopmentRecord
func fetchRecords(goalId: String) async throws -> [DevelopmentRecord]
func fetchRecord(goalId: String, recordId: String) async throws -> DevelopmentRecord
func fetchVersion(
goalId: String,
recordId: String,
versionId: String
) async throws -> DevelopmentRecord.Version
func fetchVersions(goalId: String, recordId: String) async throws -> [DevelopmentRecord.Version]
func saveDraft(
goalId: String,
recordId: String,
expectedRevisionId: String?,
draft: DevelopmentRecord.Draft
) async throws -> DevelopmentRecord
func confirmDraft(
goalId: String,
recordId: String,
versionId: String,
kind: DevelopmentRecord.Version.Kind,
sourceVersionId: String?
sourceVersionId: String?,
draftRevisionId: String?
) async throws -> DevelopmentRecord.Version
func restoreVersion(
goalId: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,11 @@
//

public protocol ConfirmDevelopmentRecordUseCase {
func execute(goalId: String, recordId: String) async throws -> DevelopmentRecord.Version
func execute(
goalId: String,
recordId: String,
versionId: String,
baseVersionId: String?,
draftRevisionId: String?
) async throws -> DevelopmentRecord.Version
Comment thread
opficdev marked this conversation as resolved.
}
Loading