1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
{{define "body-duplicate-rooms"}}
<style>
.dup-body{max-width:800px;margin:40px auto;font-family:monospace}
.dup-body h1{color:var(--danger)}
.dup-body p.hint{color:#aaa;margin-bottom:20px;line-height:1.6}
.dup-group{border:1px solid var(--border);border-radius:5px;margin-bottom:12px;overflow:hidden}
.dup-group-header{background:rgba(192,57,43,.15);padding:8px 12px;font-size:13px;font-weight:bold;color:var(--danger)}
.dup-row{display:flex;align-items:center;gap:8px;padding:6px 12px;border-top:1px solid rgba(255,255,255,.03);font-size:11px}
.dup-row .dup-path{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text)}
.dup-row .dup-path code{font-size:10px;color:#6cf}
.dup-row input{width:80px;padding:3px 5px;font-size:11px;background:var(--input-bg);color:var(--text);border:1px solid var(--input-border);border-radius:3px;font-family:monospace}
.dup-row button{padding:3px 8px;font-size:11px;white-space:nowrap}
.dup-actions{margin:20px 0;display:flex;gap:8px;align-items:center}
.dup-actions .dup-count{color:#888;font-size:11px;flex:1}
.dup-none{color:var(--success);font-size:14px;text-align:center;margin:30px 0}
</style>
<div class="dup-body">
<h1>Duplicate Room IDs Detected</h1>
<p class="hint">
The following room IDs appear in multiple files. This corrupts the map and makes
the editor unreliable. Delete extra copies or rename them to new unique IDs.
</p>
<div id="dupList"><p style="color:#888;text-align:center">Loading…</p></div>
<div class="dup-actions">
<button class="btn btn-primary" onclick="checkDups()">Re-check</button>
<span class="dup-count" id="dupCount"></span>
<button class="btn btn-success" id="continueBtn" style="display:none" onclick="window.location='/'">Continue to Map Editor</button>
</div>
<div id="dupMsg" style="margin-top:12px"></div>
</div>
<script>
function checkDups() {
var listEl = document.getElementById('dupList');
listEl.innerHTML = '<p style="color:#888;text-align:center">Loading…</p>';
API.get('/api/duplicate-rooms').then(function(data) {
var dups = data.duplicates || [];
document.getElementById('dupCount').textContent = dups.length + ' duplicate group' + (dups.length !== 1 ? 's' : '');
var continueBtn = document.getElementById('continueBtn');
continueBtn.style.display = dups.length === 0 ? 'inline-block' : 'none';
if (dups.length === 0) {
document.getElementById('dupMsg').innerHTML = '';
listEl.innerHTML = '<div class="dup-none">No duplicate room IDs found.</div>';
return;
}
var html = '';
dups.forEach(function(d) {
html += '<div class="dup-group"><div class="dup-group-header">Room ID: ' + esc(d.id) + ' (' + d.paths.length + ' copies)</div>';
d.paths.forEach(function(p, idx) {
var short = p.replace(/^.*\/data\/rooms\//, '');
html += '<div class="dup-row">';
html += '<span class="dup-path"><code>' + esc(short) + '</code></span>';
html += '<button class="btn btn-sm btn-danger" onclick="deleteDupFile(\'' + escAttr(p) + '\')">Delete</button>';
html += '<input type="number" id="rename-' + escAttr(d.id) + '-' + idx + '" placeholder="new ID" style="width:80px">';
html += '<button class="btn btn-sm btn-primary" onclick="renameDupFile(\'' + escAttr(p) + '\',\'rename-' + escAttr(d.id) + '-' + idx + '\')">Rename</button>';
html += '</div>';
});
html += '</div>';
});
listEl.innerHTML = html;
}).catch(function(e) {
listEl.innerHTML = '<p style="color:var(--danger)">Failed to load: ' + esc(e.message) + '</p>';
});
}
function deleteDupFile(path) {
if (!confirm('Delete this file?\n\n' + path)) return;
API.post('/api/rooms/resolve-duplicate', {path: path, action: 'delete'}).then(function() {
notify('Deleted', 'success');
checkDups();
}).catch(function(e) {
notify('Delete failed: ' + e.message, 'error');
});
}
function renameDupFile(path, inputId) {
var el = document.getElementById(inputId);
var newID = parseInt(el.value, 10);
if (!newID || newID <= 0) { notify('Enter a valid new room ID', 'error'); return; }
if (!confirm('Rename this file to ID ' + newID + '?\n\n' + path)) return;
API.post('/api/rooms/resolve-duplicate', {path: path, action: 'rename', new_id: newID}).then(function() {
notify('Renamed to ' + newID, 'success');
checkDups();
}).catch(function(e) {
notify('Rename failed: ' + e.message, 'error');
});
}
function esc(s) { return String(s || '').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); }
function escAttr(s) { return String(s || '').replace(/&/g,'&').replace(/"/g,'"'); }
checkDups();
</script>
{{end}}
|