Implemented both Floor Plans fixes.
This commit is contained in:
parent
601afa8806
commit
bd8067b472
@ -110,8 +110,9 @@ public sealed class FloorPlansController(IFloorPlanService floorPlans) : Control
|
|||||||
{
|
{
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
await floorPlans.SaveBlockAsync(model);
|
var floorPlanBlockId = await floorPlans.SaveBlockAsync(model);
|
||||||
TempData["FloorPlanMessage"] = "Block added.";
|
TempData["FloorPlanMessage"] = "Block added.";
|
||||||
|
return RedirectToAction(nameof(Edit), new { id = floorPlanId, selectedBlockId = floorPlanBlockId });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
|
|||||||
@ -7648,6 +7648,13 @@ public sealed class FloorPlanService(
|
|||||||
var plan = await floorPlans.GetAsync(floor.FloorPlanID)
|
var plan = await floorPlans.GetAsync(floor.FloorPlanID)
|
||||||
?? throw new InvalidOperationException("Floor plan not found.");
|
?? throw new InvalidOperationException("Floor plan not found.");
|
||||||
var projectId = plan.ProjectID;
|
var projectId = plan.ProjectID;
|
||||||
|
if (model.FloorPlanBlockID == 0)
|
||||||
|
{
|
||||||
|
var editor = await floorPlans.GetEditorAsync(plan.FloorPlanID);
|
||||||
|
var existingBlocks = editor.Blocks.Where(x => x.FloorPlanFloorID == floor.FloorPlanFloorID).ToList();
|
||||||
|
(model.X, model.Y) = FindFirstAvailablePosition(floor, existingBlocks, model.WidthCells, model.HeightCells);
|
||||||
|
}
|
||||||
|
|
||||||
await ValidateBlockAsync(model, floor, projectId);
|
await ValidateBlockAsync(model, floor, projectId);
|
||||||
return await floorPlans.SaveBlockAsync(ToBlock(model));
|
return await floorPlans.SaveBlockAsync(ToBlock(model));
|
||||||
}
|
}
|
||||||
@ -7720,6 +7727,37 @@ public sealed class FloorPlanService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static (int X, int Y) FindFirstAvailablePosition(FloorPlanFloor floor, IReadOnlyList<FloorPlanBlock> existingBlocks, int widthCells, int heightCells)
|
||||||
|
{
|
||||||
|
var width = Math.Max(1, widthCells);
|
||||||
|
var height = Math.Max(1, heightCells);
|
||||||
|
if (width > floor.GridWidth || height > floor.GridHeight)
|
||||||
|
{
|
||||||
|
return (0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var y = 0; y <= floor.GridHeight - height; y++)
|
||||||
|
{
|
||||||
|
for (var x = 0; x <= floor.GridWidth - width; x++)
|
||||||
|
{
|
||||||
|
if (!existingBlocks.Any(block => BlocksOverlap(x, y, width, height, block.X, block.Y, block.WidthCells, block.HeightCells)))
|
||||||
|
{
|
||||||
|
return (x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool BlocksOverlap(int ax, int ay, int aw, int ah, int bx, int by, int bw, int bh)
|
||||||
|
{
|
||||||
|
return ax < bx + bw
|
||||||
|
&& ax + aw > bx
|
||||||
|
&& ay < by + bh
|
||||||
|
&& ay + ah > by;
|
||||||
|
}
|
||||||
|
|
||||||
private static FloorPlanFloorEditViewModel ToFloorEdit(FloorPlanFloor floor) => new()
|
private static FloorPlanFloorEditViewModel ToFloorEdit(FloorPlanFloor floor) => new()
|
||||||
{
|
{
|
||||||
FloorPlanFloorID = floor.FloorPlanFloorID,
|
FloorPlanFloorID = floor.FloorPlanFloorID,
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
ViewData["ProjectSection"] = "Floor Plans";
|
ViewData["ProjectSection"] = "Floor Plans";
|
||||||
var activeFloor = Model.Floors.OrderBy(x => x.SortOrder).ThenBy(x => x.Name).FirstOrDefault();
|
var activeFloor = Model.Floors.OrderBy(x => x.SortOrder).ThenBy(x => x.Name).FirstOrDefault();
|
||||||
var blocksByFloor = Model.Blocks.GroupBy(x => x.FloorPlanFloorID).ToDictionary(x => x.Key, x => x.ToList());
|
var blocksByFloor = Model.Blocks.GroupBy(x => x.FloorPlanFloorID).ToDictionary(x => x.Key, x => x.ToList());
|
||||||
|
var selectedBlockId = int.TryParse(Context.Request.Query["selectedBlockId"], out var parsedSelectedBlockId) ? parsedSelectedBlockId : Model.Blocks.FirstOrDefault()?.FloorPlanBlockID ?? 0;
|
||||||
string BlockClass(string blockType) => $"floor-plan-block floor-plan-block--{blockType.ToLowerInvariant()}";
|
string BlockClass(string blockType) => $"floor-plan-block floor-plan-block--{blockType.ToLowerInvariant()}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,36 +73,6 @@
|
|||||||
<button class="btn btn-outline-primary btn-sm w-100" type="submit">Add floor</button>
|
<button class="btn btn-outline-primary btn-sm w-100" type="submit">Add floor</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@if (Model.Floors.Any() && Model.LocationOptions.Any())
|
|
||||||
{
|
|
||||||
<form asp-action="AddBlock" method="post" class="row g-2 align-items-end">
|
|
||||||
<input type="hidden" name="floorPlanId" value="@Model.FloorPlan.FloorPlanID" />
|
|
||||||
<div class="col-md-3">
|
|
||||||
<label class="form-label">Floor</label>
|
|
||||||
<select asp-for="NewBlock.FloorPlanFloorID" asp-items="@(Model.Floors.OrderBy(x => x.SortOrder).Select(x => new SelectListItem(x.Name, x.FloorPlanFloorID.ToString(), x.FloorPlanFloorID == activeFloor?.FloorPlanFloorID)))" class="form-select form-select-sm" name="FloorPlanFloorID"></select>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<label class="form-label">Location</label>
|
|
||||||
<select asp-for="NewBlock.LocationID" asp-items="Model.LocationOptions" class="form-select form-select-sm" name="LocationID"></select>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-2">
|
|
||||||
<label class="form-label">Type</label>
|
|
||||||
<select asp-for="NewBlock.BlockType" asp-items="Model.BlockTypeOptions" class="form-select form-select-sm" name="BlockType"></select>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-1">
|
|
||||||
<label class="form-label">W</label>
|
|
||||||
<input asp-for="NewBlock.WidthCells" class="form-control form-control-sm" name="WidthCells" min="1" max="80" />
|
|
||||||
</div>
|
|
||||||
<div class="col-md-1">
|
|
||||||
<label class="form-label">H</label>
|
|
||||||
<input asp-for="NewBlock.HeightCells" class="form-control form-control-sm" name="HeightCells" min="1" max="80" />
|
|
||||||
</div>
|
|
||||||
<div class="col-md-2">
|
|
||||||
<button class="btn btn-primary btn-sm w-100" type="submit">Add block</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
}
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@if (!Model.Floors.Any())
|
@if (!Model.Floors.Any())
|
||||||
@ -124,7 +95,7 @@ else
|
|||||||
@foreach (var floor in Model.Floors.OrderBy(x => x.SortOrder).ThenBy(x => x.Name))
|
@foreach (var floor in Model.Floors.OrderBy(x => x.SortOrder).ThenBy(x => x.Name))
|
||||||
{
|
{
|
||||||
var isActive = floor.FloorPlanFloorID == activeFloor?.FloorPlanFloorID;
|
var isActive = floor.FloorPlanFloorID == activeFloor?.FloorPlanFloorID;
|
||||||
<button type="button" class="floor-plan-tab @(isActive ? "active" : string.Empty)" data-floor-tab="@floor.FloorPlanFloorID">@floor.Name</button>
|
<button type="button" class="floor-plan-tab @(isActive ? "active" : string.Empty)" data-floor-tab="@floor.FloorPlanFloorID" data-floor-name="@floor.Name">@floor.Name</button>
|
||||||
}
|
}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@ -154,8 +125,8 @@ else
|
|||||||
</div>
|
</div>
|
||||||
<button class="btn btn-outline-danger btn-sm"
|
<button class="btn btn-outline-danger btn-sm"
|
||||||
type="button"
|
type="button"
|
||||||
data-delete-floor="@floor.FloorPlanFloorID"
|
data-bs-toggle="modal"
|
||||||
data-confirm-message="Delete this floor and its placed blocks? Linked locations are not deleted.">Delete floor</button>
|
data-bs-target="#delete-floor-@floor.FloorPlanFloorID">Delete floor</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="floor-plan-grid-wrap">
|
<div class="floor-plan-grid-wrap">
|
||||||
@ -184,6 +155,43 @@ else
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<aside class="floor-plan-side-panel">
|
<aside class="floor-plan-side-panel">
|
||||||
|
@if (Model.LocationOptions.Any())
|
||||||
|
{
|
||||||
|
<section class="floor-plan-add-block-panel">
|
||||||
|
<h2>Add block</h2>
|
||||||
|
<p class="muted">Adds a block to <span data-current-floor-name>@activeFloor?.Name</span>.</p>
|
||||||
|
<input type="hidden" name="FloorPlanBlockID" value="0" form="floor-plan-add-block-form" />
|
||||||
|
<input type="hidden" name="FloorPlanFloorID" value="@activeFloor?.FloorPlanFloorID" data-add-block-floor-id form="floor-plan-add-block-form" />
|
||||||
|
<input type="hidden" name="X" value="0" form="floor-plan-add-block-form" />
|
||||||
|
<input type="hidden" name="Y" value="0" form="floor-plan-add-block-form" />
|
||||||
|
<input type="hidden" name="WidthCells" value="1" data-add-block-width form="floor-plan-add-block-form" />
|
||||||
|
<input type="hidden" name="HeightCells" value="1" data-add-block-height form="floor-plan-add-block-form" />
|
||||||
|
<div class="mb-2">
|
||||||
|
<label class="form-label" for="add-block-location">Location</label>
|
||||||
|
<select id="add-block-location" class="form-select form-select-sm" name="LocationID" asp-items="Model.LocationOptions" form="floor-plan-add-block-form"></select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<label class="form-label" for="add-block-type">Block type</label>
|
||||||
|
<select id="add-block-type" class="form-select form-select-sm" name="BlockType" asp-items="Model.BlockTypeOptions" form="floor-plan-add-block-form"></select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<label class="form-label" for="add-block-size-preset">Size preset</label>
|
||||||
|
<select id="add-block-size-preset" class="form-select form-select-sm" data-size-preset>
|
||||||
|
<option value="1x1">Small Room 1 x 1</option>
|
||||||
|
<option value="2x1" selected>Medium Room 2 x 1</option>
|
||||||
|
<option value="2x2">Large Room 2 x 2</option>
|
||||||
|
<option value="1x3">Corridor 1 x 3</option>
|
||||||
|
<option value="3x2">Wide Hall 3 x 2</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="add-block-label">Label override</label>
|
||||||
|
<input id="add-block-label" class="form-control form-control-sm" name="LabelOverride" form="floor-plan-add-block-form" />
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-primary btn-sm w-100" type="submit" form="floor-plan-add-block-form">Add block</button>
|
||||||
|
</section>
|
||||||
|
}
|
||||||
|
|
||||||
<h2>Selected block</h2>
|
<h2>Selected block</h2>
|
||||||
<p class="muted" data-no-selection>Select a block on the grid to edit its details.</p>
|
<p class="muted" data-no-selection>Select a block on the grid to edit its details.</p>
|
||||||
<div class="floor-plan-overlap-warning d-none" data-overlap-warning>Some blocks overlap on this floor.</div>
|
<div class="floor-plan-overlap-warning d-none" data-overlap-warning>Some blocks overlap on this floor.</div>
|
||||||
@ -232,7 +240,8 @@ else
|
|||||||
<div class="button-row mt-3">
|
<div class="button-row mt-3">
|
||||||
<button class="btn btn-outline-danger btn-sm"
|
<button class="btn btn-outline-danger btn-sm"
|
||||||
type="button"
|
type="button"
|
||||||
data-delete-block="@Model.Blocks[i].FloorPlanBlockID">Delete block</button>
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#delete-block-@Model.Blocks[i].FloorPlanBlockID">Delete block</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@ -243,6 +252,63 @@ else
|
|||||||
<button class="btn btn-primary" type="submit">Save layout</button>
|
<button class="btn btn-primary" type="submit">Save layout</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<form id="floor-plan-add-block-form" asp-action="AddBlock" method="post">
|
||||||
|
<input type="hidden" name="floorPlanId" value="@Model.FloorPlan.FloorPlanID" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
@foreach (var floor in Model.Floors)
|
||||||
|
{
|
||||||
|
var placedBlockCount = Model.Blocks.Count(x => x.FloorPlanFloorID == floor.FloorPlanFloorID);
|
||||||
|
<div class="modal fade" id="delete-floor-@floor.FloorPlanFloorID" tabindex="-1" aria-labelledby="delete-floor-title-@floor.FloorPlanFloorID" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content plotline-confirm-modal">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h2 class="modal-title fs-5" id="delete-floor-title-@floor.FloorPlanFloorID">Delete floor?</h2>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>Delete <strong>@floor.Name</strong>?</p>
|
||||||
|
<p>This deletes @placedBlockCount placed block(s) on this floor. Linked Locations will not be deleted.</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||||
|
<form asp-action="DeleteFloor" method="post" data-no-delete-confirm="true">
|
||||||
|
<input type="hidden" name="floorPlanId" value="@Model.FloorPlan.FloorPlanID" />
|
||||||
|
<input type="hidden" name="floorPlanFloorId" value="@floor.FloorPlanFloorID" />
|
||||||
|
<button class="btn btn-danger" type="submit">Delete floor</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
@foreach (var block in Model.Blocks)
|
||||||
|
{
|
||||||
|
<div class="modal fade" id="delete-block-@block.FloorPlanBlockID" tabindex="-1" aria-labelledby="delete-block-title-@block.FloorPlanBlockID" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content plotline-confirm-modal">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h2 class="modal-title fs-5" id="delete-block-title-@block.FloorPlanBlockID">Delete placed block?</h2>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>Remove the placed block for <strong>@block.DisplayLabel</strong>?</p>
|
||||||
|
<p>Only this block is removed from the floor plan. The linked Location will not be deleted.</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||||
|
<form asp-action="DeleteBlock" method="post" data-no-delete-confirm="true">
|
||||||
|
<input type="hidden" name="floorPlanId" value="@Model.FloorPlan.FloorPlanID" />
|
||||||
|
<input type="hidden" name="floorPlanBlockId" value="@block.FloorPlanBlockID" />
|
||||||
|
<button class="btn btn-danger" type="submit">Delete block</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@section Scripts {
|
@section Scripts {
|
||||||
@ -257,12 +323,21 @@ else
|
|||||||
const blocks = [...editor.querySelectorAll("[data-block]")];
|
const blocks = [...editor.querySelectorAll("[data-block]")];
|
||||||
const noSelection = editor.querySelector("[data-no-selection]");
|
const noSelection = editor.querySelector("[data-no-selection]");
|
||||||
const warning = editor.querySelector("[data-overlap-warning]");
|
const warning = editor.querySelector("[data-overlap-warning]");
|
||||||
|
const addBlockFloor = document.querySelector("[data-add-block-floor-id]");
|
||||||
|
const addBlockFloorName = document.querySelector("[data-current-floor-name]");
|
||||||
|
const sizePreset = document.querySelector("[data-size-preset]");
|
||||||
|
const addBlockWidth = document.querySelector("[data-add-block-width]");
|
||||||
|
const addBlockHeight = document.querySelector("[data-add-block-height]");
|
||||||
|
const initialSelectedBlockId = "@selectedBlockId";
|
||||||
let selectedBlock = null;
|
let selectedBlock = null;
|
||||||
let pointerState = null;
|
let pointerState = null;
|
||||||
|
|
||||||
function setActiveFloor(floorId) {
|
function setActiveFloor(floorId) {
|
||||||
tabs.forEach(tab => tab.classList.toggle("active", tab.dataset.floorTab === floorId));
|
tabs.forEach(tab => tab.classList.toggle("active", tab.dataset.floorTab === floorId));
|
||||||
panels.forEach(panel => panel.classList.toggle("active", panel.dataset.floorPanel === floorId));
|
panels.forEach(panel => panel.classList.toggle("active", panel.dataset.floorPanel === floorId));
|
||||||
|
const activeTab = tabs.find(tab => tab.dataset.floorTab === floorId);
|
||||||
|
if (addBlockFloor) addBlockFloor.value = floorId;
|
||||||
|
if (addBlockFloorName && activeTab) addBlockFloorName.textContent = activeTab.dataset.floorName || activeTab.textContent || "the current floor";
|
||||||
checkOverlaps();
|
checkOverlaps();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,43 +489,20 @@ else
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
async function postDelete(url, fields) {
|
sizePreset?.addEventListener("change", () => {
|
||||||
const token = editor.querySelector("input[name='__RequestVerificationToken']")?.value;
|
const [width, height] = (sizePreset.value || "2x1").split("x");
|
||||||
const body = new URLSearchParams({ ...fields, __RequestVerificationToken: token || "" });
|
if (addBlockWidth) addBlockWidth.value = width || "2";
|
||||||
const response = await fetch(url, {
|
if (addBlockHeight) addBlockHeight.value = height || "1";
|
||||||
method: "POST",
|
});
|
||||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
sizePreset?.dispatchEvent(new Event("change"));
|
||||||
body
|
|
||||||
});
|
const initialBlock = blocks.find(block => block.dataset.block === initialSelectedBlockId) || blocks[0];
|
||||||
if (response.redirected) {
|
if (initialBlock) {
|
||||||
window.location.href = response.url;
|
setActiveFloor(initialBlock.dataset.floorId);
|
||||||
return;
|
selectBlock(initialBlock);
|
||||||
}
|
} else if (tabs[0]) {
|
||||||
window.location.reload();
|
setActiveFloor(tabs[0].dataset.floorTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.querySelectorAll("[data-delete-block]").forEach(button => {
|
|
||||||
button.addEventListener("click", () => {
|
|
||||||
postDelete("@Url.Action("DeleteBlock", "FloorPlans")", {
|
|
||||||
floorPlanId: "@Model.FloorPlan.FloorPlanID",
|
|
||||||
floorPlanBlockId: button.dataset.deleteBlock
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
editor.querySelectorAll("[data-delete-floor]").forEach(button => {
|
|
||||||
button.addEventListener("click", () => {
|
|
||||||
const message = button.dataset.confirmMessage || "Delete this floor?";
|
|
||||||
if (window.confirm(message)) {
|
|
||||||
postDelete("@Url.Action("DeleteFloor", "FloorPlans")", {
|
|
||||||
floorPlanId: "@Model.FloorPlan.FloorPlanID",
|
|
||||||
floorPlanFloorId: button.dataset.deleteFloor
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (blocks[0]) selectBlock(blocks[0]);
|
|
||||||
checkOverlaps();
|
checkOverlaps();
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -66,14 +66,36 @@ else
|
|||||||
</div>
|
</div>
|
||||||
<div class="button-row compact-buttons">
|
<div class="button-row compact-buttons">
|
||||||
<a class="btn btn-outline-secondary btn-sm" asp-action="Edit" asp-route-id="@floorPlan.FloorPlanID">Open editor</a>
|
<a class="btn btn-outline-secondary btn-sm" asp-action="Edit" asp-route-id="@floorPlan.FloorPlanID">Open editor</a>
|
||||||
<form asp-action="DeletePlan" method="post" data-confirm-message="Delete this floor plan? This deletes its floors and placed blocks. Linked locations are not deleted.">
|
<button class="btn btn-outline-danger btn-sm" type="button" data-bs-toggle="modal" data-bs-target="#delete-floor-plan-@floorPlan.FloorPlanID">Delete</button>
|
||||||
<input type="hidden" name="id" value="@floorPlan.FloorPlanID" />
|
|
||||||
<input type="hidden" name="projectId" value="@Model.Project.ProjectID" />
|
|
||||||
<button class="btn btn-outline-danger btn-sm" type="submit">Delete</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
@foreach (var floorPlan in Model.FloorPlans)
|
||||||
|
{
|
||||||
|
<div class="modal fade" id="delete-floor-plan-@floorPlan.FloorPlanID" tabindex="-1" aria-labelledby="delete-floor-plan-title-@floorPlan.FloorPlanID" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content plotline-confirm-modal">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h2 class="modal-title fs-5" id="delete-floor-plan-title-@floorPlan.FloorPlanID">Delete floor plan?</h2>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>Delete <strong>@floorPlan.Name</strong>?</p>
|
||||||
|
<p>This deletes its floors and placed blocks. Linked Locations will not be deleted.</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||||
|
<form asp-action="DeletePlan" method="post" data-no-delete-confirm="true">
|
||||||
|
<input type="hidden" name="id" value="@floorPlan.FloorPlanID" />
|
||||||
|
<input type="hidden" name="projectId" value="@Model.Project.ProjectID" />
|
||||||
|
<button class="btn btn-danger" type="submit">Delete floor plan</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,5 +22,11 @@
|
|||||||
"inputFiles": [
|
"inputFiles": [
|
||||||
"wwwroot/js/word-companion-host.js"
|
"wwwroot/js/word-companion-host.js"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"outputFileName": "wwwroot/css/word-companion.min.css",
|
||||||
|
"inputFiles": [
|
||||||
|
"wwwroot/css/word-companion.css"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@ -4623,6 +4623,16 @@ body.dragging-location [data-drag-type="location"] {
|
|||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.floor-plan-add-block-panel {
|
||||||
|
border-bottom: 1px solid var(--border-color, #d8ded9);
|
||||||
|
margin-bottom: 14px;
|
||||||
|
padding-bottom: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floor-plan-add-block-panel p {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.floor-plan-overlap-warning {
|
.floor-plan-overlap-warning {
|
||||||
background: rgba(180, 85, 68, .12);
|
background: rgba(180, 85, 68, .12);
|
||||||
border: 1px solid rgba(180, 85, 68, .35);
|
border: 1px solid rgba(180, 85, 68, .35);
|
||||||
|
|||||||
2
PlotLine/wwwroot/css/site.min.css
vendored
2
PlotLine/wwwroot/css/site.min.css
vendored
File diff suppressed because one or more lines are too long
1
PlotLine/wwwroot/css/word-companion.min.css
vendored
Normal file
1
PlotLine/wwwroot/css/word-companion.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user