feat(projects): 등록한 프로젝트 수정 기능 추가
- 상세(모달/단독) 소유자 영역에 '수정' 버튼 → 등록 모달을 현재 값으로 채워 재사용 - POST /projects/:id/edit 라우트 + db.updateProject(소유자 조건으로 타인 수정 차단) - 등록/수정 공용 모달을 _project_form_modal.ejs 로 추출(dashboard·project 에서 include) - pencil 아이콘 추가, modals.js 에 openEdit/openShare 초기화 로직 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -72,6 +72,16 @@
|
||||
<% } %>
|
||||
<% if (p.owner_sabun === me) { %>
|
||||
<div class="modal-actions-owner">
|
||||
<button type="button" class="comment-link" data-open-edit style="font-size:12.5px"
|
||||
data-id="<%= p.id %>"
|
||||
data-title="<%= p.title %>"
|
||||
data-desc="<%= p.description || '' %>"
|
||||
data-tags="<%= p.tags || '' %>"
|
||||
data-repo="<%= p.repo_url || '' %>"
|
||||
data-app="<%= p.app_url || '' %>"
|
||||
data-lang="<%= p.lang || '' %>"
|
||||
data-public="<%= p.is_public ? '1' : '0' %>"
|
||||
data-return="<%= returnTo %>"><%- icon("pencil", { size: 13 }) %>수정</button>
|
||||
<form method="post" action="/projects/<%= p.id %>/delete">
|
||||
<input type="hidden" name="return_to" value="/" />
|
||||
<button type="submit" class="comment-link comment-del" data-confirm="이 프로젝트를 삭제할까요? 댓글·반응도 함께 삭제됩니다." style="font-size:12.5px"><%- icon("trash", { size: 13 }) %>프로젝트 삭제</button>
|
||||
|
||||
66
views/_project_form_modal.ejs
Normal file
66
views/_project_form_modal.ejs
Normal file
@@ -0,0 +1,66 @@
|
||||
<%
|
||||
// 프로젝트 등록/수정 공용 모달. 기본은 '등록'(action=/projects)이고,
|
||||
// 상세의 '수정' 버튼을 누르면 modals.js 가 필드/제목/버튼/action 을 수정 모드로 바꿔 연다.
|
||||
%>
|
||||
<div class="modal-overlay" id="shareModal" hidden>
|
||||
<div class="share-modal">
|
||||
<div class="share-head">
|
||||
<h3 id="shareTitle">새 프로젝트 등록</h3>
|
||||
<button type="button" class="modal-close" data-close-share title="닫기"><%- icon("x", { size: 16 }) %></button>
|
||||
</div>
|
||||
<form method="post" action="/projects">
|
||||
<input type="hidden" name="return_to" value="" />
|
||||
<div class="share-body">
|
||||
<label>
|
||||
<span class="share-label">제목 <span class="req">*</span></span>
|
||||
<input class="share-input" name="title" required placeholder="예) 방화벽 정책 DSL 변환기" />
|
||||
</label>
|
||||
<label>
|
||||
<span class="share-label share-label-row">
|
||||
<span>설명 <span class="hint">Markdown 지원 · 제목·목록·코드·링크</span></span>
|
||||
<button type="button" class="readme-btn" id="readmeImport"><%- icon("repo", { size: 12 }) %>저장소 README 가져오기</button>
|
||||
</span>
|
||||
<textarea class="share-input share-textarea" name="description" rows="5" placeholder="무엇을 하는 프로젝트인가요? ## 예시 - Markdown 문법을 그대로 쓸 수 있어요 - 저장소 URL 을 넣으면 README 를 가져올 수 있어요"></textarea>
|
||||
</label>
|
||||
<label>
|
||||
<span class="share-label">태그 <span class="hint">쉼표로 구분 · 최대 5개</span></span>
|
||||
<input class="share-input" name="tags" placeholder="infra, react, poc" />
|
||||
</label>
|
||||
<label>
|
||||
<span class="share-label">저장소 URL <span class="hint">선택</span></span>
|
||||
<input class="share-input mono" name="repo_url" placeholder="https://gitea.bokdev.in/사번/repo" />
|
||||
</label>
|
||||
<label>
|
||||
<span class="share-label">메인 언어 <span class="hint">선택 · 기본은 저장소에서 자동 감지</span></span>
|
||||
<select class="share-input" name="lang">
|
||||
<option value="">자동 감지</option>
|
||||
<option value="Python">Python</option>
|
||||
<option value="JavaScript">JavaScript</option>
|
||||
<option value="TypeScript">TypeScript</option>
|
||||
<option value="Go">Go</option>
|
||||
<option value="Java">Java</option>
|
||||
<option value="Rust">Rust</option>
|
||||
<option value="Shell">Shell</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span class="share-label">배포 URL <span class="hint">선택 · 없으면 바로가기 숨김</span></span>
|
||||
<input class="share-input mono" name="app_url" placeholder="https://myapp.apps.bokdev.in" />
|
||||
</label>
|
||||
<div>
|
||||
<span class="share-label">공개 범위</span>
|
||||
<div class="vis-toggle">
|
||||
<button type="button" class="vis-opt on-public" data-vis="public"><%- icon("globe", { size: 12 }) %>공개</button>
|
||||
<button type="button" class="vis-opt" data-vis="private"><%- icon("lock", { size: 12 }) %>비공개</button>
|
||||
</div>
|
||||
<input type="hidden" name="is_public" value="1" />
|
||||
<div class="share-vishint">피드에 공개되어 동료가 볼 수 있어요</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-foot-actions">
|
||||
<button type="button" class="btn" data-close-share>취소</button>
|
||||
<button type="submit" class="btn btn-success" id="shareSubmit">등록</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -196,68 +196,8 @@
|
||||
<% }); %>
|
||||
</div>
|
||||
|
||||
<!-- 새 프로젝트 등록 모달 -->
|
||||
<div class="modal-overlay" id="shareModal" hidden>
|
||||
<div class="share-modal">
|
||||
<div class="share-head">
|
||||
<h3>새 프로젝트 등록</h3>
|
||||
<button type="button" class="modal-close" data-close-share title="닫기"><%- icon("x", { size: 16 }) %></button>
|
||||
</div>
|
||||
<form method="post" action="/projects">
|
||||
<div class="share-body">
|
||||
<label>
|
||||
<span class="share-label">제목 <span class="req">*</span></span>
|
||||
<input class="share-input" name="title" required placeholder="예) 방화벽 정책 DSL 변환기" />
|
||||
</label>
|
||||
<label>
|
||||
<span class="share-label share-label-row">
|
||||
<span>설명 <span class="hint">Markdown 지원 · 제목·목록·코드·링크</span></span>
|
||||
<button type="button" class="readme-btn" id="readmeImport"><%- icon("repo", { size: 12 }) %>저장소 README 가져오기</button>
|
||||
</span>
|
||||
<textarea class="share-input share-textarea" name="description" rows="5" placeholder="무엇을 하는 프로젝트인가요? ## 예시 - Markdown 문법을 그대로 쓸 수 있어요 - 저장소 URL 을 넣으면 README 를 가져올 수 있어요"></textarea>
|
||||
</label>
|
||||
<label>
|
||||
<span class="share-label">태그 <span class="hint">쉼표로 구분 · 최대 5개</span></span>
|
||||
<input class="share-input" name="tags" placeholder="infra, react, poc" />
|
||||
</label>
|
||||
<label>
|
||||
<span class="share-label">저장소 URL <span class="hint">선택</span></span>
|
||||
<input class="share-input mono" name="repo_url" placeholder="https://gitea.bokdev.in/사번/repo" />
|
||||
</label>
|
||||
<label>
|
||||
<span class="share-label">메인 언어 <span class="hint">선택 · 기본은 저장소에서 자동 감지</span></span>
|
||||
<select class="share-input" name="lang">
|
||||
<option value="">자동 감지</option>
|
||||
<option value="Python">Python</option>
|
||||
<option value="JavaScript">JavaScript</option>
|
||||
<option value="TypeScript">TypeScript</option>
|
||||
<option value="Go">Go</option>
|
||||
<option value="Java">Java</option>
|
||||
<option value="Rust">Rust</option>
|
||||
<option value="Shell">Shell</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span class="share-label">배포 URL <span class="hint">선택 · 없으면 바로가기 숨김</span></span>
|
||||
<input class="share-input mono" name="app_url" placeholder="https://myapp.apps.bokdev.in" />
|
||||
</label>
|
||||
<div>
|
||||
<span class="share-label">공개 범위</span>
|
||||
<div class="vis-toggle">
|
||||
<button type="button" class="vis-opt on-public" data-vis="public"><%- icon("globe", { size: 12 }) %>공개</button>
|
||||
<button type="button" class="vis-opt" data-vis="private"><%- icon("lock", { size: 12 }) %>비공개</button>
|
||||
</div>
|
||||
<input type="hidden" name="is_public" value="1" />
|
||||
<div class="share-vishint">피드에 공개되어 동료가 볼 수 있어요</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-foot-actions">
|
||||
<button type="button" class="btn" data-close-share>취소</button>
|
||||
<button type="submit" class="btn btn-success">등록</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 새 프로젝트 등록/수정 공용 모달 -->
|
||||
<%- include("_project_form_modal") %>
|
||||
|
||||
<script type="module" src="/public/js/main.js"></script>
|
||||
</body>
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- 프로젝트 수정 모달 (상세의 '수정' 버튼이 채워서 연다) -->
|
||||
<%- include("_project_form_modal") %>
|
||||
|
||||
<script type="module" src="/public/js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user