Optimise floor plan editor and add reciprocal stairs
This commit is contained in:
parent
f57913014c
commit
89c381e6bc
@ -227,8 +227,7 @@ public sealed class FloorPlansController(IFloorPlanService floorPlans) : Control
|
|||||||
var floorPlanBlockId = await floorPlans.SaveBlockAsync(model);
|
var floorPlanBlockId = await floorPlans.SaveBlockAsync(model);
|
||||||
if (isAsyncSave)
|
if (isAsyncSave)
|
||||||
{
|
{
|
||||||
var editor = await floorPlans.GetEditorAsync(floorPlanId);
|
var block = await floorPlans.GetBlockAsync(floorPlanBlockId);
|
||||||
var block = editor?.Blocks.FirstOrDefault(x => x.FloorPlanBlockID == floorPlanBlockId);
|
|
||||||
if (block is null)
|
if (block is null)
|
||||||
{
|
{
|
||||||
Response.StatusCode = StatusCodes.Status400BadRequest;
|
Response.StatusCode = StatusCodes.Status400BadRequest;
|
||||||
|
|||||||
@ -220,6 +220,8 @@ public interface IFloorPlanRepository
|
|||||||
Task<FloorPlan?> GetAsync(int floorPlanId);
|
Task<FloorPlan?> GetAsync(int floorPlanId);
|
||||||
Task<(FloorPlan? FloorPlan, IReadOnlyList<FloorPlanFloor> Floors, IReadOnlyList<FloorPlanBlock> Blocks, IReadOnlyList<FloorPlanTransition> Transitions)> GetEditorAsync(int floorPlanId);
|
Task<(FloorPlan? FloorPlan, IReadOnlyList<FloorPlanFloor> Floors, IReadOnlyList<FloorPlanBlock> Blocks, IReadOnlyList<FloorPlanTransition> Transitions)> GetEditorAsync(int floorPlanId);
|
||||||
Task<FloorPlanFloor?> GetFloorAsync(int floorPlanFloorId);
|
Task<FloorPlanFloor?> GetFloorAsync(int floorPlanFloorId);
|
||||||
|
Task<IReadOnlyList<FloorPlanBlock>> ListBlocksByFloorAsync(int floorPlanFloorId);
|
||||||
|
Task<FloorPlanBlock?> GetBlockAsync(int floorPlanBlockId);
|
||||||
Task<int> SavePlanAsync(FloorPlan floorPlan);
|
Task<int> SavePlanAsync(FloorPlan floorPlan);
|
||||||
Task DeletePlanAsync(int floorPlanId);
|
Task DeletePlanAsync(int floorPlanId);
|
||||||
Task<int> SaveFloorAsync(FloorPlanFloor floor);
|
Task<int> SaveFloorAsync(FloorPlanFloor floor);
|
||||||
@ -571,6 +573,19 @@ public sealed class FloorPlanRepository(ISqlConnectionFactory connectionFactory)
|
|||||||
return await connection.QuerySingleOrDefaultAsync<FloorPlanFloor>("dbo.FloorPlanFloor_Get", new { FloorPlanFloorID = floorPlanFloorId }, commandType: CommandType.StoredProcedure);
|
return await connection.QuerySingleOrDefaultAsync<FloorPlanFloor>("dbo.FloorPlanFloor_Get", new { FloorPlanFloorID = floorPlanFloorId }, commandType: CommandType.StoredProcedure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IReadOnlyList<FloorPlanBlock>> ListBlocksByFloorAsync(int floorPlanFloorId)
|
||||||
|
{
|
||||||
|
using var connection = connectionFactory.CreateConnection();
|
||||||
|
var rows = await connection.QueryAsync<FloorPlanBlock>("dbo.FloorPlanBlock_ListByFloor", new { FloorPlanFloorID = floorPlanFloorId }, commandType: CommandType.StoredProcedure);
|
||||||
|
return rows.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<FloorPlanBlock?> GetBlockAsync(int floorPlanBlockId)
|
||||||
|
{
|
||||||
|
using var connection = connectionFactory.CreateConnection();
|
||||||
|
return await connection.QuerySingleOrDefaultAsync<FloorPlanBlock>("dbo.FloorPlanBlock_Get", new { FloorPlanBlockID = floorPlanBlockId }, commandType: CommandType.StoredProcedure);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<int> SavePlanAsync(FloorPlan floorPlan)
|
public async Task<int> SavePlanAsync(FloorPlan floorPlan)
|
||||||
{
|
{
|
||||||
using var connection = connectionFactory.CreateConnection();
|
using var connection = connectionFactory.CreateConnection();
|
||||||
|
|||||||
@ -186,6 +186,7 @@ public interface IFloorPlanService
|
|||||||
Task<int> SaveFloorAsync(FloorPlanFloorEditViewModel model);
|
Task<int> SaveFloorAsync(FloorPlanFloorEditViewModel model);
|
||||||
Task DeleteFloorAsync(int floorPlanFloorId);
|
Task DeleteFloorAsync(int floorPlanFloorId);
|
||||||
Task<int> SaveBlockAsync(FloorPlanBlockEditViewModel model);
|
Task<int> SaveBlockAsync(FloorPlanBlockEditViewModel model);
|
||||||
|
Task<FloorPlanBlockEditViewModel?> GetBlockAsync(int floorPlanBlockId);
|
||||||
Task SaveLayoutAsync(FloorPlanEditorViewModel model);
|
Task SaveLayoutAsync(FloorPlanEditorViewModel model);
|
||||||
Task<FloorPlanBackgroundImageUploadResult> UploadBackgroundAsync(int floorPlanId, int floorPlanFloorId, IFormFile upload);
|
Task<FloorPlanBackgroundImageUploadResult> UploadBackgroundAsync(int floorPlanId, int floorPlanFloorId, IFormFile upload);
|
||||||
Task SaveBackgroundSettingsAsync(FloorPlanFloorBackgroundSettingsViewModel model);
|
Task SaveBackgroundSettingsAsync(FloorPlanFloorBackgroundSettingsViewModel model);
|
||||||
@ -7677,8 +7678,7 @@ public sealed class FloorPlanService(
|
|||||||
if (model.FloorPlanBlockID == 0)
|
if (model.FloorPlanBlockID == 0)
|
||||||
{
|
{
|
||||||
model.LocationID = await ResolveBlockLocationAsync(model, floor, plan);
|
model.LocationID = await ResolveBlockLocationAsync(model, floor, plan);
|
||||||
var editor = await floorPlans.GetEditorAsync(plan.FloorPlanID);
|
var existingBlocks = await floorPlans.ListBlocksByFloorAsync(floor.FloorPlanFloorID);
|
||||||
var existingBlocks = editor.Blocks.Where(x => x.FloorPlanFloorID == floor.FloorPlanFloorID).ToList();
|
|
||||||
(model.X, model.Y) = FindFirstAvailablePosition(floor, existingBlocks, model.WidthCells, model.HeightCells);
|
(model.X, model.Y) = FindFirstAvailablePosition(floor, existingBlocks, model.WidthCells, model.HeightCells);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7686,6 +7686,12 @@ public sealed class FloorPlanService(
|
|||||||
return await floorPlans.SaveBlockAsync(ToBlock(model));
|
return await floorPlans.SaveBlockAsync(ToBlock(model));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<FloorPlanBlockEditViewModel?> GetBlockAsync(int floorPlanBlockId)
|
||||||
|
{
|
||||||
|
var block = await floorPlans.GetBlockAsync(floorPlanBlockId);
|
||||||
|
return block is null ? null : ToBlockEdit(block);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task SaveLayoutAsync(FloorPlanEditorViewModel model)
|
public async Task SaveLayoutAsync(FloorPlanEditorViewModel model)
|
||||||
{
|
{
|
||||||
var data = await floorPlans.GetEditorAsync(model.FloorPlan.FloorPlanID);
|
var data = await floorPlans.GetEditorAsync(model.FloorPlan.FloorPlanID);
|
||||||
@ -7738,11 +7744,80 @@ public sealed class FloorPlanService(
|
|||||||
{
|
{
|
||||||
model.PositionWithinLocation = FloorPlanTransitionPositions.Centre;
|
model.PositionWithinLocation = FloorPlanTransitionPositions.Centre;
|
||||||
}
|
}
|
||||||
|
else if (model.FloorPlanTransitionID == 0)
|
||||||
|
{
|
||||||
|
var existingPrimary = data.Transitions.FirstOrDefault(x =>
|
||||||
|
x.FloorPlanFloorID == model.FloorPlanFloorID
|
||||||
|
&& x.FromLocationID == model.FromLocationID!.Value
|
||||||
|
&& x.ToLocationID == model.ToLocationID!.Value
|
||||||
|
&& string.Equals(x.TransitionType, model.TransitionType, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (existingPrimary is not null)
|
||||||
|
{
|
||||||
|
model.FloorPlanTransitionID = existingPrimary.FloorPlanTransitionID;
|
||||||
|
}
|
||||||
|
}
|
||||||
var transitionId = await floorPlans.SaveTransitionAsync(ToTransition(model));
|
var transitionId = await floorPlans.SaveTransitionAsync(ToTransition(model));
|
||||||
|
if (IsStairTransition(model.TransitionType))
|
||||||
|
{
|
||||||
|
await SaveReciprocalStairTransitionAsync(model, floor, data.Floors, data.Blocks, data.Transitions);
|
||||||
|
}
|
||||||
await activity.RecordAsync(data.FloorPlan.ProjectID, model.FloorPlanTransitionID == 0 ? "Created" : "Updated", "Floor Plan Transition", transitionId, model.TransitionType);
|
await activity.RecordAsync(data.FloorPlan.ProjectID, model.FloorPlanTransitionID == 0 ? "Created" : "Updated", "Floor Plan Transition", transitionId, model.TransitionType);
|
||||||
return transitionId;
|
return transitionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task SaveReciprocalStairTransitionAsync(
|
||||||
|
FloorPlanTransitionEditViewModel model,
|
||||||
|
FloorPlanFloor floor,
|
||||||
|
IReadOnlyList<FloorPlanFloor> floors,
|
||||||
|
IReadOnlyList<FloorPlanBlock> blocks,
|
||||||
|
IReadOnlyList<FloorPlanTransition> transitions)
|
||||||
|
{
|
||||||
|
var transitionKind = NormalizeTransitionType(model.TransitionType);
|
||||||
|
var targetLevel = floor.SortOrder + (transitionKind == "stairsup" ? 1 : -1);
|
||||||
|
var targetFloor = floors
|
||||||
|
.Where(x => x.SortOrder == targetLevel)
|
||||||
|
.OrderBy(x => x.Name)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (targetFloor is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var targetLocationIds = blocks
|
||||||
|
.Where(x => x.FloorPlanFloorID == targetFloor.FloorPlanFloorID)
|
||||||
|
.Select(x => x.LocationID)
|
||||||
|
.ToHashSet();
|
||||||
|
if (!targetLocationIds.Contains(model.ToLocationID!.Value))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var reciprocalType = transitionKind == "stairsup"
|
||||||
|
? FloorPlanTransitionTypes.StairsDown
|
||||||
|
: FloorPlanTransitionTypes.StairsUp;
|
||||||
|
var existing = transitions.FirstOrDefault(x =>
|
||||||
|
x.FloorPlanFloorID == targetFloor.FloorPlanFloorID
|
||||||
|
&& x.FromLocationID == model.ToLocationID.Value
|
||||||
|
&& x.ToLocationID == model.FromLocationID!.Value
|
||||||
|
&& string.Equals(x.TransitionType, reciprocalType, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
await floorPlans.SaveTransitionAsync(new FloorPlanTransition
|
||||||
|
{
|
||||||
|
FloorPlanTransitionID = existing?.FloorPlanTransitionID ?? 0,
|
||||||
|
FloorPlanFloorID = targetFloor.FloorPlanFloorID,
|
||||||
|
FromLocationID = model.ToLocationID.Value,
|
||||||
|
ToLocationID = model.FromLocationID!.Value,
|
||||||
|
TransitionType = reciprocalType,
|
||||||
|
Notes = model.Notes,
|
||||||
|
IsLocked = model.IsLocked,
|
||||||
|
DisplayLabel = model.DisplayLabel,
|
||||||
|
PositionWithinLocation = string.IsNullOrWhiteSpace(model.PositionWithinLocation)
|
||||||
|
? FloorPlanTransitionPositions.Centre
|
||||||
|
: model.PositionWithinLocation
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public async Task DeleteTransitionAsync(int floorPlanId, int floorPlanTransitionId)
|
public async Task DeleteTransitionAsync(int floorPlanId, int floorPlanTransitionId)
|
||||||
{
|
{
|
||||||
var data = await floorPlans.GetEditorAsync(floorPlanId);
|
var data = await floorPlans.GetEditorAsync(floorPlanId);
|
||||||
|
|||||||
@ -0,0 +1,231 @@
|
|||||||
|
CREATE OR ALTER PROCEDURE dbo.FloorPlan_GetEditor
|
||||||
|
@FloorPlanID int
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
DECLARE @ProjectID int;
|
||||||
|
SELECT @ProjectID = ProjectID
|
||||||
|
FROM dbo.FloorPlans
|
||||||
|
WHERE FloorPlanID = @FloorPlanID;
|
||||||
|
|
||||||
|
EXEC dbo.FloorPlan_Get @FloorPlanID;
|
||||||
|
|
||||||
|
CREATE TABLE #ProjectLocationPaths
|
||||||
|
(
|
||||||
|
LocationID int NOT NULL PRIMARY KEY,
|
||||||
|
LocationName nvarchar(200) NOT NULL,
|
||||||
|
LocationPath nvarchar(max) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
;WITH ProjectLocationTree AS
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
LocationID,
|
||||||
|
LocationName,
|
||||||
|
CAST(LocationName AS nvarchar(max)) AS LocationPath
|
||||||
|
FROM dbo.Locations
|
||||||
|
WHERE ProjectID = @ProjectID
|
||||||
|
AND ParentLocationID IS NULL
|
||||||
|
AND IsArchived = 0
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
child.LocationID,
|
||||||
|
child.LocationName,
|
||||||
|
CAST(parent.LocationPath + N' > ' + child.LocationName AS nvarchar(max)) AS LocationPath
|
||||||
|
FROM dbo.Locations child
|
||||||
|
INNER JOIN ProjectLocationTree parent ON parent.LocationID = child.ParentLocationID
|
||||||
|
WHERE child.ProjectID = @ProjectID
|
||||||
|
AND child.IsArchived = 0
|
||||||
|
)
|
||||||
|
INSERT #ProjectLocationPaths (LocationID, LocationName, LocationPath)
|
||||||
|
SELECT LocationID, LocationName, LocationPath
|
||||||
|
FROM ProjectLocationTree;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
fpf.FloorPlanFloorID,
|
||||||
|
fpf.FloorPlanID,
|
||||||
|
fpf.LocationID,
|
||||||
|
lp.LocationName,
|
||||||
|
lp.LocationPath,
|
||||||
|
fpf.Name,
|
||||||
|
fpf.SortOrder,
|
||||||
|
fpf.GridWidth,
|
||||||
|
fpf.GridHeight,
|
||||||
|
fpf.BackgroundImagePath,
|
||||||
|
fpf.BackgroundImageOriginalFileName,
|
||||||
|
COALESCE(fpf.BackgroundOpacity, CONVERT(decimal(5,2), 0.35)) AS BackgroundOpacity,
|
||||||
|
COALESCE(fpf.BackgroundScale, CONVERT(decimal(8,3), 1.000)) AS BackgroundScale,
|
||||||
|
COALESCE(fpf.BackgroundOffsetX, CONVERT(decimal(10,2), 0.00)) AS BackgroundOffsetX,
|
||||||
|
COALESCE(fpf.BackgroundOffsetY, CONVERT(decimal(10,2), 0.00)) AS BackgroundOffsetY,
|
||||||
|
fpf.BackgroundLocked,
|
||||||
|
fpf.CreatedDate,
|
||||||
|
fpf.ModifiedDate
|
||||||
|
FROM dbo.FloorPlanFloors fpf
|
||||||
|
LEFT JOIN #ProjectLocationPaths lp ON lp.LocationID = fpf.LocationID
|
||||||
|
WHERE fpf.FloorPlanID = @FloorPlanID
|
||||||
|
ORDER BY fpf.SortOrder, fpf.Name;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
fpb.FloorPlanBlockID,
|
||||||
|
fpb.FloorPlanFloorID,
|
||||||
|
fpb.LocationID,
|
||||||
|
lp.LocationName,
|
||||||
|
COALESCE(NULLIF(lp.LocationPath, N''), lp.LocationName) AS LocationPath,
|
||||||
|
fpb.X,
|
||||||
|
fpb.Y,
|
||||||
|
fpb.WidthCells,
|
||||||
|
fpb.HeightCells,
|
||||||
|
fpb.BlockType,
|
||||||
|
fpb.LabelOverride,
|
||||||
|
fpb.Notes,
|
||||||
|
fpb.CreatedDate,
|
||||||
|
fpb.ModifiedDate
|
||||||
|
FROM dbo.FloorPlanBlocks fpb
|
||||||
|
INNER JOIN dbo.FloorPlanFloors fpf ON fpf.FloorPlanFloorID = fpb.FloorPlanFloorID
|
||||||
|
INNER JOIN #ProjectLocationPaths lp ON lp.LocationID = fpb.LocationID
|
||||||
|
WHERE fpf.FloorPlanID = @FloorPlanID
|
||||||
|
ORDER BY fpf.SortOrder, fpb.Y, fpb.X, lp.LocationName;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
fpt.FloorPlanTransitionID,
|
||||||
|
fpt.FloorPlanFloorID,
|
||||||
|
fpt.FromLocationID,
|
||||||
|
fromPath.LocationName AS FromLocationName,
|
||||||
|
COALESCE(NULLIF(fromPath.LocationPath, N''), fromPath.LocationName) AS FromLocationPath,
|
||||||
|
fpt.ToLocationID,
|
||||||
|
toPath.LocationName AS ToLocationName,
|
||||||
|
COALESCE(NULLIF(toPath.LocationPath, N''), toPath.LocationName) AS ToLocationPath,
|
||||||
|
fpt.TransitionType,
|
||||||
|
fpt.Notes,
|
||||||
|
fpt.IsLocked,
|
||||||
|
fpt.DisplayLabel,
|
||||||
|
fpt.PositionWithinLocation,
|
||||||
|
fpt.CreatedDate,
|
||||||
|
fpt.ModifiedDate
|
||||||
|
FROM dbo.FloorPlanTransitions fpt
|
||||||
|
INNER JOIN dbo.FloorPlanFloors fpf ON fpf.FloorPlanFloorID = fpt.FloorPlanFloorID
|
||||||
|
INNER JOIN #ProjectLocationPaths fromPath ON fromPath.LocationID = fpt.FromLocationID
|
||||||
|
INNER JOIN #ProjectLocationPaths toPath ON toPath.LocationID = fpt.ToLocationID
|
||||||
|
WHERE fpf.FloorPlanID = @FloorPlanID
|
||||||
|
ORDER BY fpf.SortOrder, fromPath.LocationName, toPath.LocationName, fpt.TransitionType;
|
||||||
|
END;
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE OR ALTER PROCEDURE dbo.FloorPlanBlock_ListByFloor
|
||||||
|
@FloorPlanFloorID int
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
DECLARE @ProjectID int;
|
||||||
|
SELECT @ProjectID = fp.ProjectID
|
||||||
|
FROM dbo.FloorPlanFloors fpf
|
||||||
|
INNER JOIN dbo.FloorPlans fp ON fp.FloorPlanID = fpf.FloorPlanID
|
||||||
|
WHERE fpf.FloorPlanFloorID = @FloorPlanFloorID;
|
||||||
|
|
||||||
|
CREATE TABLE #ProjectLocationPaths
|
||||||
|
(
|
||||||
|
LocationID int NOT NULL PRIMARY KEY,
|
||||||
|
LocationName nvarchar(200) NOT NULL,
|
||||||
|
LocationPath nvarchar(max) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
;WITH ProjectLocationTree AS
|
||||||
|
(
|
||||||
|
SELECT LocationID, LocationName, CAST(LocationName AS nvarchar(max)) AS LocationPath
|
||||||
|
FROM dbo.Locations
|
||||||
|
WHERE ProjectID = @ProjectID AND ParentLocationID IS NULL AND IsArchived = 0
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
SELECT child.LocationID, child.LocationName, CAST(parent.LocationPath + N' > ' + child.LocationName AS nvarchar(max)) AS LocationPath
|
||||||
|
FROM dbo.Locations child
|
||||||
|
INNER JOIN ProjectLocationTree parent ON parent.LocationID = child.ParentLocationID
|
||||||
|
WHERE child.ProjectID = @ProjectID AND child.IsArchived = 0
|
||||||
|
)
|
||||||
|
INSERT #ProjectLocationPaths (LocationID, LocationName, LocationPath)
|
||||||
|
SELECT LocationID, LocationName, LocationPath
|
||||||
|
FROM ProjectLocationTree;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
fpb.FloorPlanBlockID,
|
||||||
|
fpb.FloorPlanFloorID,
|
||||||
|
fpb.LocationID,
|
||||||
|
lp.LocationName,
|
||||||
|
COALESCE(NULLIF(lp.LocationPath, N''), lp.LocationName) AS LocationPath,
|
||||||
|
fpb.X,
|
||||||
|
fpb.Y,
|
||||||
|
fpb.WidthCells,
|
||||||
|
fpb.HeightCells,
|
||||||
|
fpb.BlockType,
|
||||||
|
fpb.LabelOverride,
|
||||||
|
fpb.Notes,
|
||||||
|
fpb.CreatedDate,
|
||||||
|
fpb.ModifiedDate
|
||||||
|
FROM dbo.FloorPlanBlocks fpb
|
||||||
|
INNER JOIN #ProjectLocationPaths lp ON lp.LocationID = fpb.LocationID
|
||||||
|
WHERE fpb.FloorPlanFloorID = @FloorPlanFloorID
|
||||||
|
ORDER BY fpb.Y, fpb.X, lp.LocationName;
|
||||||
|
END;
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE OR ALTER PROCEDURE dbo.FloorPlanBlock_Get
|
||||||
|
@FloorPlanBlockID int
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
DECLARE @ProjectID int;
|
||||||
|
SELECT @ProjectID = fp.ProjectID
|
||||||
|
FROM dbo.FloorPlanBlocks fpb
|
||||||
|
INNER JOIN dbo.FloorPlanFloors fpf ON fpf.FloorPlanFloorID = fpb.FloorPlanFloorID
|
||||||
|
INNER JOIN dbo.FloorPlans fp ON fp.FloorPlanID = fpf.FloorPlanID
|
||||||
|
WHERE fpb.FloorPlanBlockID = @FloorPlanBlockID;
|
||||||
|
|
||||||
|
CREATE TABLE #ProjectLocationPaths
|
||||||
|
(
|
||||||
|
LocationID int NOT NULL PRIMARY KEY,
|
||||||
|
LocationName nvarchar(200) NOT NULL,
|
||||||
|
LocationPath nvarchar(max) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
;WITH ProjectLocationTree AS
|
||||||
|
(
|
||||||
|
SELECT LocationID, LocationName, CAST(LocationName AS nvarchar(max)) AS LocationPath
|
||||||
|
FROM dbo.Locations
|
||||||
|
WHERE ProjectID = @ProjectID AND ParentLocationID IS NULL AND IsArchived = 0
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
SELECT child.LocationID, child.LocationName, CAST(parent.LocationPath + N' > ' + child.LocationName AS nvarchar(max)) AS LocationPath
|
||||||
|
FROM dbo.Locations child
|
||||||
|
INNER JOIN ProjectLocationTree parent ON parent.LocationID = child.ParentLocationID
|
||||||
|
WHERE child.ProjectID = @ProjectID AND child.IsArchived = 0
|
||||||
|
)
|
||||||
|
INSERT #ProjectLocationPaths (LocationID, LocationName, LocationPath)
|
||||||
|
SELECT LocationID, LocationName, LocationPath
|
||||||
|
FROM ProjectLocationTree;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
fpb.FloorPlanBlockID,
|
||||||
|
fpb.FloorPlanFloorID,
|
||||||
|
fpb.LocationID,
|
||||||
|
lp.LocationName,
|
||||||
|
COALESCE(NULLIF(lp.LocationPath, N''), lp.LocationName) AS LocationPath,
|
||||||
|
fpb.X,
|
||||||
|
fpb.Y,
|
||||||
|
fpb.WidthCells,
|
||||||
|
fpb.HeightCells,
|
||||||
|
fpb.BlockType,
|
||||||
|
fpb.LabelOverride,
|
||||||
|
fpb.Notes,
|
||||||
|
fpb.CreatedDate,
|
||||||
|
fpb.ModifiedDate
|
||||||
|
FROM dbo.FloorPlanBlocks fpb
|
||||||
|
INNER JOIN #ProjectLocationPaths lp ON lp.LocationID = fpb.LocationID
|
||||||
|
WHERE fpb.FloorPlanBlockID = @FloorPlanBlockID;
|
||||||
|
END;
|
||||||
|
GO
|
||||||
@ -1393,6 +1393,8 @@
|
|||||||
button.dataset.blockIndex = blocks.length;
|
button.dataset.blockIndex = blocks.length;
|
||||||
button.dataset.floorId = block.floorPlanFloorID;
|
button.dataset.floorId = block.floorPlanFloorID;
|
||||||
button.dataset.locationId = block.locationID || "";
|
button.dataset.locationId = block.locationID || "";
|
||||||
|
button.dataset.locationName = block.locationName || "";
|
||||||
|
button.dataset.locationPath = block.locationPath || "";
|
||||||
button.title = block.locationPath || "";
|
button.title = block.locationPath || "";
|
||||||
button.innerHTML = `<span class="floor-plan-block-label"></span><span class="floor-plan-resize-handle" data-resize-handle aria-hidden="true"></span>`;
|
button.innerHTML = `<span class="floor-plan-block-label"></span><span class="floor-plan-resize-handle" data-resize-handle aria-hidden="true"></span>`;
|
||||||
button.querySelector(".floor-plan-block-label").textContent = block.displayLabel || block.locationName || "New block";
|
button.querySelector(".floor-plan-block-label").textContent = block.displayLabel || block.locationName || "New block";
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user