@mattli/dotmd 0.1.0 → 0.1.2
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.
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +12 -7
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/serve.d.ts.map +1 -1
- package/dist/cli/commands/serve.js +18 -1
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +10 -5
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/dashboard/_archive/wizard-client.d.ts +2 -0
- package/dist/dashboard/_archive/wizard-client.d.ts.map +1 -0
- package/dist/dashboard/_archive/wizard-client.js +412 -0
- package/dist/dashboard/_archive/wizard-client.js.map +1 -0
- package/dist/dashboard/_archive/wizard.d.ts +9 -0
- package/dist/dashboard/_archive/wizard.d.ts.map +1 -0
- package/dist/dashboard/_archive/wizard.js +317 -0
- package/dist/dashboard/_archive/wizard.js.map +1 -0
- package/dist/dashboard/help.d.ts +2 -0
- package/dist/dashboard/help.d.ts.map +1 -0
- package/dist/dashboard/help.js +73 -0
- package/dist/dashboard/help.js.map +1 -0
- package/dist/dashboard/layout.d.ts.map +1 -1
- package/dist/dashboard/layout.js +1 -0
- package/dist/dashboard/layout.js.map +1 -1
- package/dist/dashboard/server.d.ts +1 -1
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +39 -51
- package/dist/dashboard/server.js.map +1 -1
- package/dist/dashboard/settings-client.d.ts +1 -1
- package/dist/dashboard/settings-client.d.ts.map +1 -1
- package/dist/dashboard/settings-client.js +367 -162
- package/dist/dashboard/settings-client.js.map +1 -1
- package/dist/dashboard/settings.d.ts +5 -1
- package/dist/dashboard/settings.d.ts.map +1 -1
- package/dist/dashboard/settings.js +60 -45
- package/dist/dashboard/settings.js.map +1 -1
- package/dist/dashboard/wizard-client.d.ts +1 -1
- package/dist/dashboard/wizard-client.d.ts.map +1 -1
- package/dist/dashboard/wizard-client.js +226 -80
- package/dist/dashboard/wizard-client.js.map +1 -1
- package/dist/dashboard/wizard.d.ts +2 -2
- package/dist/dashboard/wizard.d.ts.map +1 -1
- package/dist/dashboard/wizard.js +113 -32
- package/dist/dashboard/wizard.js.map +1 -1
- package/package.json +1 -1
|
@@ -9,59 +9,296 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
9
9
|
return div.innerHTML;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
12
|
+
// ===== Folder management =====
|
|
13
|
+
|
|
14
|
+
var folderList = document.getElementById('folder-list');
|
|
15
|
+
var noFoldersMsg = document.getElementById('no-folders-msg');
|
|
16
|
+
|
|
17
|
+
function getAddedFolders() {
|
|
18
|
+
var folders = [];
|
|
19
|
+
if (!folderList) return folders;
|
|
20
|
+
folderList.querySelectorAll('[data-folder-chip]').forEach(function(chip) {
|
|
21
|
+
folders.push(chip.getAttribute('data-folder-chip'));
|
|
22
|
+
});
|
|
23
|
+
return folders;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function isFolderAdded(folderPath) {
|
|
27
|
+
var folders = getAddedFolders();
|
|
28
|
+
for (var i = 0; i < folders.length; i++) {
|
|
29
|
+
if (folders[i] === folderPath) return true;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function isCoveredByParent(folderPath) {
|
|
35
|
+
var folders = getAddedFolders();
|
|
36
|
+
for (var i = 0; i < folders.length; i++) {
|
|
37
|
+
if (folderPath !== folders[i] && folderPath.indexOf(folders[i] + '/') === 0) return true;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function updateNoFoldersMsg() {
|
|
43
|
+
if (!noFoldersMsg) return;
|
|
44
|
+
if (getAddedFolders().length === 0) {
|
|
45
|
+
noFoldersMsg.classList.remove('hidden');
|
|
46
|
+
} else {
|
|
47
|
+
noFoldersMsg.classList.add('hidden');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function removeFolderChip(chip) {
|
|
52
|
+
chip.remove();
|
|
53
|
+
updateNoFoldersMsg();
|
|
54
|
+
scheduleRefresh();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function addFolderChip(folderPath) {
|
|
58
|
+
if (!folderList) return;
|
|
59
|
+
if (isFolderAdded(folderPath)) return;
|
|
60
|
+
|
|
61
|
+
var tag = document.createElement('span');
|
|
62
|
+
tag.setAttribute('data-folder-chip', folderPath);
|
|
63
|
+
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';
|
|
64
|
+
tag.innerHTML = escapeHtml(folderPath) + ' <button type="button" class="ml-1 text-blue-500 hover:text-blue-700 font-bold">×</button>';
|
|
65
|
+
tag.querySelector('button').addEventListener('click', function() {
|
|
66
|
+
removeFolderChip(tag);
|
|
67
|
+
});
|
|
68
|
+
folderList.appendChild(tag);
|
|
69
|
+
updateNoFoldersMsg();
|
|
70
|
+
scheduleRefresh();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Wire up x buttons on server-rendered folder chips
|
|
74
|
+
if (folderList) {
|
|
75
|
+
folderList.querySelectorAll('[data-folder-chip] button').forEach(function(btn) {
|
|
76
|
+
btn.addEventListener('click', function() {
|
|
77
|
+
removeFolderChip(btn.parentElement);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ===== Folder browser =====
|
|
83
|
+
|
|
84
|
+
var openBrowserBtn = document.getElementById('open-browser');
|
|
85
|
+
var folderBrowser = document.getElementById('folder-browser');
|
|
86
|
+
var browserPath = document.getElementById('browser-path');
|
|
87
|
+
var browserList = document.getElementById('browser-list');
|
|
88
|
+
var browserUp = document.getElementById('browser-up');
|
|
89
|
+
|
|
90
|
+
function loadBrowserDir(dir) {
|
|
91
|
+
fetch('/api/setup/browse?dir=' + encodeURIComponent(dir || '~'))
|
|
92
|
+
.then(function(res) { return res.json(); })
|
|
93
|
+
.then(function(data) {
|
|
94
|
+
if (data.error) return;
|
|
95
|
+
currentBrowseDir = data.current;
|
|
96
|
+
if (browserPath) browserPath.textContent = data.current;
|
|
97
|
+
if (browserUp) {
|
|
98
|
+
browserUp.style.display = data.parent ? '' : 'none';
|
|
99
|
+
browserUp.onclick = function() { loadBrowserDir(data.parent); };
|
|
25
100
|
}
|
|
26
|
-
|
|
101
|
+
if (!browserList) return;
|
|
102
|
+
browserList.innerHTML = '';
|
|
103
|
+
|
|
104
|
+
data.dirs.forEach(function(entry) {
|
|
105
|
+
var added = isFolderAdded(entry.path);
|
|
106
|
+
var covered = isCoveredByParent(entry.path);
|
|
107
|
+
|
|
108
|
+
var row = document.createElement('div');
|
|
109
|
+
row.className = 'px-4 py-2 hover:bg-gray-50 flex items-center gap-2 text-sm';
|
|
110
|
+
|
|
111
|
+
var folderIcon = document.createElement('span');
|
|
112
|
+
folderIcon.innerHTML = '📁';
|
|
113
|
+
folderIcon.className = covered ? 'text-gray-300' : 'text-gray-400';
|
|
114
|
+
|
|
115
|
+
var nameSpan = document.createElement('span');
|
|
116
|
+
nameSpan.textContent = entry.name;
|
|
117
|
+
nameSpan.className = covered
|
|
118
|
+
? 'cursor-pointer flex-1 text-gray-300'
|
|
119
|
+
: 'cursor-pointer flex-1 hover:text-blue-600';
|
|
120
|
+
nameSpan.addEventListener('click', function() {
|
|
121
|
+
loadBrowserDir(entry.path);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
row.appendChild(folderIcon);
|
|
125
|
+
row.appendChild(nameSpan);
|
|
126
|
+
|
|
127
|
+
if (added) {
|
|
128
|
+
var removeBtn = document.createElement('button');
|
|
129
|
+
removeBtn.textContent = 'Remove';
|
|
130
|
+
removeBtn.type = 'button';
|
|
131
|
+
removeBtn.className = 'text-red-500 hover:text-red-700 text-xs font-medium flex-shrink-0';
|
|
132
|
+
removeBtn.addEventListener('click', function(e) {
|
|
133
|
+
e.stopPropagation();
|
|
134
|
+
var chips = folderList.querySelectorAll('[data-folder-chip]');
|
|
135
|
+
for (var i = 0; i < chips.length; i++) {
|
|
136
|
+
if (chips[i].getAttribute('data-folder-chip') === entry.path) {
|
|
137
|
+
removeFolderChip(chips[i]);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
loadBrowserDir(currentBrowseDir);
|
|
142
|
+
});
|
|
143
|
+
row.appendChild(removeBtn);
|
|
144
|
+
} else if (!covered) {
|
|
145
|
+
var addBtn = document.createElement('button');
|
|
146
|
+
addBtn.textContent = 'Add';
|
|
147
|
+
addBtn.type = 'button';
|
|
148
|
+
addBtn.className = 'text-blue-600 hover:text-blue-800 text-xs font-medium flex-shrink-0';
|
|
149
|
+
addBtn.addEventListener('click', function(e) {
|
|
150
|
+
e.stopPropagation();
|
|
151
|
+
addFolderChip(entry.path);
|
|
152
|
+
loadBrowserDir(currentBrowseDir);
|
|
153
|
+
});
|
|
154
|
+
row.appendChild(addBtn);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
browserList.appendChild(row);
|
|
158
|
+
});
|
|
27
159
|
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (openBrowserBtn && folderBrowser) {
|
|
163
|
+
openBrowserBtn.addEventListener('click', function() {
|
|
164
|
+
var isHidden = folderBrowser.classList.contains('hidden');
|
|
165
|
+
if (isHidden) {
|
|
166
|
+
folderBrowser.classList.remove('hidden');
|
|
167
|
+
openBrowserBtn.textContent = 'Hide browser';
|
|
168
|
+
loadBrowserDir('~');
|
|
169
|
+
} else {
|
|
170
|
+
folderBrowser.classList.add('hidden');
|
|
171
|
+
openBrowserBtn.textContent = 'Browse for folder...';
|
|
172
|
+
}
|
|
28
173
|
});
|
|
29
174
|
}
|
|
30
175
|
|
|
31
|
-
|
|
32
|
-
initChipToggling(document.getElementById('patterns-list'));
|
|
176
|
+
// ===== Pattern management =====
|
|
33
177
|
|
|
34
|
-
|
|
35
|
-
|
|
178
|
+
var patternList = document.getElementById('pattern-list');
|
|
179
|
+
var suggestedPatternsDiv = document.getElementById('suggested-patterns');
|
|
180
|
+
var noPatternsMsg = document.getElementById('no-patterns-msg');
|
|
181
|
+
|
|
182
|
+
function getSelectedPatterns() {
|
|
36
183
|
var values = [];
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
document.getElementById('roots-list').querySelectorAll('[data-custom-value]').forEach(function(tag) {
|
|
41
|
-
values.push(tag.getAttribute('data-custom-value'));
|
|
184
|
+
if (!patternList) return values;
|
|
185
|
+
patternList.querySelectorAll('[data-pattern-chip]').forEach(function(chip) {
|
|
186
|
+
values.push(chip.getAttribute('data-pattern-chip'));
|
|
42
187
|
});
|
|
43
188
|
return values;
|
|
44
189
|
}
|
|
45
190
|
|
|
46
|
-
function
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
191
|
+
function updateNoPatternsMsg() {
|
|
192
|
+
if (!noPatternsMsg) return;
|
|
193
|
+
if (getSelectedPatterns().length === 0) {
|
|
194
|
+
noPatternsMsg.classList.remove('hidden');
|
|
195
|
+
} else {
|
|
196
|
+
noPatternsMsg.classList.add('hidden');
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function removePatternChip(chip) {
|
|
201
|
+
var value = chip.getAttribute('data-pattern-chip');
|
|
202
|
+
chip.remove();
|
|
203
|
+
// If it's a suggested pattern, unhide it in the suggestions section
|
|
204
|
+
if (suggestedPatternsDiv && value) {
|
|
205
|
+
var suggestions = suggestedPatternsDiv.querySelectorAll('[data-suggested-pattern]');
|
|
206
|
+
for (var i = 0; i < suggestions.length; i++) {
|
|
207
|
+
if (suggestions[i].getAttribute('data-suggested-pattern') === value) {
|
|
208
|
+
suggestions[i].classList.remove('hidden');
|
|
209
|
+
// Show the suggestions section
|
|
210
|
+
var section = document.getElementById('suggestions-section');
|
|
211
|
+
if (section) section.classList.remove('hidden');
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
updateNoPatternsMsg();
|
|
217
|
+
scheduleRefresh();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function addPatternChip(value) {
|
|
221
|
+
if (!patternList) return;
|
|
222
|
+
// Check for duplicates
|
|
223
|
+
var existing = patternList.querySelectorAll('[data-pattern-chip]');
|
|
224
|
+
for (var i = 0; i < existing.length; i++) {
|
|
225
|
+
if (existing[i].getAttribute('data-pattern-chip') === value) return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
var tag = document.createElement('span');
|
|
229
|
+
tag.setAttribute('data-pattern-chip', value);
|
|
230
|
+
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';
|
|
231
|
+
tag.innerHTML = escapeHtml(value) + ' <button type="button" class="ml-1 text-blue-500 hover:text-blue-700 font-bold">×</button>';
|
|
232
|
+
tag.querySelector('button').addEventListener('click', function() {
|
|
233
|
+
removePatternChip(tag);
|
|
50
234
|
});
|
|
51
|
-
|
|
52
|
-
|
|
235
|
+
patternList.appendChild(tag);
|
|
236
|
+
updateNoPatternsMsg();
|
|
237
|
+
scheduleRefresh();
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Wire up x buttons on server-rendered pattern chips
|
|
241
|
+
if (patternList) {
|
|
242
|
+
patternList.querySelectorAll('[data-pattern-chip] button').forEach(function(btn) {
|
|
243
|
+
btn.addEventListener('click', function() {
|
|
244
|
+
removePatternChip(btn.parentElement);
|
|
245
|
+
});
|
|
53
246
|
});
|
|
54
|
-
return values;
|
|
55
247
|
}
|
|
56
248
|
|
|
57
|
-
//
|
|
249
|
+
// Wire up suggested pattern chips — click to add
|
|
250
|
+
if (suggestedPatternsDiv) {
|
|
251
|
+
suggestedPatternsDiv.querySelectorAll('[data-suggested-pattern]').forEach(function(chip) {
|
|
252
|
+
chip.addEventListener('click', function() {
|
|
253
|
+
var value = chip.getAttribute('data-suggested-pattern');
|
|
254
|
+
addPatternChip(value);
|
|
255
|
+
chip.classList.add('hidden');
|
|
256
|
+
// Hide suggestions section if all hidden
|
|
257
|
+
var anyVisible = false;
|
|
258
|
+
suggestedPatternsDiv.querySelectorAll('[data-suggested-pattern]').forEach(function(s) {
|
|
259
|
+
if (!s.classList.contains('hidden')) anyVisible = true;
|
|
260
|
+
});
|
|
261
|
+
if (!anyVisible) {
|
|
262
|
+
var section = document.getElementById('suggestions-section');
|
|
263
|
+
if (section) section.classList.add('hidden');
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Custom pattern input
|
|
270
|
+
var addCustomBtn = document.getElementById('add-custom');
|
|
271
|
+
var customInput = document.getElementById('custom-input');
|
|
272
|
+
|
|
273
|
+
function addCustomPattern() {
|
|
274
|
+
if (!customInput) return;
|
|
275
|
+
var value = customInput.value.trim();
|
|
276
|
+
if (!value) return;
|
|
277
|
+
addPatternChip(value);
|
|
278
|
+
customInput.value = '';
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (addCustomBtn) {
|
|
282
|
+
addCustomBtn.addEventListener('click', addCustomPattern);
|
|
283
|
+
}
|
|
284
|
+
if (customInput) {
|
|
285
|
+
customInput.addEventListener('keydown', function(e) {
|
|
286
|
+
if (e.key === 'Enter') {
|
|
287
|
+
e.preventDefault();
|
|
288
|
+
addCustomPattern();
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// ===== File preview =====
|
|
294
|
+
|
|
58
295
|
function scheduleRefresh() {
|
|
59
296
|
clearTimeout(debounceTimer);
|
|
60
297
|
debounceTimer = setTimeout(refreshPreview, 300);
|
|
61
298
|
}
|
|
62
299
|
|
|
63
300
|
function refreshPreview() {
|
|
64
|
-
var roots =
|
|
301
|
+
var roots = getAddedFolders();
|
|
65
302
|
var patterns = getSelectedPatterns();
|
|
66
303
|
var preview = document.getElementById('file-preview');
|
|
67
304
|
|
|
@@ -94,7 +331,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
94
331
|
return;
|
|
95
332
|
}
|
|
96
333
|
|
|
97
|
-
// Group by root
|
|
334
|
+
// Group by root
|
|
98
335
|
var groups = {};
|
|
99
336
|
var rootOrder = [];
|
|
100
337
|
files.forEach(function(f) {
|
|
@@ -106,173 +343,130 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
106
343
|
groups[root].push(f);
|
|
107
344
|
});
|
|
108
345
|
|
|
109
|
-
var
|
|
346
|
+
var totalFiles = files.length;
|
|
347
|
+
|
|
348
|
+
var html = '<div class="flex gap-3 mb-4 items-center">' +
|
|
110
349
|
'<button type="button" id="preview-select-all" class="text-sm text-blue-600 hover:underline">Select all</button>' +
|
|
111
350
|
'<button type="button" id="preview-deselect-all" class="text-sm text-blue-600 hover:underline">Deselect all</button>' +
|
|
112
|
-
'<span class="text-sm text-gray-400"
|
|
351
|
+
'<span id="file-count" class="text-sm text-gray-400"></span>' +
|
|
113
352
|
'</div>';
|
|
114
353
|
|
|
354
|
+
function checkboxHtml(filePath, displayPath) {
|
|
355
|
+
return '<label class="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-gray-50 cursor-pointer">' +
|
|
356
|
+
'<input type="checkbox" name="files" value="' + escapeHtml(filePath) + '" checked ' +
|
|
357
|
+
'class="rounded border-gray-300 text-blue-600 focus:ring-blue-500">' +
|
|
358
|
+
'<span class="font-mono text-sm">' + escapeHtml(displayPath) + '</span>' +
|
|
359
|
+
'</label>';
|
|
360
|
+
}
|
|
361
|
+
|
|
115
362
|
rootOrder.forEach(function(root) {
|
|
116
363
|
var rootFiles = groups[root];
|
|
117
364
|
if (!rootFiles || rootFiles.length === 0) return;
|
|
118
365
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
366
|
+
// Group by first subdirectory
|
|
367
|
+
var subGroups = {};
|
|
368
|
+
var subGroupOrder = [];
|
|
122
369
|
|
|
123
370
|
rootFiles.forEach(function(file) {
|
|
124
|
-
// Show path relative to the root for cleaner display
|
|
125
371
|
var displayPath = file.path;
|
|
126
372
|
if (root !== 'Other' && displayPath.indexOf(root) === 0) {
|
|
127
373
|
displayPath = displayPath.slice(root.length + 1);
|
|
128
374
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
375
|
+
var firstSlash = displayPath.indexOf('/');
|
|
376
|
+
var groupName = firstSlash === -1 ? '' : displayPath.slice(0, firstSlash);
|
|
377
|
+
if (!subGroups[groupName]) {
|
|
378
|
+
subGroups[groupName] = [];
|
|
379
|
+
subGroupOrder.push(groupName);
|
|
380
|
+
}
|
|
381
|
+
subGroups[groupName].push({ path: file.path, displayPath: displayPath });
|
|
134
382
|
});
|
|
135
383
|
|
|
384
|
+
var hasSubGroups = subGroupOrder.length > 1 || subGroupOrder[0] !== '';
|
|
385
|
+
|
|
386
|
+
html += '<div class="mb-4">';
|
|
387
|
+
html += '<h3 class="text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2">' + escapeHtml(root) + '</h3>';
|
|
388
|
+
html += '<div class="space-y-1">';
|
|
389
|
+
|
|
390
|
+
if (!hasSubGroups) {
|
|
391
|
+
subGroups[''].forEach(function(file) {
|
|
392
|
+
html += checkboxHtml(file.path, file.displayPath);
|
|
393
|
+
});
|
|
394
|
+
} else {
|
|
395
|
+
if (subGroups['']) {
|
|
396
|
+
subGroups[''].forEach(function(file) {
|
|
397
|
+
html += checkboxHtml(file.path, file.displayPath);
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
subGroupOrder.forEach(function(groupName) {
|
|
401
|
+
if (groupName === '') return;
|
|
402
|
+
var groupFiles = subGroups[groupName];
|
|
403
|
+
html += '<details class="mt-1">' +
|
|
404
|
+
'<summary class="cursor-pointer text-sm text-gray-600 hover:text-gray-800 px-3 py-1.5 rounded-lg hover:bg-gray-50 select-none">' +
|
|
405
|
+
escapeHtml(groupName) + '/ <span class="text-gray-400">(' + groupFiles.length + ')</span>' +
|
|
406
|
+
'</summary><div class="ml-4">';
|
|
407
|
+
groupFiles.forEach(function(file) {
|
|
408
|
+
html += checkboxHtml(file.path, file.displayPath);
|
|
409
|
+
});
|
|
410
|
+
html += '</div></details>';
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
|
|
136
414
|
html += '</div></div>';
|
|
137
415
|
});
|
|
138
416
|
|
|
139
417
|
preview.innerHTML = html;
|
|
140
418
|
preview.style.minHeight = '';
|
|
141
419
|
|
|
142
|
-
|
|
420
|
+
function updateFileCount() {
|
|
421
|
+
var checked = preview.querySelectorAll('input[name="files"]:checked').length;
|
|
422
|
+
var countEl = document.getElementById('file-count');
|
|
423
|
+
if (countEl) {
|
|
424
|
+
countEl.textContent = checked + ' of ' + totalFiles + ' file' + (totalFiles === 1 ? '' : 's') + ' selected';
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Listen for checkbox changes
|
|
429
|
+
preview.querySelectorAll('input[name="files"]').forEach(function(cb) {
|
|
430
|
+
cb.addEventListener('change', updateFileCount);
|
|
431
|
+
});
|
|
432
|
+
|
|
143
433
|
var selectAll = document.getElementById('preview-select-all');
|
|
144
434
|
var deselectAll = document.getElementById('preview-deselect-all');
|
|
145
435
|
if (selectAll) {
|
|
146
436
|
selectAll.addEventListener('click', function() {
|
|
147
437
|
preview.querySelectorAll('input[name="files"]').forEach(function(cb) { cb.checked = true; });
|
|
438
|
+
updateFileCount();
|
|
148
439
|
});
|
|
149
440
|
}
|
|
150
441
|
if (deselectAll) {
|
|
151
442
|
deselectAll.addEventListener('click', function() {
|
|
152
443
|
preview.querySelectorAll('input[name="files"]').forEach(function(cb) { cb.checked = false; });
|
|
444
|
+
updateFileCount();
|
|
153
445
|
});
|
|
154
446
|
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// --- Folder browser ---
|
|
158
|
-
var openBrowserBtn = document.getElementById('open-browser');
|
|
159
|
-
var folderBrowser = document.getElementById('folder-browser');
|
|
160
|
-
var browserPath = document.getElementById('browser-path');
|
|
161
|
-
var browserList = document.getElementById('browser-list');
|
|
162
|
-
var browserUp = document.getElementById('browser-up');
|
|
163
|
-
var browserAdd = document.getElementById('browser-add');
|
|
164
|
-
var rootsList = document.getElementById('roots-list');
|
|
165
|
-
|
|
166
|
-
if (browserAdd) {
|
|
167
|
-
browserAdd.addEventListener('click', function() {
|
|
168
|
-
if (currentBrowseDir) {
|
|
169
|
-
addCustomChip(rootsList, currentBrowseDir);
|
|
170
|
-
scheduleRefresh();
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
function addCustomChip(container, value) {
|
|
176
|
-
// Don't add duplicates
|
|
177
|
-
var existing = container.querySelectorAll('[data-custom-value]');
|
|
178
|
-
for (var i = 0; i < existing.length; i++) {
|
|
179
|
-
if (existing[i].getAttribute('data-custom-value') === value) return;
|
|
180
|
-
}
|
|
181
|
-
var chips = container.querySelectorAll('[data-chip]');
|
|
182
|
-
for (var i = 0; i < chips.length; i++) {
|
|
183
|
-
if (chips[i].getAttribute('data-value') === value) return;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
var tag = document.createElement('span');
|
|
187
|
-
tag.setAttribute('data-custom-value', value);
|
|
188
|
-
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';
|
|
189
|
-
tag.innerHTML = escapeHtml(value) + ' <button type="button" class="ml-1 text-blue-500 hover:text-blue-700 font-bold">×</button>';
|
|
190
|
-
tag.querySelector('button').addEventListener('click', function() {
|
|
191
|
-
tag.remove();
|
|
192
|
-
scheduleRefresh();
|
|
193
|
-
});
|
|
194
|
-
container.appendChild(tag);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
function loadBrowserDir(dir) {
|
|
198
|
-
fetch('/api/setup/browse?dir=' + encodeURIComponent(dir || '~'))
|
|
199
|
-
.then(function(res) { return res.json(); })
|
|
200
|
-
.then(function(data) {
|
|
201
|
-
if (data.error) return;
|
|
202
|
-
currentBrowseDir = data.current;
|
|
203
|
-
if (browserPath) browserPath.textContent = data.current;
|
|
204
|
-
if (browserUp) {
|
|
205
|
-
browserUp.style.display = data.parent ? '' : 'none';
|
|
206
|
-
browserUp.onclick = function() { loadBrowserDir(data.parent); };
|
|
207
|
-
}
|
|
208
|
-
if (!browserList) return;
|
|
209
|
-
browserList.innerHTML = '';
|
|
210
|
-
|
|
211
|
-
data.dirs.forEach(function(entry) {
|
|
212
|
-
var row = document.createElement('div');
|
|
213
|
-
row.className = 'px-4 py-2 hover:bg-gray-50 cursor-pointer flex items-center gap-2 text-sm';
|
|
214
|
-
row.innerHTML = '<span class="text-gray-400">📁</span> ' + escapeHtml(entry.name);
|
|
215
|
-
row.addEventListener('click', function() {
|
|
216
|
-
loadBrowserDir(entry.path);
|
|
217
|
-
});
|
|
218
|
-
browserList.appendChild(row);
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
if (openBrowserBtn && folderBrowser) {
|
|
224
|
-
openBrowserBtn.addEventListener('click', function() {
|
|
225
|
-
var isHidden = folderBrowser.classList.contains('hidden');
|
|
226
|
-
if (isHidden) {
|
|
227
|
-
folderBrowser.classList.remove('hidden');
|
|
228
|
-
openBrowserBtn.textContent = 'Hide browser';
|
|
229
|
-
loadBrowserDir('~');
|
|
230
|
-
} else {
|
|
231
|
-
folderBrowser.classList.add('hidden');
|
|
232
|
-
openBrowserBtn.textContent = 'Browse for folder...';
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// --- Custom pattern input ---
|
|
238
|
-
var addBtn = document.getElementById('add-custom');
|
|
239
|
-
var customInput = document.getElementById('custom-input');
|
|
240
|
-
var patternsList = document.getElementById('patterns-list');
|
|
241
447
|
|
|
242
|
-
|
|
243
|
-
if (!customInput || !patternsList) return;
|
|
244
|
-
var value = customInput.value.trim();
|
|
245
|
-
if (!value) return;
|
|
246
|
-
addCustomChip(patternsList, value);
|
|
247
|
-
customInput.value = '';
|
|
248
|
-
scheduleRefresh();
|
|
448
|
+
updateFileCount();
|
|
249
449
|
}
|
|
250
450
|
|
|
251
|
-
|
|
252
|
-
addBtn.addEventListener('click', addCustomPattern);
|
|
253
|
-
}
|
|
254
|
-
if (customInput) {
|
|
255
|
-
customInput.addEventListener('keydown', function(e) {
|
|
256
|
-
if (e.key === 'Enter') {
|
|
257
|
-
e.preventDefault();
|
|
258
|
-
addCustomPattern();
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
}
|
|
451
|
+
// ===== Save =====
|
|
262
452
|
|
|
263
|
-
// --- Save ---
|
|
264
453
|
var saveBtn = document.getElementById('save-btn');
|
|
265
454
|
var saveStatus = document.getElementById('save-status');
|
|
266
455
|
|
|
267
456
|
if (saveBtn) {
|
|
268
457
|
saveBtn.addEventListener('click', function() {
|
|
458
|
+
var roots = getAddedFolders();
|
|
459
|
+
var patterns = getSelectedPatterns();
|
|
460
|
+
|
|
461
|
+
if (roots.length === 0 || patterns.length === 0) {
|
|
462
|
+
alert('Please select at least one folder and one pattern.');
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
|
|
269
466
|
saveBtn.disabled = true;
|
|
270
467
|
saveBtn.textContent = 'Saving...';
|
|
271
468
|
if (saveStatus) saveStatus.classList.add('hidden');
|
|
272
469
|
|
|
273
|
-
var roots = getSelectedRoots();
|
|
274
|
-
var patterns = getSelectedPatterns();
|
|
275
|
-
|
|
276
470
|
var excludedFiles = [];
|
|
277
471
|
document.querySelectorAll('#file-preview input[name="files"]').forEach(function(cb) {
|
|
278
472
|
if (!cb.checked) {
|
|
@@ -287,23 +481,34 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
287
481
|
})
|
|
288
482
|
.then(function(res) { return res.json(); })
|
|
289
483
|
.then(function(data) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
484
|
+
if (data.success) {
|
|
485
|
+
var shouldRedirect = saveBtn.getAttribute('data-redirect') === 'true';
|
|
486
|
+
if (shouldRedirect) {
|
|
487
|
+
window.location.href = '/?setup=complete&count=' + data.trackedCount;
|
|
488
|
+
} else {
|
|
489
|
+
saveBtn.disabled = false;
|
|
490
|
+
saveBtn.textContent = 'Save';
|
|
491
|
+
if (saveStatus) {
|
|
492
|
+
saveStatus.textContent = 'Settings saved. Tracking ' + data.trackedCount + ' file' + (data.trackedCount === 1 ? '' : 's') + '.';
|
|
493
|
+
saveStatus.classList.remove('hidden');
|
|
494
|
+
setTimeout(function() { saveStatus.classList.add('hidden'); }, 3000);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
} else {
|
|
498
|
+
saveBtn.disabled = false;
|
|
499
|
+
saveBtn.textContent = saveBtn.getAttribute('data-redirect') === 'true' ? 'Start Tracking' : 'Save';
|
|
500
|
+
alert('Error saving. Please try again.');
|
|
296
501
|
}
|
|
297
502
|
})
|
|
298
503
|
.catch(function() {
|
|
299
504
|
saveBtn.disabled = false;
|
|
300
|
-
saveBtn.textContent = 'Save';
|
|
301
|
-
alert('Error saving
|
|
505
|
+
saveBtn.textContent = saveBtn.getAttribute('data-redirect') === 'true' ? 'Start Tracking' : 'Save';
|
|
506
|
+
alert('Error saving. Please try again.');
|
|
302
507
|
});
|
|
303
508
|
});
|
|
304
509
|
}
|
|
305
510
|
|
|
306
|
-
//
|
|
511
|
+
// ===== Initial load =====
|
|
307
512
|
refreshPreview();
|
|
308
513
|
});
|
|
309
514
|
</script>`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-client.js","sourceRoot":"","sources":["../../src/dashboard/settings-client.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,sBAAsB,GAAG
|
|
1
|
+
{"version":3,"file":"settings-client.js","sourceRoot":"","sources":["../../src/dashboard/settings-client.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAigB5B,CAAC"}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import { DotmdConfig } from "../config/defaults.js";
|
|
2
|
-
|
|
2
|
+
interface SetupPageOptions {
|
|
3
|
+
isInit?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare function setupPage(config: DotmdConfig, suggestedRoots: string[], suggestedPatterns: string[], options?: SetupPageOptions): string;
|
|
6
|
+
export {};
|
|
3
7
|
//# sourceMappingURL=settings.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/dashboard/settings.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/dashboard/settings.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAyBpD,UAAU,gBAAgB;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,SAAS,CACvB,MAAM,EAAE,WAAW,EACnB,cAAc,EAAE,MAAM,EAAE,EACxB,iBAAiB,EAAE,MAAM,EAAE,EAC3B,OAAO,GAAE,gBAAqB,GAC7B,MAAM,CAoGR"}
|