@mattli/dotmd 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/dashboard/_archive/wizard-client.d.ts +2 -0
  2. package/dist/dashboard/_archive/wizard-client.d.ts.map +1 -0
  3. package/dist/dashboard/_archive/wizard-client.js +412 -0
  4. package/dist/dashboard/_archive/wizard-client.js.map +1 -0
  5. package/dist/dashboard/_archive/wizard.d.ts +9 -0
  6. package/dist/dashboard/_archive/wizard.d.ts.map +1 -0
  7. package/dist/dashboard/_archive/wizard.js +317 -0
  8. package/dist/dashboard/_archive/wizard.js.map +1 -0
  9. package/dist/dashboard/help.d.ts +2 -0
  10. package/dist/dashboard/help.d.ts.map +1 -0
  11. package/dist/dashboard/help.js +73 -0
  12. package/dist/dashboard/help.js.map +1 -0
  13. package/dist/dashboard/layout.d.ts.map +1 -1
  14. package/dist/dashboard/layout.js +1 -0
  15. package/dist/dashboard/layout.js.map +1 -1
  16. package/dist/dashboard/server.d.ts.map +1 -1
  17. package/dist/dashboard/server.js +15 -45
  18. package/dist/dashboard/server.js.map +1 -1
  19. package/dist/dashboard/settings-client.d.ts +1 -1
  20. package/dist/dashboard/settings-client.d.ts.map +1 -1
  21. package/dist/dashboard/settings-client.js +367 -162
  22. package/dist/dashboard/settings-client.js.map +1 -1
  23. package/dist/dashboard/settings.d.ts +5 -1
  24. package/dist/dashboard/settings.d.ts.map +1 -1
  25. package/dist/dashboard/settings.js +60 -45
  26. package/dist/dashboard/settings.js.map +1 -1
  27. package/dist/dashboard/wizard-client.d.ts +1 -1
  28. package/dist/dashboard/wizard-client.d.ts.map +1 -1
  29. package/dist/dashboard/wizard-client.js +226 -80
  30. package/dist/dashboard/wizard-client.js.map +1 -1
  31. package/dist/dashboard/wizard.d.ts +2 -2
  32. package/dist/dashboard/wizard.d.ts.map +1 -1
  33. package/dist/dashboard/wizard.js +113 -32
  34. package/dist/dashboard/wizard.js.map +1 -1
  35. package/package.json +1 -1
