feat: 작업실 개요를 파일 폴더 대신 개요 탭으로 + /api/files 텍스트 charset 수정
- workshop-app: 메모 탭과 동일 구조의 "개요" 탭(textarea) 추가 — project.description 직접 편집, 채팅 set_description으로 쓴 내용은 응답 후 softRefresh로 갱신 - readme.md 자동생성(syncProjectReadmes) 철회 — 파일탭이 산만해져서 사용자 지정으로 탭 방식으로 전환, 생성된 개요 폴더들도 삭제. description/set_description은 유지 - server.ts IMAGE_TYPES: 텍스트 계열(.md/.txt/.csv 등) charset=utf-8 명시 — charset 없이 text/plain으로 뱉으면 브라우저가 latin1로 해석해 한글이 전부 깨짐(실측) Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -218,6 +218,7 @@ body{background:var(--bg);color:var(--text);font-family:system-ui,sans-serif;dis
|
||||
<button class="rb-tab-btn" data-tab="tasks" onclick="switchTab('tasks')">작업</button>
|
||||
<button class="rb-tab-btn" data-tab="equip" onclick="switchTab('equip')">장비</button>
|
||||
<button class="rb-tab-btn" data-tab="files" onclick="switchTab('files')">파일</button>
|
||||
<button class="rb-tab-btn" data-tab="overview" onclick="switchTab('overview')">개요</button>
|
||||
<button class="rb-tab-btn" data-tab="notes" onclick="switchTab('notes')">메모</button>
|
||||
</div>
|
||||
|
||||
@@ -266,6 +267,10 @@ body{background:var(--bg);color:var(--text);font-family:system-ui,sans-serif;dis
|
||||
<div id="files-list-container"></div>
|
||||
</div>
|
||||
|
||||
<div class="rb-pane" id="pane-overview">
|
||||
<textarea class="rb-notes" id="overview-textarea" placeholder="프로젝트 개요 — 무엇을 만드는지/목표/구성. 채팅에서 '개요 써줘'로도 쓸 수 있다." oninput="onOverviewChange()"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="rb-pane" id="pane-notes">
|
||||
<textarea class="rb-notes" id="notes-textarea" placeholder="자유 메모..." oninput="onNotesChange()"></textarea>
|
||||
</div>
|
||||
@@ -323,6 +328,7 @@ let workshopData={projects:[],activeProjectId:''};
|
||||
let parts=[];
|
||||
let phases=[];
|
||||
let notes='';
|
||||
let overviewDesc='';
|
||||
let saveTimer=null;
|
||||
let saveDebounce=null;
|
||||
|
||||
@@ -347,6 +353,7 @@ function loadLocalFromProject(){
|
||||
parts=proj?(proj.parts||[]):[];
|
||||
phases=proj?(proj.phases||[]):[];
|
||||
notes=proj?(proj.notes||''):'';
|
||||
overviewDesc=proj?(proj.description||''):'';
|
||||
}
|
||||
|
||||
function syncLocalToProject(){
|
||||
@@ -355,6 +362,7 @@ function syncLocalToProject(){
|
||||
proj.parts=parts;
|
||||
proj.phases=phases;
|
||||
proj.notes=notes;
|
||||
proj.description=overviewDesc;
|
||||
}
|
||||
|
||||
function renderProjectSelector(){
|
||||
@@ -371,6 +379,7 @@ function refreshAllPanes(){
|
||||
renderParts();
|
||||
renderPhases();
|
||||
document.getElementById('notes-textarea').value=notes;
|
||||
document.getElementById('overview-textarea').value=overviewDesc;
|
||||
updateBudget();
|
||||
}
|
||||
|
||||
@@ -389,7 +398,7 @@ function createProjectPrompt(){
|
||||
const name=(prompt('새 프로젝트 이름을 입력하세요:')||'').trim();
|
||||
if(!name)return;
|
||||
const id=genId('proj');
|
||||
workshopData.projects.push({id,name,parts:[],phases:[],notes:''});
|
||||
workshopData.projects.push({id,name,parts:[],phases:[],notes:'',description:''});
|
||||
workshopData.activeProjectId=id;
|
||||
loadLocalFromProject();
|
||||
clearStlSelection();
|
||||
@@ -425,7 +434,7 @@ async function loadWorkshopData(){
|
||||
}catch{}
|
||||
if(!workshopData.projects.length){
|
||||
const id=genId('proj');
|
||||
workshopData.projects=[{id,name:'새 프로젝트',parts:[],phases:[],notes:''}];
|
||||
workshopData.projects=[{id,name:'새 프로젝트',parts:[],phases:[],notes:'',description:''}];
|
||||
workshopData.activeProjectId=id;
|
||||
}
|
||||
loadLocalFromProject();
|
||||
@@ -461,6 +470,8 @@ async function softRefreshWorkshop(){
|
||||
renderPhases();
|
||||
const ta=document.getElementById('notes-textarea');
|
||||
if(ta&&ta.value!==notes)ta.value=notes;
|
||||
const ota=document.getElementById('overview-textarea');
|
||||
if(ota&&ota.value!==overviewDesc)ota.value=overviewDesc;
|
||||
updateBudget();
|
||||
}catch{}
|
||||
}
|
||||
@@ -1052,6 +1063,14 @@ function onNotesChange(){
|
||||
scheduleSave();
|
||||
}
|
||||
|
||||
// ── 개요 ──────────────────────────────────────────────────────────────────────
|
||||
// 메모 탭과 같은 구조 — 프로젝트 서술형 설명(description). 채팅 도구 set_description
|
||||
// 으로도 쓸 수 있고, 채팅 응답 후 softRefreshWorkshop이 갱신해준다.
|
||||
function onOverviewChange(){
|
||||
overviewDesc=document.getElementById('overview-textarea').value;
|
||||
scheduleSave();
|
||||
}
|
||||
|
||||
// ── 채팅 패널 ─────────────────────────────────────────────────────────────────
|
||||
// 세션ID를 프로젝트별로 분리한다("ws_" 접두어는 유지 — tool-scope.ts가 이 세션에서는
|
||||
// 키워드 없이도 workshop_project 도구를 항상 열어주고, 메인 사이드바 목록에서도 걸러진다).
|
||||
|
||||
Reference in New Issue
Block a user