Order Screen fully ported to Giraffe View Engine
This commit is contained in:
@@ -25,5 +25,4 @@ let setCookie name value (expiry: DateTimeOffset) (context: HttpContext) =
|
||||
options.Expires <- expiry
|
||||
context.Response.Cookies.Append(name, value, options);
|
||||
|
||||
let redirect url (context: HttpContext) =
|
||||
context.Response.Redirect url
|
||||
let redirect url (context: HttpContext) = context.Response.Redirect url
|
||||
@@ -20,6 +20,7 @@
|
||||
<Compile Include="Entities\Floorplan_Decorations\View.fs" />
|
||||
<Compile Include="Entities\Floorplan_Decorations\Controller.fs" />
|
||||
<Compile Include="Entities\Floorplan_Decorations\Router.fs" />
|
||||
<Compile Include="Entities\Buttons\Model.fs" />
|
||||
<Compile Include="Authenticate\Model.fs" />
|
||||
<Compile Include="Authenticate\View.fs" />
|
||||
<Compile Include="Authenticate\Controller.fs" />
|
||||
|
||||
19
Entities/Buttons/Model.fs
Normal file
19
Entities/Buttons/Model.fs
Normal 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
|
||||
| _ -> []
|
||||
@@ -87,14 +87,20 @@ let saveOrderToTable orderXML tableNumber =
|
||||
|
||||
File.WriteAllText(tableFile, tableXML)
|
||||
|
||||
let getTable (tableNumber : int) =
|
||||
let getTableSafely (tableNumber: int) =
|
||||
let query = select {
|
||||
table "floorplan_tables"
|
||||
where (eq "table_number" tableNumber + eq "venue_id" (getCurrentVenue()))
|
||||
}
|
||||
|
||||
let result = query |> Database.Select<floorplan_table>
|
||||
result |> first
|
||||
query
|
||||
|> 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) =
|
||||
select {
|
||||
|
||||
@@ -101,6 +101,19 @@ 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 =
|
||||
html [] [
|
||||
head [] [
|
||||
|
||||
@@ -4,6 +4,7 @@ open DredgePos
|
||||
open DredgeFramework
|
||||
open DredgePos.Types
|
||||
open DredgePos.Global.Controller
|
||||
open Saturn.CSRF
|
||||
open Thoth.Json.Net
|
||||
open Giraffe
|
||||
open Microsoft.AspNetCore.Http
|
||||
@@ -20,14 +21,6 @@ let getOrderScreenData (tableNumber: int) =
|
||||
|> ajaxSuccess
|
||||
|> json
|
||||
|
||||
let loadGrid (gridId: int) =
|
||||
let grid = Entity.GetById<grid> gridId
|
||||
let gridHtml = Model.loadGrid gridId
|
||||
if gridHtml = "Error" then ajaxFail gridHtml
|
||||
else ajaxSuccess {|grid=grid;gridHtml=gridHtml|}
|
||||
|> json
|
||||
|
||||
|
||||
let renderGrid (grid: grid) =
|
||||
let gridData = grid.data |> Decode.Auto.fromString<Map<string, int[]>>
|
||||
match gridData with
|
||||
@@ -44,9 +37,25 @@ let renderGrid (grid: grid) =
|
||||
|> View.gridPage grid
|
||||
)
|
||||
|
||||
let loadGrid (gridId: int) =
|
||||
let grid = Entity.GetById<grid> gridId
|
||||
let gridNodes = (renderGrid grid) |> List.ofArray
|
||||
let gridHtml = Giraffe.ViewEngine.RenderView.AsString.htmlNodes gridNodes
|
||||
|
||||
if gridHtml = "Error" then ajaxFail gridHtml
|
||||
else ajaxSuccess {|grid=grid;gridHtml=gridHtml|}
|
||||
|> json
|
||||
|
||||
let loadOrderScreenView (ctx: HttpContext) (tableNumber: int) =
|
||||
Authenticate.Model.RequireClerkAuthentication ctx
|
||||
let tableOption = DredgePos.Floorplan.Model.getTableSafely tableNumber
|
||||
let attr = Giraffe.ViewEngine.HtmlElements.attr
|
||||
|
||||
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
|
||||
@@ -70,70 +79,12 @@ let loadOrderScreenView (ctx: HttpContext) (tableNumber: int) =
|
||||
|> View.pageGroup page_group
|
||||
)
|
||||
|
||||
|
||||
|
||||
View.index tableNumber styles scripts metaTags currentClerk printGroupButtons orderScreenPageGroupButtons pageGroupNodes
|
||||
|
||||
let loadOrderScreen (ctx: HttpContext) (tableNumber: int) : HttpHandler =
|
||||
Authenticate.Model.RequireClerkAuthentication ctx
|
||||
|
||||
let table = Floorplan.Model.getTable tableNumber
|
||||
|
||||
let covers = if tableNumber > 0 then table.default_covers else 0
|
||||
let coverString = language.getAndReplace "covers" [covers]
|
||||
|
||||
let changeCoverNumberButton = if tableNumber > 0 then Theme.loadTemplateWithVars "orderScreen/change_cover_number_button" (map ["covers", coverString]) else ""
|
||||
|
||||
let orderNumber =
|
||||
if tableNumber > 0 then language.getAndReplace "active_table" [tableNumber]
|
||||
else language.get "new_order"
|
||||
|
||||
let containerAttributes =
|
||||
if tableNumber > 0 then
|
||||
map ["data-table", jsonEncode table]
|
||||
|> Theme.htmlAttributes
|
||||
else ""
|
||||
|
||||
let categoryList =
|
||||
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.getAllPageGridsInVenue ()
|
||||
|> Array.map Model.getPagesHTML
|
||||
|> joinWithNewLine
|
||||
|
||||
let coverSelectorButtons =
|
||||
Array.init (covers+1) id
|
||||
Array.init (table.default_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"
|
||||
Global.View.PosButton "coverSelectorButton" (map ["data-cover", coverNumber]) text
|
||||
)
|
||||
|
||||
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.index tableNumber styles scripts metaTags currentClerk printGroupButtons orderScreenPageGroupButtons pageGroupNodes coverSelectorButtons
|
||||
@@ -13,124 +13,6 @@ let getAllPageGridsInVenue () =
|
||||
|> 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> "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) =
|
||||
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
|
||||
|
||||
@@ -10,6 +10,5 @@ let router = router {
|
||||
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 -> htmlView <| Controller.loadOrderScreenView (snd ctx) number)))
|
||||
}
|
||||
@@ -1,19 +1,23 @@
|
||||
module DredgePos.OrderScreen.View
|
||||
|
||||
open DredgeFramework
|
||||
open DredgePos.Types
|
||||
open DredgePos.Global.View
|
||||
open DredgePos.Global.Controller
|
||||
open DredgePos.Entities.Buttons.Model
|
||||
open Thoth.Json.Net
|
||||
open Giraffe.ViewEngine
|
||||
open language
|
||||
|
||||
let coverSelector = div [_class "coverSelector"] []
|
||||
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"] [
|
||||
coverSelector
|
||||
posButton "changeCoverNumberButton" [] [str (getAndReplace "covers" [floorplanTable.default_covers])]
|
||||
posButton "" [] [str (getAndReplace "logged_in_as" [clerk.name])]
|
||||
]
|
||||
div [_class "orderBox"] [
|
||||
@@ -53,7 +57,7 @@ let pageContainer floorplanTable (clerk: clerk) printGroupButtons orderScreenPag
|
||||
]
|
||||
div [_class "functionColumn"] [
|
||||
posButton "voidButton" [ActiveInMode "void"] [str (get "void")]
|
||||
posButton "open_item_button" [] [str (get "custom_item_button")]
|
||||
posButton "openItemButton" [] [str (get "custom_item_button")]
|
||||
posButton "freetextButton" [] [str (get "freetext_button")]
|
||||
posButton "numpadButton" [] [str (get "numpad_button")]
|
||||
]
|
||||
@@ -101,25 +105,28 @@ let gridContainer =
|
||||
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 itemButton (button: button) =
|
||||
let extraClasses =
|
||||
if button.primary_action = "spacer" then button.extra_classes + " invisible"
|
||||
elif button.image.Length > 0 then button.extra_classes + " hasImage"
|
||||
else button.extra_classes
|
||||
|
||||
let image =
|
||||
if button.image.Length = 0 then str ""
|
||||
else
|
||||
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
|
||||
] [
|
||||
image
|
||||
if button.image.Length > 0 then itemButtonImage button
|
||||
span [_class "text "] [str button.text]
|
||||
]
|
||||
|
||||
@@ -142,12 +149,11 @@ let gridPage (grid: grid) buttonNodes =
|
||||
]
|
||||
|
||||
|
||||
let index orderNumber styles scripts tags clerk printGroupButtons orderScreenPageGroupButtons pageGroupNodes =
|
||||
|
||||
let index orderNumber styles scripts tags clerk printGroupButtons orderScreenPageGroupButtons pageGroupNodes coverSelectorButtons =
|
||||
[|
|
||||
pageContainer (DredgePos.Floorplan.Model.getTable orderNumber) clerk printGroupButtons orderScreenPageGroupButtons pageGroupNodes
|
||||
posButtonTemplate
|
||||
gridContainer
|
||||
coverSelector
|
||||
coverSelector coverSelectorButtons
|
||||
|]
|
||||
|> HtmlPage "Order" (GetScripts scripts) (GetStyles styles) (GetMetaTags tags)
|
||||
@@ -268,6 +268,9 @@
|
||||
text-align: center
|
||||
width: 60%
|
||||
|
||||
.itemIdCell
|
||||
display: none
|
||||
|
||||
.qtyCell
|
||||
width: 10%
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ const addInstructionToOrderBox = (instruction: orderItem) => {
|
||||
|
||||
|
||||
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 orderItem : orderItem = {
|
||||
id: OrderScreen.order_item_id_generator.next().value,
|
||||
@@ -221,11 +221,11 @@ const getLastInstructionRow = (row: JQuery) => {
|
||||
return $(finalRow)
|
||||
}
|
||||
|
||||
const getParentRow = (row: JQuery) => {
|
||||
return row.hasClass('instructionRow')
|
||||
const getParentRow = (row: JQuery) =>
|
||||
row.hasClass('instructionRow')
|
||||
? row.prevAll('.itemRow').first()
|
||||
: row
|
||||
}
|
||||
|
||||
|
||||
const incrementRowQty = (row: JQuery, qty: number) => {
|
||||
const existingQty = Number(row.getColumnValue(lang('qty_header')))
|
||||
@@ -304,7 +304,6 @@ const gridButtonClicked = (e: JQuery.TriggeredEvent) => {
|
||||
ajax(`/order/getGridHtml/${grid}`, null, null,gridHtmlGenerated, null, null)
|
||||
}
|
||||
|
||||
|
||||
const hideGrids = () => $('.gridContainer').hide()
|
||||
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ interface grid {id: number; name: string; rows: number; cols: number; data: stri
|
||||
interface item {
|
||||
id: number
|
||||
code: string
|
||||
category: number
|
||||
sales_category_id: number
|
||||
name: string
|
||||
item_type: string
|
||||
price1: number
|
||||
|
||||
Reference in New Issue
Block a user