journal: multi-select emotions and per-category writing templates
- Mood switches from a single enum column to a many-to-many JournalEntryMood table so an entry can carry several feelings at once; the vocabulary is trimmed to 9 named emotions (dropped the overlapping satisfaction scale) with unified noun-style labels. - Categories can define a content_template that pre-fills the "new entry" textarea when selected (only if the user hasn't started typing), seeded with a Story/Feelings/Decisions/Insights/Actions reflection template on the default "일상" category. - Fixes a real attribute-injection bug found while building the template feature: Jinja's built-in |tojson filter doesn't escape double quotes, which breaks a double-quoted x-data="..." attribute when the JSON payload contains one; added |forceescape and a regression test. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,10 @@
|
||||
<label for="edit-category-color-{{ category.id }}">색상</label>
|
||||
<input type="color" id="edit-category-color-{{ category.id }}" name="color" value="{{ category.color or '#d97757' }}" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="edit-category-template-{{ category.id }}">기본 작성 틀 (선택)</label>
|
||||
<textarea id="edit-category-template-{{ category.id }}" name="content_template" rows="4" placeholder="이 카테고리로 새 기록을 쓸 때 내용칸에 미리 채워줄 틀을 입력하세요">{{ category.content_template or '' }}</textarea>
|
||||
</div>
|
||||
<div id="journal-category-edit-error-{{ category.id }}" class="form-error-text"></div>
|
||||
<div style="display:flex; gap:8px;">
|
||||
<button type="submit" class="btn btn-primary" style="flex:1;">저장</button>
|
||||
@@ -85,6 +89,10 @@
|
||||
<label for="new-category-color">색상 (선택)</label>
|
||||
<input type="color" id="new-category-color" name="color" value="#d97757" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="new-category-template">기본 작성 틀 (선택)</label>
|
||||
<textarea id="new-category-template" name="content_template" rows="4" placeholder="이 카테고리로 새 기록을 쓸 때 내용칸에 미리 채워줄 틀을 입력하세요"></textarea>
|
||||
</div>
|
||||
<div id="journal-category-error" class="form-error-text"></div>
|
||||
<button type="submit" class="btn btn-primary btn-block">추가하기</button>
|
||||
</form>
|
||||
@@ -113,6 +121,17 @@
|
||||
open: false,
|
||||
moods: [],
|
||||
toggleMood(v) { this.moods.includes(v) ? this.moods = this.moods.filter(m => m !== v) : this.moods.push(v) },
|
||||
categoryTemplates: {{ category_templates|tojson|forceescape }},
|
||||
content: '',
|
||||
lastAutoFilled: '',
|
||||
onCategoryChange(categoryId) {
|
||||
const tmpl = this.categoryTemplates[categoryId] || '';
|
||||
if (this.content === this.lastAutoFilled) {
|
||||
this.content = tmpl;
|
||||
this.lastAutoFilled = tmpl;
|
||||
}
|
||||
},
|
||||
init() { this.onCategoryChange(this.$refs.categorySelect.value); },
|
||||
}"
|
||||
>
|
||||
<button type="button" class="btn btn-primary btn-block" @click="open = !open">
|
||||
@@ -135,7 +154,7 @@
|
||||
>
|
||||
<div class="field">
|
||||
<label for="new-entry-category">카테고리</label>
|
||||
<select id="new-entry-category" name="category_id">
|
||||
<select id="new-entry-category" name="category_id" x-ref="categorySelect" @change="onCategoryChange($event.target.value)">
|
||||
{% for category in categories %}
|
||||
<option value="{{ category.id }}" {{ 'selected' if category_id == category.id }}>{{ category.name }}</option>
|
||||
{% endfor %}
|
||||
@@ -154,7 +173,7 @@
|
||||
|
||||
<div class="field">
|
||||
<label for="new-entry-content">내용</label>
|
||||
<textarea id="new-entry-content" name="content" rows="5" required placeholder="오늘 하루는 어땠나요?"></textarea>
|
||||
<textarea id="new-entry-content" name="content" rows="8" required placeholder="오늘 하루는 어땠나요?" x-model="content"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
|
||||
Reference in New Issue
Block a user