AI DEV portal 초기 커밋
Express+EJS+Postgres 사내 개발 포털. - Keycloak OIDC(사번 로그인), GitHub 감성 UI - 사이트 모음 + 프로젝트 공유/코멘트/스타 - DB: OpenEverest appdb portal schema (portal_app role) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
17
views/_header.ejs
Normal file
17
views/_header.ejs
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title><%= brand %></title>
|
||||
<link rel="stylesheet" href="/public/style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<a class="brand" href="/"><span>🧠</span><%= brand %></a>
|
||||
<div class="spacer"></div>
|
||||
<% if (user) { %>
|
||||
<span class="who"><%= user.name %> (<%= user.sabun %>)</span>
|
||||
<a class="navlink" href="/logout">로그아웃</a>
|
||||
<% } %>
|
||||
</div>
|
||||
79
views/dashboard.ejs
Normal file
79
views/dashboard.ejs
Normal file
@@ -0,0 +1,79 @@
|
||||
<%- include("_header") %>
|
||||
<div class="container">
|
||||
<div class="layout">
|
||||
<!-- 메인: 사이트 모음 + 공유 프로젝트 -->
|
||||
<div>
|
||||
<div class="box">
|
||||
<div class="box-header">🔗 개발 사이트 바로가기</div>
|
||||
<div class="box-body">
|
||||
<% siteGroups.forEach(function(g){ %>
|
||||
<div class="group-title"><%= g.group %></div>
|
||||
<div class="site-grid">
|
||||
<% g.sites.forEach(function(s){ %>
|
||||
<a class="site-card" href="<%= s.url %>" target="_blank" rel="noopener">
|
||||
<span class="ico"><%= s.icon %></span>
|
||||
<span>
|
||||
<span class="name"><%= s.name %></span><br/>
|
||||
<span class="desc"><%= s.desc %></span>
|
||||
</span>
|
||||
</a>
|
||||
<% }); %>
|
||||
</div>
|
||||
<% }); %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box" style="margin-top:24px">
|
||||
<div class="box-header">📂 공유 프로젝트</div>
|
||||
<% if (projects.length === 0) { %>
|
||||
<div class="box-body muted">아직 공유된 프로젝트가 없습니다. 오른쪽에서 추가해 보세요.</div>
|
||||
<% } else { %>
|
||||
<% projects.forEach(function(p){ %>
|
||||
<div class="proj-item">
|
||||
<a class="proj-title" href="/projects/<%= p.id %>"><%= p.title %></a>
|
||||
<div class="proj-meta">
|
||||
<%= p.owner_name %> · <%= new Date(p.updated_at).toLocaleDateString("ko-KR") %>
|
||||
<span class="counter">⭐ <%= p.star_count %></span>
|
||||
<span class="counter">💬 <%= p.comment_count %></span>
|
||||
</div>
|
||||
<% if (p.description) { %><div class="muted" style="margin-top:6px"><%= p.description %></div><% } %>
|
||||
<% if (p.tags) { %>
|
||||
<div style="margin-top:8px">
|
||||
<% p.tags.split(",").map(t=>t.trim()).filter(Boolean).forEach(function(t){ %>
|
||||
<span class="tag"><%= t %></span>
|
||||
<% }); %>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<% }); %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 사이드바: 프로젝트 공유 폼 -->
|
||||
<div>
|
||||
<div class="box">
|
||||
<div class="box-header">➕ 프로젝트 공유</div>
|
||||
<div class="box-body">
|
||||
<form method="post" action="/projects">
|
||||
<label>제목 *</label>
|
||||
<input type="text" name="title" required placeholder="내 앱 이름" />
|
||||
<label>설명</label>
|
||||
<textarea name="description" placeholder="무엇을 만들었나요?"></textarea>
|
||||
<label>Repo URL</label>
|
||||
<input type="url" name="repo_url" placeholder="https://gitea.bokdev.in/..." />
|
||||
<label>앱 URL</label>
|
||||
<input type="url" name="app_url" placeholder="https://....apps.bokdev.in" />
|
||||
<label>태그 (콤마 구분)</label>
|
||||
<input type="text" name="tags" placeholder="node, ai" />
|
||||
<div style="margin-top:16px">
|
||||
<button class="btn btn-primary" style="width:100%" type="submit">공유하기</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
14
views/login.ejs
Normal file
14
views/login.ejs
Normal file
@@ -0,0 +1,14 @@
|
||||
<%- include("_header") %>
|
||||
<div class="login-wrap">
|
||||
<div class="box login-card">
|
||||
<div class="login-logo">🧠</div>
|
||||
<div class="login-title"><%= brand %></div>
|
||||
<% if (typeof error !== "undefined" && error) { %>
|
||||
<div class="alert"><%= error %></div>
|
||||
<% } %>
|
||||
<a class="btn btn-primary" style="width:100%" href="/auth/login">Keycloak 으로 로그인</a>
|
||||
<p class="muted" style="margin-top:16px">사번으로 로그인합니다. (사내 SSO)</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
46
views/project.ejs
Normal file
46
views/project.ejs
Normal file
@@ -0,0 +1,46 @@
|
||||
<%- include("_header") %>
|
||||
<div class="container" style="max-width:760px">
|
||||
<a href="/" class="muted">← 대시보드</a>
|
||||
<div class="box" style="margin-top:12px">
|
||||
<div class="box-body">
|
||||
<h2 style="margin:0 0 4px"><%= project.title %></h2>
|
||||
<div class="proj-meta"><%= project.owner_name %> 님이 공유 · <%= new Date(project.created_at).toLocaleDateString("ko-KR") %></div>
|
||||
<% if (project.description) { %><p style="margin-top:12px; white-space:pre-wrap"><%= project.description %></p><% } %>
|
||||
<div style="margin-top:12px; display:flex; gap:8px; align-items:center; flex-wrap:wrap">
|
||||
<% if (project.repo_url) { %><a class="btn btn-sm" href="<%= project.repo_url %>" target="_blank">🍵 Repo</a><% } %>
|
||||
<% if (project.app_url) { %><a class="btn btn-sm" href="<%= project.app_url %>" target="_blank">🚀 앱 열기</a><% } %>
|
||||
<form method="post" action="/projects/<%= project.id %>/star" style="display:inline">
|
||||
<button class="btn btn-sm" type="submit"><%= starred ? "★ 스타 취소" : "☆ 스타" %> (<%= project.star_count %>)</button>
|
||||
</form>
|
||||
</div>
|
||||
<% if (project.tags) { %>
|
||||
<div style="margin-top:12px">
|
||||
<% project.tags.split(",").map(t=>t.trim()).filter(Boolean).forEach(function(t){ %>
|
||||
<span class="tag"><%= t %></span>
|
||||
<% }); %>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 style="margin:24px 0 12px">💬 코멘트 (<%= comments.length %>)</h3>
|
||||
<% comments.forEach(function(c){ %>
|
||||
<div class="comment">
|
||||
<div class="comment-head"><strong><%= c.author_name %></strong> · <%= new Date(c.created_at).toLocaleString("ko-KR") %></div>
|
||||
<div class="comment-body"><%= c.body %></div>
|
||||
</div>
|
||||
<% }); %>
|
||||
|
||||
<div class="box" style="margin-top:16px">
|
||||
<div class="box-body">
|
||||
<form method="post" action="/projects/<%= project.id %>/comments">
|
||||
<textarea name="body" placeholder="코멘트를 남겨보세요" required></textarea>
|
||||
<div style="margin-top:8px; text-align:right">
|
||||
<button class="btn btn-primary" type="submit">코멘트 등록</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user