@@ -0,0 +1,2 @@
1
+ export declare const WIZARD_CLIENT_SCRIPT = "<script>\ndocument.addEventListener('DOMContentLoaded', function() {\n // --- Pattern list (step 2) ---\n var patternList = document.getElementById('pattern-list');\n var suggestedPatternsDiv = document.getElementById('suggested-patterns');\n var noPatternsMsg = document.getElementById('no-patterns-msg');\n\n function updateNoPatternsMsg() {\n if (!noPatternsMsg) return;\n if (getSelectedValues().length === 0) {\n noPatternsMsg.classList.remove('hidden');\n } else {\n noPatternsMsg.classList.add('hidden');\n }\n }\n\n function addPatternChip(value) {\n if (!patternList) return;\n // Check for duplicates\n var existing = patternList.querySelectorAll('[data-pattern-chip]');\n for (var i = 0; i < existing.length; i++) {\n if (existing[i].getAttribute('data-pattern-chip') === value) return;\n }\n\n var tag = document.createElement('span');\n tag.setAttribute('data-pattern-chip', value);\n tag.className = 'inline-flex items-center gap-1 px-3 py-1.5 rounded-full text-sm font-medium bg-blue-100 text-blue-800 border border-blue-300';\n tag.innerHTML = value + ' <button type=\"button\" class=\"ml-1 text-blue-500 hover:text-blue-700 font-bold\">&times;</button>';\n tag.querySelector('button').addEventListener('click', function() {\n tag.remove();\n updateNextBtn();\n updateNoPatternsMsg();\n });\n patternList.appendChild(tag);\n updateNextBtn();\n updateNoPatternsMsg();\n }\n\n // Wire up x buttons on server-rendered pattern chips\n if (patternList) {\n patternList.querySelectorAll('[data-pattern-chip] button').forEach(function(btn) {\n btn.addEventListener('click', function() {\n btn.parentElement.remove();\n updateNextBtn();\n updateNoPatternsMsg();\n });\n });\n }\n\n // Wire up suggested pattern chips \u2014 click to add\n if (suggestedPatternsDiv) {\n suggestedPatternsDiv.querySelectorAll('[data-suggested-pattern]').forEach(function(chip) {\n chip.addEventListener('click', function() {\n var value = chip.getAttribute('data-suggested-pattern');\n addPatternChip(value);\n chip.remove();\n // Hide suggestions section if empty\n if (suggestedPatternsDiv.children.length === 0) {\n suggestedPatternsDiv.parentElement.style.display = 'none';\n }\n });\n });\n }\n\n // --- Folder list (step 1) ---\n var folderList = document.getElementById('folder-list');\n var noFoldersMsg = document.getElementById('no-folders-msg');\n\n function getAddedFolders() {\n var folders = [];\n if (!folderList) return folders;\n folderList.querySelectorAll('[data-folder-chip]').forEach(function(chip) {\n folders.push(chip.getAttribute('data-folder-chip'));\n });\n return folders;\n }\n\n function isFolderAdded(folderPath) {\n var folders = getAddedFolders();\n for (var i = 0; i < folders.length; i++) {\n if (folders[i] === folderPath) return true;\n }\n return false;\n }\n\n function isCoveredByParent(folderPath) {\n var folders = getAddedFolders();\n for (var i = 0; i < folders.length; i++) {\n // Check if an existing folder is a parent of this one\n if (folderPath !== folders[i] && folderPath.indexOf(folders[i] + '/') === 0) return true;\n }\n return false;\n }\n\n function updateNoFoldersMsg() {\n if (!noFoldersMsg) return;\n if (getAddedFolders().length === 0) {\n noFoldersMsg.classList.remove('hidden');\n } else {\n noFoldersMsg.classList.add('hidden');\n }\n }\n\n function removeFolderChip(chip) {\n chip.remove();\n updateNextBtn();\n updateNoFoldersMsg();\n }\n\n function addFolderChip(folderPath) {\n if (!folderList) return;\n if (isFolderAdded(folderPath)) return;\n\n var tag = document.createElement('span');\n tag.setAttribute('data-folder-chip', folderPath);\n tag.className = 'inline-flex items-center gap-1 px-3 py-1.5 rounded-full text-sm font-medium bg-blue-100 text-blue-800 border border-blue-300';\n tag.innerHTML = folderPath + ' <button type=\"button\" class=\"ml-1 text-blue-500 hover:text-blue-700 font-bold\">&times;</button>';\n tag.querySelector('button').addEventListener('click', function() {\n removeFolderChip(tag);\n });\n folderList.appendChild(tag);\n updateNextBtn();\n updateNoFoldersMsg();\n }\n\n // Wire up x buttons on server-rendered folder chips\n if (folderList) {\n folderList.querySelectorAll('[data-folder-chip] button').forEach(function(btn) {\n btn.addEventListener('click', function() {\n removeFolderChip(btn.parentElement);\n });\n });\n }\n\n // --- Folder browser ---\n var openBrowserBtn = document.getElementById('open-browser');\n var folderBrowser = document.getElementById('folder-browser');\n var browserPath = document.getElementById('browser-path');\n var browserList = document.getElementById('browser-list');\n var browserUp = document.getElementById('browser-up');\n\n var currentBrowserDir = null;\n\n function loadBrowserDir(dir) {\n fetch('/api/setup/browse?dir=' + encodeURIComponent(dir || '~'))\n .then(function(res) { return res.json(); })\n .then(function(data) {\n if (data.error) return;\n currentBrowserDir = data.current;\n if (browserPath) browserPath.textContent = data.current;\n if (browserUp) {\n browserUp.style.display = data.parent ? '' : 'none';\n browserUp.onclick = function() { loadBrowserDir(data.parent); };\n }\n if (!browserList) return;\n browserList.innerHTML = '';\n\n data.dirs.forEach(function(entry) {\n var added = isFolderAdded(entry.path);\n var covered = isCoveredByParent(entry.path);\n\n var row = document.createElement('div');\n row.className = 'px-4 py-2 hover:bg-gray-50 flex items-center gap-2 text-sm';\n\n var folderIcon = document.createElement('span');\n folderIcon.innerHTML = '&#128193;';\n folderIcon.className = covered ? 'text-gray-300' : 'text-gray-400';\n\n var nameSpan = document.createElement('span');\n nameSpan.textContent = entry.name;\n nameSpan.className = covered\n ? 'cursor-pointer flex-1 text-gray-300'\n : 'cursor-pointer flex-1 hover:text-blue-600';\n nameSpan.addEventListener('click', function() {\n loadBrowserDir(entry.path);\n });\n\n row.appendChild(folderIcon);\n row.appendChild(nameSpan);\n\n if (added) {\n var removeBtn = document.createElement('button');\n removeBtn.textContent = 'Remove';\n removeBtn.type = 'button';\n removeBtn.className = 'text-red-500 hover:text-red-700 text-xs font-medium flex-shrink-0';\n removeBtn.addEventListener('click', function(e) {\n e.stopPropagation();\n var chips = folderList.querySelectorAll('[data-folder-chip]');\n for (var i = 0; i < chips.length; i++) {\n if (chips[i].getAttribute('data-folder-chip') === entry.path) {\n removeFolderChip(chips[i]);\n break;\n }\n }\n loadBrowserDir(currentBrowserDir);\n });\n row.appendChild(removeBtn);\n } else if (!covered) {\n var addBtn = document.createElement('button');\n addBtn.textContent = 'Add';\n addBtn.type = 'button';\n addBtn.className = 'text-blue-600 hover:text-blue-800 text-xs font-medium flex-shrink-0';\n addBtn.addEventListener('click', function(e) {\n e.stopPropagation();\n addFolderChip(entry.path);\n loadBrowserDir(currentBrowserDir);\n });\n row.appendChild(addBtn);\n }\n\n browserList.appendChild(row);\n });\n });\n }\n\n if (openBrowserBtn && folderBrowser) {\n openBrowserBtn.addEventListener('click', function() {\n var isHidden = folderBrowser.classList.contains('hidden');\n if (isHidden) {\n folderBrowser.classList.remove('hidden');\n openBrowserBtn.textContent = 'Hide browser';\n loadBrowserDir('~');\n } else {\n folderBrowser.classList.add('hidden');\n openBrowserBtn.textContent = 'Browse for folder...';\n }\n });\n }\n\n // --- Custom input for patterns (step 2) ---\n var addCustomBtn = document.getElementById('add-custom');\n var customInput = document.getElementById('custom-input');\n\n function addCustomPattern() {\n if (!customInput || !patternList) return;\n var value = customInput.value.trim();\n if (!value) return;\n addPatternChip(value);\n customInput.value = '';\n }\n\n if (addCustomBtn) {\n addCustomBtn.addEventListener('click', addCustomPattern);\n }\n if (customInput) {\n customInput.addEventListener('keydown', function(e) {\n if (e.key === 'Enter') {\n e.preventDefault();\n addCustomPattern();\n }\n });\n }\n\n // --- Update Next button disabled state ---\n function updateNextBtn() {\n var btn = document.getElementById('next-btn');\n if (!btn) return;\n var hasSelection = getSelectedValues().length > 0;\n btn.disabled = !hasSelection;\n if (hasSelection) {\n btn.classList.remove('opacity-50', 'cursor-not-allowed');\n } else {\n btn.classList.add('opacity-50', 'cursor-not-allowed');\n }\n }\n\n // --- Collect selected values ---\n function getSelectedValues() {\n var values = [];\n // Folder chips (step 1)\n document.querySelectorAll('[data-folder-chip]').forEach(function(chip) {\n values.push(chip.getAttribute('data-folder-chip'));\n });\n // Pattern chips (step 2)\n document.querySelectorAll('[data-pattern-chip]').forEach(function(chip) {\n values.push(chip.getAttribute('data-pattern-chip'));\n });\n return values;\n }\n\n // --- Initial button state ---\n updateNextBtn();\n\n // --- Step 1: Next button ---\n var nextBtn = document.getElementById('next-btn');\n if (nextBtn && nextBtn.getAttribute('data-step') === '1') {\n nextBtn.addEventListener('click', function() {\n var roots = getSelectedValues();\n if (roots.length === 0) return;\n var params = new URLSearchParams();\n roots.forEach(function(r) { params.append('roots', r); });\n // Preserve patterns if returning from step 2\n var urlParams = new URLSearchParams(window.location.search);\n urlParams.getAll('patterns').forEach(function(p) { params.append('patterns', p); });\n window.location.href = '/setup/step2?' + params.toString();\n });\n }\n\n // --- Step 2: Back button ---\n var backBtn = document.getElementById('back-btn');\n if (backBtn) {\n backBtn.addEventListener('click', function() {\n var urlParams = new URLSearchParams(window.location.search);\n var roots = urlParams.getAll('roots');\n var patterns = getSelectedValues();\n var params = new URLSearchParams();\n roots.forEach(function(r) { params.append('roots', r); });\n patterns.forEach(function(p) { params.append('patterns', p); });\n window.location.href = '/setup?' + params.toString();\n });\n }\n\n // --- Step 2: Preview button ---\n if (nextBtn && nextBtn.getAttribute('data-step') === '2') {\n nextBtn.addEventListener('click', function() {\n var patterns = getSelectedValues();\n if (patterns.length === 0) return;\n var urlParams = new URLSearchParams(window.location.search);\n var roots = urlParams.getAll('roots');\n var params = new URLSearchParams();\n roots.forEach(function(r) { params.append('roots', r); });\n patterns.forEach(function(p) { params.append('patterns', p); });\n window.location.href = '/setup/step3?' + params.toString();\n });\n }\n\n // --- Step 3: Select/deselect by group ---\n document.querySelectorAll('[data-group-select]').forEach(function(btn) {\n btn.addEventListener('click', function() {\n var group = btn.getAttribute('data-group-select');\n var container = document.querySelector('[data-group=\"' + group + '\"]');\n if (container) {\n container.querySelectorAll('input[name=\"files\"]').forEach(function(cb) {\n cb.checked = true;\n });\n }\n });\n });\n document.querySelectorAll('[data-group-deselect]').forEach(function(btn) {\n btn.addEventListener('click', function() {\n var group = btn.getAttribute('data-group-deselect');\n var container = document.querySelector('[data-group=\"' + group + '\"]');\n if (container) {\n container.querySelectorAll('input[name=\"files\"]').forEach(function(cb) {\n cb.checked = false;\n });\n }\n });\n });\n\n // --- Step 3: Select all / Deselect all ---\n var selectAllBtn = document.getElementById('select-all');\n var deselectAllBtn = document.getElementById('deselect-all');\n\n if (selectAllBtn) {\n selectAllBtn.addEventListener('click', function() {\n document.querySelectorAll('input[name=\"files\"]').forEach(function(cb) {\n cb.checked = true;\n });\n });\n }\n if (deselectAllBtn) {\n deselectAllBtn.addEventListener('click', function() {\n document.querySelectorAll('input[name=\"files\"]').forEach(function(cb) {\n cb.checked = false;\n });\n });\n }\n\n // --- Step 3: Confirm button ---\n var confirmBtn = document.getElementById('confirm-btn');\n if (confirmBtn) {\n confirmBtn.addEventListener('click', function() {\n confirmBtn.disabled = true;\n confirmBtn.textContent = 'Saving...';\n\n var urlParams = new URLSearchParams(window.location.search);\n var roots = urlParams.getAll('roots');\n var patterns = urlParams.getAll('patterns');\n\n var excludedFiles = [];\n document.querySelectorAll('input[name=\"files\"]').forEach(function(cb) {\n if (!cb.checked) {\n excludedFiles.push(cb.value);\n }\n });\n\n fetch('/api/setup/confirm', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ roots: roots, patterns: patterns, excludedFiles: excludedFiles })\n })\n .then(function(res) { return res.json(); })\n .then(function(data) {\n if (data.success) {\n window.location.href = '/setup/complete?count=' + data.trackedCount;\n } else {\n alert('Error saving config. Please try again.');\n confirmBtn.disabled = false;\n confirmBtn.textContent = 'Confirm & Start Tracking';\n }\n })\n .catch(function() {\n alert('Error saving config. Please try again.');\n confirmBtn.disabled = false;\n confirmBtn.textContent = 'Confirm & Start Tracking';\n });\n });\n }\n});\n</script>";
2
+ //# sourceMappingURL=wizard-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wizard-client.d.ts","sourceRoot":"","sources":["../../../src/dashboard/_archive/wizard-client.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,2pdA0ZvB,CAAC"}
@@ -0,0 +1,412 @@
1
+ export const WIZARD_CLIENT_SCRIPT = `<script>
2
+ document.addEventListener('DOMContentLoaded', function() {
3
+ // --- Pattern list (step 2) ---
4
+ var patternList = document.getElementById('pattern-list');
5
+ var suggestedPatternsDiv = document.getElementById('suggested-patterns');
6
+ var noPatternsMsg = document.getElementById('no-patterns-msg');
7
+
8
+ function updateNoPatternsMsg() {
9
+ if (!noPatternsMsg) return;
10
+ if (getSelectedValues().length === 0) {
11
+ noPatternsMsg.classList.remove('hidden');
12
+ } else {
13
+ noPatternsMsg.classList.add('hidden');
14
+ }
15
+ }
16
+
17
+ function addPatternChip(value) {
18
+ if (!patternList) return;
19
+ // Check for duplicates
20
+ var existing = patternList.querySelectorAll('[data-pattern-chip]');
21
+ for (var i = 0; i < existing.length; i++) {
22
+ if (existing[i].getAttribute('data-pattern-chip') === value) return;
23
+ }
24
+
25
+ var tag = document.createElement('span');
26
+ tag.setAttribute('data-pattern-chip', value);
27
+ tag.className = 'inline-flex items-center gap-1 px-3 py-1.5 rounded-full text-sm font-medium bg-blue-100 text-blue-800 border border-blue-300';
28
+ tag.innerHTML = value + ' <button type="button" class="ml-1 text-blue-500 hover:text-blue-700 font-bold">&times;</button>';
29
+ tag.querySelector('button').addEventListener('click', function() {
30
+ tag.remove();
31
+ updateNextBtn();
32
+ updateNoPatternsMsg();
33
+ });
34
+ patternList.appendChild(tag);
35
+ updateNextBtn();
36
+ updateNoPatternsMsg();
37
+ }
38
+
39
+ // Wire up x buttons on server-rendered pattern chips
40
+ if (patternList) {
41
+ patternList.querySelectorAll('[data-pattern-chip] button').forEach(function(btn) {
42
+ btn.addEventListener('click', function() {
43
+ btn.parentElement.remove();
44
+ updateNextBtn();
45
+ updateNoPatternsMsg();
46
+ });
47
+ });
48
+ }
49
+
50
+ // Wire up suggested pattern chips — click to add
51
+ if (suggestedPatternsDiv) {
52
+ suggestedPatternsDiv.querySelectorAll('[data-suggested-pattern]').forEach(function(chip) {
53
+ chip.addEventListener('click', function() {
54
+ var value = chip.getAttribute('data-suggested-pattern');
55
+ addPatternChip(value);
56
+ chip.remove();
57
+ // Hide suggestions section if empty
58
+ if (suggestedPatternsDiv.children.length === 0) {
59
+ suggestedPatternsDiv.parentElement.style.display = 'none';
60
+ }
61
+ });
62
+ });
63
+ }
64
+
65
+ // --- Folder list (step 1) ---
66
+ var folderList = document.getElementById('folder-list');
67
+ var noFoldersMsg = document.getElementById('no-folders-msg');
68
+
69
+ function getAddedFolders() {
70
+ var folders = [];
71
+ if (!folderList) return folders;
72
+ folderList.querySelectorAll('[data-folder-chip]').forEach(function(chip) {
73
+ folders.push(chip.getAttribute('data-folder-chip'));
74
+ });
75
+ return folders;
76
+ }
77
+
78
+ function isFolderAdded(folderPath) {
79
+ var folders = getAddedFolders();
80
+ for (var i = 0; i < folders.length; i++) {
81
+ if (folders[i] === folderPath) return true;
82
+ }
83
+ return false;
84
+ }
85
+
86
+ function isCoveredByParent(folderPath) {
87
+ var folders = getAddedFolders();
88
+ for (var i = 0; i < folders.length; i++) {
89
+ // Check if an existing folder is a parent of this one
90
+ if (folderPath !== folders[i] && folderPath.indexOf(folders[i] + '/') === 0) return true;
91
+ }
92
+ return false;
93
+ }
94
+
95
+ function updateNoFoldersMsg() {
96
+ if (!noFoldersMsg) return;
97
+ if (getAddedFolders().length === 0) {
98
+ noFoldersMsg.classList.remove('hidden');
99
+ } else {
100
+ noFoldersMsg.classList.add('hidden');
101
+ }
102
+ }
103
+
104
+ function removeFolderChip(chip) {
105
+ chip.remove();
106
+ updateNextBtn();
107
+ updateNoFoldersMsg();
108
+ }
109
+
110
+ function addFolderChip(folderPath) {
111
+ if (!folderList) return;
112
+ if (isFolderAdded(folderPath)) return;
113
+
114
+ var tag = document.createElement('span');
115
+ tag.setAttribute('data-folder-chip', folderPath);
116
+ tag.className = 'inline-flex items-center gap-1 px-3 py-1.5 rounded-full text-sm font-medium bg-blue-100 text-blue-800 border border-blue-300';
117
+ tag.innerHTML = folderPath + ' <button type="button" class="ml-1 text-blue-500 hover:text-blue-700 font-bold">&times;</button>';
118
+ tag.querySelector('button').addEventListener('click', function() {
119
+ removeFolderChip(tag);
120
+ });
121
+ folderList.appendChild(tag);
122
+ updateNextBtn();
123
+ updateNoFoldersMsg();
124
+ }
125
+
126
+ // Wire up x buttons on server-rendered folder chips
127
+ if (folderList) {
128
+ folderList.querySelectorAll('[data-folder-chip] button').forEach(function(btn) {
129
+ btn.addEventListener('click', function() {
130
+ removeFolderChip(btn.parentElement);
131
+ });
132
+ });
133
+ }
134
+
135
+ // --- Folder browser ---
136
+ var openBrowserBtn = document.getElementById('open-browser');
137
+ var folderBrowser = document.getElementById('folder-browser');
138
+ var browserPath = document.getElementById('browser-path');
139
+ var browserList = document.getElementById('browser-list');
140
+ var browserUp = document.getElementById('browser-up');
141
+
142
+ var currentBrowserDir = null;
143
+
144
+ function loadBrowserDir(dir) {
145
+ fetch('/api/setup/browse?dir=' + encodeURIComponent(dir || '~'))
146
+ .then(function(res) { return res.json(); })
147
+ .then(function(data) {
148
+ if (data.error) return;
149
+ currentBrowserDir = data.current;
150
+ if (browserPath) browserPath.textContent = data.current;
151
+ if (browserUp) {
152
+ browserUp.style.display = data.parent ? '' : 'none';
153
+ browserUp.onclick = function() { loadBrowserDir(data.parent); };
154
+ }
155
+ if (!browserList) return;
156
+ browserList.innerHTML = '';
157
+
158
+ data.dirs.forEach(function(entry) {
159
+ var added = isFolderAdded(entry.path);
160
+ var covered = isCoveredByParent(entry.path);
161
+
162
+ var row = document.createElement('div');
163
+ row.className = 'px-4 py-2 hover:bg-gray-50 flex items-center gap-2 text-sm';
164
+
165
+ var folderIcon = document.createElement('span');
166
+ folderIcon.innerHTML = '&#128193;';
167
+ folderIcon.className = covered ? 'text-gray-300' : 'text-gray-400';
168
+
169
+ var nameSpan = document.createElement('span');
170
+ nameSpan.textContent = entry.name;
171
+ nameSpan.className = covered
172
+ ? 'cursor-pointer flex-1 text-gray-300'
173
+ : 'cursor-pointer flex-1 hover:text-blue-600';
174
+ nameSpan.addEventListener('click', function() {
175
+ loadBrowserDir(entry.path);
176
+ });
177
+
178
+ row.appendChild(folderIcon);
179
+ row.appendChild(nameSpan);
180
+
181
+ if (added) {
182
+ var removeBtn = document.createElement('button');
183
+ removeBtn.textContent = 'Remove';
184
+ removeBtn.type = 'button';
185
+ removeBtn.className = 'text-red-500 hover:text-red-700 text-xs font-medium flex-shrink-0';
186
+ removeBtn.addEventListener('click', function(e) {
187
+ e.stopPropagation();
188
+ var chips = folderList.querySelectorAll('[data-folder-chip]');
189
+ for (var i = 0; i < chips.length; i++) {
190
+ if (chips[i].getAttribute('data-folder-chip') === entry.path) {
191
+ removeFolderChip(chips[i]);
192
+ break;
193
+ }
194
+ }
195
+ loadBrowserDir(currentBrowserDir);
196
+ });
197
+ row.appendChild(removeBtn);
198
+ } else if (!covered) {
199
+ var addBtn = document.createElement('button');
200
+ addBtn.textContent = 'Add';
201
+ addBtn.type = 'button';
202
+ addBtn.className = 'text-blue-600 hover:text-blue-800 text-xs font-medium flex-shrink-0';
203
+ addBtn.addEventListener('click', function(e) {
204
+ e.stopPropagation();
205
+ addFolderChip(entry.path);
206
+ loadBrowserDir(currentBrowserDir);
207
+ });
208
+ row.appendChild(addBtn);
209
+ }
210
+
211
+ browserList.appendChild(row);
212
+ });
213
+ });
214
+ }
215
+
216
+ if (openBrowserBtn && folderBrowser) {
217
+ openBrowserBtn.addEventListener('click', function() {
218
+ var isHidden = folderBrowser.classList.contains('hidden');
219
+ if (isHidden) {
220
+ folderBrowser.classList.remove('hidden');
221
+ openBrowserBtn.textContent = 'Hide browser';
222
+ loadBrowserDir('~');
223
+ } else {
224
+ folderBrowser.classList.add('hidden');
225
+ openBrowserBtn.textContent = 'Browse for folder...';
226
+ }
227
+ });
228
+ }
229
+
230
+ // --- Custom input for patterns (step 2) ---
231
+ var addCustomBtn = document.getElementById('add-custom');
232
+ var customInput = document.getElementById('custom-input');
233
+
234
+ function addCustomPattern() {
235
+ if (!customInput || !patternList) return;
236
+ var value = customInput.value.trim();
237
+ if (!value) return;
238
+ addPatternChip(value);
239
+ customInput.value = '';
240
+ }
241
+
242
+ if (addCustomBtn) {
243
+ addCustomBtn.addEventListener('click', addCustomPattern);
244
+ }
245
+ if (customInput) {
246
+ customInput.addEventListener('keydown', function(e) {
247
+ if (e.key === 'Enter') {
248
+ e.preventDefault();
249
+ addCustomPattern();
250
+ }
251
+ });
252
+ }
253
+
254
+ // --- Update Next button disabled state ---
255
+ function updateNextBtn() {
256
+ var btn = document.getElementById('next-btn');
257
+ if (!btn) return;
258
+ var hasSelection = getSelectedValues().length > 0;
259
+ btn.disabled = !hasSelection;
260
+ if (hasSelection) {
261
+ btn.classList.remove('opacity-50', 'cursor-not-allowed');
262
+ } else {
263
+ btn.classList.add('opacity-50', 'cursor-not-allowed');
264
+ }
265
+ }
266
+
267
+ // --- Collect selected values ---
268
+ function getSelectedValues() {
269
+ var values = [];
270
+ // Folder chips (step 1)
271
+ document.querySelectorAll('[data-folder-chip]').forEach(function(chip) {
272
+ values.push(chip.getAttribute('data-folder-chip'));
273
+ });
274
+ // Pattern chips (step 2)
275
+ document.querySelectorAll('[data-pattern-chip]').forEach(function(chip) {
276
+ values.push(chip.getAttribute('data-pattern-chip'));
277
+ });
278
+ return values;
279
+ }
280
+
281
+ // --- Initial button state ---
282
+ updateNextBtn();
283
+
284
+ // --- Step 1: Next button ---
285
+ var nextBtn = document.getElementById('next-btn');
286
+ if (nextBtn && nextBtn.getAttribute('data-step') === '1') {
287
+ nextBtn.addEventListener('click', function() {
288
+ var roots = getSelectedValues();
289
+ if (roots.length === 0) return;
290
+ var params = new URLSearchParams();
291
+ roots.forEach(function(r) { params.append('roots', r); });
292
+ // Preserve patterns if returning from step 2
293
+ var urlParams = new URLSearchParams(window.location.search);
294
+ urlParams.getAll('patterns').forEach(function(p) { params.append('patterns', p); });
295
+ window.location.href = '/setup/step2?' + params.toString();
296
+ });
297
+ }
298
+
299
+ // --- Step 2: Back button ---
300
+ var backBtn = document.getElementById('back-btn');
301
+ if (backBtn) {
302
+ backBtn.addEventListener('click', function() {
303
+ var urlParams = new URLSearchParams(window.location.search);
304
+ var roots = urlParams.getAll('roots');
305
+ var patterns = getSelectedValues();
306
+ var params = new URLSearchParams();
307
+ roots.forEach(function(r) { params.append('roots', r); });
308
+ patterns.forEach(function(p) { params.append('patterns', p); });
309
+ window.location.href = '/setup?' + params.toString();
310
+ });
311
+ }
312
+
313
+ // --- Step 2: Preview button ---
314
+ if (nextBtn && nextBtn.getAttribute('data-step') === '2') {
315
+ nextBtn.addEventListener('click', function() {
316
+ var patterns = getSelectedValues();
317
+ if (patterns.length === 0) return;
318
+ var urlParams = new URLSearchParams(window.location.search);
319
+ var roots = urlParams.getAll('roots');
320
+ var params = new URLSearchParams();
321
+ roots.forEach(function(r) { params.append('roots', r); });
322
+ patterns.forEach(function(p) { params.append('patterns', p); });
323
+ window.location.href = '/setup/step3?' + params.toString();
324
+ });
325
+ }
326
+
327
+ // --- Step 3: Select/deselect by group ---
328
+ document.querySelectorAll('[data-group-select]').forEach(function(btn) {
329
+ btn.addEventListener('click', function() {
330
+ var group = btn.getAttribute('data-group-select');
331
+ var container = document.querySelector('[data-group="' + group + '"]');
332
+ if (container) {
333
+ container.querySelectorAll('input[name="files"]').forEach(function(cb) {
334
+ cb.checked = true;
335
+ });
336
+ }
337
+ });
338
+ });
339
+ document.querySelectorAll('[data-group-deselect]').forEach(function(btn) {
340
+ btn.addEventListener('click', function() {
341
+ var group = btn.getAttribute('data-group-deselect');
342
+ var container = document.querySelector('[data-group="' + group + '"]');
343
+ if (container) {
344
+ container.querySelectorAll('input[name="files"]').forEach(function(cb) {
345
+ cb.checked = false;
346
+ });
347
+ }
348
+ });
349
+ });
350
+
351
+ // --- Step 3: Select all / Deselect all ---
352
+ var selectAllBtn = document.getElementById('select-all');
353
+ var deselectAllBtn = document.getElementById('deselect-all');
354
+
355
+ if (selectAllBtn) {
356
+ selectAllBtn.addEventListener('click', function() {
357
+ document.querySelectorAll('input[name="files"]').forEach(function(cb) {
358
+ cb.checked = true;
359
+ });
360
+ });
361
+ }
362
+ if (deselectAllBtn) {
363
+ deselectAllBtn.addEventListener('click', function() {
364
+ document.querySelectorAll('input[name="files"]').forEach(function(cb) {
365
+ cb.checked = false;
366
+ });
367
+ });
368
+ }
369
+
370
+ // --- Step 3: Confirm button ---
371
+ var confirmBtn = document.getElementById('confirm-btn');
372
+ if (confirmBtn) {
373
+ confirmBtn.addEventListener('click', function() {
374
+ confirmBtn.disabled = true;
375
+ confirmBtn.textContent = 'Saving...';
376
+
377
+ var urlParams = new URLSearchParams(window.location.search);
378
+ var roots = urlParams.getAll('roots');
379
+ var patterns = urlParams.getAll('patterns');
380
+
381
+ var excludedFiles = [];
382
+ document.querySelectorAll('input[name="files"]').forEach(function(cb) {
383
+ if (!cb.checked) {
384
+ excludedFiles.push(cb.value);
385
+ }
386
+ });
387
+
388
+ fetch('/api/setup/confirm', {
389
+ method: 'POST',
390
+ headers: { 'Content-Type': 'application/json' },
391
+ body: JSON.stringify({ roots: roots, patterns: patterns, excludedFiles: excludedFiles })
392
+ })
393
+ .then(function(res) { return res.json(); })
394
+ .then(function(data) {
395
+ if (data.success) {
396
+ window.location.href = '/setup/complete?count=' + data.trackedCount;
397
+ } else {
398
+ alert('Error saving config. Please try again.');
399
+ confirmBtn.disabled = false;
400
+ confirmBtn.textContent = 'Confirm & Start Tracking';
401
+ }
402
+ })
403
+ .catch(function() {
404
+ alert('Error saving config. Please try again.');
405
+ confirmBtn.disabled = false;
406
+ confirmBtn.textContent = 'Confirm & Start Tracking';
407
+ });
408
+ });
409
+ }
410
+ });
411
+ </script>`;
412
+ //# sourceMappingURL=wizard-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wizard-client.js","sourceRoot":"","sources":["../../../src/dashboard/_archive/wizard-client.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA0Z1B,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare function setupFoldersPage(existingDirs: string[], preservedRoots?: string[]): string;
2
+ export declare function setupPatternsPage(selectedRoots: string[], suggestedPatterns: string[], selectedPatterns: string[]): string;
3
+ export declare function setupPreviewPage(files: Array<{
4
+ path: string;
5
+ category: string;
6
+ root: string;
7
+ }>, roots: string[], patterns: string[]): string;
8
+ export declare function setupCompletePage(fileCount: number): string;
9
+ //# sourceMappingURL=wizard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wizard.d.ts","sourceRoot":"","sources":["../../../src/dashboard/_archive/wizard.ts"],"names":[],"mappings":"AA+EA,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EAAE,EACtB,cAAc,CAAC,EAAE,MAAM,EAAE,GACxB,MAAM,CA2CR;AAED,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,MAAM,EAAE,EACvB,iBAAiB,EAAE,MAAM,EAAE,EAC3B,gBAAgB,EAAE,MAAM,EAAE,GACzB,MAAM,CAiER;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAC9D,KAAK,EAAE,MAAM,EAAE,EACf,QAAQ,EAAE,MAAM,EAAE,GACjB,MAAM,CA+IR;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAe3D"}