Merge pull request #8 from dredgy/orderscreen_view

Orderscreen view
This commit is contained in:
dredgy
2022-07-02 14:23:28 +10:00
committed by GitHub
17 changed files with 397 additions and 272 deletions

View File

@@ -25,5 +25,4 @@ let setCookie name value (expiry: DateTimeOffset) (context: HttpContext) =
options.Expires <- expiry options.Expires <- expiry
context.Response.Cookies.Append(name, value, options); context.Response.Cookies.Append(name, value, options);
let redirect url (context: HttpContext) = let redirect url (context: HttpContext) = context.Response.Redirect url
context.Response.Redirect url

View File

@@ -20,6 +20,7 @@
<Compile Include="Entities\Floorplan_Decorations\View.fs" /> <Compile Include="Entities\Floorplan_Decorations\View.fs" />
<Compile Include="Entities\Floorplan_Decorations\Controller.fs" /> <Compile Include="Entities\Floorplan_Decorations\Controller.fs" />
<Compile Include="Entities\Floorplan_Decorations\Router.fs" /> <Compile Include="Entities\Floorplan_Decorations\Router.fs" />
<Compile Include="Entities\Buttons\Model.fs" />
<Compile Include="Authenticate\Model.fs" /> <Compile Include="Authenticate\Model.fs" />
<Compile Include="Authenticate\View.fs" /> <Compile Include="Authenticate\View.fs" />
<Compile Include="Authenticate\Controller.fs" /> <Compile Include="Authenticate\Controller.fs" />
@@ -36,6 +37,7 @@
<Compile Include="Floorplan\Controller.fs" /> <Compile Include="Floorplan\Controller.fs" />
<Compile Include="Floorplan\Router.fs" /> <Compile Include="Floorplan\Router.fs" />
<Compile Include="OrderScreen\Model.fs" /> <Compile Include="OrderScreen\Model.fs" />
<Compile Include="OrderScreen\View.fs" />
<Compile Include="OrderScreen\Controller.fs" /> <Compile Include="OrderScreen\Controller.fs" />
<Compile Include="OrderScreen\Router.fs" /> <Compile Include="OrderScreen\Router.fs" />
<Compile Include="Reservations\Model.fs" /> <Compile Include="Reservations\Model.fs" />

19
Entities/Buttons/Model.fs Normal file
View File

@@ -0,0 +1,19 @@
module DredgePos.Entities.Buttons.Model
open DredgePos.Types
open DredgeFramework
let attr = Giraffe.ViewEngine.HtmlElements.attr
let getItemActionAttributes (itemCode: string) =
let item = Entity.GetFirstByColumn<item> "code" (StringTrim itemCode)
[(attr "data-item") <| jsonEncode item]
let getGridActionAttributes (gridId: int) = [(attr "data-grid") <| jsonEncode gridId]
let getActionAttributes (action: string) (actionValue: string) =
match action with
| "item" -> getItemActionAttributes actionValue
| "grid" -> actionValue |> int |> getGridActionAttributes
| _ -> []

View File

@@ -87,14 +87,20 @@ let saveOrderToTable orderXML tableNumber =
File.WriteAllText(tableFile, tableXML) File.WriteAllText(tableFile, tableXML)
let getTable (tableNumber : int) = let getTableSafely (tableNumber: int) =
let query = select { let query = select {
table "floorplan_tables" table "floorplan_tables"
where (eq "table_number" tableNumber + eq "venue_id" (getCurrentVenue())) where (eq "table_number" tableNumber + eq "venue_id" (getCurrentVenue()))
} }
let result = query |> Database.Select<floorplan_table> query
result |> first |> Database.Select<floorplan_table>
|> Array.tryItem 0
let getTable (tableNumber : int) =
match getTableSafely tableNumber with
| None -> failwith $"Table {tableNumber} not found in current venue"
| Some table -> table
let getTableById (id : int) = let getTableById (id : int) =
select { select {

View File

@@ -8,9 +8,7 @@ open Giraffe.ViewEngine
open DredgeFramework open DredgeFramework
let VisibleInMode (value: string list) = value |> jsonEncode |> (attr "data-visible-in-mode")
let InvisibleInMode (value: string list) = value |> jsonEncode |> (attr "data-invisible-in-mode")
let ActiveInMode (value: string) = value |> (attr "data-active-in-mode")
let pageContainer (clerk: clerk) roomMenu = let pageContainer (clerk: clerk) roomMenu =

View File

@@ -8,4 +8,11 @@ let htmlViewWithContext func =
func (snd ctx) func (snd ctx)
|> htmlView |> htmlView
) )
|> warbler
let htmlViewWithContextAndId (id: int) func =
(fun ctx ->
func (snd ctx) id
|> htmlView
)
|> warbler |> warbler

View File

