feat(B01,B03): 프로젝트 생성 전 임시 보관함 (temp upload)
라이다 원본은 업로드에 오래 걸려 프로젝트 정보 확정 전에 미리 올릴 수 있어야 한다.
계정에 묶인 임시 보관함을 만들고, 나중에 만든 프로젝트로 자료를 옮겨 쓴다.
저장·DB
- storage/tmp/{user_id}/{batch_id}/ 아래에 프로젝트 저장소와 동일한 구조를 써서
청크 저장·병합 엔진(resolve_upload_destination/merge_upload_chunks)을 그대로 재사용
- 010_temp_upload.sql: temp_upload_batches / temp_upload_files 신설,
upload_sessions.project_id NULL 허용 + temp_batch_id 추가(FK명 조회 후 재생성)
- config: TEMP_UPLOAD_DIR_NAME / TEMP_UPLOAD_RETENTION_DAYS(30) /
TEMP_UPLOAD_CLEANUP_INTERVAL_HOURS(6)
백엔드
- B03_FileInput_Router_Temp.py: 묶음 생성·목록·삭제, 일반/청크 업로드, finalize,
이어올리기 상태 조회, 프로젝트 연결(attach)
- attach: 파일 이동 후 input_files 등록, stage 0 완료, WF1·자동 설계 체인 트리거
- common_util_temp_cleanup.py: 완료 시각 기준 만료분 주기 삭제(서버 시작 시 1회 포함)
프론트엔드
- B01 대시보드 임시 보관함 섹션: 프로젝트 등록과 같은 폼 + 보관 목록.
진행률은 모달이 아니라 리스트 행에 표시, 새로고침 후 이어올리기 지원
- B03 업로드 컨테이너 내부 불러오기 버튼과 선택 모달.
완료된 묶음만 노출하고, 선택 후 업로드를 누르면 이동과 분석으로 이어짐
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
/* =============================================================================
|
||||
* B01_Dashboard_UI_Style_Temp.css
|
||||
* 임시 보관함 섹션 — 등록 폼 + 보관 목록(행에 진행률 표시)
|
||||
* 색·간격은 theme.css 변수만 사용한다.
|
||||
* ========================================================================== */
|
||||
|
||||
.b01-temp__form {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr auto;
|
||||
gap: var(--spacing-16);
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.b01-temp__field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-8);
|
||||
font-size: 13px;
|
||||
color: var(--color-muted-text, var(--color-primary-text));
|
||||
}
|
||||
|
||||
.b01-temp__field input {
|
||||
padding: var(--spacing-8);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-cards);
|
||||
background: var(--color-paper);
|
||||
color: var(--color-primary-text);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.b01-temp__hint {
|
||||
margin: var(--spacing-8) 0 var(--spacing-16);
|
||||
font-size: 12px;
|
||||
color: var(--color-muted-text, var(--color-primary-text));
|
||||
}
|
||||
|
||||
.b01-temp__empty {
|
||||
padding: var(--spacing-16);
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
color: var(--color-muted-text, var(--color-primary-text));
|
||||
}
|
||||
|
||||
.b01-temp__list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-8);
|
||||
}
|
||||
|
||||
.b01-temp__row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-8);
|
||||
padding: var(--spacing-16);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-cards);
|
||||
background: var(--color-paper);
|
||||
}
|
||||
|
||||
/* 프로젝트로 옮긴 묶음은 이력이라 흐리게 — 목록에서 현재 쓸 수 있는 자료와 구분한다. */
|
||||
.b01-temp__row.is-linked {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.b01-temp__row-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: var(--spacing-8);
|
||||
}
|
||||
|
||||
.b01-temp__badge {
|
||||
padding: 2px var(--spacing-8);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-cards);
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.b01-temp__row.is-completed .b01-temp__badge {
|
||||
border-color: var(--color-success);
|
||||
color: var(--color-success);
|
||||
}
|
||||
|
||||
.b01-temp__row.is-uploading .b01-temp__badge {
|
||||
border-color: var(--color-warning);
|
||||
color: var(--color-warning);
|
||||
}
|
||||
|
||||
.b01-temp__row-meta {
|
||||
font-size: 12px;
|
||||
color: var(--color-muted-text, var(--color-primary-text));
|
||||
}
|
||||
|
||||
.b01-temp__files {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--spacing-8);
|
||||
}
|
||||
|
||||
.b01-temp__chip {
|
||||
padding: 2px var(--spacing-8);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-cards);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
/* 업로드 진행률은 모달이 아니라 이 행 안에서 보여 준다(2026-08-08 사용자 지시). */
|
||||
.b01-temp__progress {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
width: 100%;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.b01-temp__progress-bar {
|
||||
height: 6px;
|
||||
border-radius: 3px;
|
||||
background: var(--color-canvas);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.b01-temp__progress-bar > div {
|
||||
height: 100%;
|
||||
background: var(--color-primary);
|
||||
transition: width 0.2s ease;
|
||||
}
|
||||
|
||||
.b01-temp__row-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: var(--spacing-8);
|
||||
}
|
||||
|
||||
@media (max-width: 860px) {
|
||||
.b01-temp__form {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user