Replace row/col number inputs with graphical grid cell picker
Click a cell in the visual grid to select it. Cell images shown where available. Selected cell highlighted with accent border. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1625,8 +1625,9 @@ function open_inventory_dialog(entry = null, default_component_id = null, defaul
|
||||
const new_comp_btn = qs(dlg, '#i-new-component');
|
||||
const grid_row_div = qs(dlg, '#i-grid-row');
|
||||
const grid_sel = qs(dlg, '#i-grid-select');
|
||||
const row_num_input = qs(dlg, '#i-grid-row-num');
|
||||
const col_num_input = qs(dlg, '#i-grid-col-num');
|
||||
const grid_visual = qs(dlg, '#i-grid-visual');
|
||||
let picker_row = null;
|
||||
let picker_col = null;
|
||||
|
||||
title.textContent = entry ? 'Edit inventory entry' : 'Add inventory entry';
|
||||
|
||||
@@ -1659,8 +1660,44 @@ function open_inventory_dialog(entry = null, default_component_id = null, defaul
|
||||
}))
|
||||
);
|
||||
if (effective_grid_cell?.grid_id) { grid_sel.value = effective_grid_cell.grid_id; }
|
||||
row_num_input.value = effective_grid_cell?.grid_row != null ? effective_grid_cell.grid_row + 1 : 1;
|
||||
col_num_input.value = effective_grid_cell?.grid_col != null ? effective_grid_cell.grid_col + 1 : 1;
|
||||
picker_row = effective_grid_cell?.grid_row ?? null;
|
||||
picker_col = effective_grid_cell?.grid_col ?? null;
|
||||
|
||||
function rebuild_grid_visual() {
|
||||
const grid = all_grids.find(g => g.id === grid_sel.value);
|
||||
if (!grid) { grid_visual.replaceChildren(); return; }
|
||||
grid_visual.style.gridTemplateColumns = `repeat(${grid.cols}, 1fr)`;
|
||||
const cells = [];
|
||||
for (let r = 0; r < grid.rows; r++) {
|
||||
for (let c = 0; c < grid.cols; c++) {
|
||||
const cell = document.createElement('div');
|
||||
cell.className = 'igv-cell';
|
||||
if (r === picker_row && c === picker_col) cell.classList.add('igv-selected');
|
||||
const filename = grid.cells?.[r]?.[c];
|
||||
if (filename) {
|
||||
const img = document.createElement('img');
|
||||
img.src = `/img/${filename}`;
|
||||
img.className = 'igv-img';
|
||||
cell.appendChild(img);
|
||||
}
|
||||
cell.addEventListener('click', () => {
|
||||
picker_row = r;
|
||||
picker_col = c;
|
||||
grid_visual.querySelectorAll('.igv-cell').forEach(el => el.classList.remove('igv-selected'));
|
||||
cell.classList.add('igv-selected');
|
||||
});
|
||||
cells.push(cell);
|
||||
}
|
||||
}
|
||||
grid_visual.replaceChildren(...cells);
|
||||
}
|
||||
|
||||
rebuild_grid_visual();
|
||||
|
||||
const old_grid_handler = grid_sel._change_handler;
|
||||
if (old_grid_handler) grid_sel.removeEventListener('change', old_grid_handler);
|
||||
grid_sel._change_handler = () => { picker_row = null; picker_col = null; rebuild_grid_visual(); };
|
||||
grid_sel.addEventListener('change', grid_sel._change_handler);
|
||||
|
||||
function update_ref_label() {
|
||||
ref_label.textContent = ref_label_for_type(type_sel.value);
|
||||
@@ -1700,8 +1737,8 @@ function open_inventory_dialog(entry = null, default_component_id = null, defaul
|
||||
quantity: qty_input.value.trim(),
|
||||
notes: notes_input.value.trim(),
|
||||
grid_id: is_grid ? (grid_sel.value || null) : null,
|
||||
grid_row: is_grid ? parseInt(row_num_input.value) - 1 : null,
|
||||
grid_col: is_grid ? parseInt(col_num_input.value) - 1 : null,
|
||||
grid_row: is_grid ? picker_row : null,
|
||||
grid_col: is_grid ? picker_col : null,
|
||||
};
|
||||
if (entry) {
|
||||
const result = await api.update_inventory(entry.id, body);
|
||||
|
||||
@@ -1504,15 +1504,38 @@ nav {
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.i-grid-coords {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
font-size: 0.9rem;
|
||||
.i-grid-visual {
|
||||
display: grid;
|
||||
gap: 2px;
|
||||
max-height: 320px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.input-narrow {
|
||||
width: 4rem;
|
||||
.igv-cell {
|
||||
position: relative;
|
||||
aspect-ratio: 1;
|
||||
background: var(--surface-raised);
|
||||
border: 2px solid transparent;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.igv-cell:hover {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.igv-cell.igv-selected {
|
||||
border-color: var(--accent);
|
||||
box-shadow: inset 0 0 0 1px var(--accent);
|
||||
}
|
||||
|
||||
.igv-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* ===== CELL INVENTORY OVERLAY ===== */
|
||||
|
||||
@@ -444,12 +444,7 @@
|
||||
<label>Grid cell</label>
|
||||
<div class="i-grid-cell-picker">
|
||||
<select id="i-grid-select" class="filter-select"></select>
|
||||
<div class="i-grid-coords">
|
||||
<label for="i-grid-row-num">Row</label>
|
||||
<input type="number" id="i-grid-row-num" min="1" class="input-narrow">
|
||||
<label for="i-grid-col-num">Col</label>
|
||||
<input type="number" id="i-grid-col-num" min="1" class="input-narrow">
|
||||
</div>
|
||||
<div id="i-grid-visual" class="i-grid-visual"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
|
||||
Reference in New Issue
Block a user