Skip to content

Commit 4809cb0

Browse files
authored
Merge pull request #114 from Denis-RZ/codex/enhance-visual-feedback-for-layout-zones
Improve visual feedback in page editor
2 parents aaeccd5 + 52e84d3 commit 4809cb0

2 files changed

Lines changed: 71 additions & 3 deletions

File tree

website/MyWebApp/wwwroot/css/admin.css

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,3 +1290,28 @@ form.mb-3 {
12901290
.zone-sections {
12911291
min-height: 10px;
12921292
}
1293+
.zone-group.drag-over {
1294+
border-color: #0ea5e9;
1295+
background: #f0f9ff;
1296+
}
1297+
.drop-indicator {
1298+
height: 4px;
1299+
background: #0ea5e9;
1300+
margin: 4px 0;
1301+
border-radius: 2px;
1302+
}
1303+
.section-editor {
1304+
border: 1px solid #cbd5e1;
1305+
background: #fff;
1306+
padding: 0.5rem;
1307+
margin-bottom: 0.5rem;
1308+
}
1309+
.section-editor:hover {
1310+
box-shadow: 0 0 0 2px #0ea5e9 inset;
1311+
}
1312+
.layout-preview {
1313+
border: 1px solid #e2e8f0;
1314+
padding: 0.5rem;
1315+
}
1316+
.zone-group[data-zone="main"] { border-color: #2563eb; }
1317+
.zone-group[data-zone="sidebar"] { border-color: #16a34a; }

website/MyWebApp/wwwroot/js/page-editor.js

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ window.addEventListener('load', () => {
1515
group.className = 'zone-group';
1616
group.dataset.zone = z;
1717
const h = document.createElement('h3');
18-
h.textContent = z;
18+
h.innerHTML = `<span class="zone-name">${z}</span> <span class="zone-count"></span>`;
1919
const div = document.createElement('div');
2020
div.className = 'zone-sections';
2121
group.appendChild(h);
@@ -24,6 +24,14 @@ window.addEventListener('load', () => {
2424
});
2525
}
2626

27+
function updateZoneCounts() {
28+
document.querySelectorAll('.zone-group').forEach(g => {
29+
const count = g.querySelectorAll('.section-editor').length;
30+
const span = g.querySelector('.zone-count');
31+
if (span) span.textContent = `(${count})`;
32+
});
33+
}
34+
2735
function populateZones(select) {
2836
if (!select) return;
2937
const current = select.dataset.selected || select.value;
@@ -47,14 +55,17 @@ window.addEventListener('load', () => {
4755
const div = document.createElement('div');
4856
div.className = 'preview-zone';
4957
div.dataset.zone = z;
50-
div.textContent = z;
58+
const count = container.querySelectorAll(`.zone-group[data-zone='${z}'] .section-editor`).length;
59+
div.textContent = `${z} (${count})`;
5160
preview.appendChild(div);
5261
});
5362
}
5463

5564
document.getElementById('layout-preview')?.addEventListener('click', e => {
5665
const zone = e.target.closest('.preview-zone');
5766
if (!zone) return;
67+
const group = container.querySelector(`.zone-group[data-zone='${zone.dataset.zone}']`);
68+
if (group) group.scrollIntoView({ behavior: 'smooth' });
5869
if (activeIndex !== null) {
5970
const select = document.querySelector(`.zone-select[data-index='${activeIndex}']`);
6071
if (select) {
@@ -96,6 +107,7 @@ window.addEventListener('load', () => {
96107
initSectionEditor(idx);
97108
});
98109
updatePreview();
110+
updateZoneCounts();
99111

100112
document.getElementById('add-section').addEventListener('click', () => {
101113
addSection();
@@ -110,12 +122,14 @@ window.addEventListener('load', () => {
110122
});
111123
updateIndexes();
112124
updatePreview();
125+
updateZoneCounts();
113126
});
114127

115128
container.addEventListener('click', e => {
116129
if (e.target.classList.contains('remove-section')) {
117130
e.target.closest('.section-editor').remove();
118131
updateIndexes();
132+
updateZoneCounts();
119133
} else if (e.target.classList.contains('duplicate-section')) {
120134
const original = e.target.closest('.section-editor');
121135
duplicateSection(original);
@@ -127,6 +141,7 @@ window.addEventListener('load', () => {
127141
const section = e.target.closest('.section-editor');
128142
placeSection(section);
129143
updateIndexes();
144+
updateZoneCounts();
130145
}
131146
});
132147

@@ -142,6 +157,7 @@ window.addEventListener('load', () => {
142157
initSectionEditor(index);
143158
updateIndexes();
144159
updatePreview();
160+
updateZoneCounts();
145161
}
146162

147163
function duplicateSection(original) {
@@ -173,6 +189,7 @@ window.addEventListener('load', () => {
173189
}
174190
updateIndexes();
175191
updatePreview();
192+
updateZoneCounts();
176193
}
177194

178195
function updateIndexes() {
@@ -187,22 +204,48 @@ window.addEventListener('load', () => {
187204
}
188205

189206
let dragged = null;
207+
const dropIndicator = document.createElement('div');
208+
dropIndicator.className = 'drop-indicator';
209+
190210
container.addEventListener('dragstart', e => {
191211
dragged = e.target.closest('.section-editor');
212+
if (dragged) {
213+
dragged.classList.add('dragging');
214+
document.querySelectorAll('.zone-group').forEach(z => z.classList.add('drag-over'));
215+
}
192216
e.dataTransfer.effectAllowed = 'move';
193217
});
218+
194219
container.addEventListener('dragover', e => {
195220
e.preventDefault();
221+
const zone = e.target.closest('.zone-group');
196222
const target = e.target.closest('.section-editor');
223+
if (zone) zone.classList.add('drag-over');
197224
if (dragged && target && target !== dragged) {
198225
const rect = target.getBoundingClientRect();
199226
const next = (e.clientY - rect.top) > (rect.height / 2);
200-
target.parentNode.insertBefore(dragged, next ? target.nextSibling : target);
227+
target.parentNode.insertBefore(dropIndicator, next ? target.nextSibling : target);
201228
}
202229
});
230+
231+
['dragleave', 'drop'].forEach(evt => {
232+
container.addEventListener(evt, e => {
233+
const zone = e.target.closest('.zone-group');
234+
if (zone) zone.classList.remove('drag-over');
235+
});
236+
});
237+
203238
container.addEventListener('drop', e => {
204239
e.preventDefault();
240+
if (dropIndicator.parentNode) {
241+
dropIndicator.parentNode.insertBefore(dragged, dropIndicator);
242+
dropIndicator.remove();
243+
}
244+
document.querySelectorAll('.zone-group.drag-over').forEach(z => z.classList.remove('drag-over'));
245+
if (dragged) dragged.classList.remove('dragging');
246+
dragged = null;
205247
updateIndexes();
248+
updateZoneCounts();
206249
});
207250

208251
const form = document.querySelector('form');

0 commit comments

Comments
 (0)