Separated models, controllers and routers

This commit is contained in:
2022-02-13 19:33:50 +10:00
parent 6cbd670260
commit 39dbba45f7
33 changed files with 338 additions and 328 deletions

127
Floorplan/Controller.fs Normal file
View File

@@ -0,0 +1,127 @@
module DredgePos.Floorplan.Controller
open DredgeFramework
open DredgePos
open DredgePos.Types
open Giraffe
open Microsoft.AspNetCore.Http
open Model
let makeRoomButton (room: floorplan_room) =
let vars = map [
"roomId", room.id |> string
"roomName", room.room_name
]
Theme.loadTemplateWithVars "roomButton" vars
let getActiveTables venue = Model.getActiveTables venue |> ajaxSuccess |> json
let mergeTables (tables: floorplan_table[]) =
let status =
if mergeTables tables[0].table_number tables[1].table_number then
let outputTables = map [
"parent", tables[0];
"child", tables[1];
"merged", Model.getTable tables[0].table_number;
]
ajaxSuccess outputTables
else ajaxFail "Could Not Merge Tables"
status |> json
let unmergeTable tableNumber =
let unmerged = unmergeTable tableNumber
let unmergedTables =
match unmerged with
| Some (parent, child) ->
map ["parent", parent; "child", child] |> ajaxSuccess
| None -> ajaxFail "Could not Unmerge Table"
unmergedTables |> json
let getFloorplanData (id: int) =
let tableList = Entity.GetAllInVenue<floorplan_table>
let reservationList = getReservationList tableList
{|
tables = tableList
decorations = Entity.GetAllInVenue<floorplan_decoration>
activeTableNumbers = Model.getActiveTables (getCurrentVenue())
rooms = Entity.GetAllInVenue<floorplan_room>
reservations = reservationList
|}
|> ajaxSuccess
|> json
let transformTable (table: floorplan_table) =
Entity.Update table
|> ajaxSuccess
|> json
let createTable (tableData: floorplan_table) =
if tableExists tableData.table_number = "False" then
ajaxSuccess (addNewTable tableData)
else ajaxFail (tableExists tableData.table_number)
|> json
let deleteTable (table: floorplan_table) =
Entity.DeleteById<floorplan_table> table.id
|> ignore
table |> ajaxSuccess |> json
let transferTable (origin, destination) =
Model.transferTable origin destination
let data = map ["origin", getTable origin ; "destination", getTable destination]
ajaxSuccess data |> json
let AddDecoration (data: floorplan_decoration) =
let image = "wwwroot/images/decorations/" + data.decoration_image
let width, height = image |> GetImageSize
let aspectRatio = decimal width / decimal height
let decoration : floorplan_decoration = {
id = 0
decoration_height = (200m / aspectRatio) |> int
decoration_width = 200
decoration_rotation = 0
decoration_image = data.decoration_image
decoration_pos_x = data.decoration_pos_x
decoration_pos_y = data.decoration_pos_y
decoration_room = data.decoration_room
venue_id = data.venue_id
}
Entity.Create decoration
|> ajaxSuccess
|> json
let UpdateDecoration (data: floorplan_decoration) =
Entity.Update data
|> ignore
ajaxSuccess "true" |> json
let DeleteDecoration (decorationToDelete: floorplan_decoration) =
Entity.DeleteById<floorplan_decoration> decorationToDelete.id
|> ajaxSuccess
|> json
let loadFloorplan (ctx: HttpContext) : HttpHandler =
Authenticate.Model.RequireClerkAuthentication ctx
let roomMenu =
Entity.GetAllInVenue<floorplan_room>
|> Array.map makeRoomButton
|> joinWithNewLine
let variables = map [
"title", "Floorplan"
"roomMenu", roomMenu
"decorator", Entities.Floorplan_Decorations.Controller.generateDecorator()
]
let styles = ["dredgepos.floorplan.css"]
let scripts = ["../external/konva.min.js" ; "dredgepos.floorplan.js"]
let currentClerk = recordToMap <| Authenticate.Model.getCurrentClerk ctx
let arrays = map ["clerk", currentClerk]
htmlString <| Theme.loadTemplateWithVarsArraysScriptsAndStyles "floorplan" variables arrays scripts styles

295
Floorplan/Model.fs Normal file
View File

