Merge pull request #4 from dredgy/project-structure

Project structure
This commit is contained in:
dredgy
2022-02-13 19:35:26 +10:00
committed by GitHub
34 changed files with 339 additions and 328 deletions

1
.gitignore vendored
View File

@@ -8,3 +8,4 @@
/.idea/ /.idea/
/wwwroot/scripts/js/ /wwwroot/scripts/js/
/wwwroot/styles/css/* /wwwroot/styles/css/*
/Folder.DotSettings.user

15
Ajax/Controller.fs Normal file
View File

@@ -0,0 +1,15 @@
module DredgePos.Ajax.Controller
open DredgeFramework
open language
open Giraffe
let getLanguageVars = ajaxSuccess languageVars
let getKeyboardLayout (language: string) =
let layout = $"""wwwroot/languages/{language}/keyboardLayout.json"""
|> GetFileContents
map [
"status", "success"
"data", layout
] |> json

14
Ajax/Router.fs Normal file
View File

@@ -0,0 +1,14 @@
module DredgePos.Ajax.Router
open Saturn
open Giraffe
let pipeline = pipeline {
use_warbler
}
let router = router {
getf "/getKeyboardLayout/%s" Controller.getKeyboardLayout
get "/languageVars" (json Controller.getLanguageVars)
}

View File

@@ -0,0 +1,17 @@
module DredgePos.Authenticate.Controller
open Giraffe
open DredgeFramework
open Microsoft.AspNetCore.Http
let loadAuthenticatePage (): HttpHandler =
let variables = map ["title", "Log In"]
let scripts = ["dredgepos.authenticate.js"]
let styles = ["dredgepos.authenticate.css"]
Theme.loadTemplateWithVarsScriptsAndStyles "authenticate" variables scripts styles
|> htmlString
let loginWithLoginCode (context: HttpContext) (login_code: int) =
if Model.clerkLogin login_code context then ajaxSuccess "success"
else ajaxFail "fail"

View File

@@ -1,13 +1,27 @@
module Session module DredgePos.Authenticate.Model
open System open System
open DredgeFramework open DredgeFramework
open Dapper.FSharp open Dapper.FSharp
open Clerk
open DredgePos open DredgePos
open Thoth.Json.Net open Thoth.Json.Net
open Types open Types
let getClerkByLoginCode (loginCode: int) =
let clerk =
select {
table "clerks"
where (eq "clerk_login_code" loginCode)
take 1
}
|> db.Select<clerk>
|> EnumerableToArray
if (clerk |> length) > 0 then
Some (first clerk)
else
None
let deleteSession sessionId context = let deleteSession sessionId context =
delete { delete {
table "sessions" table "sessions"
@@ -65,12 +79,10 @@ let sessionExists (sessionId: string) context =
let checkAuthentication clerk = let checkAuthentication clerk =
let existingClerk = getClerkByLoginCode clerk.clerk_login_code let existingClerk = getClerkByLoginCode clerk.clerk_login_code
if existingClerk.IsSome existingClerk.IsSome
&& existingClerk.Value.id = clerk.id && existingClerk.Value.id = clerk.id
&& existingClerk.Value.clerk_name = clerk.clerk_name && existingClerk.Value.clerk_name = clerk.clerk_name
&& existingClerk.Value.clerk_login_code = clerk.clerk_login_code && existingClerk.Value.clerk_login_code = clerk.clerk_login_code
then true
else false
let getLoginCookie context = Browser.getCookie "dredgepos_clerk_logged_in" context let getLoginCookie context = Browser.getCookie "dredgepos_clerk_logged_in" context

18
Authenticate/Router.fs Normal file
View File

@@ -0,0 +1,18 @@
module DredgePos.Authenticate.Router
open Saturn
open Giraffe
let homepage = (warbler (fun _ -> Controller.loadAuthenticatePage() ))
let handlePostRoute<'a> handlerFunction post next ctx = json (handlerFunction ctx post) next ctx
let pipeline = pipeline{
use_warbler
}
let router = router {
pipe_through pipeline
get "/" homepage
get "" homepage
post "/authenticateClerk" (bindJson<int> (handlePostRoute Controller.loginWithLoginCode) )
}

View File

@@ -1,37 +0,0 @@
module Clerk
open Dapper.FSharp
open DredgeFramework
open DredgePos
open Thoth.Json.Net
open Types
let mutable loginCookie = ""
let clerk_decoder : Decoder<clerk> =
Decode.object
(fun get ->
{
id = get.Required.Field "clerk_id" Decode.int
clerk_name = get.Required.Field "clerk_name" Decode.string
clerk_login_code = get.Required.Field "clerk_login_code" Decode.int
clerk_usergroup = get.Required.Field "clerk_usergroup" Decode.int
})
type user = {clerk_name:string}
let getClerkByLoginCode (loginCode: int) =
let clerk =
select {
table "clerks"
where (eq "clerk_login_code" loginCode)
take 1
}
|> db.Select<clerk>
|> EnumerableToArray
if (clerk |> length) > 0 then
Some (first clerk)
else
None

View File

@@ -1,48 +0,0 @@
module Decorations
open System
open System.IO
open System.Text.RegularExpressions
open DredgeFramework
open Dapper.FSharp
open DredgePos
open Types
let decorationsInRoom (roomId: int) = Entity.GetAllByColumn "decoration_room" roomId
let getImageName (image: string, path: string) =
let imageName =
image
|> StringReplace "-" " "
|> StringReplace "_" " "
|> ToTitleCase
imageName, path
let isImageFile (fileName: string) = Regex.IsMatch(fileName |> ToLowerCase, @"^.+\.(jpg|jpeg|png|gif)$")
let getImageHTML (imageName: string, imageUrl: string) =
let vars = map [
"image_name", imageName
"image_url", imageUrl
]
Theme.loadTemplateWithVars "decoratorItem" vars
let GetFileNameWithoutExtension (path: string) =
let name = Path.GetFileNameWithoutExtension path
name, path |> Path.GetFileName
let getImageRowHtml (imagesInRow: string[]) =
let vars = map ["decorations", String.Join("", imagesInRow)]
Theme.loadTemplateWithVars "decoratorRow" vars
let generateDecorator () =
"wwwroot/images/decorations"
|> Directory.GetFiles
|> Array.filter isImageFile
|> Array.map GetFileNameWithoutExtension
|> Array.map getImageName
|> Array.map getImageHTML
|> Array.chunkBySize 4
|> Array.map getImageRowHtml
|> JoinArray ""

View File

@@ -5,23 +5,31 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Types.fs" /> <Compile Include="Core\Types.fs" />
<Compile Include="DredgeFramework.module.fs" /> <Compile Include="Core\DredgeFramework.module.fs" />
<Compile Include="Browser.module.fs" /> <Compile Include="Core\Browser.module.fs" />
<Compile Include="Database.module.fs" /> <Compile Include="Core\Database.module.fs" />
<Compile Include="GenericEntities.module.fs" /> <Compile Include="Core\GenericEntities.module.fs" />
<Compile Include="Language.module.fs" /> <Compile Include="Core\Language.module.fs" />
<Compile Include="Theme.module.fs" /> <Compile Include="Core\Theme.module.fs" />
<Compile Include="Reservations.module.fs" />
<Compile Include="Floorplan.module.fs" />
<Compile Include="Printer.module.fs" /> <Compile Include="Printer.module.fs" />
<Compile Include="Orders.module.fs" /> <Compile Include="Entities\Floorplan_Decorations\Model.fs" />
<Compile Include="OrderScreen.module.fs" /> <Compile Include="Entities\Floorplan_Decorations\Controller.fs" />
<Compile Include="Decorations.module.fs" /> <Compile Include="Entities\Floorplan_Decorations\Router.fs" />
<Compile Include="Clerk.module.fs" /> <Compile Include="Authenticate\Model.fs" />
<Compile Include="Session.module.fs" /> <Compile Include="Authenticate\Controller.fs" />
<Compile Include="PageController.fs" /> <Compile Include="Authenticate\Router.fs" />
<Compile Include="AjaxController.fs" /> <Compile Include="Ajax\Controller.fs" />
<Compile Include="Ajax\Router.fs" />
<Compile Include="Floorplan\Model.fs" />
<Compile Include="Floorplan\Controller.fs" />
<Compile Include="Floorplan\Router.fs" />
<Compile Include="OrderScreen\Model.fs" />
<Compile Include="OrderScreen\Controller.fs" />
<Compile Include="OrderScreen\Router.fs" />
<Compile Include="Reservations\Model.fs" />
<Compile Include="Reservations\Controller.fs" />
<Compile Include="Reservations\Router.fs" />
<Compile Include="Program.fs" /> <Compile Include="Program.fs" />
</ItemGroup> </ItemGroup>

View File

@@ -0,0 +1,27 @@
module DredgePos.Entities.Floorplan_Decorations.Controller
open DredgeFramework
open System
open System.IO
let getImageHTML (imageName: string, imageUrl: string) =
let vars = map [
"image_name", imageName
"image_url", imageUrl
]
Theme.loadTemplateWithVars "decoratorItem" vars
let getImageRowHtml (imagesInRow: string[]) =
let vars = map ["decorations", String.Join("", imagesInRow)]
Theme.loadTemplateWithVars "decoratorRow" vars
let generateDecorator () =
"wwwroot/images/decorations"
|> Directory.GetFiles
|> Array.filter Model.isImageFile
|> Array.map Model.GetFileNameWithoutExtension
|> Array.map Model.getImageName
|> Array.map getImageHTML
|> Array.chunkBySize 4
|> Array.map getImageRowHtml
|> JoinArray ""

View File

@@ -0,0 +1,24 @@
module DredgePos.Entities.Floorplan_Decorations.Model
open System
open System.IO
open System.Text.RegularExpressions
open DredgeFramework
let decorationsInRoom (roomId: int) = Entity.GetAllByColumn "decoration_room" roomId
let getImageName (image: string, path: string) =
let imageName =
image
|> StringReplace "-" " "
|> StringReplace "_" " "
|> ToTitleCase
imageName, path
let isImageFile (fileName: string) = Regex.IsMatch(fileName |> ToLowerCase, @"^.+\.(jpg|jpeg|png|gif)$")
let GetFileNameWithoutExtension (path: string) =
let name = Path.GetFileNameWithoutExtension path
name, path |> Path.GetFileName

View File

@@ -0,0 +1,2 @@
module DredgePos.Entities.Floorplan_Decorations.Router

View File

@@ -1,22 +1,21 @@
module AjaxController module DredgePos.Floorplan.Controller
open DredgeFramework open DredgeFramework
open DredgePos open DredgePos
open DredgePos.Types open DredgePos.Types
open Floorplan
open Microsoft.AspNetCore.Http
open Reservations
open language
open Giraffe open Giraffe
open Types open Microsoft.AspNetCore.Http
open Model
let loginWithLoginCode (context: HttpContext) (login_code: int) = let makeRoomButton (room: floorplan_room) =
if Session.clerkLogin login_code context then ajaxSuccess "success" let vars = map [
else ajaxFail "fail" "roomId", room.id |> string
"roomName", room.room_name
]
let getLanguageVars = ajaxSuccess languageVars Theme.loadTemplateWithVars "roomButton" vars
let getActiveTables venue = Floorplan.getActiveTables venue |> ajaxSuccess |> json let getActiveTables venue = Model.getActiveTables venue |> ajaxSuccess |> json
let mergeTables (tables: floorplan_table[]) = let mergeTables (tables: floorplan_table[]) =
let status = let status =
@@ -24,14 +23,14 @@ let mergeTables (tables: floorplan_table[]) =
let outputTables = map [ let outputTables = map [
"parent", tables[0]; "parent", tables[0];
"child", tables[1]; "child", tables[1];
"merged", getTable tables[0].table_number; "merged", Model.getTable tables[0].table_number;
] ]
ajaxSuccess outputTables ajaxSuccess outputTables
else ajaxFail "Could Not Merge Tables" else ajaxFail "Could Not Merge Tables"
status |> json status |> json
let unmergeTable tableNumber = let unmergeTable tableNumber =
let unmerged = Floorplan.unmergeTable tableNumber let unmerged = unmergeTable tableNumber
let unmergedTables = let unmergedTables =
match unmerged with match unmerged with
| Some (parent, child) -> | Some (parent, child) ->
@@ -47,32 +46,13 @@ let getFloorplanData (id: int) =
{| {|
tables = tableList tables = tableList
decorations = Entity.GetAllInVenue<floorplan_decoration> decorations = Entity.GetAllInVenue<floorplan_decoration>
activeTableNumbers = Floorplan.getActiveTables (getCurrentVenue()) activeTableNumbers = Model.getActiveTables (getCurrentVenue())
rooms = Entity.GetAllInVenue<floorplan_room> rooms = Entity.GetAllInVenue<floorplan_room>
reservations = reservationList reservations = reservationList
|} |}
|> ajaxSuccess |> ajaxSuccess
|> json |> json
let getOrderScreenData (tableNumber: int) =
{|
order_screen_pages = Entity.GetAllInVenue<order_screen_page_group>
sales_categories = Entity.GetAllInVenue<sales_category>
print_groups = Entity.GetAllInVenue<print_group>
custom_item = Entity.GetAllByColumn<item> "item_code" "OPEN000" |> first
table = getTable tableNumber
|}
|> ajaxSuccess
|> json
let getKeyboardLayout (language: string) =
let layout = $"""wwwroot/languages/{language}/keyboardLayout.json"""
|> GetFileContents
map [
"status", "success"
"data", layout
] |> json
let transformTable (table: floorplan_table) = let transformTable (table: floorplan_table) =
Entity.Update table Entity.Update table
|> ajaxSuccess |> ajaxSuccess
@@ -90,7 +70,7 @@ let deleteTable (table: floorplan_table) =
table |> ajaxSuccess |> json table |> ajaxSuccess |> json
let transferTable (origin, destination) = let transferTable (origin, destination) =
Floorplan.transferTable origin destination Model.transferTable origin destination
let data = map ["origin", getTable origin ; "destination", getTable destination] let data = map ["origin", getTable origin ; "destination", getTable destination]
ajaxSuccess data |> json ajaxSuccess data |> json
@@ -125,32 +105,23 @@ let DeleteDecoration (decorationToDelete: floorplan_decoration) =
|> ajaxSuccess |> ajaxSuccess
|> json |> json
let newEmptyReservation (reservation: reservation) = let loadFloorplan (ctx: HttpContext) : HttpHandler =
let newReservation = {reservation with Authenticate.Model.RequireClerkAuthentication ctx
created_at = CurrentTime()
time = CurrentTime()
}
if reservation.floorplan_table_id > 0 then let roomMenu =
let table = {(getTableById reservation.floorplan_table_id) with Entity.GetAllInVenue<floorplan_room>
status = 2 |> Array.map makeRoomButton
default_covers = reservation.covers} |> joinWithNewLine
updateTablePosition table |> ignore
let createdReservation = Floorplan.createEmptyReservation newReservation let variables = map [
ajaxSuccess createdReservation |> json "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 updateReservation (reservation: reservation) = updateReservation reservation |> ajaxSuccess |> json let arrays = map ["clerk", currentClerk]
let unreserveTable (table: floorplan_table) = htmlString <| Theme.loadTemplateWithVarsArraysScriptsAndStyles "floorplan" variables arrays scripts styles
let newTable = {table with status = 0}
updateTablePosition newTable |> ignore
DeleteReservation newTable.id
newTable |> ajaxSuccess |> json
let loadGrid (gridId: int) =
let grid = Entity.GetById<grid> gridId
let gridHtml = OrderScreen.loadGrid gridId
if gridHtml = "Error" then ajaxFail gridHtml
else ajaxSuccess {|grid=grid;gridHtml=gridHtml|}
|> json

View File

@@ -1,19 +1,12 @@
module Floorplan module DredgePos.Floorplan.Model
open DredgePos
open DredgePos.Types open DredgePos.Types
open Org.BouncyCastle.Asn1.X509
open Reservations
open System open System
open System.IO open System.IO
open System.Xml.Linq open System.Xml.Linq
open DredgeFramework open DredgeFramework
open Dapper
open Dapper.FSharp open Dapper.FSharp
open Thoth.Json.Net open Thoth.Json.Net
open Types
let activeTablePath = "tables/active/" let activeTablePath = "tables/active/"
let getTableFile (tableNumber: int) = let getTableFile (tableNumber: int) =
@@ -281,13 +274,7 @@ let unmergeTable tableNumber = //Separates a merged table into itself and the la
Some (getTable currentTable.table_number, unmergedChild) Some (getTable currentTable.table_number, unmergedChild)
| Error _ -> None | Error _ -> None
let makeRoomButton (room: floorplan_room) =
let vars = map [
"roomId", room.id |> string
"roomName", room.room_name
]
Theme.loadTemplateWithVars "roomButton" vars
let getReservationList (tableList: floorplan_table[]) = let getReservationList (tableList: floorplan_table[]) =
tableList |> Array.collect Entity.GetAllRelated<reservation, floorplan_table> tableList |> Array.collect Entity.GetAllRelated<reservation, 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
}

View File

@@ -1,46 +1,35 @@
module PageController module DredgePos.OrderScreen.Controller
open System open DredgePos
open DredgePos.Types
open FSharp.Data
open Microsoft.AspNetCore.Http
open Floorplan
open Giraffe
open DredgeFramework open DredgeFramework
open DredgePos.Types
open Giraffe
open Microsoft.AspNetCore.Http
let loadHomePage(): HttpHandler = let getOrderScreenData (tableNumber: int) =
let variables = map ["title", "Log In"] {|
let scripts = ["dredgepos.authenticate.js"] order_screen_pages = Entity.GetAllInVenue<order_screen_page_group>
let styles = ["dredgepos.authenticate.css"] sales_categories = Entity.GetAllInVenue<sales_category>
print_groups = Entity.GetAllInVenue<print_group>
custom_item = Entity.GetAllByColumn<item> "item_code" "OPEN000" |> first
table = Floorplan.Model.getTable tableNumber
|}
|> ajaxSuccess
|> json
Theme.loadTemplateWithVarsScriptsAndStyles "authenticate" variables scripts styles let loadGrid (gridId: int) =
|> htmlString let grid = Entity.GetById<grid> gridId
let gridHtml = Model.loadGrid gridId
let loadFloorplan (ctx: HttpContext) : HttpHandler = if gridHtml = "Error" then ajaxFail gridHtml
Session.RequireClerkAuthentication ctx else ajaxSuccess {|grid=grid;gridHtml=gridHtml|}
|> json
let roomMenu =
Entity.GetAllInVenue<floorplan_room>
|> Array.map makeRoomButton
|> joinWithNewLine
let variables = map [
"title", "Floorplan"
"roomMenu", roomMenu
"decorator", Decorations.generateDecorator()
]
let styles = ["dredgepos.floorplan.css"]
let scripts = ["../external/konva.min.js" ; "dredgepos.floorplan.js"]
let currentClerk = recordToMap <| Session.getCurrentClerk ctx
let arrays = map ["clerk", currentClerk]
htmlString <| Theme.loadTemplateWithVarsArraysScriptsAndStyles "floorplan" variables arrays scripts styles
let loadOrderScreen (ctx: HttpContext) (tableNumber: int) : HttpHandler = let loadOrderScreen (ctx: HttpContext) (tableNumber: int) : HttpHandler =
Session.RequireClerkAuthentication ctx Authenticate.Model.RequireClerkAuthentication ctx
let covers = if tableNumber > 0 then (getTable tableNumber).default_covers else 0 let table = Floorplan.Model.getTable tableNumber
let covers = if tableNumber > 0 then table.default_covers else 0
let coverString = language.getAndReplace "covers" [covers] let coverString = language.getAndReplace "covers" [covers]
let changeCoverNumberButton = if tableNumber > 0 then Theme.loadTemplateWithVars "orderScreen/change_cover_number_button" (map ["covers", coverString]) else "" let changeCoverNumberButton = if tableNumber > 0 then Theme.loadTemplateWithVars "orderScreen/change_cover_number_button" (map ["covers", coverString]) else ""
@@ -51,7 +40,7 @@ let loadOrderScreen (ctx: HttpContext) (tableNumber: int) : HttpHandler =
let containerAttributes = let containerAttributes =
if tableNumber > 0 then if tableNumber > 0 then
map ["data-table", jsonEncode (getTable tableNumber)] map ["data-table", jsonEncode table]
|> Theme.htmlAttributes |> Theme.htmlAttributes
else "" else ""
@@ -67,8 +56,8 @@ let loadOrderScreen (ctx: HttpContext) (tableNumber: int) : HttpHandler =
|> joinWithNewLine |> joinWithNewLine
let grids = let grids =
OrderScreen.getAllPageGrids () Model.getAllPageGrids ()
|> Array.map OrderScreen.getPagesHTML |> Array.map Model.getPagesHTML
|> joinWithNewLine |> joinWithNewLine
let coverSelectorButtons = let coverSelectorButtons =
@@ -87,26 +76,14 @@ let loadOrderScreen (ctx: HttpContext) (tableNumber: int) : HttpHandler =
"orderNumber", orderNumber "orderNumber", orderNumber
"changeCoverNumberButton", changeCoverNumberButton "changeCoverNumberButton", changeCoverNumberButton
"covers", coverString "covers", coverString
"salesCategoryOverrideButtons", OrderScreen.generateSalesCategoryOverrideButtons () "salesCategoryOverrideButtons", Model.generateSalesCategoryOverrideButtons ()
"coverSelectorButtons", coverSelectorButtons "coverSelectorButtons", coverSelectorButtons
] ]
let styles = ["dredgepos.orderScreen.css"] let styles = ["dredgepos.orderScreen.css"]
let scripts = ["dredgepos.tables.js";"../external/currency.min.js";"dredgepos.orderScreen.js"; ] let scripts = ["dredgepos.tables.js";"../external/currency.min.js";"dredgepos.orderScreen.js"; ]
let currentClerk = recordToMap <| Session.getCurrentClerk ctx let currentClerk = recordToMap <| Authenticate.Model.getCurrentClerk ctx
let arrays = map ["clerk", currentClerk] let arrays = map ["clerk", currentClerk]
Theme.loadTemplateWithVarsArraysScriptsAndStyles "orderScreen" variables arrays scripts styles Theme.loadTemplateWithVarsArraysScriptsAndStyles "orderScreen" variables arrays scripts styles
|> htmlString |> htmlString
let getOpenTables() =
let rows = openTables()
rows |> jsonEncode
let mergeTables parent child =
mergeTables parent child |> ignore
"done"
let unmergeTables table =
unmergeTable table |> ignore
"done"

View File

@@ -1,4 +1,5 @@
module OrderScreen module DredgePos.OrderScreen.Model
open DredgeFramework open DredgeFramework
open DredgePos open DredgePos
open DredgePos.Types open DredgePos.Types
@@ -133,5 +134,3 @@ let getPagesHTML (gridInfo: grid * order_screen_page_group) =
renderGrid grid renderGrid grid
|> renderPageGroup pageGroup |> renderPageGroup pageGroup

15
OrderScreen/Router.fs Normal file
View File

@@ -0,0 +1,15 @@
module DredgePos.OrderScreen.Router
open DredgePos
open DredgePos.Types
open Saturn
open Giraffe
let router = router {
pipe_through Ajax.Router.pipeline
getf "/getOrderScreenData/%i" Controller.getOrderScreenData
getf "/getGridHtml/%i" Controller.loadGrid
post "/updateCovers" (bindJson<floorplan_table> (fun table -> Entity.Update table |> Array.head |> DredgeFramework.ajaxSuccess |> json))
get "/" (warbler (fun ctx -> Controller.loadOrderScreen (snd ctx) 0))
getf "/%i" (fun number -> (warbler (fun ctx -> Controller.loadOrderScreen (snd ctx) number)))
}

View File

@@ -1,3 +0,0 @@
module Orders
let getHighestOrderNumber () = 6

View File

@@ -1,71 +1,26 @@
namespace WebApplication namespace DredgePos
open DredgePos open DredgePos
open DredgePos.Types
open Microsoft.AspNetCore.Server.Kestrel.Core
open Reservations
open Saturn open Saturn
open Giraffe open Giraffe
open Types
module Program = module Program =
let router = router {
let handlePostRoute<'a> handlerFunction post next ctx = pipe_through Ajax.Router.pipeline
json (handlerFunction ctx post) next ctx
let browser = pipeline {
use_warbler
}
let floorplanRouter = router {
pipe_through browser
post "/authenticateClerk" (bindJson<int> (handlePostRoute AjaxController.loginWithLoginCode) )
post "/transformTable" (bindJson<floorplan_table> AjaxController.transformTable)
post "/createTable" (bindJson<floorplan_table> AjaxController.createTable)
post "/addDecoration" (bindJson<floorplan_decoration> AjaxController.AddDecoration)
post "/updateDecoration" (bindJson<floorplan_decoration> AjaxController.UpdateDecoration)
post "/deleteDecoration" (bindJson<floorplan_decoration> AjaxController.DeleteDecoration)
post "/deleteTable" (bindJson<floorplan_table> AjaxController.deleteTable)
post "/mergeTables" (bindJson<floorplan_table[]> AjaxController.mergeTables)
post "/newEmptyReservation" (bindJson<reservation> AjaxController.newEmptyReservation)
post "/updateReservation" (bindJson<reservation> AjaxController.updateReservation)
post "/getReservation" (bindJson<int> (fun reservation -> json <| GetReservationById reservation) )
post "/unreserveTable" (bindJson<floorplan_table> AjaxController.unreserveTable )
getf "/getKeyboardLayout/%s" AjaxController.getKeyboardLayout
get "/languageVars" (json <| AjaxController.getLanguageVars)
get "/getOpenTables" (json <| Floorplan.getActiveTables (DredgeFramework.getCurrentVenue()))
getf "/getFloorplanData/%i" AjaxController.getFloorplanData
getf "/tableIsOpen/%i" (fun tableNumber -> json <| Floorplan.tableNumberIsOpen tableNumber)
getf "/transferTable/%i/%i" AjaxController.transferTable
getf "/unmergeTable/%i" AjaxController.unmergeTable
getf "/tableExists/%i" (fun tableNumber -> json <| Floorplan.tableExists tableNumber)
}
let orderScreenRouter = router {
pipe_through browser
getf "/getOrderScreenData/%i" AjaxController.getOrderScreenData
getf "/getGridHtml/%i" AjaxController.loadGrid
post "/updateCovers" (bindJson<floorplan_table> (fun table -> Entity.Update table |> Array.head |> DredgeFramework.ajaxSuccess |> json))
}
let pageRouter = router {
pipe_through browser
not_found_handler (setStatusCode 404 >=> text "404") not_found_handler (setStatusCode 404 >=> text "404")
get "/" (redirectTo true "/login") get "/" (redirectTo true "/login")
get "/login" (warbler (fun _ -> PageController.loadHomePage() )) forward "/ajax" Ajax.Router.router
get "/floorplan" (warbler (fun ctx -> PageController.loadFloorplan (snd ctx))) forward "/floorplan" DredgePos.Floorplan.Router.router
get "/order" (warbler (fun ctx -> PageController.loadOrderScreen (snd ctx) 0)) forward "/order" DredgePos.OrderScreen.Router.router
getf "/order/%i" (fun number -> (warbler (fun ctx -> PageController.loadOrderScreen (snd ctx) number))) forward "/login" DredgePos.Authenticate.Router.router
forward "/ajax" floorplanRouter forward "/reservations" DredgePos.Reservations.Router.router
forward "/orderScreen" orderScreenRouter
} }
let app = application { let app = application {
use_mime_types [(".woff", "application/font-woff")] use_mime_types [(".woff", "application/font-woff")]
use_static "wwwroot" use_static "wwwroot"
use_router pageRouter use_router router
url "http://0.0.0.0:5001" url "http://0.0.0.0:5001"
} }
run app run app

View File

@@ -0,0 +1,29 @@
module DredgePos.Reservations.Controller
open DredgeFramework
open DredgePos
open DredgePos.Types
open Giraffe
let newEmptyReservation (reservation: reservation) =
let newReservation = {reservation with
created_at = CurrentTime()
time = CurrentTime()
}
if reservation.floorplan_table_id > 0 then
let table = {(Entity.GetById<floorplan_table> reservation.floorplan_table_id) with
status = 2
default_covers = reservation.covers}
Floorplan.Model.updateTablePosition table |> ignore
let createdReservation = Floorplan.Model.createEmptyReservation newReservation
ajaxSuccess createdReservation |> json
let updateReservation (reservation: reservation) = Model.updateReservation reservation |> ajaxSuccess |> json
let unreserveTable (table: floorplan_table) =
let newTable = {table with status = 0}
Floorplan.Model.updateTablePosition newTable |> ignore
Model.DeleteReservation newTable.id
newTable |> ajaxSuccess |> json

View File

@@ -1,19 +1,10 @@
module Reservations module DredgePos.Reservations.Model
open System
open DredgeFramework open DredgeFramework
open Dapper.FSharp open Dapper.FSharp
open DredgePos open DredgePos
open Types open Types
let GetReservationById (id: int) =
select {
table "reservations"
where (eq "id" id)
}
|> db.Select<reservation>
|> first
let updateReservation (reservation: reservation) = let updateReservation (reservation: reservation) =
update{ update{
table "reservations" table "reservations"
@@ -25,5 +16,5 @@ let updateReservation (reservation: reservation) =
let DeleteReservation (tableId: int) = let DeleteReservation (tableId: int) =
delete { delete {
table "reservations" table "reservations"
where (eq "reservation_table_id" tableId) where (eq "floorplan_table_id" tableId)
} |> db.Delete |> ignore } |> db.Delete |> ignore

13
Reservations/Router.fs Normal file
View File

@@ -0,0 +1,13 @@
module DredgePos.Reservations.Router
open DredgePos
open DredgePos.Types
open Saturn
open Giraffe
let router = router {
pipe_through Ajax.Router.pipeline
post "/newEmptyReservation" (bindJson<reservation> Controller.newEmptyReservation)
post "/updateReservation" (bindJson<reservation> Controller.updateReservation)
post "/unreserveTable" (bindJson<floorplan_table> Controller.unreserveTable )
}

View File

@@ -1,9 +1,9 @@
let showLoginBox = () => showVirtualNumpad('Enter Login Code', 6, true, false, false, authenticate) let showLoginBox = () => showVirtualNumpad('Enter Login Code', 6, true, false, false, authenticate)
let authenticate = (input : string) => { let authenticate = (input : string) => {
let login = ajaxSync('/ajax/authenticateClerk', input) let login = ajaxSync('/login/authenticateClerk', input)
if(login === 'success'){ if(login === 'success'){
location.assign('/floorplan') location.assign('/floorplan/')
} }
else else
showLoginBox() showLoginBox()

View File

@@ -50,7 +50,7 @@ const Floorplan: floorplan = {
selectedDecorationId: 0 selectedDecorationId: 0
}; };
$(() => ajax('/ajax/getFloorplanData/1', null, 'get', setupFloorplan, null, null) ) $(() => ajax('/floorplan/getFloorplanData/1', null, 'get', setupFloorplan, null, null) )
const setupFloorplanEvents = () => { const setupFloorplanEvents = () => {
@@ -276,7 +276,7 @@ const saveTable = (tableToUpdate: floorplan_table) => {
tables.push(tableToUpdate) tables.push(tableToUpdate)
Floorplan.tables = tables Floorplan.tables = tables
ajax("/ajax/transformTable", tableToUpdate, 'post', null,null,null) ajax("/floorplan/transformTable", tableToUpdate, 'post', null,null,null)
} }
const setTransformerNodes = (nodes: Konva.Shape[]) => { const setTransformerNodes = (nodes: Konva.Shape[]) => {
@@ -347,7 +347,7 @@ const createEmptyReservation = (covers: number) => {
time: 0, time: 0,
} }
ajax('/ajax/newEmptyReservation', newReservation,'post', emptyReservationCreated, null, null ) ajax('/reservations/newEmptyReservation', newReservation,'post', emptyReservationCreated, null, null )
} }
const emptyReservationCreated = (reservation: reservation) => { const emptyReservationCreated = (reservation: reservation) => {
@@ -366,7 +366,7 @@ const addReservationName = (name: string) => {
hideVirtualKeyboard() hideVirtualKeyboard()
const reservation = Floorplan.reservations.filter(reservation => reservation.floorplan_table_id == getSelectedTableData().id)[0] const reservation = Floorplan.reservations.filter(reservation => reservation.floorplan_table_id == getSelectedTableData().id)[0]
reservation.name = name reservation.name = name
ajax('/ajax/updateReservation', reservation, 'post', reservationNameAdded, null, null) ajax('/reservations/updateReservation', reservation, 'post', reservationNameAdded, null, null)
} }
const reservationNameAdded = (updatedReservation: reservation) => { const reservationNameAdded = (updatedReservation: reservation) => {
@@ -386,7 +386,7 @@ const updateTableData = (tableToRemove: floorplan_table) => {
const unreserveTable = () => { const unreserveTable = () => {
const selectedTable = getSelectedTableData() const selectedTable = getSelectedTableData()
selectedTable.status = 0 selectedTable.status = 0
ajax('/ajax/unreserveTable', selectedTable, 'post', tableUnreserved, null, null) ajax('/reservations/unreserveTable', selectedTable, 'post', tableUnreserved, null, null)
} }
const tableUnreserved = (table: floorplan_table) => { const tableUnreserved = (table: floorplan_table) => {
@@ -500,7 +500,7 @@ const createDecorationShape = (decoration:decoration, select?: boolean) => {
} }
} }
decorationShape.src = 'images/decorations/' + decoration.decoration_image decorationShape.src = '/images/decorations/' + decoration.decoration_image
} }
const setupDecorationEvents = (decorationShape: Konva.Image) => { const setupDecorationEvents = (decorationShape: Konva.Image) => {
@@ -567,7 +567,7 @@ const saveDecoration = (decorationToUpdate: decoration) => {
decorations.push(decorationToUpdate) decorations.push(decorationToUpdate)
Floorplan.decorations = decorations Floorplan.decorations = decorations
ajax("/ajax/updateDecoration", decorationToUpdate, 'post', null,null,null) ajax("/floorplan/updateDecoration", decorationToUpdate, 'post', null,null,null)
} }
const showDecorator = () => $('#decorator').css('display', 'flex') const showDecorator = () => $('#decorator').css('display', 'flex')
@@ -588,7 +588,7 @@ const addDecoration = (e: Event) => {
venue_id: Floorplan.currentRoom.venue_id venue_id: Floorplan.currentRoom.venue_id
} }
ajax('/ajax/addDecoration', newDecoration, 'post', decorationAdded, null, null) ajax('/floorplan/addDecoration', newDecoration, 'post', decorationAdded, null, null)
} }
const decorationAdded = (decoration: decoration) => { const decorationAdded = (decoration: decoration) => {
@@ -600,7 +600,7 @@ const decorationAdded = (decoration: decoration) => {
const deleteDecoration = () => ajax( const deleteDecoration = () => ajax(
'/ajax/deleteDecoration', '/floorplan/deleteDecoration',
getDecorationDataById(Floorplan.selectedDecorationId), getDecorationDataById(Floorplan.selectedDecorationId),
'post', decorationDeleted, null, null) 'post', decorationDeleted, null, null)
@@ -616,7 +616,7 @@ const setRoomBackground = (roomToLoad: room) => {
const height = Floorplan.floorplanDiv.height() const height = Floorplan.floorplanDiv.height()
if(roomToLoad.background_image) { if(roomToLoad.background_image) {
Floorplan.floorplanDiv.css("background-image", `url(images/rooms/${roomToLoad?.background_image})`) Floorplan.floorplanDiv.css("background-image", `url(/images/rooms/${roomToLoad?.background_image})`)
Floorplan.floorplanDiv.css("background-size", `${width}px ${height}px`) Floorplan.floorplanDiv.css("background-size", `${width}px ${height}px`)
} }
} }
@@ -735,7 +735,7 @@ const addTable = (tableNumber: number) => {
venue_id: 1 venue_id: 1
}; };
ajax('/ajax/createTable', newTable, 'post', tableAdded, tableNotAdded, null) ajax('/floorplan/createTable', newTable, 'post', tableAdded, tableNotAdded, null)
} }
const tableAdded = (table: floorplan_table) => { const tableAdded = (table: floorplan_table) => {
@@ -763,7 +763,7 @@ const deleteTable = (tableNumber: number) => {
return false return false
} }
ajax(`/ajax/deleteTable`, tableToDelete, 'post', tableDeleted, null, null); ajax(`/floorplan/deleteTable`, tableToDelete, 'post', tableDeleted, null, null);
} }
const tableDeleted = (deletedTable: floorplan_table) => { const tableDeleted = (deletedTable: floorplan_table) => {
@@ -782,7 +782,7 @@ const mergeTables = (table1: floorplan_table, table2: floorplan_table ) => {
posAlert(lang('error_self_merge')) posAlert(lang('error_self_merge'))
return false; return false;
} }
ajax('/ajax/mergeTables', [table1, table2], 'post', tablesMerged, null, null) ajax('/floorplan/mergeTables', [table1, table2], 'post', tablesMerged, null, null)
} }
const tablesMerged = (tables: Record<'child'|'parent'|'merged', floorplan_table>) => { const tablesMerged = (tables: Record<'child'|'parent'|'merged', floorplan_table>) => {
@@ -795,7 +795,7 @@ const tablesMerged = (tables: Record<'child'|'parent'|'merged', floorplan_table>
tableGroup.draggable(true) tableGroup.draggable(true)
} }
const unmergeTable = () => ajax(`/ajax/unmergeTable/${Floorplan.selectedTableNumber}`, null, 'get', tablesUnmerged, null, null) const unmergeTable = () => ajax(`/floorplan/unmergeTable/${Floorplan.selectedTableNumber}`, null, 'get', tablesUnmerged, null, null)
const tablesUnmerged = (tables: Record<'child'|'parent', floorplan_table>) => { const tablesUnmerged = (tables: Record<'child'|'parent', floorplan_table>) => {
const parentTable = tables['parent'] const parentTable = tables['parent']
@@ -815,7 +815,7 @@ const transferTables = (origin: floorplan_table, destination: floorplan_table) =
return return
} }
ajax(`/ajax/transferTable/${origin.table_number}/${destination.table_number}`, null, 'get', tableTransferred, null, null) ajax(`/floorplan/transferTable/${origin.table_number}/${destination.table_number}`, null, 'get', tableTransferred, null, null)
} }
const tableTransferred = (tables: Record<"origin"|"destination", floorplan_table>) => { const tableTransferred = (tables: Record<"origin"|"destination", floorplan_table>) => {

View File

@@ -303,7 +303,7 @@ const itemButtonClicked = (e: JQuery.TriggeredEvent) => {
const gridButtonClicked = (e: JQuery.TriggeredEvent) => { const gridButtonClicked = (e: JQuery.TriggeredEvent) => {
const button = $(e.target).closest('.posButton') const button = $(e.target).closest('.posButton')
const grid : number = button.data('grid') const grid : number = button.data('grid')
ajax(`/orderScreen/getGridHtml/${grid}`, null, null,gridHtmlGenerated, null, null) ajax(`/order/getGridHtml/${grid}`, null, null,gridHtmlGenerated, null, null)
} }
@@ -571,7 +571,7 @@ const changeCoverNumberPromptSubmitted = (value: string) => updateCoverNumbers(N
const updateCoverNumbers = (covers: number) => { const updateCoverNumbers = (covers: number) => {
let newTable = Object.assign({}, OrderScreen.table) let newTable = Object.assign({}, OrderScreen.table)
newTable.default_covers = covers newTable.default_covers = covers
ajax('/orderScreen/updateCovers', newTable, 'post', coverNumbersUpdated, null, null) ajax('/order/updateCovers', newTable, 'post', coverNumbersUpdated, null, null)
} }
const coverNumbersUpdated = (newTable: floorplan_table) => { const coverNumbersUpdated = (newTable: floorplan_table) => {
@@ -600,5 +600,5 @@ const generateCoverSelector = () => {
$(() => { $(() => {
OrderScreen.table = $('#pageContainer').data('table') || null OrderScreen.table = $('#pageContainer').data('table') || null
ajax('/orderScreen/getOrderScreenData/1', null, 'get', setupOrderScreen, null, null) ajax('/order/getOrderScreenData/1', null, 'get', setupOrderScreen, null, null)
}) })

View File

@@ -1,4 +1,4 @@
<div class="decoratorItem" data-image="<!--[var:image_url]-->"> <div class="decoratorItem" data-image="<!--[var:image_url]-->">
<a style="background-image:url('images/decorations/<!--[var:image_url]-->')"></a> <a style="background-image:url('/images/decorations/<!--[var:image_url]-->')"></a>
<a><!--[var:image_name]--></a> <a><!--[var:image_name]--></a>
</div> </div>