Diff -- /var/www/vhosts/3dshawn.com/ptmatrix.3dshawn.com/TEMPLATES/tf_kb.html
Diff

/var/www/vhosts/3dshawn.com/ptmatrix.3dshawn.com/TEMPLATES/tf_kb.html

added on local at 2026-07-01 12:34:59

Added
+124
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to 17510aff90eb
Restore this content →
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
1<style>
2.kb-card { background:var(--col-bg-2); border:1px solid var(--col-border); border-radius:10px; padding:18px; margin-bottom:18px; }
3.kb-form { display:grid; grid-template-columns:1fr 1fr; gap:12px; }
4.kb-form .full { grid-column:1/-1; }
5.kb-form label { display:block; font-size:11px; color:var(--col-text-muted); margin-bottom:3px; text-transform:uppercase; letter-spacing:.5px; font-weight:600; }
6.kb-form input, .kb-form textarea, .kb-form select { width:100%; background:var(--col-bg-1); border:1px solid var(--col-border); color:var(--col-text); padding:7px 10px; border-radius:6px; font-size:13px; font-family:inherit; }
7.kb-form textarea { min-height:160px; }
8.kb-btn { padding:8px 14px; border-radius:7px; font-size:12px; font-weight:600; cursor:pointer; border:1px solid var(--col-border); background:transparent; color:var(--col-text); }
9.kb-btn-primary { background:var(--col-brand-1); color:#fff; border-color:var(--col-brand-2); }
10.kb-btn-danger { color:#ef4444; border-color:rgba(239,68,68,0.4); }
11.kb-flash { padding:10px 14px; border-radius:7px; margin-bottom:14px; font-size:13px; }
12.kb-flash.ok { background:rgba(110,231,167,0.10); border:1px solid rgba(110,231,167,0.4); color:#6ee7a7; }
13.kb-flash.err { background:rgba(239,68,68,0.10); border:1px solid rgba(239,68,68,0.4); color:#ef4444; }
14.kb-row { display:flex; gap:10px; padding:10px; border-bottom:1px solid var(--col-border); align-items:center; font-size:13px; }
15.kb-row .meta { color:var(--col-text-muted); font-size:11px; }
16.kb-actions { margin-top:14px; display:flex; gap:8px; flex-wrap:wrap; }
17.kb-tabs { display:flex; gap:8px; margin-bottom:18px; }
18.kb-tab { padding:8px 14px; background:transparent; border:1px solid var(--col-border); border-radius:7px; cursor:pointer; color:var(--col-text-muted); text-decoration:none; font-size:13px; }
19.kb-tab.active { background:rgba(90,169,255,0.10); border-color:#5aa9ff; color:#5aa9ff; }
20@media (max-width:640px) { .kb-form { grid-template-columns:1fr; } }
21</style>
22
23<div class="page-header">
24 <div>
25 <h1>Knowledge Base</h1>
26 <p class="subtitle">Internal documentation + customer-facing help articles + canned responses for fast replies.</p>
27 </div>
28</div>
29
30[if:$has_flash]<div class="kb-flash $flash_kind">$flash_msg</div>[/if]
31[if:$schema_missing]<div class="kb-flash err">Run <code>_kb_migration.sql</code> to enable this page.</div>[/if]
32
33[if:$schema_ready]
34
35<div class="kb-tabs">
36 <a href="#articles" class="kb-tab active" onclick="kbTab('articles', this)">Articles</a>
37 <a href="#canned" class="kb-tab" onclick="kbTab('canned', this)">Canned Responses</a>
38</div>
39
40<div id="kb-articles">
41 [if:$has_articles]
42 <div class="kb-card">
43 <h3>Articles</h3>
44 [loop:@articles]
45 <div class="kb-row">
46 <div style="flex:1">
47 <strong>$loop1.title</strong> [if:$loop1.is_public]<span style="font-size:10px;background:rgba(110,231,167,0.15);color:#6ee7a7;padding:2px 6px;border-radius:8px;margin-left:6px">PUBLIC</span>[/if][if:!$loop1.is_active]<span style="font-size:10px;background:rgba(255,255,255,0.06);color:var(--col-text-muted);padding:2px 6px;border-radius:8px;margin-left:6px">DRAFT</span>[/if]
48 <div class="meta">[if:$loop1.category]$loop1.category &middot; [/if]$loop1.view_count views &middot; updated $loop1.updated_at</div>
49 </div>
50 <form method="POST" style="display:inline" onsubmit="return confirm('Delete this article?');">
51 <input type="hidden" name="act" value="delete_article">
52 <input type="hidden" name="id" value="$loop1.id">
53 <button class="kb-btn kb-btn-danger">Delete</button>
54 </form>
55 </div>
56 [/loop]
57 </div>
58 [/if]
59
60 [if:$is_admin]
61 <form method="POST" action="/kb.cgi" class="kb-card" style="border:1px dashed var(--col-border)">
62 <input type="hidden" name="act" value="save_article">
63 <h3>New article</h3>
64 <div class="kb-form">
65 <div class="full"><label>Title</label><input type="text" name="title" required maxlength="280"></div>
66 <div><label>Category</label><input type="text" name="category" maxlength="120" placeholder="Getting started"></div>
67 <div><label>Tags (comma-separated)</label><input type="text" name="tags" maxlength="500"></div>
68 <div class="full"><label>Body (markdown OK)</label><textarea name="body" required></textarea></div>
69 <div><label><input type="checkbox" name="is_public" value="1"> Public (visible in customer portal)</label></div>
70 <div><label><input type="checkbox" name="is_active" value="1" checked> Active</label></div>
71 </div>
72 <div class="kb-actions"><button class="kb-btn kb-btn-primary">Save article</button></div>
73 </form>
74 [/if]
75</div>
76
77<div id="kb-canned" style="display:none">
78 [if:$has_canned]
79 <div class="kb-card">
80 <h3>Canned responses</h3>
81 [loop:@canned]
82 <div class="kb-row">
83 <div style="flex:1">
84 <strong>$loop1.name</strong>
85 [if:$loop1.shortcode]<code style="font-size:11px;background:var(--col-bg-1);padding:1px 6px;border-radius:5px;margin-left:6px">$loop1.shortcode</code>[/if]
86 [if:!$loop1.is_active]<span style="font-size:10px;color:var(--col-text-muted);margin-left:6px">disabled</span>[/if]
87 <div class="meta">used $loop1.use_count times</div>
88 </div>
89 <form method="POST" style="display:inline" onsubmit="return confirm('Delete this response?');">
90 <input type="hidden" name="act" value="delete_canned">
91 <input type="hidden" name="id" value="$loop1.id">
92 <button class="kb-btn kb-btn-danger">Delete</button>
93 </form>
94 </div>
95 [/loop]
96 </div>
97 [/if]
98
99 [if:$is_admin]
100 <form method="POST" action="/kb.cgi" class="kb-card" style="border:1px dashed var(--col-border)">
101 <input type="hidden" name="act" value="save_canned">
102 <h3>New canned response</h3>
103 <div class="kb-form">
104 <div><label>Name</label><input type="text" name="name" required maxlength="120" placeholder="Thanks for your patience"></div>
105 <div><label>Shortcode (optional)</label><input type="text" name="shortcode" maxlength="40" placeholder="/thanks"></div>
106 <div class="full"><label>Body</label><textarea name="body" required></textarea></div>
107 <div><label><input type="checkbox" name="is_active" value="1" checked> Active</label></div>
108 </div>
109 <div class="kb-actions"><button class="kb-btn kb-btn-primary">Save response</button></div>
110 </form>
111 [/if]
112</div>
113
114<script>
115function kbTab(which, el) {
116 document.getElementById('kb-articles').style.display = (which === 'articles') ? '' : 'none';
117 document.getElementById('kb-canned').style.display = (which === 'canned') ? '' : 'none';
118 document.querySelectorAll('.kb-tab').forEach(t => t.classList.remove('active'));
119 el.classList.add('active');
120 return false;
121}
122</script>
123
124[/if]
Keyboard: j next diff k previous diff g top G bottom r restore c compile-check ? help