Files
dbx-main/app/modules/project/templates/project/index.html
T
king b74d2be6d3 feat(project): 좌측 트리를 클라이언트 렌더 → 업무 추가/수정/삭제 즉시 반영
- 사이드 프로젝트 트리를 tasks 로부터 JS 로 재렌더(renderTree)
- refreshActiveView 에서 트리도 갱신 → 새로고침 없이 좌측에 바로 표시
- 새 업무 추가 시 해당 프로젝트 자동 펼침
- projectsMeta 에 created_by 추가(트리 삭제 권한용)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 17:58:37 +09:00

172 lines
7.0 KiB
HTML

{% extends "erp_base.html" %}
{% block head_extra %}
<link rel="stylesheet" href="/static/project.css?v=20260626b" />
<link rel="stylesheet" href="/static/vendor/material-symbols/material-symbols.css" />
{% endblock %}
{% block content %}
<div class="pj-wrap" data-is-admin="{{ 'true' if is_admin else 'false' }}"
data-is-super="{{ 'true' if user.is_super_admin else 'false' }}"
data-me="{{ user.email }}">
<div class="pj-home">
<!-- 프로젝트 목록 -->
<section class="pj-home-main">
<div class="pj-section-head">
<h2>프로젝트</h2>
<div class="pj-toolbar-right">
{% set done_count = tree | selectattr('status', 'equalto', 'completed') | list | length %}
{% if done_count %}
<button type="button" class="pj-btn" id="pj-toggle-done" data-count="{{ done_count }}">
완료 {{ done_count }}개 숨기기
</button>
{% endif %}
<a class="pj-bell" href="/project/inbox" title="알림센터">
<span class="material-symbols-outlined">notifications</span>
<span class="pj-bell-badge" id="pj-bell-badge" hidden>0</span>
</a>
{% if is_admin %}
<button type="button" class="pj-btn pj-btn-primary" id="pj-new-project">
+ 새 프로젝트
</button>
{% endif %}
</div>
</div>
{% if not tree %}
<div class="pj-empty">
아직 프로젝트가 없습니다.
{% if is_admin %}상단의 <b>새 프로젝트</b> 버튼으로 만들어 보세요.
{% else %}관리자가 프로젝트에 배정하면 여기에 표시됩니다.{% endif %}
</div>
{% endif %}
<div class="pj-project-grid" id="pj-project-grid">
{% for p in tree %}
<div class="pj-project-card {% if p.status == 'completed' %}is-done{% endif %}"
style="--pj-color: {{ p.color }}"
data-id="{{ p.id }}"
data-name="{{ p.name }}"
data-desc="{{ p.description or '' }}"
data-start="{{ p.start_date or '' }}"
data-due="{{ p.due_date or '' }}"
data-color="{{ p.color }}"
data-status="{{ p.status or 'active' }}"
data-creator="{{ p.created_by or '' }}">
<a class="pj-project-cardlink" href="/project/p/{{ p.id }}">
<span class="pj-project-dot"></span>
<div class="pj-project-body">
<div class="pj-project-name">{{ p.name }}
{% if p.status == 'completed' %}<span class="pj-chip pj-chip-sm">완료</span>{% endif %}
</div>
{% if p.description %}<div class="pj-project-desc">{{ p.description }}</div>{% endif %}
<div class="pj-project-meta">
{% if p.due_date %}<span class="pj-chip">마감 {{ p.due_date }}</span>{% endif %}
</div>
</div>
</a>
{% if is_admin %}
<button type="button" class="pj-icon-btn pj-card-edit" title="프로젝트 수정">
<span class="material-symbols-outlined">edit</span>
</button>
{% endif %}
</div>
{% endfor %}
</div>
</section>
<!-- 내 업무 -->
<aside class="pj-home-side">
<div class="pj-section-head"><h2>내 업무</h2></div>
{% if not my_projects %}
<div class="pj-empty pj-empty-sm">배정된 업무가 없습니다.</div>
{% else %}
<div class="pj-mytree">
{% for p in my_projects %}
<div class="pj-mytree-group">
<a class="pj-mytree-proj" href="/project/p/{{ p.id }}">
<span class="material-symbols-outlined" style="color: {{ p.color }}; font-size:18px;">folder</span>
<span class="pj-mytree-proj-name">{{ p.name }}</span>
</a>
<ul class="pj-mytree-tasks">
{% for t in p.tasks %}
<li class="pj-mytree-task {% if t.completed_at %}is-done{% endif %}">
<a href="/project/p/{{ t.project_id }}?task={{ t.id }}">
<span class="material-symbols-outlined pj-mytree-ic" style="color: {{ t.project_color }};">{% if t.completed_at %}task_alt{% else %}radio_button_unchecked{% endif %}</span>
<span class="pj-mytree-body">
<span class="pj-mytree-title">{{ t.title }}</span>
{% if t.start_date or t.due_date %}
<span class="pj-mytree-dates">
{% if t.start_date and t.due_date %}{{ t.start_date }} ~ {{ t.due_date }}
{% elif t.due_date %}~ {{ t.due_date }}
{% else %}{{ t.start_date }} ~{% endif %}
</span>
{% endif %}
</span>
</a>
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
</div>
{% endif %}
</aside>
</div>
</div>
<!-- 새 프로젝트 모달 -->
{% if is_admin %}
<div class="pj-modal" id="pj-modal-project" hidden>
<div class="pj-modal-card">
<h3>새 프로젝트</h3>
<label>이름<input type="text" id="pj-f-name" placeholder="프로젝트 이름" /></label>
<label>설명<textarea id="pj-f-desc" rows="2"></textarea></label>
<div class="pj-form-row">
<label>시작일<input type="date" id="pj-f-start" /></label>
<label>마감일<input type="date" id="pj-f-due" /></label>
</div>
<label>색상
<span class="pj-color-palette" id="pj-f-colors"></span>
</label>
<div class="pj-modal-actions">
<button type="button" class="pj-btn" data-close>취소</button>
<button type="button" class="pj-btn pj-btn-primary" id="pj-save-project">만들기</button>
</div>
</div>
</div>
<!-- 프로젝트 수정 모달 -->
<div class="pj-modal" id="pj-modal-edit" hidden>
<div class="pj-modal-card">
<h3>프로젝트 수정</h3>
<input type="hidden" id="pj-e-id" />
<label>이름<input type="text" id="pj-e-name" placeholder="프로젝트 이름" /></label>
<label>설명<textarea id="pj-e-desc" rows="2"></textarea></label>
<div class="pj-form-row">
<label>시작일<input type="date" id="pj-e-start" /></label>
<label>마감일<input type="date" id="pj-e-due" /></label>
</div>
<label>색상
<span class="pj-color-palette" id="pj-e-colors"></span>
</label>
<label class="pj-time-toggle">
<input type="checkbox" id="pj-e-done" /> 프로젝트 완료 (목록 끝으로 이동·비활성)
</label>
<div class="pj-modal-actions">
<button type="button" class="pj-btn pj-btn-danger" id="pj-delete-project">삭제</button>
<span style="flex:1"></span>
<button type="button" class="pj-btn" data-close>취소</button>
<button type="button" class="pj-btn pj-btn-primary" id="pj-save-edit">저장</button>
</div>
</div>
</div>
{% endif %}
<script>
window.PJ_COLORS = {{ ["#4573d2","#37a3a3","#62a420","#e8a33d","#e8384f","#aa62e3","#f06a6a","#5a6772"] | tojson }};
</script>
<script src="/static/project.js?v=20260626b" defer></script>
{% endblock %}