feat(B03): 선택 영역 설명 이관 · 임시 보관함 이름·테두리 정리 · 계획노선은 shapefile만

사용자 지시 4건(2026-09-03).

- 선택 영역의 설명 문구를 좌측 안내 패널로 옮기고 본문에는 「입력 파일 선택」만 남김.
- [임시 보관함에서 불러오기] → [임시 보관함]. 버튼을 감싸던 점선 테두리 삭제 —
  버튼 자신의 테두리와 이중이었음.
- 계획노선 도형 카드는 `.shp` 만 받음. CSV 는 내부 계산이 만드는 파일이라 사용자가 넣는
  자료가 아님(사용자 확인). 컨테이너의 CSV 안내 문구도 삭제.
- 이미 `.csv` 로 올라간 옛 프로젝트가 「미등록」으로 보이지 않도록 **서버 파일 매핑에만**
  `.csv → 계획노선 도형` 예외를 둠. 새로 받는 확장자와 이미 받은 것을 갈라 둔다.

좌측 안내 문구도 함께 갱신 — CSV 언급 제거, 버튼 새 이름 반영.

검증: 실측 — 선택 영역 텍스트 「입력 파일 선택」, 보관함 테두리 none·라벨 「임시 보관함」,
계획노선 안내 문구 없음, 카드 확장자 `.shp`, 옛 CSV 는 「완료 · 용화_계획노선.csv」 유지.
typecheck·prettier 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-03 21:02:19 +09:00
co-authored by Claude Opus 5
parent b0fa00f335
commit 7c3a65e814
4 changed files with 22 additions and 29 deletions
+8 -4
View File
@@ -95,9 +95,8 @@ export async function renderB03FileInput(root: HTMLElement): Promise<void> {
dropzone.tabIndex = 0; dropzone.tabIndex = 0;
const dropzoneLabel = document.createElement("strong"); const dropzoneLabel = document.createElement("strong");
dropzoneLabel.textContent = L("B03_File_Select_Label"); dropzoneLabel.textContent = L("B03_File_Select_Label");
const dropzoneHint = document.createElement("span"); // 설명은 좌측 안내 패널 몫이다(2026-09-03 사용자 지시) — 여기는 자리 이름만 남긴다.
dropzoneHint.textContent = L("B03_File_Select_Hint"); dropzone.append(dropzoneLabel, fileInput);
dropzone.append(dropzoneLabel, dropzoneHint, fileInput);
const pageError = document.createElement("p"); const pageError = document.createElement("p");
pageError.className = "b03-file__error"; pageError.className = "b03-file__error";
@@ -435,6 +434,10 @@ export async function renderB03FileInput(root: HTMLElement): Promise<void> {
? inRouteSet ? inRouteSet
? "route_prj" ? "route_prj"
: "prj" : "prj"
: // 옛 프로젝트의 노선은 `.csv`로 올라가 있다 — 이제 받지는 않지만(2026-09-03)
// 이미 올라간 것은 계획노선 도형 카드에 그대로 보여야 한다.
extension === ".csv"
? "csv"
: Array.from(slots.values()).find( : Array.from(slots.values()).find(
(candidate) => (candidate) =>
candidate.slot !== "route_prj" && candidate.extensions.includes(extension), candidate.slot !== "route_prj" && candidate.extensions.includes(extension),
@@ -752,11 +755,12 @@ export async function renderB03FileInput(root: HTMLElement): Promise<void> {
// 자료의 출처가 둘로 갈린다 — 원청이 준 계획노선, 측량이 준 지형(LAS·래스터). // 자료의 출처가 둘로 갈린다 — 원청이 준 계획노선, 측량이 준 지형(LAS·래스터).
// 좌표계 파일(.prj)도 각각 하나씩 오므로 컨테이너를 나눠야 어느 칸에 무엇을 넣는지 // 좌표계 파일(.prj)도 각각 하나씩 오므로 컨테이너를 나눠야 어느 칸에 무엇을 넣는지
// 화면만 보고 안다(2026-08-31 사용자 지시). // 화면만 보고 안다(2026-08-31 사용자 지시).
// 안내 문구 없음 — CSV 관련 설명이 붙어 있었으나 CSV는 사용자가 넣는 자료가 아니다
// (2026-09-03 사용자 지시: 내부 계산 파일).
const routeGroup = createCardGroup( const routeGroup = createCardGroup(
L("B03_File_Group_Route"), L("B03_File_Group_Route"),
ROUTE_SLOTS, ROUTE_SLOTS,
"b03-file__group--route", "b03-file__group--route",
L("B03_File_Group_Route_Hint"),
); );
const terrainGroup = createCardGroup( const terrainGroup = createCardGroup(
L("B03_File_Group_Terrain"), L("B03_File_Group_Terrain"),
@@ -4,14 +4,11 @@
* 모달 껍데기(.b03-file__modal / -backdrop)는 기존 확인 모달 스타일을 그대로 쓴다. * 모달 껍데기(.b03-file__modal / -backdrop)는 기존 확인 모달 스타일을 그대로 쓴다.
* ========================================================================== */ * ========================================================================== */
/* 버튼 하나만 담는 자리 — 테두리를 또 두르면 버튼 테두리와 이중이 된다
(2026-09-03 사용자 지시). */
.b03-file__temp-picker { .b03-file__temp-picker {
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--spacing-12);
flex-wrap: wrap;
padding: var(--spacing-12);
border: 1px dashed var(--color-border);
border-radius: var(--radius-cards);
} }
.b03-file__temp-modal { .b03-file__temp-modal {
+3 -1
View File
@@ -60,7 +60,9 @@ const SLOT_CONFIGS: readonly SlotConfig[] = [
slot: "csv", slot: "csv",
labelKey: "B03_File_Slot_PlannedRoute", labelKey: "B03_File_Slot_PlannedRoute",
icon: "⌁", icon: "⌁",
extensions: [".csv", ".shp"], // `.csv`는 받지 않는다 — 내부 계산이 만드는 파일이라 사용자가 넣는 자료가 아니다
// (2026-09-03 사용자 지시). 슬롯 키 `csv`는 저장·서버 규약이라 그대로 둔다.
extensions: [".shp"],
isRequired: true, isRequired: true,
}, },
{ {
+5 -15
View File
@@ -224,17 +224,11 @@ export const ui_locales_b1 = {
"Upload the required planned route, terrain, and point cloud files.", "Upload the required planned route, terrain, and point cloud files.",
], ],
B03_File_Select_Label: ["입력 파일 선택", "Select input files"], B03_File_Select_Label: ["입력 파일 선택", "Select input files"],
/* 긴 설명은 좌측 안내 패널(B03_Guide_*)로 옮겼다 — 선택 영역은 한 줄만 남긴다
(2026-09-03 사용자 지시). */
B03_File_Select_Hint: [
"끌어 놓거나 눌러서 고르면 확장자대로 카드에 나뉩니다.",
"Drop files here or click to pick — they are sorted into cards by extension.",
],
/* --- 좌측 안내 패널 (2026-09-03) --- */ /* --- 좌측 안내 패널 (2026-09-03) --- */
B03_Guide_Files_Title: ["필요한 파일", "Files you need"], B03_Guide_Files_Title: ["필요한 파일", "Files you need"],
B03_Guide_Files_Route: [ B03_Guide_Files_Route: [
"계획노선 — CSV 한 장, 또는 shapefile 한 벌(.shp·.shx·.dbf·.cpg·.prj) 5개.", "계획노선 — shapefile 한 벌(.shp·.shx·.dbf·.cpg·.prj) 5개.",
"Planned route — one CSV, or the five shapefile parts (.shp, .shx, .dbf, .cpg, .prj).", "Planned route — the five shapefile parts (.shp, .shx, .dbf, .cpg, .prj).",
], ],
B03_Guide_Files_Terrain: [ B03_Guide_Files_Terrain: [
"지형 — 포인트클라우드 LAS/LAZ 1개와 좌표계 PRJ, 래스터 기준 TFW.", "지형 — 포인트클라우드 LAS/LAZ 1개와 좌표계 PRJ, 래스터 기준 TFW.",
@@ -254,8 +248,8 @@ export const ui_locales_b1 = {
"Use a card's [Select] to set one slot, or ✕ to clear it.", "Use a card's [Select] to set one slot, or ✕ to clear it.",
], ],
B03_Guide_How_Temp: [ B03_Guide_How_Temp: [
"[임시 보관함에서 불러오기]는 대시보드에 미리 올려 둔 자료를 가져옵니다.", "[임시 보관함]은 대시보드에 미리 올려 둔 자료를 가져옵니다.",
"[Load from temporary storage] pulls files you staged on the dashboard.", "[Temporary storage] pulls files you staged on the dashboard.",
], ],
B03_Guide_Notes_Title: ["알아 둘 것", "Before you upload"], B03_Guide_Notes_Title: ["알아 둘 것", "Before you upload"],
B03_Guide_Notes_Replace: [ B03_Guide_Notes_Replace: [
@@ -310,10 +304,6 @@ export const ui_locales_b1 = {
B03_File_Group_Inputs: ["입력 자료", "Input files"], B03_File_Group_Inputs: ["입력 자료", "Input files"],
B03_File_Group_Route: ["계획노선 자료", "Planned route files"], B03_File_Group_Route: ["계획노선 자료", "Planned route files"],
B03_File_Group_Terrain: ["지형 자료 (LAS)", "Terrain files (LAS)"], B03_File_Group_Terrain: ["지형 자료 (LAS)", "Terrain files (LAS)"],
B03_File_Group_Route_Hint: [
"shapefile은 파일 5개가 한 벌입니다. CSV 한 장으로 넣어도 됩니다.",
"A shapefile is a set of five files. A single CSV also works.",
],
B03_File_Group_Terrain_Hint: [ B03_File_Group_Terrain_Hint: [
"여기의 PRJ·TFW는 지형 자료의 좌표계입니다 — 노선 PRJ와 별개입니다.", "여기의 PRJ·TFW는 지형 자료의 좌표계입니다 — 노선 PRJ와 별개입니다.",
"The PRJ and TFW here describe the terrain data, separate from the route PRJ.", "The PRJ and TFW here describe the terrain data, separate from the route PRJ.",
@@ -337,7 +327,7 @@ export const ui_locales_b1 = {
B03_File_Slot_TerrainDem: ["지형 래스터", "Terrain DEM"], B03_File_Slot_TerrainDem: ["지형 래스터", "Terrain DEM"],
B03_File_Slot_CadDrawing: ["CAD 도면", "CAD Drawing"], B03_File_Slot_CadDrawing: ["CAD 도면", "CAD Drawing"],
/* --- B03 임시 보관함 불러오기 (2026-08-08) --- */ /* --- B03 임시 보관함 불러오기 (2026-08-08) --- */
B03_Temp_Btn_Open: ["임시 보관함에서 불러오기", "Load from temporary storage"], B03_Temp_Btn_Open: ["임시 보관함", "Temporary storage"],
B03_Temp_FileCount: ["개 파일", " files"], B03_Temp_FileCount: ["개 파일", " files"],
B03_Temp_Modal_Title: ["보관 자료 선택", "Select stored files"], B03_Temp_Modal_Title: ["보관 자료 선택", "Select stored files"],
B03_Temp_Modal_Empty: [ B03_Temp_Modal_Empty: [