@@ -1,12 +1,20 @@
module DredgePos.Global.View module DredgePos.Global.View
open Giraffe.ViewEngine
open DredgeFramework open DredgeFramework
open DredgePos.Types
open Giraffe.ViewEngine
let Value = attr "data-value" let Value = attr "data-value"
let _table (value: floorplan_table) = value |> jsonEncode |> (attr "data-table")
let VisibleInMode (value: string list) = value |> jsonEncode |> (attr "data-visible-in-mode")
let InvisibleInMode (value: string list) = value |> jsonEncode |> (attr "data-invisible-in-mode")
let ActiveInMode (value: string) = value |> (attr "data-active-in-mode")
let innerText = str let innerText = str
let lang key = language.get key |> str let lang key = language.get key |> str
let template = tag "template"
let scriptToHTML (scriptFile: string) = let scriptToHTML (scriptFile: string) =
let scriptPath = $"/scripts/{scriptFile}" let scriptPath = $"/scripts/{scriptFile}"
match FileExists ("wwwroot" + scriptPath) with match FileExists ("wwwroot" + scriptPath) with
@@ -89,6 +97,23 @@ let keyboards = [|
alert alert
|] |]
let posButton (extraClasses: string) attrs content =
let allAttrs = [_class $"posButton {extraClasses}"] |> List.append attrs
a allAttrs content
let PosButton classes (attrs: Map<string, 'x>) text =
let attrArray =
attrs
|> Map.map (fun key value ->
(attr key) (string value)
)
|> Map.values
|> Array.ofSeq
posButton classes [
yield! attrArray
] [str text]
let HtmlPage pageTitle scripts styles tags content = let HtmlPage pageTitle scripts styles tags content =
html [] [ html [] [
head [] [ head [] [

View File

@@ -4,6 +4,8 @@ open DredgeFramework
open DredgePos.Types open DredgePos.Types
open System.IO open System.IO
let spaceButton () = (Entity.GetFirstByColumn<button> "primary_action" "spacer").id
let CreatePageFromDirectory index (dir: string) = let CreatePageFromDirectory index (dir: string) =
let dirName = DirectoryInfo(dir).Name let dirName = DirectoryInfo(dir).Name
@@ -103,6 +105,33 @@ let CreateDefaultSalesCategories (path: string) =
path path
let CreateDefaultButtons (path: string) =
Entity.Create {
id = 0
text = ""
primary_action = "spacer"
secondary_action = ""
primary_action_value = ""
secondary_action_value = ""
image = ""
extra_classes = "invisible"
extra_styles = ""
}
|> ignore
path
let CreateDefaultItems (path: string) =
Entity.Create {
id = 0
name = "Custom Item"
code = "OPEN000"
sales_category_id = (Entity.GetFirstByColumn<sales_category> "name" "Food").id
item_type = "item"
price1 = 0
}
|> ignore
path
let CreateRooms () = let CreateRooms () =
"wwwroot/images/rooms" "wwwroot/images/rooms"
|> Directory.GetFiles |> Directory.GetFiles
@@ -122,23 +151,24 @@ let populateEntreeGrid () =
let DipSalesCategory = Entity.GetFirstByColumn<sales_category> "name" "Dips" let DipSalesCategory = Entity.GetFirstByColumn<sales_category> "name" "Dips"
let Entrees = Entity.GetAllByColumn<item> "sales_category_id" SalesCategory.id let Entrees = Entity.GetAllByColumn<item> "sales_category_id" SalesCategory.id
let Dips = Entity.GetAllByColumn<item> "sales_category_id" DipSalesCategory.id let Dips = Entity.GetAllByColumn<item> "sales_category_id" DipSalesCategory.id
let space = spaceButton()
let GridData = let GridData =
[| [|
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
|] |]
|> Array.mapi (fun index current -> |> Array.mapi (fun index current ->
let isFirstColumn = (index % 6) = 0 let isFirstColumn = (index % 6) = 0
if not isFirstColumn then current else if not isFirstColumn then current else
let entree = Entrees |> Array.tryItem (index/6) let entree = Entrees |> Array.tryItem (index/6)
match entree with match entree with
| None -> 0 | None -> space
| Some x -> x.id | Some x -> x.id
) )
|> Array.mapi (fun index current -> |> Array.mapi (fun index current ->
@@ -146,7 +176,7 @@ let populateEntreeGrid () =
if not isSecondRow then current else if not isSecondRow then current else
let entree = Dips |> Array.tryItem (index-7) let entree = Dips |> Array.tryItem (index-7)
match entree with match entree with
| None -> 0 | None -> space
| Some x -> x.id | Some x -> x.id
) )
@@ -162,20 +192,21 @@ let populateEntreeGrid () =
let populateMainGrid (category: string) () = let populateMainGrid (category: string) () =
let SalesCategory = Entity.GetFirstByColumn<sales_category> "name" category let SalesCategory = Entity.GetFirstByColumn<sales_category> "name" category
let Mains = Entity.GetAllByColumn<item> "sales_category_id" SalesCategory.id let Mains = Entity.GetAllByColumn<item> "sales_category_id" SalesCategory.id
let space = spaceButton()
let getId index = let getId index =
match Mains |> Array.tryItem index with match Mains |> Array.tryItem index with
| None -> 0 | None -> space
| Some x -> x.id | Some x -> x.id
let GridData = let GridData =
[| [|
getId 0; 0; getId 1; 0; getId 2; 0; getId 0; space; getId 1; space; getId 2; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
getId 3; 0; getId 4; 0; getId 5; 0; getId 3; space; getId 4; space; getId 5; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
|] |]
let grid = let grid =
@@ -186,22 +217,23 @@ let populateMainGrid (category: string) () =
Entity.Update newGrid |> ignore Entity.Update newGrid |> ignore
let populateDessertGrid () = let populateDessertGrid () =
let space = spaceButton()
let SalesCategory = Entity.GetFirstByColumn<sales_category> "name" "Dessert" let SalesCategory = Entity.GetFirstByColumn<sales_category> "name" "Dessert"
let Desserts = Entity.GetAllByColumn<item> "sales_category_id" SalesCategory.id let Desserts = Entity.GetAllByColumn<item> "sales_category_id" SalesCategory.id
let getId index = let getId index =
match Desserts |> Array.tryItem index with match Desserts |> Array.tryItem index with
| None -> 0 | None -> space
| Some x -> x.id | Some x -> x.id
let GridData = let GridData =
[| [|
getId 0; 0; getId 1; 0; 0 ; 0; getId 0; space; getId 1; space; space ; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; getId 2; 0; getId 4; 0; 0; space; getId 2; space; getId 4; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
|] |]
let grid = let grid =
@@ -212,38 +244,43 @@ let populateDessertGrid () =
Entity.Update newGrid |> ignore Entity.Update newGrid |> ignore
let populateBeerGrid () = let populateBeerGrid () =
let space = spaceButton()
let SalesCategory = Entity.GetFirstByColumn<sales_category> "name" "Beer" let SalesCategory = Entity.GetFirstByColumn<sales_category> "name" "Beer"
let Beers = Entity.GetAllByColumn<item> "sales_category_id" SalesCategory.id let Beers = Entity.GetAllByColumn<item> "sales_category_id" SalesCategory.id
let grid = let grid =
Entity.GetFirstByColumn<order_screen_page_group> "label" "Beer" Entity.GetFirstByColumn<order_screen_page_group> "label" "Beer"
|> Entity.GetRelated<grid, order_screen_page_group> |> Entity.GetRelated<grid, order_screen_page_group>
let GridData = let mutable buttonMap = Map.empty<string, int[]>
Beers Beers
|> Array.chunkBySize 24 |> Array.chunkBySize 24
|> Array.map (fun beerPage -> |> Array.map (fun beerPage ->
let getId index = let getId index =
match beerPage |> Array.tryItem index with match beerPage |> Array.tryItem index with
| None -> 0 | None -> space
| Some x -> x.id | Some x -> x.id
[| [|
getId 0; getId 1; getId 2; getId 3; getId 4 ; getId 5; getId 0; getId 1; getId 2; getId 3; getId 4 ; getId 5;
0; 0; 0; 0; 0 ;0; space; space; space; space; space; space;
getId 6; getId 7; getId 8; getId 9; getId 10 ; getId 11; getId 6; getId 7; getId 8; getId 9; getId 10 ; getId 11;
0; 0; 0; 0; 0 ;0; space; space; space; space; space; space;
getId 12; getId 13; getId 14; getId 15; getId 16 ; getId 17; getId 12; getId 13; getId 14; getId 15; getId 16 ; getId 17;
0; 0; 0; 0; 0 ;0; space; space; space; space; space; space;
getId 18; getId 19; getId 20; getId 21; getId 22 ; getId 23; getId 18; getId 19; getId 20; getId 21; getId 22 ; getId 23;
0; 0; 0; 0; 0 ;0; space; space; space; space; space; space;
|] |]
) )
|> Array.mapi (fun index beerpage -> (map [$"page{index+1}", beerpage])) |> Array.iteri (fun index buttonIds ->
|> jsonEncode buttonMap <- buttonMap |> Map.add $"page{index+1}" buttonIds
)
let GridData = buttonMap |> jsonEncode
let newGrid = {grid with data=GridData} let newGrid = {grid with data=GridData}
Entity.Update newGrid |> ignore Entity.Update newGrid |> ignore
let populateSteakTemperaturesGrid () = let populateSteakTemperaturesGrid () =
let space = spaceButton()
let SalesCategory = Entity.GetFirstByColumn<sales_category> "name" "Steak Temperatures" let SalesCategory = Entity.GetFirstByColumn<sales_category> "name" "Steak Temperatures"
let Temps = Entity.GetAllByColumn<item> "sales_category_id" SalesCategory.id let Temps = Entity.GetAllByColumn<item> "sales_category_id" SalesCategory.id
let grid = let grid =
@@ -252,18 +289,14 @@ let populateSteakTemperaturesGrid () =
let getId index = let getId index =
match Temps |> Array.tryItem index with match Temps |> Array.tryItem index with
| None -> 0 | None -> space
| Some x -> x.id | Some x -> x.id
let GridData = let GridData =
[| [|
getId 0; 0; getId 1; 0; getId 2; 0; getId 0; space; getId 1; space; getId 2; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
getId 3; 0; getId 4; 0; getId 5; 0; getId 3; space; getId 4; space; getId 5; space;
0; 0; 0; 0; 0; 0; space; space; space; space; space; space;
0; 0; 0; 0; 0; 0;
0; 0; 0; 0; 0; 0;
0; 0; 0; 0; 0; 0;
0; 0; 0; 0; 0; 0;
|] |]
let newGrid = {grid with data=(jsonEncode {|page1=GridData|}); rows=4; cols=6} let newGrid = {grid with data=(jsonEncode {|page1=GridData|}); rows=4; cols=6}
@@ -310,7 +343,7 @@ let CreateItemFromFileName (index: int) (dirName: string) (file: string) =
| "beer" | "dessert" -> "doubleHeight" | "beer" | "dessert" -> "doubleHeight"
| "mains" | "wine" | "steak temperatures" -> "doubleHeight doubleWidth" | "mains" | "wine" | "steak temperatures" -> "doubleHeight doubleWidth"
| "entrees" -> "doubleWidth" | "entrees" -> "doubleWidth"
| _ -> "" | _ -> "normal"
Entity.Create { Entity.Create {
id=0 id=0
@@ -338,6 +371,8 @@ let run () =
|> CreateDefaultClerk |> CreateDefaultClerk
|> CreateDefaultPrintGroups |> CreateDefaultPrintGroups
|> CreateDefaultSalesCategories |> CreateDefaultSalesCategories
|> CreateDefaultItems
|> CreateDefaultButtons
|> Directory.GetDirectories |> Directory.GetDirectories
|> Array.mapi CreatePageFromDirectory |> Array.mapi CreatePageFromDirectory
|> Array.iter CreateItemsAndButtons |> Array.iter CreateItemsAndButtons

View File

@@ -3,87 +3,88 @@
open DredgePos open DredgePos
open DredgeFramework open DredgeFramework
open DredgePos.Types open DredgePos.Types
open DredgePos.Global.Controller
open Saturn.CSRF
open Thoth.Json.Net
open Giraffe open Giraffe
open Microsoft.AspNetCore.Http open Microsoft.AspNetCore.Http
open FSharp.Collections
let getOrderScreenData (tableNumber: int) = let getOrderScreenData (tableNumber: int) =
{| {|
order_screen_pages = Entity.GetAllInVenue<order_screen_page_group> order_screen_pages = Entity.GetAllInVenue<order_screen_page_group>
sales_categories = Entity.GetAllInVenue<sales_category> sales_categories = Entity.GetAllInVenue<sales_category>
print_groups = Entity.GetAllInVenue<print_group> print_groups = Entity.GetAllInVenue<print_group>
custom_item = Entity.GetAllByColumn<item> "item_code" "OPEN000" |> first custom_item = Entity.GetFirstByColumn<item> "code" "OPEN000"
table = Floorplan.Model.getTable tableNumber table = Floorplan.Model.getTable tableNumber
|} |}
|> ajaxSuccess |> ajaxSuccess
|> json |> json
let renderGrid (grid: grid) =
let gridData = grid.data |> Decode.Auto.fromString<Map<string, int[]>>
match gridData with
| Error message -> failwith message
| Ok data ->
data
|> Map.toArray
|> Array.map snd
|> Array.map(
fun buttonIds ->
buttonIds
|> Array.map Entity.GetById<button>
|> Array.map View.itemButton
|> View.gridPage grid
)
let loadGrid (gridId: int) = let loadGrid (gridId: int) =
let grid = Entity.GetById<grid> gridId let grid = Entity.GetById<grid> gridId
let gridHtml = Model.loadGrid gridId let gridNodes = (renderGrid grid) |> List.ofArray
let gridHtml = Giraffe.ViewEngine.RenderView.AsString.htmlNodes gridNodes
if gridHtml = "Error" then ajaxFail gridHtml if gridHtml = "Error" then ajaxFail gridHtml
else ajaxSuccess {|grid=grid;gridHtml=gridHtml|} else ajaxSuccess {|grid=grid;gridHtml=gridHtml|}
|> json |> json
let loadOrderScreen (ctx: HttpContext) (tableNumber: int) : HttpHandler = let loadOrderScreenView (ctx: HttpContext) (tableNumber: int) =
Authenticate.Model.RequireClerkAuthentication ctx Authenticate.Model.RequireClerkAuthentication ctx
let tableOption = DredgePos.Floorplan.Model.getTableSafely tableNumber
let attr = Giraffe.ViewEngine.HtmlElements.attr
let table = Floorplan.Model.getTable tableNumber match tableOption with
| None ->
Browser.redirect "/" ctx
View.posButtonTemplate
| Some table ->
let currentClerk = Authenticate.Model.getCurrentClerk ctx
let styles = [|"dredgepos.orderScreen.css"|] |> addDefaultStyles
let scripts = [|"dredgepos.tables.js";"./external/currency.min.js";"dredgepos.orderScreen.js"; |] |> addDefaultScripts
let metaTags = [|"viewport", "user-scalable = no, initial-scale=0.8,maximum-scale=0.8 ,shrink-to-fit=yes"|] |> addDefaultMetaTags
let covers = if tableNumber > 0 then table.default_covers else 0 let printGroupButtons =
let coverString = language.getAndReplace "covers" [covers] Entity.GetAllInVenue<sales_category>
|> Array.map View.printGroupButton
let changeCoverNumberButton = if tableNumber > 0 then Theme.loadTemplateWithVars "orderScreen/change_cover_number_button" (map ["covers", coverString]) else "" let orderScreenPageGroupButtons =
Entity.GetAllInVenue<order_screen_page_group>
|> Array.filter (fun page_group -> page_group.id <> 0)
|> Array.sortBy (fun {order=order} -> order)
|> Array.map View.pageGroupButton
let orderNumber = let grids = Model.getAllPageGridsInVenue ()
if tableNumber > 0 then language.getAndReplace "active_table" [tableNumber] let pageGroupNodes =
else language.get "new_order" grids
|> Array.map(fun (grid, page_group) ->
renderGrid grid
|> View.pageGroup page_group
)
let containerAttributes = let coverSelectorButtons =
if tableNumber > 0 then Array.init (table.default_covers + 1) id
map ["data-table", jsonEncode table] |> Array.map(fun coverNumber ->
|> Theme.htmlAttributes let text = if coverNumber > 0 then language.getAndReplace "selected_cover" [coverNumber]
else "" else language.get "cover_zero"
Global.View.PosButton "coverSelectorButton" (map ["data-cover", coverNumber]) text
)
let categoryList = View.index tableNumber styles scripts metaTags currentClerk printGroupButtons orderScreenPageGroupButtons pageGroupNodes coverSelectorButtons
Entity.GetAllInVenue<order_screen_page_group>
|> Array.filter (fun page_group -> page_group.id <> 0)
|> Array.sortBy (fun {order=order} -> order)
|> Array.map (fun category ->
let categoryMap = recordToMap category
let categoryArray = map ["page", categoryMap]
Theme.loadTemplateWithArrays "orderScreen/page_group_button" categoryArray
)
|> joinWithNewLine
let grids =
Model.getAllPageGrids ()
|> Array.map Model.getPagesHTML
|> joinWithNewLine
let coverSelectorButtons =
Array.init (covers+1) id
|> Array.map(fun coverNumber ->
let text = if coverNumber > 0 then language.getAndReplace "selected_cover" [coverNumber]
else language.get "cover_zero"
Theme.PosButton text "coverSelectorButton" $"""data-cover="{coverNumber}" """)
|> String.concat "\n"
let variables = map [
"title", "Order"
"containerAttributes", containerAttributes
"categoryList", categoryList
"pageGroups", grids
"orderNumber", orderNumber
"changeCoverNumberButton", changeCoverNumberButton
"covers", coverString
"salesCategoryOverrideButtons", Model.generateSalesCategoryOverrideButtons ()
"coverSelectorButtons", coverSelectorButtons
]
let styles = ["dredgepos.orderScreen.css"]
let scripts = ["dredgepos.tables.js";"./external/currency.min.js";"dredgepos.orderScreen.js"; ]
let currentClerk = recordToMap <| Authenticate.Model.getCurrentClerk ctx
let arrays = map ["clerk", currentClerk]
Theme.loadTemplateWithVarsArraysScriptsAndStyles "orderScreen" variables arrays scripts styles
|> htmlString

View File

@@ -8,129 +8,11 @@ open Thoth.Json.Net
open Theme open Theme
let getAllPageGrids () = Entity.GetAllInVenue<order_screen_page_group> let getAllPageGridsInVenue () =
|> Array.filter(fun pageGroup -> pageGroup.grid_id <> 0) Entity.GetAllInVenue<order_screen_page_group>
|> Array.map(fun pageGroup -> (Entity.GetById<grid> pageGroup.grid_id), pageGroup) |> Array.filter(fun pageGroup -> pageGroup.grid_id <> 0)
|> Array.map(fun pageGroup -> (Entity.GetById<grid> pageGroup.grid_id), pageGroup)
let getImageButtonData (button: button) =
let itemCode =
if button.primary_action = "item" then button.primary_action_value
else button.secondary_action_value
let item = Entity.GetAllByColumn<item> "item_code" itemCode
|> first
let extraData =
map [
"data-item", jsonEncode item
] |> htmlAttributes
{|
extra_data = extraData
text = item.name
|}
let getGridButtonData (button: button) =
let gridId =
if button.primary_action = "grid" then button.primary_action_value
else button.secondary_action_value
|> int
let grid = Entity.GetById<grid> gridId
{|
extra_data = map ["data-grid", jsonEncode gridId] |> htmlAttributes
text = grid.name
|}
let getActionData (button: button) (action: string) =
let actionValue =
if action = "primary" then button.primary_action
else button.secondary_action
match actionValue with
| "item" -> getImageButtonData button
| "grid" -> getGridButtonData button
| "spacer" -> {|extra_data=""; text=""|}
| _ -> {|extra_data=""; text=""|}
let renderButton (buttonId: int) =
let button = Entity.GetById<button> buttonId
let extra_styles =
match button.extra_styles.Length with
| 0 -> ""
| _ -> $""" style="{button.extra_styles}" """
let imageClass = if button.image.Length > 0 then "hasImage" else ""
let spacerClass = if button.primary_action = "spacer" || button.secondary_action = "spacer"
then "invisible"
else ""
let image = if button.image.Length > 0 then loadTemplateWithVars "orderScreen/button_image" (map ["image", button.image]) else ""
let extraClasses = [|imageClass; spacerClass|] |> String.concat " "
let primary_action_data = getActionData button "primary"
let secondary_action_data = getActionData button "secondary"
let action_extra_data = primary_action_data.extra_data + " " + secondary_action_data.extra_data
let button_text =
if button.text.Length > 0 then button.text
else
if primary_action_data.text.Length > 0 then primary_action_data.text
else secondary_action_data.text
let vars = map [
"extra_classes", button.extra_classes + " " + extraClasses
"extra_styles", extra_styles
"primary_action", button.primary_action
"secondary_action", button.secondary_action
"text", button_text
"image", image
"extra_data", action_extra_data
]
loadTemplateWithVars "orderScreen/grid_button" vars
let renderPage (grid: grid) (buttonHTML: string) =
let vars = map ["pageButtons", buttonHTML; "rows", string grid.rows; "cols", string grid.cols]
loadTemplateWithVars "orderScreen/page" vars
let renderPageGroup (pageGroup: order_screen_page_group) (pageHTML: string) =
let vars = map [
"pages", pageHTML
"page_group_id", string pageGroup.id
]
loadTemplateWithVars "orderScreen/page_group" vars
let printGroupPosButton (printGroup: print_group) = let printGroupPosButton (printGroup: print_group) =
PosButton (language.getAndReplace "print_with" [printGroup.name]) "printGroupOverrideButton toggle" $"""data-value="{printGroup.id}" """ PosButton (language.getAndReplace "print_with" [printGroup.name]) "printGroupOverrideButton toggle" $"""data-value="{printGroup.id}" """
let generateSalesCategoryOverrideButtons () =
Entity.GetAllInVenue<print_group>
|> Array.map printGroupPosButton
|> Array.append [|PosButton (language.getAndReplace "print_with" ["default"]) "printGroupOverrideButton toggle default active" """data-value="0" """|]
|> joinWithNewLine
let renderGrid (grid: grid) =
let gridData = grid.data |> Decode.Auto.fromString<Map<string, int[]>>
match gridData with
| Error _ -> "Error"
| Ok pages ->
pages
|> Map.toArray
|> Array.map snd
|> Array.map(fun row -> row |> Array.map renderButton |> String.concat "\n")
|> Array.map (renderPage grid)
|> joinWithNewLine
let loadGrid gridId = renderGrid (Entity.GetById<grid> gridId)
let getPagesHTML (gridInfo: grid * order_screen_page_group) =
let grid, pageGroup = gridInfo
renderGrid grid
|> renderPageGroup pageGroup

View File

@@ -10,6 +10,5 @@ let router = router {
getf "/getOrderScreenData/%i" Controller.getOrderScreenData getf "/getOrderScreenData/%i" Controller.getOrderScreenData
getf "/getGridHtml/%i" Controller.loadGrid getf "/getGridHtml/%i" Controller.loadGrid
post "/updateCovers" (bindJson<floorplan_table> (fun table -> Entity.Update table |> Array.head |> DredgeFramework.ajaxSuccess |> json)) 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 -> htmlView <| Controller.loadOrderScreenView (snd ctx) number)))
getf "/%i" (fun number -> (warbler (fun ctx -> Controller.loadOrderScreen (snd ctx) number)))
} }

159
OrderScreen/View.fs Normal file
View File

@@ -0,0 +1,159 @@
module DredgePos.OrderScreen.View
open DredgeFramework
open DredgePos.Types
open DredgePos.Global.View
open DredgePos.Entities.Buttons.Model
open Thoth.Json.Net
open Giraffe.ViewEngine
open language
let coverSelector buttons = div [_class "coverSelector"] [
yield! buttons
]
let pageContainer floorplanTable (clerk: clerk) printGroupButtons orderScreenPageGroupButtons pageGroups =
div [_id "pageContainer" ; _table floorplanTable] [
div [_id "leftColumn"] [
h1 [_class "tableHeading"] [str (getAndReplace "active_table" [floorplanTable.table_number])]
div [_class "tableInfo"] [
posButton "changeCoverNumberButton" [] [str (getAndReplace "covers" [floorplanTable.default_covers])]
posButton "" [] [str (getAndReplace "logged_in_as" [clerk.name])]
]
div [_class "orderBox"] [
table [_class "orderBoxTable"] [
thead [] [
tr [] [
th [_class "orderBoxCell qtyCell"] [str (get "qty_header")]
th [_class "orderBoxCell itemIdCell"] [str (get "id_header")]
th [_class "orderBoxCell itemCell"] [str (get "item_header")]
th [_class "orderBoxCell unitPriceCell"] [str (get "price_header")]
th [_class "orderBoxCell totalPriceCell"] [str (get "total_price_header")]
th [_class "orderBoxCell printGroupCell"] [str (get "printgroup_header")]
]
]
tbody [] []
]
]
div [_class "orderBoxInfo"] [
span [_class "voidModeWarning"; VisibleInMode ["void"]] [str (get "void_mode")]
]
div [_class "orderBoxFooter"] [
span [_class "totalPrice"] [str (getAndReplace "totalPrice" ["0.00"])]
small [_class "selectedPrice"] [str (getAndReplace "selectedPrice" ["0.00"])]
]
]
div [_id "rightColumn"] [
div [_id "topHalf"] [
div [_class "functionButtons"] [
div [_class "printGroupButtons toggleGroup"] [
input [_type "hidden"; _class "value"]
yield! printGroupButtons
]
div [_class "functionColumn"] [
posButton "accumulateButton" [ActiveInMode "accumulate"] [str (get "accumulate_function")]
posButton "showCoverSelectorButton" [] [str (get "select_covers")]
]
div [_class "functionColumn"] [
posButton "voidButton" [ActiveInMode "void"] [str (get "void")]
posButton "openItemButton" [] [str (get "custom_item_button")]
posButton "freetextButton" [] [str (get "freetext_button")]
posButton "numpadButton" [] [str (get "numpad_button")]
]
div [_class "functionColumn"] [
posButton "" [] ["pay_function" |> get |> str]
posButton "" [] ["print_function" |> get |> str]
]
]
]
div [_id "pageList"] [
yield! orderScreenPageGroupButtons
]
div [_id "pageGroupContainer"] [
yield! pageGroups
]
div [_class "pageNavigation"] [
posButton "prevButton" [] ["prev_page" |> get |> str]
posButton "nextButton" [] ["next_page" |> get |> str]
]
]
]
(* Grid Container, Cover Selector *)
let posButtonTemplate =
template [_id "posButtonTemplate"] [
posButton "" [] []
]
let gridContainer =
div [_class "gridContainer"] [
div [_class "gridContainerHeader"] [
span [] []
div [_class "posButton closeGrid"] [str "×"]
]
div [_class "gridContainerGrid"] [
div [_class "pageGroup"] []
]
div [_class "pageNavigation"] [
posButton "prevButton" [] ["prev_page" |> get |> str]
posButton "nextButton" [] ["next_page" |> get |> str]
]
]
let pageGroupButton (pageGroup: order_screen_page_group) = posButton "loadPageGroup" [(attr "data-page-group-id") (string pageGroup.id)] [str pageGroup.label]
let printGroupButton (printGroup: sales_category) = posButton "" [(attr "data-print-group-id") (string printGroup.id)] [str printGroup.name]
let itemButtonImage (button: button) =
span [
_class "buttonImg"
_style $"background-image:url(\"/images/items/{button.image}\");"
] []
let itemButton (button: button) =
let extraClasses =
if button.image.Length > 0 then button.extra_classes + " hasImage"
else button.extra_classes
let primaryAttributes = getActionAttributes button.primary_action button.primary_action_value
let secondaryAttributes = getActionAttributes button.secondary_action button.secondary_action_value
posButton extraClasses [
yield! primaryAttributes
yield! secondaryAttributes
_style button.extra_styles
(attr "data-primary-action") button.primary_action
(attr "data-secondary-action") button.secondary_action
] [
if button.image.Length > 0 then itemButtonImage button
span [_class "text "] [str button.text]
]
let _dataPageGroup = attr "data-page-group"
let _dataPageGroupId = attr "data-page-group-id"
let pageGroup (page_group: order_screen_page_group) gridNodes =
div [_class "pageGroup"; _dataPageGroupId (string page_group.id); ] [
yield! gridNodes
]
let gridPage (grid: grid) buttonNodes =
div [
_class "gridPage"
_style $"
grid-template-columns: repeat({grid.cols}, 1fr);
grid-template-rows: repeat({grid.rows}, 1fr);"
] [
yield! buttonNodes
]
let index orderNumber styles scripts tags clerk printGroupButtons orderScreenPageGroupButtons pageGroupNodes coverSelectorButtons =
[|
pageContainer (DredgePos.Floorplan.Model.getTable orderNumber) clerk printGroupButtons orderScreenPageGroupButtons pageGroupNodes
posButtonTemplate
gridContainer
coverSelector coverSelectorButtons
|]
|> HtmlPage "Order" (GetScripts scripts) (GetStyles styles) (GetMetaTags tags)

View File

@@ -268,6 +268,9 @@
text-align: center text-align: center
width: 60% width: 60%
.itemIdCell
display: none
.qtyCell .qtyCell
width: 10% width: 10%

10
sql.log
View File

@@ -1,10 +0,0 @@
create table if not exists migrations
(
id serial
constraint migrations_pk
primary key,
"name" varchar(100) not null,
"timestamp" int not null
);

View File

@@ -615,8 +615,8 @@ const setRoomBackground = (roomToLoad: room) => {
const width = Floorplan.floorplanDiv.width() const width = Floorplan.floorplanDiv.width()
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`)
} else { } else {
Floorplan.floorplanDiv.css("background-image", "none") Floorplan.floorplanDiv.css("background-image", "none")

View File

@@ -43,7 +43,6 @@ const loadPageGroup = (e: Event) => {
button.addClass('active') button.addClass('active')
let pageGroupId = button.data('page-group-id') let pageGroupId = button.data('page-group-id')
container.find('.pageGroup').hide() container.find('.pageGroup').hide()
let activeGrid = $(`.pageGroup[data-page-group-id=${pageGroupId}]`) let activeGrid = $(`.pageGroup[data-page-group-id=${pageGroupId}]`)
@@ -59,7 +58,6 @@ const loadPageGroup = (e: Event) => {
const setupOrderScreen = (data: OrderScreenData) => { const setupOrderScreen = (data: OrderScreenData) => {
$('.coverSelector, .gridContainer').hide()
OrderScreen.order_screen_pages = data.order_screen_pages OrderScreen.order_screen_pages = data.order_screen_pages
OrderScreen.sales_categories = data.sales_categories OrderScreen.sales_categories = data.sales_categories
@@ -186,7 +184,7 @@ const addInstructionToOrderBox = (instruction: orderItem) => {
const addNewItem = (item: item, qty = 1) => { const addNewItem = (item: item, qty = 1) => {
const salesCategory = OrderScreen.sales_categories.where('id', item.category) const salesCategory = OrderScreen.sales_categories.where('id', item.sales_category_id)
const printGroup = OrderScreen.print_group_override ?? OrderScreen.print_groups.where('id', salesCategory.print_group_id) const printGroup = OrderScreen.print_group_override ?? OrderScreen.print_groups.where('id', salesCategory.print_group_id)
const orderItem : orderItem = { const orderItem : orderItem = {
id: OrderScreen.order_item_id_generator.next().value, id: OrderScreen.order_item_id_generator.next().value,
@@ -223,11 +221,11 @@ const getLastInstructionRow = (row: JQuery) => {
return $(finalRow) return $(finalRow)
} }
const getParentRow = (row: JQuery) => { const getParentRow = (row: JQuery) =>
return row.hasClass('instructionRow') row.hasClass('instructionRow')
? row.prevAll('.itemRow').first() ? row.prevAll('.itemRow').first()
: row : row
}
const incrementRowQty = (row: JQuery, qty: number) => { const incrementRowQty = (row: JQuery, qty: number) => {
const existingQty = Number(row.getColumnValue(lang('qty_header'))) const existingQty = Number(row.getColumnValue(lang('qty_header')))
@@ -306,7 +304,6 @@ const gridButtonClicked = (e: JQuery.TriggeredEvent) => {
ajax(`/order/getGridHtml/${grid}`, null, null,gridHtmlGenerated, null, null) ajax(`/order/getGridHtml/${grid}`, null, null,gridHtmlGenerated, null, null)
} }
const hideGrids = () => $('.gridContainer').hide() const hideGrids = () => $('.gridContainer').hide()
@@ -426,6 +423,7 @@ const getTotalOfRows = (rows: JQuery) => {
const getQty = (row: JQuery) => Number(row.getColumnValue(lang('qty_header'))) const getQty = (row: JQuery) => Number(row.getColumnValue(lang('qty_header')))
const getUnitPrice = (row: JQuery) => moneyFromString(row.getColumnValue(lang('price_header'))) const getUnitPrice = (row: JQuery) => moneyFromString(row.getColumnValue(lang('price_header')))
const calculateRowTotal = (row: JQuery) => { const calculateRowTotal = (row: JQuery) => {
let price = getUnitPrice(row) let price = getUnitPrice(row)
let qty = getQty(row) let qty = getQty(row)
@@ -600,5 +598,7 @@ const generateCoverSelector = () => {
$(() => { $(() => {
OrderScreen.table = $('#pageContainer').data('table') || null OrderScreen.table = $('#pageContainer').data('table') || null
ajax('/order/getOrderScreenData/1', null, 'get', setupOrderScreen, null, null) $('.coverSelector, .gridContainer').hide()
if(OrderScreen.table)
ajax(`/order/getOrderScreenData/${OrderScreen.table.table_number}`, null, 'get', setupOrderScreen, null, null)
}) })

View File

@@ -92,7 +92,7 @@ interface grid {id: number; name: string; rows: number; cols: number; data: stri
interface item { interface item {
id: number id: number
code: string code: string
category: number sales_category_id: number
name: string name: string
item_type: string item_type: string
price1: number price1: number