Aggiunge spostamento tra gruppi 0.4.2
This commit is contained in:
1 parent
eb5f51795b
commit
f1224b21c4
5 files changed
+140
-31
No files matched your search
+118
-28
@@ -1184,7 +1184,7 @@ function drawingLayerLabel(layer, layerType) {
|
||||
function layerManagerCategories() {
|
||||
return [
|
||||
{ key: "gpsPosition", label: "Posizione GPS", roots: [lmeState.gpsMarker, lmeState.gpsAccuracy].filter(Boolean) },
|
||||
{ key: "drawings", label: "Disegni e POI", roots: [lmeState.drawings].filter(Boolean) },
|
||||
{ key: "drawings", label: "Disegni e POI", roots: [lmeState.drawings].filter(Boolean), blocks: true },
|
||||
{ key: "gpsTrail", label: "Traccia GPS", roots: [lmeState.gpsTrail].filter(Boolean) },
|
||||
{ key: "gpsParcels", label: "Particella rilevata dal GPS", roots: [lmeState.gpsParcelLayer].filter(Boolean) },
|
||||
{ key: "selectedParcels", label: "Particelle catastali evidenziate", roots: [lmeState.selectedParcelsLayer].filter(Boolean) },
|
||||
@@ -1382,11 +1382,11 @@ function managedObjectCanRemove(record) {
|
||||
return ["drawings", "imported", "importedSheets", "selectedParcels", "gpsParcels"].includes(record.categoryKey);
|
||||
}
|
||||
|
||||
function layerManagerRowActions(renameButton, removeButton) {
|
||||
if (!renameButton && !removeButton) {
|
||||
function layerManagerRowActions(renameButton, moveButton, removeButton) {
|
||||
if (!renameButton && !moveButton && !removeButton) {
|
||||
return "";
|
||||
}
|
||||
return `<span class="layer-row-actions">${renameButton}${removeButton}</span>`;
|
||||
return `<span class="layer-row-actions">${renameButton}${moveButton}${removeButton}</span>`;
|
||||
}
|
||||
|
||||
const layerManagerPalettes = [
|
||||
@@ -1472,7 +1472,87 @@ function removeManagedRecords(records, subject) {
|
||||
setInfo(`${records.length === 1 ? "Oggetto rimosso" : `${records.length} oggetti rimossi`} dal progetto.`);
|
||||
}
|
||||
|
||||
function moveManagedRecordsToCategory(records, targetCategory) {
|
||||
function managedMoveDestinations() {
|
||||
return layerManagerCategories()
|
||||
.filter(category => ["drawings", "imported"].includes(category.key))
|
||||
.map(category => {
|
||||
const records = managedRecordsForCategory(category);
|
||||
const groups = new Map();
|
||||
records.forEach(record => {
|
||||
if (!groups.has(record.source)) {
|
||||
groups.set(record.source, managedBlockName(record.source, [record]));
|
||||
}
|
||||
});
|
||||
if (!groups.size) {
|
||||
groups.set("Progetto corrente", "Gruppo principale");
|
||||
}
|
||||
return {
|
||||
key: category.key,
|
||||
name: managedCategoryName(category, records),
|
||||
groups: [...groups].map(([source, name]) => ({ source, name }))
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function showMoveManagedRecordsDialog(records, subject) {
|
||||
if (lmeState.readOnly) { setInfo("Il progetto e' in sola lettura."); return; }
|
||||
if (!records.length || records.some(record => !["drawings", "imported"].includes(record.categoryKey))) {
|
||||
setInfo("Questo oggetto o gruppo non puo essere spostato.");
|
||||
return;
|
||||
}
|
||||
if (records.some(record => record.layer?.feature?.properties?._lmeLocked)) {
|
||||
setInfo("Sblocca prima tutti gli oggetti da spostare.");
|
||||
return;
|
||||
}
|
||||
const destinations = managedMoveDestinations();
|
||||
const categoryOptions = destinations.map(destination =>
|
||||
`<option value="${escapeHtml(destination.key)}">${escapeHtml(destination.name)}</option>`).join("");
|
||||
const dialog = showAppDialog("Sposta nel gruppo", `<form class="lme-edit-form move-group-form"><p>Cambia l'appartenenza di ${escapeHtml(subject)} senza modificarne la posizione sulla mappa.</p><label>Categoria<select name="category">${categoryOptions}</select></label><label>Gruppo esistente<select name="group"></select></label><label>Oppure crea un nuovo gruppo<input name="newGroup" type="text" maxlength="120" placeholder="Nome del nuovo gruppo"></label><div class="dialog-command-row"><button type="button" data-cancel>Annulla</button><button type="submit" class="primary-command">Sposta nel gruppo</button></div></form>`);
|
||||
const form = dialog.querySelector("form");
|
||||
const categorySelect = form.elements.category;
|
||||
const groupSelect = form.elements.group;
|
||||
const newGroupInput = form.elements.newGroup;
|
||||
const currentCategory = records.every(record => record.categoryKey === records[0].categoryKey)
|
||||
? records[0].categoryKey
|
||||
: "drawings";
|
||||
categorySelect.value = currentCategory;
|
||||
const refreshGroups = () => {
|
||||
const destination = destinations.find(item => item.key === categorySelect.value);
|
||||
groupSelect.innerHTML = (destination?.groups || []).map(group =>
|
||||
`<option value="${escapeHtml(group.source)}">${escapeHtml(group.name)}</option>`).join("");
|
||||
const currentSource = records.every(record => record.source === records[0].source)
|
||||
? records[0].source
|
||||
: "";
|
||||
if (destination?.key === currentCategory && currentSource
|
||||
&& destination.groups.some(group => group.source === currentSource)) {
|
||||
groupSelect.value = currentSource;
|
||||
}
|
||||
};
|
||||
categorySelect.addEventListener("change", refreshGroups);
|
||||
refreshGroups();
|
||||
dialog.querySelector("[data-cancel]").addEventListener("click", () => dialog.remove());
|
||||
form.addEventListener("submit", event => {
|
||||
event.preventDefault();
|
||||
const destination = destinations.find(item => item.key === categorySelect.value);
|
||||
if (!destination) return;
|
||||
const requestedName = newGroupInput.value.trim().slice(0, 120);
|
||||
const existingByName = requestedName
|
||||
? destination.groups.find(group => group.name.toLocaleLowerCase("it") === requestedName.toLocaleLowerCase("it"))
|
||||
: null;
|
||||
const selectedGroup = destination.groups.find(group => group.source === groupSelect.value);
|
||||
const target = existingByName || (requestedName
|
||||
? { source: `Gruppo ${requestedName}`, name: requestedName }
|
||||
: selectedGroup);
|
||||
if (!target) {
|
||||
setInfo("Scegli un gruppo di destinazione o inserisci il nome di un nuovo gruppo.");
|
||||
return;
|
||||
}
|
||||
dialog.remove();
|
||||
moveManagedRecordsToGroup(records, destination.key, target.source, target.name);
|
||||
});
|
||||
}
|
||||
|
||||
function moveManagedRecordsToGroup(records, targetCategory, targetSource, targetGroupName) {
|
||||
if (lmeState.readOnly) { setInfo("Il progetto e' in sola lettura."); return; }
|
||||
const movable = records.filter(record => ["drawings", "imported"].includes(record.categoryKey));
|
||||
if (!movable.length || !["drawings", "imported"].includes(targetCategory)) {
|
||||
@@ -1488,8 +1568,10 @@ function moveManagedRecordsToCategory(records, targetCategory) {
|
||||
const feature = record.layer.toGeoJSON();
|
||||
feature.properties = {
|
||||
...(feature.properties || {}),
|
||||
_lmeSource: feature.properties?._lmeSource || "Progetto corrente"
|
||||
_lmeSource: targetSource,
|
||||
_lmeGroupName: targetGroupName
|
||||
};
|
||||
delete feature.properties._lmeManagerId;
|
||||
return feature;
|
||||
});
|
||||
movable.forEach(record => {
|
||||
@@ -1505,8 +1587,9 @@ function moveManagedRecordsToCategory(records, targetCategory) {
|
||||
refreshImportedMeasurements();
|
||||
refreshDrawingMeasurements();
|
||||
refreshLayerManager();
|
||||
finishMapChange(`Spostati ${features.length} oggetti in ${targetCategory === "drawings" ? "Disegni e POI" : "Progetti e dati importati"}.`);
|
||||
setInfo(`${features.length} oggetti spostati in ${targetCategory === "drawings" ? "Disegni e POI" : "Progetti e dati importati"}.`);
|
||||
const categoryName = targetCategory === "drawings" ? "Disegni e POI" : "Progetti e dati importati";
|
||||
finishMapChange(`Spostati ${features.length} oggetti in ${categoryName} > ${targetGroupName}.`);
|
||||
setInfo(`${features.length} oggetti spostati in ${categoryName} > ${targetGroupName}.`);
|
||||
}
|
||||
|
||||
function managedObjectDetails(layer) {
|
||||
@@ -1614,7 +1697,10 @@ function renderLayerManagerCategory(category, records) {
|
||||
const removeButton = managedCategoryCanRemove(category, records)
|
||||
? `<button type="button" class="layer-remove-button" aria-label="Rimuovi gruppo dal progetto" title="Rimuovi dal progetto">Rimuovi</button>`
|
||||
: "";
|
||||
const rowActions = layerManagerRowActions(renameButton, removeButton);
|
||||
const moveButton = records.length && ["drawings", "imported"].includes(category.key)
|
||||
? `<button type="button" class="layer-membership-button" aria-label="Sposta gruppo in un altro gruppo" title="Sposta nel gruppo">Sposta nel gruppo</button>`
|
||||
: "";
|
||||
const rowActions = layerManagerRowActions(renameButton, moveButton, removeButton);
|
||||
group.classList.toggle("layer-manager-with-actions", Boolean(rowActions));
|
||||
const visibleCount = records.filter(record => !lmeState.managerHiddenObjectIds.has(record.id)).length;
|
||||
const categoryVisible = !lmeState.managerHiddenCategories.has(category.key)
|
||||
@@ -1641,6 +1727,11 @@ function renderLayerManagerCategory(category, records) {
|
||||
event.stopPropagation();
|
||||
removeManagedRecords(records, `il gruppo '${categoryName}'`);
|
||||
});
|
||||
group.querySelector(".layer-membership-button")?.addEventListener("click", event => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
showMoveManagedRecordsDialog(records, `il gruppo '${categoryName}'`);
|
||||
});
|
||||
bindManagedParentHighlight(group, `category:${category.key}`, records);
|
||||
const children = group.querySelector(".layer-manager-children");
|
||||
if (records.length) children.appendChild(renderManagedGroupTools(records));
|
||||
@@ -1674,6 +1765,7 @@ function renderLayerManagerBlock(category, source, records) {
|
||||
const blockName = managedBlockName(source, records);
|
||||
const rowActions = layerManagerRowActions(
|
||||
`<button type="button" class="layer-rename-button" aria-label="Rinomina gruppo" title="Rinomina">Rinomina</button>`,
|
||||
`<button type="button" class="layer-membership-button" aria-label="Sposta gruppo in un altro gruppo" title="Sposta nel gruppo">Sposta nel gruppo</button>`,
|
||||
`<button type="button" class="layer-remove-button" aria-label="Rimuovi gruppo dal progetto" title="Rimuovi dal progetto">Rimuovi</button>`);
|
||||
block.classList.add("layer-manager-with-actions");
|
||||
const blockLocked = records.length > 0 && records.every(record => Boolean(record.layer?.feature?.properties?._lmeLocked));
|
||||
@@ -1700,6 +1792,11 @@ function renderLayerManagerBlock(category, source, records) {
|
||||
event.stopPropagation();
|
||||
removeManagedRecords(records, `il gruppo '${blockName}'`);
|
||||
});
|
||||
block.querySelector(".layer-membership-button").addEventListener("click", event => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
showMoveManagedRecordsDialog(records, `il gruppo '${blockName}'`);
|
||||
});
|
||||
bindManagedParentHighlight(block, `block:${category.key}:${source}`, records);
|
||||
const children = block.querySelector(".layer-manager-children");
|
||||
children.appendChild(renderManagedGroupTools(records));
|
||||
@@ -1724,7 +1821,10 @@ function renderLayerManagerObject(record, index) {
|
||||
const removeButton = managedObjectCanRemove(record)
|
||||
? `<button type="button" class="layer-remove-button" aria-label="Rimuovi oggetto dal progetto" title="Rimuovi dal progetto">Rimuovi</button>`
|
||||
: "";
|
||||
const rowActions = layerManagerRowActions(renameButton, removeButton);
|
||||
const moveButton = ["drawings", "imported"].includes(record.categoryKey)
|
||||
? `<button type="button" class="layer-membership-button" aria-label="Sposta oggetto in un altro gruppo" title="Sposta nel gruppo">Sposta nel gruppo</button>`
|
||||
: "";
|
||||
const rowActions = layerManagerRowActions(renameButton, moveButton, removeButton);
|
||||
object.classList.toggle("layer-manager-with-actions", Boolean(rowActions));
|
||||
const objectName = managedObjectLabel(record, index);
|
||||
const locked = Boolean(record.layer?.feature?.properties?._lmeLocked);
|
||||
@@ -1743,6 +1843,11 @@ function renderLayerManagerObject(record, index) {
|
||||
event.stopPropagation();
|
||||
removeManagedRecords([record], `'${objectName}'`);
|
||||
});
|
||||
object.querySelector(".layer-membership-button")?.addEventListener("click", event => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
showMoveManagedRecordsDialog([record], `'${objectName}'`);
|
||||
});
|
||||
object.querySelector(".layer-inline-lock")?.addEventListener("click", event => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@@ -1786,7 +1891,7 @@ function renderLayerSelectionToolbar() {
|
||||
toolbar.innerHTML = `<label>Cerca oggetti<input type="search" value="${escapeHtml(lmeState.managerSearchText)}" placeholder="Nome o gruppo"></label>
|
||||
<div class="layer-selection-summary"><strong>${selectedCount} selezionati</strong><button type="button" data-action="clear">Deseleziona</button></div>
|
||||
<div class="layer-batch-actions">
|
||||
<button type="button" data-action="duplicate">Duplica</button><button type="button" data-action="move">Sposta</button>
|
||||
<button type="button" data-action="duplicate">Duplica</button><button type="button" data-action="move">Sposta geometria</button>
|
||||
<button type="button" data-action="buffer">Buffer</button><button type="button" data-action="union">Unisci</button>
|
||||
<button type="button" data-action="split">Dividi</button><button type="button" data-action="delete" class="danger-command">Rimuovi</button>
|
||||
</div>`;
|
||||
@@ -1818,17 +1923,11 @@ function renderManagedGroupTools(records) {
|
||||
const tools = document.createElement("div");
|
||||
tools.className = "layer-group-tools";
|
||||
const properties = records[0]?.layer?.feature?.properties || {};
|
||||
const sourceCategory = records[0]?.categoryKey;
|
||||
const membershipAction = sourceCategory === "drawings"
|
||||
? `<button type="button" data-group-action="membership">Sposta in Progetti e dati importati</button>`
|
||||
: sourceCategory === "imported"
|
||||
? `<button type="button" data-group-action="membership">Sposta in Disegni e POI</button>`
|
||||
: "";
|
||||
tools.innerHTML = `<strong>Azioni gruppo</strong><span class="layer-group-totals">${escapeHtml(managedGroupTotals(records))}</span><div class="layer-style-controls">
|
||||
<label>Colore<input type="color" value="${normalizedColor(properties._lmeColor, "#16806a")}"></label>
|
||||
<label>Spessore<input type="range" min="1" max="10" step="1" value="${Number(properties._lmeWeight) || 3}"></label>
|
||||
<label>Opacita<input type="range" min="0.1" max="1" step="0.1" value="${Number(properties._lmeOpacity) || 1}"></label></div>
|
||||
<div class="layer-compact-actions"><button type="button" data-group-action="select">Seleziona tutti</button><button type="button" data-group-action="lock">Blocca/sblocca</button><button type="button" data-group-action="labels">Etichette</button>${membershipAction}</div>`;
|
||||
<div class="layer-compact-actions"><button type="button" data-group-action="select">Seleziona tutti</button><button type="button" data-group-action="lock">Blocca/sblocca</button><button type="button" data-group-action="labels">Etichette</button></div>`;
|
||||
const inputs = tools.querySelectorAll("input");
|
||||
inputs.forEach(input => input.addEventListener("change", () => {
|
||||
applyManagedStyle(records, { color: inputs[0].value, weight: Number(inputs[1].value), opacity: Number(inputs[2].value) });
|
||||
@@ -1845,8 +1944,6 @@ function renderManagedGroupTools(records) {
|
||||
const visible = !records.every(record => Boolean(record.layer?.feature?.properties?._lmeLabelVisible));
|
||||
updateManagedProperties(records, properties => { properties._lmeLabelVisible = visible; });
|
||||
});
|
||||
tools.querySelector("[data-group-action='membership']")?.addEventListener("click", () =>
|
||||
moveManagedRecordsToCategory(records, sourceCategory === "drawings" ? "imported" : "drawings"));
|
||||
return tools;
|
||||
}
|
||||
|
||||
@@ -1869,11 +1966,6 @@ function renderManagedObjectTools(record) {
|
||||
const properties = record.layer.feature?.properties || (record.layer.feature = { type: "Feature", properties: {} }).properties;
|
||||
const selected = lmeState.managerSelectedObjectIds.has(record.id);
|
||||
const locked = Boolean(properties._lmeLocked);
|
||||
const membershipAction = record.categoryKey === "drawings"
|
||||
? `<button type="button" data-action="membership">Sposta in Progetti e dati importati</button>`
|
||||
: record.categoryKey === "imported"
|
||||
? `<button type="button" data-action="membership">Sposta in Disegni e POI</button>`
|
||||
: "";
|
||||
const tools = document.createElement("section");
|
||||
tools.className = "layer-object-tools";
|
||||
tools.innerHTML = `<label class="layer-manager-suboption"><input type="checkbox" data-field="selected" ${selected ? "checked" : ""}><span>Seleziona per azioni multiple</span></label>
|
||||
@@ -1888,7 +1980,7 @@ function renderManagedObjectTools(record) {
|
||||
<label>Note<textarea data-field="notes" rows="2" maxlength="1000" placeholder="Note tecniche">${escapeHtml(properties._lmeNotes || "")}</textarea></label>
|
||||
<label class="layer-photo-picker">Foto<input type="file" data-field="photo" accept="image/*"></label>
|
||||
${properties._lmePhoto ? `<img class="layer-photo-preview" src="${properties._lmePhoto}" alt="Foto allegata"><button type="button" data-action="remove-photo">Rimuovi foto</button>` : ""}
|
||||
<div class="layer-compact-actions"><button type="button" data-action="attributes">Attributi</button><button type="button" data-action="duplicate">Duplica</button><button type="button" data-action="numeric">Coordinate</button><button type="button" data-action="inspect">WGS84 / UTM</button><button type="button" data-action="move">Sposta geometria</button><button type="button" data-action="buffer">Buffer</button>${membershipAction}</div>`;
|
||||
<div class="layer-compact-actions"><button type="button" data-action="attributes">Attributi</button><button type="button" data-action="duplicate">Duplica</button><button type="button" data-action="numeric">Coordinate</button><button type="button" data-action="inspect">WGS84 / UTM</button><button type="button" data-action="move">Sposta geometria</button><button type="button" data-action="buffer">Buffer</button></div>`;
|
||||
tools.querySelector("[data-field='selected']").addEventListener("change", event => {
|
||||
if (event.target.checked) lmeState.managerSelectedObjectIds.add(record.id);
|
||||
else lmeState.managerSelectedObjectIds.delete(record.id);
|
||||
@@ -1918,8 +2010,6 @@ function renderManagedObjectTools(record) {
|
||||
tools.querySelector("[data-action='inspect']").addEventListener("click", () => showCoordinateInspectorForRecord(record));
|
||||
tools.querySelector("[data-action='move']").addEventListener("click", () => moveManagedRecords([record]));
|
||||
tools.querySelector("[data-action='buffer']").addEventListener("click", () => bufferManagedRecords([record]));
|
||||
tools.querySelector("[data-action='membership']")?.addEventListener("click", () =>
|
||||
moveManagedRecordsToCategory([record], record.categoryKey === "drawings" ? "imported" : "drawings"));
|
||||
return tools;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user