Skip to content

Commit a2665ab

Browse files
author
Paul C
committed
feat: WolfNote per-feature folder selection and note margins
Each feature toggle (AI, events, incidents, backups, alerts) now has a folder picker so notes are filed into the right WolfNote folder. AI-created notes are wrapped with margins for readable formatting.
1 parent b1d74be commit a2665ab

4 files changed

Lines changed: 99 additions & 24 deletions

File tree

src/ai/mod.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -832,10 +832,19 @@ async fn execute_wolfnote_tags(response: &str) -> String {
832832
let title = extract_attr(tag_header, "title").unwrap_or_else(|| "Untitled Note".to_string());
833833

834834
// Content is between the closing ] of the opening tag and [/WOLFNOTE]
835-
let content = result[tag_header_end + 1..end_tag].trim().to_string();
835+
let raw_content = result[tag_header_end + 1..end_tag].trim().to_string();
836+
// Wrap with margins for readable formatting in WolfNote
837+
let content = format!("<div style=\"margin: 16px 20px;\">{}</div>", raw_content);
838+
839+
// Use the configured AI folder
840+
let folder_id = if config.features.ai_folder_id.is_empty() {
841+
None
842+
} else {
843+
Some(config.features.ai_folder_id.as_str())
844+
};
836845

837846
// Create the note
838-
let replacement = match client.create_note(&title, &content, None).await {
847+
let replacement = match client.create_note(&title, &content, folder_id).await {
839848
Ok(note) => format!("*Note \"{}\" saved to WolfNote (ID: {})*", title, note.id),
840849
Err(e) => format!("*Failed to save note: {}*", e),
841850
};

src/wolfnote.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,28 +39,43 @@ pub struct WolfNoteFeatures {
3939
/// Allow AI chat to create notes
4040
#[serde(default = "default_true")]
4141
pub ai_create_notes: bool,
42+
#[serde(default)]
43+
pub ai_folder_id: String,
4244
/// Auto-log server events as notes
4345
#[serde(default)]
4446
pub auto_log_events: bool,
47+
#[serde(default)]
48+
pub events_folder_id: String,
4549
/// Auto-create incident notes from status page incidents
4650
#[serde(default)]
4751
pub incident_notes: bool,
52+
#[serde(default)]
53+
pub incidents_folder_id: String,
4854
/// Auto-log backup results as notes
4955
#[serde(default)]
5056
pub backup_notes: bool,
57+
#[serde(default)]
58+
pub backups_folder_id: String,
5159
/// Auto-log alert events as notes
5260
#[serde(default)]
5361
pub alert_notes: bool,
62+
#[serde(default)]
63+
pub alerts_folder_id: String,
5464
}
5565

5666
impl Default for WolfNoteFeatures {
5767
fn default() -> Self {
5868
Self {
5969
ai_create_notes: true,
70+
ai_folder_id: String::new(),
6071
auto_log_events: false,
72+
events_folder_id: String::new(),
6173
incident_notes: false,
74+
incidents_folder_id: String::new(),
6275
backup_notes: false,
76+
backups_folder_id: String::new(),
6377
alert_notes: false,
78+
alerts_folder_id: String::new(),
6479
}
6580
}
6681
}

web/index.html

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4167,41 +4167,56 @@ <h4 style="margin:0;font-size:16px;font-weight:600;">WolfNote Integration</h4>
41674167
<!-- Feature Toggles -->
41684168
<h4 style="margin:0 0 12px 0;font-size:15px;font-weight:600;">Features</h4>
41694169
<div style="display:flex;flex-direction:column;gap:10px;margin-bottom:24px;">
4170-
<label style="display:flex;align-items:center;gap:10px;cursor:pointer;padding:8px 12px;background:var(--bg-tertiary);border-radius:6px;">
4170+
<div style="display:flex;align-items:center;gap:10px;padding:8px 12px;background:var(--bg-tertiary);border-radius:6px;">
41714171
<input type="checkbox" id="wolfnote-feat-ai" onchange="wolfnoteSaveFeatures()" checked>
4172-
<div>
4172+
<div style="flex:1;">
41734173
<div style="font-weight:600;font-size:13px;">AI Note Creation</div>
41744174
<div style="font-size:11px;color:var(--text-muted);">Allow the AI chat assistant to create WolfNote notes on your behalf</div>
41754175
</div>
4176-
</label>
4177-
<label style="display:flex;align-items:center;gap:10px;cursor:pointer;padding:8px 12px;background:var(--bg-tertiary);border-radius:6px;">
4176+
<select id="wolfnote-folder-ai" class="form-control" onchange="wolfnoteSaveFeatures()" style="width:160px;font-size:12px;">
4177+
<option value="">No folder</option>
4178+
</select>
4179+
</div>
4180+
<div style="display:flex;align-items:center;gap:10px;padding:8px 12px;background:var(--bg-tertiary);border-radius:6px;">
41784181
<input type="checkbox" id="wolfnote-feat-events" onchange="wolfnoteSaveFeatures()">
4179-
<div>
4182+
<div style="flex:1;">
41804183
<div style="font-weight:600;font-size:13px;">Server Event Logging</div>
41814184
<div style="font-size:11px;color:var(--text-muted);">Auto-log container and VM lifecycle events (create, destroy, start, stop)</div>
41824185
</div>
4183-
</label>
4184-
<label style="display:flex;align-items:center;gap:10px;cursor:pointer;padding:8px 12px;background:var(--bg-tertiary);border-radius:6px;">
4186+
<select id="wolfnote-folder-events" class="form-control" onchange="wolfnoteSaveFeatures()" style="width:160px;font-size:12px;">
4187+
<option value="">No folder</option>
4188+
</select>
4189+
</div>
4190+
<div style="display:flex;align-items:center;gap:10px;padding:8px 12px;background:var(--bg-tertiary);border-radius:6px;">
41854191
<input type="checkbox" id="wolfnote-feat-incidents" onchange="wolfnoteSaveFeatures()">
4186-
<div>
4192+
<div style="flex:1;">
41874193
<div style="font-weight:600;font-size:13px;">Incident Notes</div>
41884194
<div style="font-size:11px;color:var(--text-muted);">Create a note when status page incidents are opened or resolved</div>
41894195
</div>
4190-
</label>
4191-
<label style="display:flex;align-items:center;gap:10px;cursor:pointer;padding:8px 12px;background:var(--bg-tertiary);border-radius:6px;">
4196+
<select id="wolfnote-folder-incidents" class="form-control" onchange="wolfnoteSaveFeatures()" style="width:160px;font-size:12px;">
4197+
<option value="">No folder</option>
4198+
</select>
4199+
</div>
4200+
<div style="display:flex;align-items:center;gap:10px;padding:8px 12px;background:var(--bg-tertiary);border-radius:6px;">
41924201
<input type="checkbox" id="wolfnote-feat-backups" onchange="wolfnoteSaveFeatures()">
4193-
<div>
4202+
<div style="flex:1;">
41944203
<div style="font-weight:600;font-size:13px;">Backup Reports</div>
41954204
<div style="font-size:11px;color:var(--text-muted);">Log backup success/failure reports as notes</div>
41964205
</div>
4197-
</label>
4198-
<label style="display:flex;align-items:center;gap:10px;cursor:pointer;padding:8px 12px;background:var(--bg-tertiary);border-radius:6px;">
4206+
<select id="wolfnote-folder-backups" class="form-control" onchange="wolfnoteSaveFeatures()" style="width:160px;font-size:12px;">
4207+
<option value="">No folder</option>
4208+
</select>
4209+
</div>
4210+
<div style="display:flex;align-items:center;gap:10px;padding:8px 12px;background:var(--bg-tertiary);border-radius:6px;">
41994211
<input type="checkbox" id="wolfnote-feat-alerts" onchange="wolfnoteSaveFeatures()">
4200-
<div>
4212+
<div style="flex:1;">
42014213
<div style="font-weight:600;font-size:13px;">Alert Notes</div>
42024214
<div style="font-size:11px;color:var(--text-muted);">Log fired alerts (CPU/RAM/disk thresholds) as notes</div>
42034215
</div>
4204-
</label>
4216+
<select id="wolfnote-folder-alerts" class="form-control" onchange="wolfnoteSaveFeatures()" style="width:160px;font-size:12px;">
4217+
<option value="">No folder</option>
4218+
</select>
4219+
</div>
42054220
</div>
42064221

42074222
<!-- Quick Note Creator -->

web/js/app.js

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20998,6 +20998,15 @@ async function loadWolfNoteConfig() {
2099820998
document.getElementById('wolfnote-feat-backups').checked = data.features?.backup_notes ?? false;
2099920999
document.getElementById('wolfnote-feat-alerts').checked = data.features?.alert_notes ?? false;
2100021000

21001+
// Store folder selections to apply after folders load
21002+
window._wolfnoteFolderSelections = {
21003+
ai: data.features?.ai_folder_id || '',
21004+
events: data.features?.events_folder_id || '',
21005+
incidents: data.features?.incidents_folder_id || '',
21006+
backups: data.features?.backups_folder_id || '',
21007+
alerts: data.features?.alerts_folder_id || '',
21008+
};
21009+
2100121010
// Load folders and notes
2100221011
loadWolfNoteFolders();
2100321012
loadWolfNoteNotes();
@@ -21071,10 +21080,15 @@ async function wolfnoteDisconnect() {
2107121080
async function wolfnoteSaveFeatures() {
2107221081
const features = {
2107321082
ai_create_notes: document.getElementById('wolfnote-feat-ai').checked,
21083+
ai_folder_id: document.getElementById('wolfnote-folder-ai').value,
2107421084
auto_log_events: document.getElementById('wolfnote-feat-events').checked,
21085+
events_folder_id: document.getElementById('wolfnote-folder-events').value,
2107521086
incident_notes: document.getElementById('wolfnote-feat-incidents').checked,
21087+
incidents_folder_id: document.getElementById('wolfnote-folder-incidents').value,
2107621088
backup_notes: document.getElementById('wolfnote-feat-backups').checked,
21089+
backups_folder_id: document.getElementById('wolfnote-folder-backups').value,
2107721090
alert_notes: document.getElementById('wolfnote-feat-alerts').checked,
21091+
alerts_folder_id: document.getElementById('wolfnote-folder-alerts').value,
2107821092
};
2107921093
try {
2108021094
await fetch('/api/wolfnote/config', {
@@ -21093,14 +21107,36 @@ async function loadWolfNoteFolders() {
2109321107
const data = await resp.json();
2109421108
if (data.error) return;
2109521109

21096-
const select = document.getElementById('wolfnote-quick-folder');
21097-
select.innerHTML = '<option value="">No folder</option>';
21098-
(Array.isArray(data) ? data : []).forEach(f => {
21099-
const opt = document.createElement('option');
21100-
opt.value = f.id;
21101-
opt.textContent = f.name;
21102-
select.appendChild(opt);
21110+
const folders = Array.isArray(data) ? data : [];
21111+
const selectors = [
21112+
'wolfnote-quick-folder',
21113+
'wolfnote-folder-ai',
21114+
'wolfnote-folder-events',
21115+
'wolfnote-folder-incidents',
21116+
'wolfnote-folder-backups',
21117+
'wolfnote-folder-alerts',
21118+
];
21119+
selectors.forEach(id => {
21120+
const sel = document.getElementById(id);
21121+
if (!sel) return;
21122+
sel.innerHTML = '<option value="">No folder</option>';
21123+
folders.forEach(f => {
21124+
const opt = document.createElement('option');
21125+
opt.value = f.id;
21126+
opt.textContent = f.name;
21127+
sel.appendChild(opt);
21128+
});
2110321129
});
21130+
21131+
// Restore saved folder selections
21132+
const s = window._wolfnoteFolderSelections;
21133+
if (s) {
21134+
document.getElementById('wolfnote-folder-ai').value = s.ai;
21135+
document.getElementById('wolfnote-folder-events').value = s.events;
21136+
document.getElementById('wolfnote-folder-incidents').value = s.incidents;
21137+
document.getElementById('wolfnote-folder-backups').value = s.backups;
21138+
document.getElementById('wolfnote-folder-alerts').value = s.alerts;
21139+
}
2110421140
} catch (e) {
2110521141
console.error('Failed to load WolfNote folders:', e);
2110621142
}

0 commit comments

Comments
 (0)