@@ -0,0 +1,295 @@
module DredgePos.Floorplan.Model
open DredgePos.Types
open System
open System.IO
open System.Xml.Linq
open DredgeFramework
open Dapper.FSharp
open Thoth.Json.Net
let activeTablePath = "tables/active/"
let getTableFile (tableNumber: int) =
let tableNumberString = tableNumber |> string
activeTablePath + "table" + tableNumberString + ".table"
let tableNumberIsOpen (tableNumber: int) =
let tableFile = getTableFile tableNumber
File.Exists tableFile
let tableIsOpen (table: floorplan_table) = tableNumberIsOpen table.table_number
let fileNameToTableNumber (fileName: string) = //Takes a file name for a floorplan table and returns the table number
if fileName.Contains ".table" then
let fileName = (fileName.Split ".")[0]
(fileName.Split "/table")[1] |> int
else 0
let openTables () = //Get a list of all open tables.
let tableList = Directory.GetFiles(activeTablePath)
tableList
|> Array.map fileNameToTableNumber
|> Array.filter(fun tableNumber -> tableNumber > 0)
let getTableNumber table = table.table_number
let tablesInRoom (roomId: int) = //Get a list of all tables in a particular room.
select {
table "floorplan_tables"
where (eq "room_id" roomId)
}
|> db.Select<floorplan_table>
let getActiveTables (venueId: int) =
select{
table "floorplan_tables"
where (eq "venue_id" venueId)
}
|> db.Select
|> Array.filter tableIsOpen
|> Array.map (fun table -> table.table_number)
let openNewTable tableNumber = //Create a new table file pre-populated with skeleton data
let tableFile = getTableFile tableNumber
if not <| File.Exists tableFile then
let newTableTemplate = $"""
<table openedby="" number="{tableNumber}"></table>
"""
File.Create tableFile |> ignore
File.WriteAllText (tableFile, newTableTemplate)
let transferTable origin destination = //Transfers a table from one to another
let originFile = getTableFile origin
let destinationFile = getTableFile destination
if tableNumberIsOpen origin then
(* If the destination is not an already open table,
then we simply have to rename the origin to destination *)
if not <| tableNumberIsOpen destination then
let content = File.ReadAllText originFile
let newContent = content.Replace($"number=\"{origin|>string}\">", $"number=\"{destination|>string}\">")
File.WriteAllText(originFile, newContent)
File.Move(originFile, destinationFile)
else
let originXML = XDocument.Load originFile
let destinationXML = XDocument.Load destinationFile
destinationXML.Root.Add(originXML.Root.Elements())
destinationXML.Save destinationFile
File.Delete originFile
let saveOrderToTable orderXML tableNumber =
let tableFile = getTableFile tableNumber
let tableXML = tableFile
|> File.ReadAllText
|> StringReplace "</table>" (orderXML + "</table>")
File.WriteAllText(tableFile, tableXML)
let getTable (tableNumber : int) =
let query = select {
table "floorplan_tables"
where (eq "table_number" tableNumber + eq "venue_id" (getCurrentVenue()))
}
let result = query |> db.Select<floorplan_table>
result |> first
let getTableById (id : int) =
select {
table "floorplan_tables"
where (eq "id" id)
}
|> db.Select<floorplan_table>
|> first
let getRoom (roomId: int) =
select {
table "floorplan_rooms"
where (eq "id" roomId)
} |> db.Select<floorplan_room> |> first
let updateTablePosition (floorplanTable: floorplan_table) = Entity.Update floorplanTable
let createEmptyReservation (reservation: reservation) =
update {
table "floorplan_tables"
set {| status = 2 |}
where(eq "id" reservation.floorplan_table_id)
} |> db.Update |> ignore
Entity.Create reservation
let getChildTables tableNumber =
let table = getTable tableNumber
let json = table.merged_children
let result = json |> Decode.Auto.fromString<floorplan_table[]>
match result with
| Ok tables -> tables
| Error _ -> [||]
let matchTable (tableNumberToMatch: int) (floorplanTableToCheck: floorplan_table) =
tableNumberToMatch = floorplanTableToCheck.table_number
let findChildTable (childTable: int) (parentTable: floorplan_table) =
let json = parentTable.merged_children
let childTables = json |> Decode.Auto.fromString<floorplan_table[]>
let matchedTables =
match childTables with
| Ok table -> table |> Array.map(matchTable childTable)
| Error _ -> [|false|]
|> removeFalseValues
|> length
match matchedTables with
| 0 -> 0
| _ -> parentTable.table_number
let tableExists (tableNumber: int) =
let numberOfResults =
select{
table "floorplan_tables"
where (eq "table_number" tableNumber + eq "venue_id" (getCurrentVenue()))
} |> db.Select<floorplan_table> |> length
match numberOfResults with
| 0 ->
let allTables =
Entity.GetAllInVenue<floorplan_table>
|> Array.map(findChildTable tableNumber)
|> Array.filter(fun tableNumber -> tableNumber <> 0)
match allTables.Length with
| 0 -> false |> string //Table does not exist
| _ ->
let parentTableData = getTable allTables[0]
let parentRoom = getRoom parentTableData.room_id
let parentRoomName = parentRoom.room_name
language.getAndReplace "error_table_exists_merged" [parentRoomName; parentTableData.table_number.ToString()]
| _ ->
let tableData = getTable tableNumber
let room = getRoom tableData.room_id
language.getAndReplace "error_table_exists" [room.room_name]
let addNewTableWithoutOutput (newTable: floorplan_table) =
insert{
table "floorplan_tables"
value newTable
}
|> db.Insert
let addNewTable (newTable: floorplan_table) = Entity.Create newTable
let mergeTables parent child = //Merge two tables together
if parent = child then false else
let parentTable = getTable parent
let childTable = getTable child
let xDiff = (parentTable.pos_x - childTable.pos_x) |> Math.Abs
let yDiff = (parentTable.pos_y - childTable.pos_y) |> Math.Abs
let newHeight =
if xDiff < yDiff then parentTable.height + childTable.height
else parentTable.height
let newWidth =
if xDiff >= yDiff then parentTable.width + childTable.width
else parentTable.width
let newPosX =
if parentTable.pos_x <= childTable.pos_x then parentTable.pos_x + xDiff/2
else parentTable.pos_x - xDiff/2
let newPosY =
if parentTable.pos_y <= childTable.pos_y then parentTable.pos_y + yDiff/2
else parentTable.pos_y - yDiff/2
let newChildTable = childTable
let existingChildrenJson = parentTable.merged_children |> StringTrim
let existingChildren =
existingChildrenJson |> Decode.Auto.fromString<floorplan_table[]>
let tableList =
match existingChildren with
| Error _ -> [|newChildTable|]
| Ok tables -> [tables ; [|newChildTable|]] |> Array.concat
let newChildrenJson = tableList |> jsonEncode
let parentPreviousState = parentTable |> jsonEncode
update {
table "floorplan_tables"
set {|
merged_children = newChildrenJson
previous_state = parentPreviousState
height = newHeight
width = newWidth
pos_x = newPosX
pos_y = newPosY
default_covers = parentTable.default_covers + childTable.default_covers
|}
where (eq "table_number" parent + eq "venue_id" (getCurrentVenue()))
} |> db.Update |> ignore
Entity.DeleteById<floorplan_table> newChildTable.id
|> ignore
true
let updateUnmergedTables parentTable childTable =
update {
table "floorplan_tables"
set parentTable
where(eq "table_number" parentTable.table_number + eq "venue_id" (getCurrentVenue()))
} |> db.Update |> ignore
addNewTableWithoutOutput childTable |> ignore
true
let processUnmerge originalTable unmergedChild =
let previousState = originalTable.previous_state |> Decode.Auto.fromString<floorplan_table>
match previousState with
| Ok table -> updateUnmergedTables table unmergedChild
| Error _ -> false
let unmergeTable tableNumber = //Separates a merged table into itself and the last table merged into it.
let currentTable = getTable tableNumber
let mergedChildren = currentTable.merged_children |> Decode.Auto.fromString<floorplan_table[]>
match mergedChildren with
| Ok listOfChildTables ->
let unmergedChild = listOfChildTables |> last
processUnmerge currentTable unmergedChild |> ignore
Some (getTable currentTable.table_number, unmergedChild)
| Error _ -> None
let getReservationList (tableList: floorplan_table[]) =
tableList |> Array.collect Entity.GetAllRelated<reservation, floorplan_table>
let newReservation name time covers =
let reservation = {
id = 0
name = name
time = time
covers = covers
floorplan_table_id = 0
created_at = CurrentTime()
}
Entity.Create reservation
let tableList () = Entity.GetAllInVenue<floorplan_table>

24
Floorplan/Router.fs Normal file
View File

@@ -0,0 +1,24 @@
module DredgePos.Floorplan.Router
open DredgePos
open DredgePos.Types
open Saturn
open Giraffe
let floorplan = (warbler (fun ctx -> DredgePos.Floorplan.Controller.loadFloorplan (snd ctx)))
let router = router {
pipe_through Ajax.Router.pipeline
get "/" floorplan
get "" floorplan
post "/mergeTables" (bindJson<floorplan_table[]> Controller.mergeTables)
post "/transformTable" (bindJson<floorplan_table> Controller.transformTable)
post "/createTable" (bindJson<floorplan_table> Controller.createTable)
post "/addDecoration" (bindJson<floorplan_decoration> Controller.AddDecoration)
post "/updateDecoration" (bindJson<floorplan_decoration> Controller.UpdateDecoration)
post "/deleteDecoration" (bindJson<floorplan_decoration> Controller.DeleteDecoration)
post "/deleteTable" (bindJson<floorplan_table> Controller.deleteTable)
getf "/getFloorplanData/%i" Controller.getFloorplanData
getf "/transferTable/%i/%i" Controller.transferTable
getf "/unmergeTable/%i" Controller.unmergeTable
}