Compare commits
13 Commits
order_scre
...
installer
| Author | SHA1 | Date | |
|---|---|---|---|
| 207edf0de3 | |||
|
|
6439b4326c | ||
| cb58262507 | |||
|
|
b5a2514495 | ||
| a1d3ad19c3 | |||
| 300fb23905 | |||
| 6892b3d34c | |||
| c73184808c | |||
|
|
c7f3d7d2fb | ||
| e3794fc222 | |||
| 39dbba45f7 | |||
|
|
6cbd670260 | ||
|
|
abfb2331ba |
6
.gitignore
vendored
@@ -6,5 +6,7 @@
|
||||
/tables/*
|
||||
/Properties/
|
||||
/.idea/
|
||||
/wwwroot/scripts/js/
|
||||
/wwwroot/styles/css/*
|
||||
/wwwroot/scripts/*.js
|
||||
/wwwroot/scripts/*.js.map
|
||||
/wwwroot/styles/*
|
||||
/Folder.DotSettings.user
|
||||
|
||||
15
Ajax/Controller.fs
Normal 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
@@ -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)
|
||||
}
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
module AjaxController
|
||||
|
||||
open DredgeFramework
|
||||
open DredgePos
|
||||
open DredgePos.Types
|
||||
open Floorplan
|
||||
open Microsoft.AspNetCore.Http
|
||||
open Reservations
|
||||
open language
|
||||
open Giraffe
|
||||
open Types
|
||||
|
||||
let loginWithLoginCode (context: HttpContext) (login_code: int) =
|
||||
if Session.clerkLogin login_code context then ajaxSuccess "success"
|
||||
else ajaxFail "fail"
|
||||
|
||||
let getLanguageVars = ajaxSuccess languageVars
|
||||
|
||||
let getActiveTables venue = Floorplan.getActiveTables venue |> ajaxSuccess |> json
|
||||
|
||||
let mergeTables (tables: floorplan_table[]) =
|
||||
let status =
|
||||
if mergeTables tables[0].table_number tables[1].table_number then
|
||||
let outputTables = map [
|
||||
"parent", tables[0];
|
||||
"child", tables[1];
|
||||
"merged", getTable tables[0].table_number;
|
||||
]
|
||||
ajaxSuccess outputTables
|
||||
else ajaxFail "Could Not Merge Tables"
|
||||
status |> json
|
||||
|
||||
let unmergeTable tableNumber =
|
||||
let unmerged = Floorplan.unmergeTable tableNumber
|
||||
let unmergedTables =
|
||||
match unmerged with
|
||||
| Some (parent, child) ->
|
||||
map ["parent", parent; "child", child] |> ajaxSuccess
|
||||
| None -> ajaxFail "Could not Unmerge Table"
|
||||
|
||||
unmergedTables |> json
|
||||
|
||||
|
||||
let getFloorplanData (id: int) =
|
||||
let tableList = Entity.GetAllInVenue<floorplan_table>
|
||||
let reservationList = getReservationList tableList
|
||||
{|
|
||||
tables = tableList
|
||||
decorations = Entity.GetAllInVenue<floorplan_decoration>
|
||||
activeTableNumbers = Floorplan.getActiveTables (getCurrentVenue())
|
||||
rooms = Entity.GetAllInVenue<floorplan_room>
|
||||
reservations = reservationList
|
||||
|}
|
||||
|> ajaxSuccess
|
||||
|> 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) =
|
||||
Entity.Update table
|
||||
|> ajaxSuccess
|
||||
|> json
|
||||
|
||||
let createTable (tableData: floorplan_table) =
|
||||
if tableExists tableData.table_number = "False" then
|
||||
ajaxSuccess (addNewTable tableData)
|
||||
else ajaxFail (tableExists tableData.table_number)
|
||||
|> json
|
||||
|
||||
let deleteTable (table: floorplan_table) =
|
||||
Entity.DeleteById<floorplan_table> table.id
|
||||
|> ignore
|
||||
table |> ajaxSuccess |> json
|
||||
|
||||
let transferTable (origin, destination) =
|
||||
Floorplan.transferTable origin destination
|
||||
let data = map ["origin", getTable origin ; "destination", getTable destination]
|
||||
ajaxSuccess data |> json
|
||||
|
||||
let AddDecoration (data: floorplan_decoration) =
|
||||
let image = "wwwroot/images/decorations/" + data.decoration_image
|
||||
let width, height = image |> GetImageSize
|
||||
let aspectRatio = decimal width / decimal height
|
||||
|
||||
let decoration : floorplan_decoration = {
|
||||
id = 0
|
||||
decoration_height = (200m / aspectRatio) |> int
|
||||
decoration_width = 200
|
||||
decoration_rotation = 0
|
||||
decoration_image = data.decoration_image
|
||||
decoration_pos_x = data.decoration_pos_x
|
||||
decoration_pos_y = data.decoration_pos_y
|
||||
decoration_room = data.decoration_room
|
||||
venue_id = data.venue_id
|
||||
}
|
||||
|
||||
Entity.Create decoration
|
||||
|> ajaxSuccess
|
||||
|> json
|
||||
|
||||
let UpdateDecoration (data: floorplan_decoration) =
|
||||
Entity.Update data
|
||||
|> ignore
|
||||
ajaxSuccess "true" |> json
|
||||
|
||||
let DeleteDecoration (decorationToDelete: floorplan_decoration) =
|
||||
Entity.DeleteById<floorplan_decoration> decorationToDelete.id
|
||||
|> ajaxSuccess
|
||||
|> json
|
||||
|
||||
let newEmptyReservation (reservation: reservation) =
|
||||
let newReservation = {reservation with
|
||||
created_at = CurrentTime()
|
||||
time = CurrentTime()
|
||||
}
|
||||
|
||||
if reservation.floorplan_table_id > 0 then
|
||||
let table = {(getTableById reservation.floorplan_table_id) with
|
||||
status = 2
|
||||
default_covers = reservation.covers}
|
||||
updateTablePosition table |> ignore
|
||||
|
||||
let createdReservation = Floorplan.createEmptyReservation newReservation
|
||||
ajaxSuccess createdReservation |> json
|
||||
|
||||
let updateReservation (reservation: reservation) = updateReservation reservation |> ajaxSuccess |> json
|
||||
|
||||
let unreserveTable (table: floorplan_table) =
|
||||
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
|
||||
16
Authenticate/Controller.fs
Normal file
@@ -0,0 +1,16 @@
|
||||
module DredgePos.Authenticate.Controller
|
||||
|
||||
open DredgeFramework
|
||||
open Microsoft.AspNetCore.Http
|
||||
open DredgePos.Global.Controller
|
||||
|
||||
let loadAuthenticatePage =
|
||||
let scripts = [|"dredgepos.authenticate.js"|] |> addDefaultScripts
|
||||
let styles = [|"dredgepos.authenticate.css"|] |> addDefaultStyles
|
||||
let metaTags = [|"viewport", "user-scalable = no, initial-scale=0.8,maximum-scale=0.8 ,shrink-to-fit=yes"|] |> addDefaultMetaTags
|
||||
|
||||
View.index scripts styles metaTags
|
||||
|
||||
let loginWithLoginCode (context: HttpContext) (login_code: int) =
|
||||
if Model.clerkLogin login_code context then ajaxSuccess "success"
|
||||
else ajaxFail "fail"
|
||||
@@ -1,30 +1,44 @@
|
||||
module Session
|
||||
module DredgePos.Authenticate.Model
|
||||
|
||||
open System
|
||||
open DredgeFramework
|
||||
open Dapper.FSharp
|
||||
open Clerk
|
||||
open DredgePos
|
||||
open Thoth.Json.Net
|
||||
open Types
|
||||
|
||||
let getClerkByLoginCode (loginCode: int) =
|
||||
let clerk =
|
||||
select {
|
||||
table "clerks"
|
||||
where (eq "login_code" loginCode)
|
||||
take 1
|
||||
}
|
||||
|> Database.Select<clerk>
|
||||
|> EnumerableToArray
|
||||
|
||||
if (clerk |> length) > 0 then
|
||||
Some (first clerk)
|
||||
else
|
||||
None
|
||||
|
||||
let deleteSession sessionId context =
|
||||
delete {
|
||||
table "sessions"
|
||||
where (eq "session_id" sessionId)
|
||||
} |> db.Delete |> ignore
|
||||
} |> Database.Delete |> ignore
|
||||
Browser.deleteCookie "dredgepos_clerk_logged_in" context
|
||||
|
||||
let deleteSessionByClerkId clerk_id context =
|
||||
delete {
|
||||
table "sessions"
|
||||
where (eq "clerk_id" clerk_id)
|
||||
} |> db.Delete |> ignore
|
||||
} |> Database.Delete |> ignore
|
||||
|
||||
Browser.deleteCookie "dredgepos_clerk_logged_in" context
|
||||
|
||||
let createNewSession (clerk: clerk) context =
|
||||
if (getClerkByLoginCode clerk.clerk_login_code).IsSome then
|
||||
if (getClerkByLoginCode clerk.login_code).IsSome then
|
||||
deleteSessionByClerkId clerk.id context
|
||||
let newSessionId = (Guid.NewGuid().ToString "N") + (Guid.NewGuid().ToString "N")
|
||||
|
||||
@@ -39,18 +53,14 @@ let createNewSession (clerk: clerk) context =
|
||||
table "sessions"
|
||||
value newSession
|
||||
}
|
||||
|> db.Insert
|
||||
|> Database.Insert
|
||||
|> ignore
|
||||
|
||||
Browser.setCookie "dredgepos_clerk_logged_in" newSessionId (DateTimeOffset.UtcNow.AddHours(24.0)) context
|
||||
|
||||
|
||||
let sessionExists (sessionId: string) context =
|
||||
let sessions =
|
||||
select {
|
||||
table "sessions"
|
||||
where (eq "session_id" sessionId)
|
||||
} |> db.Select<session>
|
||||
let sessions = Entity.GetAllByColumn<session> "session_id" sessionId
|
||||
|
||||
match sessions |> length with
|
||||
| 0 -> false
|
||||
@@ -64,13 +74,11 @@ let sessionExists (sessionId: string) context =
|
||||
false
|
||||
|
||||
let checkAuthentication clerk =
|
||||
let existingClerk = getClerkByLoginCode clerk.clerk_login_code
|
||||
if existingClerk.IsSome
|
||||
&& existingClerk.Value.id = clerk.id
|
||||
&& existingClerk.Value.clerk_name = clerk.clerk_name
|
||||
&& existingClerk.Value.clerk_login_code = clerk.clerk_login_code
|
||||
then true
|
||||
else false
|
||||
let existingClerk = getClerkByLoginCode clerk.login_code
|
||||
existingClerk.IsSome
|
||||
&& existingClerk.Value.id = clerk.id
|
||||
&& existingClerk.Value.name = clerk.name
|
||||
&& existingClerk.Value.login_code = clerk.login_code
|
||||
|
||||
let getLoginCookie context = Browser.getCookie "dredgepos_clerk_logged_in" context
|
||||
|
||||
@@ -79,7 +87,7 @@ let getSession (sessionId: string) =
|
||||
select {
|
||||
table "sessions"
|
||||
where (eq "session_id" sessionId)
|
||||
} |> db.Select<session>
|
||||
} |> Database.Select<session>
|
||||
|
||||
match sessions |> length with
|
||||
| 0 -> {session_id = ""; clerk_json = ""; clerk_id= 0; expires= 0; id=0}
|
||||
@@ -87,7 +95,7 @@ let getSession (sessionId: string) =
|
||||
|
||||
let getCurrentClerk context =
|
||||
let cookie = getLoginCookie context
|
||||
let emptyClerk = {id=0; clerk_login_code=0; clerk_usergroup=0; clerk_name=""}
|
||||
let emptyClerk = {id=0; login_code=0; user_group_id=0; name=""}
|
||||
match cookie with
|
||||
| "" ->
|
||||
Browser.redirect "/login" context
|
||||
18
Authenticate/Router.fs
Normal file
@@ -0,0 +1,18 @@
|
||||
module DredgePos.Authenticate.Router
|
||||
|
||||
open Saturn
|
||||
open Giraffe
|
||||
|
||||
let homepage = (warbler (fun _ -> htmlView 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) )
|
||||
}
|
||||
10
Authenticate/View.fs
Normal file
@@ -0,0 +1,10 @@
|
||||
module DredgePos.Authenticate.View
|
||||
|
||||
open DredgePos.Global.View
|
||||
open Giraffe.ViewEngine
|
||||
|
||||
let content = div [_id "authenticator"] []
|
||||
|
||||
let index scripts styles metaTags = HtmlPage "Floorplan" (GetScripts scripts) (GetStyles styles) (GetMetaTags metaTags) [|content|]
|
||||
|
||||
|
||||
@@ -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
|
||||
98
Core/Database.module.fs
Normal file
@@ -0,0 +1,98 @@
|
||||
module Database
|
||||
|
||||
open Dapper
|
||||
open Dapper.FSharp.PostgreSQL
|
||||
open DredgeFramework
|
||||
open DredgePos.Types
|
||||
open Npgsql
|
||||
|
||||
|
||||
let connect connectionString = new NpgsqlConnection(connectionString)
|
||||
|
||||
let getDatabaseSettings () = (getConfig ()).database
|
||||
|
||||
let getConnectionString () =
|
||||
let db = getDatabaseSettings ()
|
||||
$"Server={db.host};Port={db.port};User Id={db.username};Password={db.password};Database={db.db_name};Include Error Detail=true"
|
||||
|
||||
let connectToDatabase () = connect (getConnectionString ())
|
||||
|
||||
let closeAndReturn (connection: NpgsqlConnection) (result: 'a) =
|
||||
connection.Dispose()
|
||||
result
|
||||
|
||||
let Select<'a> asyncQuery =
|
||||
let connection = connectToDatabase ()
|
||||
asyncQuery
|
||||
|> connection.SelectAsync<'a>
|
||||
|> RunSynchronously
|
||||
|> EnumerableToArray
|
||||
|> closeAndReturn connection
|
||||
|
||||
let SelectJoin<'a, 'b> asyncQuery =
|
||||
let connection = connectToDatabase ()
|
||||
asyncQuery
|
||||
|> connection.SelectAsync<'a, 'b>
|
||||
|> RunSynchronously
|
||||
|> EnumerableToArray
|
||||
|> closeAndReturn connection
|
||||
|
||||
|
||||
let Insert<'a> asyncQuery =
|
||||
let connection = connectToDatabase ()
|
||||
asyncQuery
|
||||
|> connection.InsertAsync<'a>
|
||||
|> RunSynchronously
|
||||
|> closeAndReturn connection
|
||||
|
||||
|
||||
let InsertOutput<'a> asyncQuery =
|
||||
let connection = connectToDatabase ()
|
||||
asyncQuery
|
||||
|> connection.InsertOutputAsync<'a, 'a>
|
||||
|> RunSynchronously
|
||||
|> EnumerableToArray
|
||||
|> closeAndReturn connection
|
||||
|
||||
let Update<'a> asyncQuery =
|
||||
let connection = connectToDatabase ()
|
||||
asyncQuery
|
||||
|> connection.UpdateOutputAsync<'a, 'a>
|
||||
|> RunSynchronously
|
||||
|> EnumerableToArray
|
||||
|> closeAndReturn connection
|
||||
|
||||
let Delete<'a> asyncQuery =
|
||||
let connection = connectToDatabase ()
|
||||
asyncQuery
|
||||
|> connection.DeleteAsync
|
||||
|> RunSynchronously
|
||||
|> closeAndReturn connection
|
||||
|
||||
let NonDbSpecificQuery (sql: string) (connection: NpgsqlConnection) =
|
||||
sql
|
||||
|> fun str -> System.IO.File.WriteAllText("sql.log", str); str
|
||||
|> connection.Execute
|
||||
|> closeAndReturn connection
|
||||
|
||||
let rawQuery (sql: string) = connectToDatabase () |> NonDbSpecificQuery sql
|
||||
|
||||
let CreateTable (tableName: string) (columnList: (string * string) list) =
|
||||
let columns =
|
||||
columnList
|
||||
|> List.filter (fun (columnName, _) -> columnName <> "id")
|
||||
|> List.map (fun (columnName, columnType) -> $""" "{columnName}" {columnType} not null""")
|
||||
|> String.concat ",\n\t\t\t"
|
||||
|
||||
$"""
|
||||
create table if not exists {tableName}
|
||||
(
|
||||
id serial
|
||||
constraint {tableName}_pk
|
||||
primary key,
|
||||
{columns}
|
||||
);
|
||||
"""
|
||||
|> fun str -> System.IO.File.WriteAllText("sql.log", str); str
|
||||
|> rawQuery
|
||||
|> ignore
|
||||
@@ -2,14 +2,13 @@
|
||||
|
||||
open System.Collections.Generic
|
||||
open System.Globalization
|
||||
open FSharp.Data.Sql
|
||||
open System
|
||||
open System.Drawing
|
||||
open System.IO
|
||||
open System.Linq
|
||||
open System.Xml;
|
||||
open System.Xml.XPath;
|
||||
open System.Xml.Xsl
|
||||
open DredgePos.Types
|
||||
open FSharp.Reflection
|
||||
|
||||
open Thoth.Json.Net
|
||||
@@ -35,8 +34,9 @@ let EnumerableToArray (enumerable: IEnumerable<'T>) = enumerable.ToArray()
|
||||
|
||||
let getFileExtension (file: string) = Path.GetExtension file
|
||||
|
||||
let GetFileContents (file: string) = File.ReadAllText file
|
||||
let GetFileContents = File.ReadAllText
|
||||
let GetFileName (file: string) = Path.GetFileName file
|
||||
let FileExists = File.Exists
|
||||
|
||||
let length (variable: 'T[]) = variable.Length
|
||||
let first (array: 'a[]) = array[0]
|
||||
@@ -101,3 +101,13 @@ let GetImageSize image =
|
||||
loadedImage.Width, loadedImage.Height
|
||||
|
||||
let CurrentTime() = DateTimeOffset.Now.ToUnixTimeSeconds() |> int
|
||||
|
||||
let getConfig () =
|
||||
"config.json"
|
||||
|> GetFileContents
|
||||
|> Decode.Auto.fromString<config>
|
||||
|> (fun result ->
|
||||
match result with
|
||||
| Ok config -> config
|
||||
| Error message -> failwith ("config.json is not valid :" + message)
|
||||
)
|
||||
@@ -1,4 +1,5 @@
|
||||
module Entity
|
||||
open Dapper
|
||||
open Dapper.FSharp
|
||||
open DredgeFramework
|
||||
open Pluralize.NET.Core
|
||||
@@ -15,7 +16,7 @@ let Create (record: 'x)=
|
||||
value record
|
||||
excludeColumn "id"
|
||||
}
|
||||
|> db.InsertOutput
|
||||
|> Database.InsertOutput
|
||||
|> first
|
||||
|
||||
|
||||
@@ -28,7 +29,7 @@ let inline Update (record: ^x) =
|
||||
where (eq "id" id)
|
||||
excludeColumn "id"
|
||||
}
|
||||
|> db.Update
|
||||
|> Database.Update
|
||||
|
||||
let GetAll<'x> =
|
||||
let tableName = GetDatabaseTable<'x>
|
||||
@@ -36,7 +37,7 @@ let GetAll<'x> =
|
||||
select {
|
||||
table tableName
|
||||
}
|
||||
|> db.Select<'x>
|
||||
|> Database.Select<'x>
|
||||
|
||||
let GetAllByColumn<'x> (column: string) (value: obj) =
|
||||
let tableName = GetDatabaseTable<'x>
|
||||
@@ -44,7 +45,9 @@ let GetAllByColumn<'x> (column: string) (value: obj) =
|
||||
select {
|
||||
table tableName
|
||||
where (eq column value)
|
||||
} |> db.Select<'x>
|
||||
} |> Database.Select<'x>
|
||||
|
||||
let GetFirstByColumn<'x> (column: string) (value: obj) = (GetAllByColumn<'x> column value) |> first
|
||||
|
||||
let GetAllInVenue<'x> = GetAllByColumn<'x> "venue_id" (getCurrentVenue ())
|
||||
let GetById<'x> (id: int) = GetAllByColumn<'x> "id" id |> first
|
||||
@@ -67,7 +70,7 @@ let DeleteById<'x> id =
|
||||
delete {
|
||||
table tableName
|
||||
where (eq "id" id)
|
||||
} |> db.Delete |> ignore
|
||||
} |> Database.Delete |> ignore
|
||||
|
||||
entity
|
||||
|
||||
@@ -10,8 +10,8 @@ open DredgeFramework
|
||||
let currentTheme = "restaurant"
|
||||
|
||||
let getHTMLForFile file =
|
||||
let stylePath = $"/styles/css/{file}"
|
||||
let scriptPath = $"/scripts/js/{file}"
|
||||
let stylePath = $"/styles/{file}"
|
||||
let scriptPath = $"/scripts/{file}"
|
||||
let fileExtension = file |> getFileExtension
|
||||
let scriptFileExists = File.Exists ("wwwroot"+stylePath) || File.Exists("wwwroot"+scriptPath)
|
||||
match scriptFileExists with
|
||||
@@ -26,7 +26,7 @@ let getHTMLForFile file =
|
||||
|
||||
|
||||
let ParseScriptsAndStylesheets files html =
|
||||
let defaultScriptsAndStyles = ["dark.theme.css"; "../external/jquery.js" ; "dredgepos.core.js"; "keyboards.js";]
|
||||
let defaultScriptsAndStyles = ["dark.theme.css"; "./external/jquery.js" ; "dredgepos.core.js"; "keyboards.js";]
|
||||
let scriptsAndStylesheets = defaultScriptsAndStyles @ files
|
||||
|
||||
let scriptAndStylesheetHTML =
|
||||
@@ -89,7 +89,7 @@ let ParseLanguageVariablesWithReplacements (string: string) =
|
||||
))
|
||||
|
||||
let getTemplateFilePath templateName =
|
||||
"wwwroot/themes/"+ currentTheme + "/" + templateName + ".tpl.htm"
|
||||
"views/"+ currentTheme + "/" + templateName + ".tpl.htm"
|
||||
|
||||
let templateExists templateName =
|
||||
templateName
|
||||
@@ -13,7 +13,7 @@ type reservation = {
|
||||
[<CLIMutable>]
|
||||
type venue = {
|
||||
id: int
|
||||
venue_name: string
|
||||
name: string
|
||||
}
|
||||
|
||||
[<CLIMutable>]
|
||||
@@ -38,7 +38,7 @@ type floorplan_table = {
|
||||
type print_group = {
|
||||
id: int
|
||||
name: string
|
||||
printer: int
|
||||
printer_id: int
|
||||
venue_id: int
|
||||
}
|
||||
|
||||
@@ -47,14 +47,14 @@ type sales_category = {
|
||||
id: int
|
||||
parent: int
|
||||
name: string
|
||||
print_group: int
|
||||
print_group_id: int
|
||||
venue_id: int
|
||||
}
|
||||
|
||||
[<CLIMutable>]
|
||||
type floorplan_room = {
|
||||
type room = {
|
||||
id: int
|
||||
room_name: string
|
||||
name: string
|
||||
background_image: string
|
||||
venue_id: int
|
||||
}
|
||||
@@ -62,18 +62,23 @@ type floorplan_room = {
|
||||
[<CLIMutable>]
|
||||
type floorplan_decoration = {
|
||||
id: int
|
||||
decoration_room: int
|
||||
decoration_pos_x: int
|
||||
decoration_pos_y: int
|
||||
decoration_rotation: int
|
||||
decoration_width: int
|
||||
decoration_height: int
|
||||
decoration_image: string
|
||||
room_id: int
|
||||
pos_x: int
|
||||
pos_y: int
|
||||
rotation: int
|
||||
width: int
|
||||
height: int
|
||||
image: string
|
||||
venue_id: int
|
||||
}
|
||||
|
||||
[<CLIMutable>]
|
||||
type clerk = {id: int; clerk_name: string; clerk_login_code: int; clerk_usergroup: int}
|
||||
type clerk = {
|
||||
id: int
|
||||
name: string
|
||||
login_code: int
|
||||
user_group_id: int
|
||||
}
|
||||
|
||||
[<CLIMutable>]
|
||||
type session = {id: int; session_id: string; clerk_json: string; clerk_id: int; expires: int}
|
||||
@@ -82,7 +87,7 @@ type session = {id: int; session_id: string; clerk_json: string; clerk_id: int;
|
||||
type order_screen_page_group = {id: int; order: int; venue_id: int; label: string; grid_id: int}
|
||||
|
||||
[<CLIMutable>]
|
||||
type grid = {id: int; grid_name: string; grid_rows: int; grid_cols: int; grid_data: string}
|
||||
type grid = {id: int; name: string; rows: int; cols: int; data: string}
|
||||
|
||||
[<CLIMutable>]
|
||||
type button = {
|
||||
@@ -100,13 +105,30 @@ type button = {
|
||||
[<CLIMutable>]
|
||||
type item = {
|
||||
id: int
|
||||
item_code: string
|
||||
item_category: int
|
||||
item_name: string
|
||||
code: string
|
||||
sales_category_id: int
|
||||
name: string
|
||||
item_type: string
|
||||
price1: int
|
||||
price2: int
|
||||
price3: int
|
||||
price4: int
|
||||
price5: int
|
||||
}
|
||||
|
||||
[<CLIMutable>]
|
||||
type db_config = {
|
||||
db_name: string
|
||||
username: string
|
||||
password: string
|
||||
host: string
|
||||
port: int
|
||||
}
|
||||
|
||||
[<CLIMutable>]
|
||||
type config = {
|
||||
database: db_config
|
||||
}
|
||||
|
||||
[<CLIMutable>]
|
||||
type migration = {
|
||||
id: int
|
||||
name: string
|
||||
timestamp: int
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
module db
|
||||
|
||||
open Dapper
|
||||
open Dapper.FSharp
|
||||
open Dapper.FSharp.PostgreSQL
|
||||
|
||||
|
||||
open DredgeFramework
|
||||
|
||||
let connString = "Server=localhost;Port=5432;User Id=postgres;Password=root;Database=dredgepos;Include Error Detail=true"
|
||||
//let connString = "server=localhost;uid=root;pwd=;database=dredgepos;table cache = false"
|
||||
let connection = new Npgsql.NpgsqlConnection(connString)
|
||||
|
||||
let Select<'a> asyncQuery =
|
||||
asyncQuery
|
||||
|> connection.SelectAsync<'a>
|
||||
|> RunSynchronously
|
||||
|> EnumerableToArray
|
||||
|
||||
let SelectJoin<'a, 'b> asyncQuery =
|
||||
asyncQuery
|
||||
|> connection.SelectAsync<'a, 'b>
|
||||
|> RunSynchronously
|
||||
|> EnumerableToArray
|
||||
|
||||
let Insert<'a> asyncQuery =
|
||||
asyncQuery
|
||||
|> connection.InsertAsync<'a>
|
||||
|> RunSynchronously
|
||||
|
||||
let InsertOutput<'a> asyncQuery =
|
||||
asyncQuery
|
||||
|> connection.InsertOutputAsync<'a, 'a>
|
||||
|> RunSynchronously
|
||||
|> EnumerableToArray
|
||||
|
||||
let Update<'a> asyncQuery =
|
||||
asyncQuery
|
||||
|> connection.UpdateOutputAsync<'a, 'a>
|
||||
|> RunSynchronously
|
||||
|> EnumerableToArray
|
||||
|
||||
let Delete<'a> asyncQuery =
|
||||
asyncQuery
|
||||
|> connection.DeleteAsync
|
||||
|> RunSynchronously
|
||||
@@ -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 ""
|
||||
131
DredgePos.fsproj
@@ -5,23 +5,42 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Types.fs" />
|
||||
<Compile Include="DredgeFramework.module.fs" />
|
||||
<Compile Include="Browser.module.fs" />
|
||||
<Compile Include="Database.module.fs" />
|
||||
<Compile Include="GenericEntities.module.fs" />
|
||||
<Compile Include="Language.module.fs" />
|
||||
<Compile Include="Theme.module.fs" />
|
||||
<Compile Include="Reservations.module.fs" />
|
||||
<Compile Include="Floorplan.module.fs" />
|
||||
<Compile Include="Core\Types.fs" />
|
||||
<Compile Include="Core\DredgeFramework.module.fs" />
|
||||
<Compile Include="Core\Browser.module.fs" />
|
||||
<Compile Include="Core\Database.module.fs" />
|
||||
<Compile Include="Core\GenericEntities.module.fs" />
|
||||
<Compile Include="Core\Language.module.fs" />
|
||||
<Compile Include="Core\Theme.module.fs" />
|
||||
<Compile Include="Printer.module.fs" />
|
||||
<Compile Include="Orders.module.fs" />
|
||||
<Compile Include="OrderScreen.module.fs" />
|
||||
<Compile Include="Decorations.module.fs" />
|
||||
<Compile Include="Clerk.module.fs" />
|
||||
<Compile Include="Session.module.fs" />
|
||||
<Compile Include="PageController.fs" />
|
||||
<Compile Include="AjaxController.fs" />
|
||||
<Compile Include="Global\View.fs" />
|
||||
<Compile Include="Global\Controller.fs" />
|
||||
<Compile Include="Global\Router.fs" />
|
||||
<Compile Include="Entities\Floorplan_Decorations\Model.fs" />
|
||||
<Compile Include="Entities\Floorplan_Decorations\View.fs" />
|
||||
<Compile Include="Entities\Floorplan_Decorations\Controller.fs" />
|
||||
<Compile Include="Entities\Floorplan_Decorations\Router.fs" />
|
||||
<Compile Include="Authenticate\Model.fs" />
|
||||
<Compile Include="Authenticate\View.fs" />
|
||||
<Compile Include="Authenticate\Controller.fs" />
|
||||
<Compile Include="Authenticate\Router.fs" />
|
||||
<Compile Include="Ajax\Controller.fs" />
|
||||
<Compile Include="Ajax\Router.fs" />
|
||||
<Compile Include="Migrations\CreateDatabaseSchema.fs" />
|
||||
<Compile Include="Migrations\PopulateTestData.fs" />
|
||||
<Compile Include="Installer\Model.fs" />
|
||||
<Compile Include="Installer\Controller.fs" />
|
||||
<Compile Include="Installer\Router.fs" />
|
||||
<Compile Include="Floorplan\Model.fs" />
|
||||
<Compile Include="Floorplan\View.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" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -38,27 +57,75 @@
|
||||
<Content Remove="node_modules\**" />
|
||||
<Content Remove="wwwroot\scripts\ts\test.ts" />
|
||||
<Content Remove="languages\**" />
|
||||
<Content Include="sass\dark.theme.sass">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="sass\dredgepos.authenticate.sass">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="sass\dredgepos.core.sass">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="sass\dredgepos.floorplan.sass">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="sass\dredgepos.keyboards.sass">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="sass\dredgepos.orderScreen.sass">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="typescript\dredgepos.authenticate.ts">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="typescript\dredgepos.core.ts">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="typescript\dredgepos.floorplan.ts">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="typescript\dredgepos.orderScreen.ts">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="typescript\dredgepos.tables.ts">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="typescript\keyboards.ts">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="typescript\types.ts">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="typescript\typings\currency.d.ts">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="typescript\typings\konva.d.ts">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Folder Include="wwwroot\styles" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Dapper" Version="2.0.78" />
|
||||
<PackageReference Include="Dapper.Contrib" Version="2.0.78" />
|
||||
<PackageReference Include="Dapper.FSharp" Version="2.4.1" />
|
||||
<PackageReference Include="FSharp.Data" Version="4.0.1" />
|
||||
<PackageReference Include="Giraffe" Version="6.0.0-alpha-2" />
|
||||
<PackageReference Include="Npgsql" Version="6.0.0" />
|
||||
<PackageReference Include="Pluralize.NET.Core" Version="1.0.0" />
|
||||
<PackageReference Include="Saturn" Version="0.15.0-preview03" />
|
||||
<PackageReference Include="System.Data.SqlClient" Version="4.8.0" />
|
||||
<PackageReference Include="FSharp.Data.SqlClient" Version="2.1.0-beta1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0-preview.2.21154.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.0-preview.2.21154.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MySql.Data" Version="8.0.23" />
|
||||
<PackageReference Include="MySql.Data.EntityFrameworkCore" Version="8.0.22" />
|
||||
<PackageReference Include="SQLProvider" Version="1.2.1" />
|
||||
<PackageReference Include="Saturn" Version="0.15.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="6.0.0-preview.5.21301.5" />
|
||||
<PackageReference Include="Thoth.Json.Net" Version="5.0.0" />
|
||||
<PackageReference Update="FSharp.Core" Version="6.0.2-beta.21631.1" />
|
||||
@@ -70,12 +137,10 @@
|
||||
<Content Include="xslt\orderHtmltoXML.xslt" />
|
||||
<Content Include="xslt\htmlToEscPos.xslt" />
|
||||
<Content Include=".gitignore" />
|
||||
<Folder Include="wwwroot\fonts" />
|
||||
<Folder Include="wwwroot\styles\css" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_ContentIncludedByDefault Remove="wwwroot\themes\default\index.tpl.html" />
|
||||
<_ContentIncludedByDefault Remove="wwwroot\themes\default\index.tpl.html" />
|
||||
<_ContentIncludedByDefault Remove="wwwroot\themes\default\scripts\global.js" />
|
||||
<_ContentIncludedByDefault Remove="wwwroot\themes\default\scripts\index.js" />
|
||||
<_ContentIncludedByDefault Remove="wwwroot\themes\default\styles\global.css" />
|
||||
|
||||
16
DredgePos.sln
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "DredgePos", "DredgePos.fsproj", "{3C52169C-8E40-472B-B87B-82F43F96BFB0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3C52169C-8E40-472B-B87B-82F43F96BFB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3C52169C-8E40-472B-B87B-82F43F96BFB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3C52169C-8E40-472B-B87B-82F43F96BFB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3C52169C-8E40-472B-B87B-82F43F96BFB0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
13
Entities/Floorplan_Decorations/Controller.fs
Normal file
@@ -0,0 +1,13 @@
|
||||
module DredgePos.Entities.Floorplan_Decorations.Controller
|
||||
|
||||
open System.IO
|
||||
|
||||
let generateDecorator () =
|
||||
"wwwroot/images/decorations"
|
||||
|> Directory.GetFiles
|
||||
|> Array.filter Model.isImageFile
|
||||
|> Array.map Model.GetFileNameWithoutExtension
|
||||
|> Array.map Model.getImageName
|
||||
|> Array.map View.decoratorItem
|
||||
|> Array.chunkBySize 4
|
||||
|> Array.map View.decoratorRow
|
||||
24
Entities/Floorplan_Decorations/Model.fs
Normal 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
|
||||
|
||||
2
Entities/Floorplan_Decorations/Router.fs
Normal file
@@ -0,0 +1,2 @@
|
||||
module DredgePos.Entities.Floorplan_Decorations.Router
|
||||
|
||||
24
Entities/Floorplan_Decorations/View.fs
Normal file
@@ -0,0 +1,24 @@
|
||||
module DredgePos.Entities.Floorplan_Decorations.View
|
||||
|
||||
open Giraffe.ViewEngine
|
||||
open DredgePos.Global.View
|
||||
|
||||
let decoratorItem (imageName, imageUrl) =
|
||||
let image = attr "data-image"
|
||||
div [_class "decoratorItem"; image imageUrl] [
|
||||
a [_style $"background-image:url('/images/decorations/{imageUrl}')"] []
|
||||
a [] [str imageName]
|
||||
]
|
||||
|
||||
let decoratorRow decoratorItems = div [_class "decoratorRow"] [yield! decoratorItems]
|
||||
|
||||
let decorator (decorationRows: XmlNode[]) =
|
||||
div [_id "decorator"] [
|
||||
div [_id "decoratorHeader"] [
|
||||
h2 [] [lang "choose_decoration"]
|
||||
a [_class "posButton hideDecorator"] [str "×"]
|
||||
]
|
||||
div [_id "decoratorContent"] [
|
||||
yield! decorationRows
|
||||
]
|
||||
]
|
||||
119
Floorplan/Controller.fs
Normal file
@@ -0,0 +1,119 @@
|
||||
module DredgePos.Floorplan.Controller
|
||||
|
||||
open DredgeFramework
|
||||
open DredgePos
|
||||
open DredgePos.Global.Controller
|
||||
open DredgePos.Entities
|
||||
open DredgePos.Types
|
||||
open Giraffe
|
||||
open Microsoft.AspNetCore.Http
|
||||
open Model
|
||||
open System.IO
|
||||
|
||||
let makeRoomButton (room: room) =
|
||||
let vars = map [
|
||||
"roomId", room.id |> string
|
||||
"roomName", room.name
|
||||
]
|
||||
|
||||
Theme.loadTemplateWithVars "roomButton" vars
|
||||
|
||||
let getActiveTables venue = Model.getActiveTables venue |> ajaxSuccess |> json
|
||||
|
||||
let mergeTables (tables: floorplan_table[]) =
|
||||
let status =
|
||||
if mergeTables tables[0].table_number tables[1].table_number then
|
||||
let outputTables = map [
|
||||
"parent", tables[0];
|
||||
"child", tables[1];
|
||||
"merged", Model.getTable tables[0].table_number;
|
||||
]
|
||||
ajaxSuccess outputTables
|
||||
else ajaxFail "Could Not Merge Tables"
|
||||
status |> json
|
||||
|
||||
let unmergeTable tableNumber =
|
||||
let unmerged = unmergeTable tableNumber
|
||||
let unmergedTables =
|
||||
match unmerged with
|
||||
| Some (parent, child) ->
|
||||
map ["parent", parent; "child", child] |> ajaxSuccess
|
||||
| None -> ajaxFail "Could not Unmerge Table"
|
||||
|
||||
unmergedTables |> json
|
||||
|
||||
|
||||
let getFloorplanData (id: int) =
|
||||
let tableList = Entity.GetAllInVenue<floorplan_table>
|
||||
let reservationList = getReservationList tableList
|
||||
{|
|
||||
tables = tableList
|
||||
decorations = Entity.GetAllInVenue<floorplan_decoration>
|
||||
activeTableNumbers = Model.getActiveTables (getCurrentVenue())
|
||||
rooms = Entity.GetAllInVenue<room>
|
||||
reservations = reservationList
|
||||
|}
|
||||
|> ajaxSuccess
|
||||
|> json
|
||||
|
||||
let transformTable (table: floorplan_table) =
|
||||
Entity.Update table
|
||||
|> ajaxSuccess
|
||||
|> json
|
||||
|
||||
let createTable (tableData: floorplan_table) =
|
||||
if tableExists tableData.table_number = "False" then
|
||||
ajaxSuccess (addNewTable tableData)
|
||||
else ajaxFail (tableExists tableData.table_number)
|
||||
|> json
|
||||
|
||||
let deleteTable (table: floorplan_table) =
|
||||
Entity.DeleteById<floorplan_table> table.id
|
||||
|> ignore
|
||||
table |> ajaxSuccess |> json
|
||||
|
||||
let transferTable (origin, destination) =
|
||||
transferTable origin destination
|
||||
let data = map ["origin", getTable origin ; "destination", getTable destination]
|
||||
ajaxSuccess data |> json
|
||||
|
||||
let AddDecoration (data: floorplan_decoration) =
|
||||
let image = "wwwroot/images/decorations/" + data.image
|
||||
let width, height = image |> GetImageSize
|
||||
let aspectRatio = decimal width / decimal height
|
||||
|
||||
let decoration : floorplan_decoration = {
|
||||
id = 0
|
||||
height = (200m / aspectRatio) |> int
|
||||
width = 200
|
||||
rotation = 0
|
||||
image = data.image
|
||||
pos_x = data.pos_x
|
||||
pos_y = data.pos_y
|
||||
room_id = data.room_id
|
||||
venue_id = data.venue_id
|
||||
}
|
||||
|
||||
Entity.Create decoration
|
||||
|> ajaxSuccess
|
||||
|> json
|
||||
|
||||
let UpdateDecoration (data: floorplan_decoration) =
|
||||
Entity.Update data
|
||||
|> ignore
|
||||
ajaxSuccess "true" |> json
|
||||
|
||||
let DeleteDecoration (decorationToDelete: floorplan_decoration) =
|
||||
Entity.DeleteById<floorplan_decoration> decorationToDelete.id
|
||||
|> ajaxSuccess
|
||||
|> json
|
||||
|
||||
let loadFloorplanView (ctx: HttpContext) =
|
||||
Authenticate.Model.RequireClerkAuthentication ctx
|
||||
let roomMenu = Entity.GetAllInVenue<room> |> Array.map View.roomButton
|
||||
let currentClerk = Authenticate.Model.getCurrentClerk ctx
|
||||
let styles = [|"dredgepos.floorplan.css"|] |> addDefaultStyles
|
||||
let scripts = [|"./external/konva.min.js" ; "dredgepos.floorplan.js"|] |> addDefaultScripts
|
||||
let metaTags = [|"viewport", "user-scalable = no, initial-scale=0.8,maximum-scale=0.8 ,shrink-to-fit=yes"|] |> addDefaultMetaTags
|
||||
|
||||
View.index styles scripts metaTags currentClerk (Floorplan_Decorations.Controller.generateDecorator ()) roomMenu
|
||||
@@ -1,19 +1,12 @@
|
||||
module Floorplan
|
||||
module DredgePos.Floorplan.Model
|
||||
|
||||
open DredgePos
|
||||
open DredgePos.Types
|
||||
open Org.BouncyCastle.Asn1.X509
|
||||
open Reservations
|
||||
|
||||
open System
|
||||
open System.IO
|
||||
open System.Xml.Linq
|
||||
open DredgeFramework
|
||||
open Dapper
|
||||
open Dapper.FSharp
|
||||
open Thoth.Json.Net
|
||||
open Types
|
||||
|
||||
let activeTablePath = "tables/active/"
|
||||
|
||||
let getTableFile (tableNumber: int) =
|
||||
@@ -46,7 +39,7 @@ let tablesInRoom (roomId: int) = //Get a list of all tables in a particular room
|
||||
table "floorplan_tables"
|
||||
where (eq "room_id" roomId)
|
||||
}
|
||||
|> db.Select<floorplan_table>
|
||||
|> Database.Select<floorplan_table>
|
||||
|
||||
|
||||
let getActiveTables (venueId: int) =
|
||||
@@ -54,7 +47,7 @@ let getActiveTables (venueId: int) =
|
||||
table "floorplan_tables"
|
||||
where (eq "venue_id" venueId)
|
||||
}
|
||||
|> db.Select
|
||||
|> Database.Select
|
||||
|> Array.filter tableIsOpen
|
||||
|> Array.map (fun table -> table.table_number)
|
||||
|
||||
@@ -100,7 +93,7 @@ let getTable (tableNumber : int) =
|
||||
where (eq "table_number" tableNumber + eq "venue_id" (getCurrentVenue()))
|
||||
}
|
||||
|
||||
let result = query |> db.Select<floorplan_table>
|
||||
let result = query |> Database.Select<floorplan_table>
|
||||
result |> first
|
||||
|
||||
let getTableById (id : int) =
|
||||
@@ -108,14 +101,14 @@ let getTableById (id : int) =
|
||||
table "floorplan_tables"
|
||||
where (eq "id" id)
|
||||
}
|
||||
|> db.Select<floorplan_table>
|
||||
|> Database.Select<floorplan_table>
|
||||
|> first
|
||||
|
||||
let getRoom (roomId: int) =
|
||||
select {
|
||||
table "floorplan_rooms"
|
||||
where (eq "id" roomId)
|
||||
} |> db.Select<floorplan_room> |> first
|
||||
} |> Database.Select<room> |> first
|
||||
|
||||
let updateTablePosition (floorplanTable: floorplan_table) = Entity.Update floorplanTable
|
||||
|
||||
@@ -124,7 +117,7 @@ let createEmptyReservation (reservation: reservation) =
|
||||
table "floorplan_tables"
|
||||
set {| status = 2 |}
|
||||
where(eq "id" reservation.floorplan_table_id)
|
||||
} |> db.Update |> ignore
|
||||
} |> Database.Update |> ignore
|
||||
|
||||
Entity.Create reservation
|
||||
|
||||
@@ -161,7 +154,7 @@ let tableExists (tableNumber: int) =
|
||||
select{
|
||||
table "floorplan_tables"
|
||||
where (eq "table_number" tableNumber + eq "venue_id" (getCurrentVenue()))
|
||||
} |> db.Select<floorplan_table> |> length
|
||||
} |> Database.Select<floorplan_table> |> length
|
||||
|
||||
match numberOfResults with
|
||||
| 0 ->
|
||||
@@ -176,14 +169,14 @@ let tableExists (tableNumber: int) =
|
||||
| _ ->
|
||||
let parentTableData = getTable allTables[0]
|
||||
let parentRoom = getRoom parentTableData.room_id
|
||||
let parentRoomName = parentRoom.room_name
|
||||
let parentRoomName = parentRoom.name
|
||||
language.getAndReplace "error_table_exists_merged" [parentRoomName; parentTableData.table_number.ToString()]
|
||||
|
||||
|
||||
| _ ->
|
||||
let tableData = getTable tableNumber
|
||||
let room = getRoom tableData.room_id
|
||||
language.getAndReplace "error_table_exists" [room.room_name]
|
||||
language.getAndReplace "error_table_exists" [room.name]
|
||||
|
||||
|
||||
let addNewTableWithoutOutput (newTable: floorplan_table) =
|
||||
@@ -191,7 +184,7 @@ let addNewTableWithoutOutput (newTable: floorplan_table) =
|
||||
table "floorplan_tables"
|
||||
value newTable
|
||||
}
|
||||
|> db.Insert
|
||||
|> Database.Insert
|
||||
|
||||
let addNewTable (newTable: floorplan_table) = Entity.Create newTable
|
||||
|
||||
@@ -245,7 +238,7 @@ let mergeTables parent child = //Merge two tables together
|
||||
default_covers = parentTable.default_covers + childTable.default_covers
|
||||
|}
|
||||
where (eq "table_number" parent + eq "venue_id" (getCurrentVenue()))
|
||||
} |> db.Update |> ignore
|
||||
} |> Database.Update |> ignore
|
||||
|
||||
Entity.DeleteById<floorplan_table> newChildTable.id
|
||||
|> ignore
|
||||
@@ -258,7 +251,7 @@ let updateUnmergedTables parentTable childTable =
|
||||
table "floorplan_tables"
|
||||
set parentTable
|
||||
where(eq "table_number" parentTable.table_number + eq "venue_id" (getCurrentVenue()))
|
||||
} |> db.Update |> ignore
|
||||
} |> Database.Update |> ignore
|
||||
|
||||
addNewTableWithoutOutput childTable |> ignore
|
||||
true
|
||||
@@ -281,13 +274,7 @@ let unmergeTable tableNumber = //Separates a merged table into itself and the la
|
||||
Some (getTable currentTable.table_number, unmergedChild)
|
||||
| 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[]) =
|
||||
tableList |> Array.collect Entity.GetAllRelated<reservation, floorplan_table>
|
||||
25
Floorplan/Router.fs
Normal file
@@ -0,0 +1,25 @@
|
||||
module DredgePos.Floorplan.Router
|
||||
|
||||
open DredgePos
|
||||
open DredgePos.Global.Router
|
||||
open DredgePos.Types
|
||||
open Saturn
|
||||
open Giraffe
|
||||
|
||||
let floorplan = (htmlViewWithContext Controller.loadFloorplanView)
|
||||
|
||||
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
|
||||
}
|
||||
88
Floorplan/View.fs
Normal file
@@ -0,0 +1,88 @@
|
||||
module DredgePos.Floorplan.View
|
||||
|
||||
open DredgePos.Global
|
||||
open DredgePos.Global.View
|
||||
open DredgePos.Entities
|
||||
open DredgePos.Types
|
||||
open Giraffe.ViewEngine
|
||||
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 loggedInText = str (language.getAndReplace "logged_in_as" [clerk.name])
|
||||
|
||||
div [_id "pageContainer"] [
|
||||
div [_id "floorplanLeftColumn"] [
|
||||
div [_class "topCell"] [
|
||||
a [_class "posHeader"] [loggedInText]
|
||||
]
|
||||
div [_class "middleCell"] []
|
||||
div [_class "bottomCell"] []
|
||||
]
|
||||
|
||||
div [_id "floorplanCenterColumn"] [
|
||||
div [_class "topCell"] [
|
||||
yield! roomMenu
|
||||
]
|
||||
div [_class "middleCell"] [
|
||||
div [_id "floorplanCanvas"] []
|
||||
div [_id "floorplanCanvas"] []
|
||||
]
|
||||
|
||||
div [_class "bottomCell"] [
|
||||
div [_class "editControls" ; VisibleInMode ["tableSelected"]] [
|
||||
div [_class "posHeader currentTable"] [
|
||||
b [_class "selectedTableNumber"] []
|
||||
a [_class "reservationStatus"; VisibleInMode ["reservedTableSelected"]] []
|
||||
small [_class "selectedTableCovers"] []
|
||||
]
|
||||
|
||||
a [_class "posButton placeOrderButton"] [lang "order_table"]
|
||||
a [_class "posButton reserveTableButton"; InvisibleInMode ["reservedTableSelected"; "activeTableSelected"]] [lang "reserve_table"]
|
||||
a [_class "posButton unreserveTableButton"; VisibleInMode ["reservedTableSelected"]] [lang "unreserve_table"]
|
||||
a [_class "posButton payTableButton"; VisibleInMode ["activeTableSelected"]] [lang "pay_table"]
|
||||
a [_class "posButton viewTableButton"; VisibleInMode ["activeTableSelected"]] [lang "view_table"]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
div [_id "floorplanRightColumn"] [
|
||||
div [_class "topCell"] [
|
||||
a [_class "posButton logOut"] [str "×"]
|
||||
]
|
||||
|
||||
div [_class "middleCell"] [
|
||||
a [_class "posButton editModeButton"] [lang "edit_floorplan"]
|
||||
div [_class "floorplanControls useVisibility"; VisibleInMode ["edit"]] [
|
||||
a [_class "posButton addTableButton"] [lang "add_table"]
|
||||
a [_class "posButton addDecoration"] [lang "add_decoration"]
|
||||
a [_class "posButton deleteDecoration useVisibility"; VisibleInMode ["decorationSelected"; "edit"] ] [lang "delete_decoration"]
|
||||
a [_class "posButton deleteTableButton useVisibility"; VisibleInMode ["tableSelected"; "edit"]] [lang "delete_table"]
|
||||
a [_class "posButton changeShapeButton useVisibility"; VisibleInMode ["tableSelected"; "edit"]] [lang "change_shape"]
|
||||
]
|
||||
|
||||
div [_class "mergeControls useVisibility"; VisibleInMode ["tableSelected"]] [
|
||||
a [_class "posButton mergeButton"; ActiveInMode "merge"] [lang "merge_table"]
|
||||
a [_class "posButton unmergeButton"; VisibleInMode ["tableSelected"]] [lang "unmerge_table"]
|
||||
a [_class "posButton transferTableButton" ; ActiveInMode "transfer" ; VisibleInMode ["activeTableSelected"]] [lang "transfer_table"]
|
||||
]
|
||||
]
|
||||
|
||||
div [_class "bottomCell"] []
|
||||
]
|
||||
]
|
||||
|
||||
let roomButton (room: room) = a [_class "posButton roomButton"; Value (string room.id)] [str room.name ]
|
||||
|
||||
let index styles scripts tags clerk decoratorRows roomMenu =
|
||||
[|
|
||||
pageContainer clerk roomMenu
|
||||
decoratorRows |> Floorplan_Decorations.View.decorator
|
||||
|]
|
||||
|> HtmlPage "Floorplan" (GetScripts scripts) (GetStyles styles) (GetMetaTags tags)
|
||||
|
||||
7
Global/Controller.fs
Normal file
@@ -0,0 +1,7 @@
|
||||
module DredgePos.Global.Controller
|
||||
|
||||
open DredgeFramework
|
||||
|
||||
let addDefaultScripts scripts = scripts |> Array.append [|"./external/jquery.js" ; "dredgepos.core.js"; "keyboards.js";|]
|
||||
let addDefaultStyles styles = styles |> Array.append [|"dark.theme.css";|]
|
||||
let addDefaultMetaTags (tags: (string*string)[]) = tags |> Array.append [|"apple-mobile-web-app-capable", "yes"|]
|
||||
11
Global/Router.fs
Normal file
@@ -0,0 +1,11 @@
|
||||
module DredgePos.Global.Router
|
||||
|
||||
open Saturn
|
||||
open Giraffe
|
||||
|
||||
let htmlViewWithContext func =
|
||||
(fun ctx ->
|
||||
func (snd ctx)
|
||||
|> htmlView
|
||||
)
|
||||
|> warbler
|
||||
109
Global/View.fs
Normal file
@@ -0,0 +1,109 @@
|
||||
module DredgePos.Global.View
|
||||
|
||||
open Giraffe.ViewEngine
|
||||
open DredgeFramework
|
||||
|
||||
let Value = attr "data-value"
|
||||
let innerText = str
|
||||
let lang key = language.get key |> str
|
||||
|
||||
let scriptToHTML (scriptFile: string) =
|
||||
let scriptPath = $"/scripts/{scriptFile}"
|
||||
match FileExists ("wwwroot" + scriptPath) with
|
||||
| true -> script [_src scriptPath] []
|
||||
| false -> comment $"[Missing script: {scriptFile}]"
|
||||
let GetScripts (scripts: string[]) = scripts |> Array.map scriptToHTML
|
||||
|
||||
let styleToHTML (stylesheet:string) =
|
||||
let stylePath = $"/styles/{stylesheet}"
|
||||
match FileExists ("wwwroot" + stylePath) with
|
||||
| true -> link [_rel "stylesheet" ; _href stylePath]
|
||||
| false -> comment $"[Missing style: {stylesheet}]"
|
||||
|
||||
let GetStyles (scripts: string[]) = scripts |> Array.map styleToHTML
|
||||
|
||||
let tagToHtml (tag, content) = meta [_name tag; _content content]
|
||||
|
||||
let GetMetaTags (tags: (string * string)[]) = tags |> Array.map tagToHtml
|
||||
|
||||
let VirtualKeyboardRow numberOfButtons =
|
||||
let buttons = Array.init numberOfButtons (fun _ -> a [] [])
|
||||
div [_class "virtualKeyboardRow"] [
|
||||
yield! buttons
|
||||
]
|
||||
|
||||
let VirtualKeyboard =
|
||||
div [_id "virtualKeyboard"] [
|
||||
div [_class "headingRow"] [
|
||||
h3 [_id "virtualKeyboardHeading"] []
|
||||
a [_class "posButton closeKeyboards"] [str "X"]
|
||||
]
|
||||
input [_type "text"; _name "virtualKeyboardInput"; _id "virtualKeyboardInput"]
|
||||
div [_id "virtualKeyboardButtons"] [
|
||||
VirtualKeyboardRow 13
|
||||
VirtualKeyboardRow 14
|
||||
VirtualKeyboardRow 13
|
||||
VirtualKeyboardRow 11
|
||||
VirtualKeyboardRow 1
|
||||
]
|
||||
span [_class "forceFocus"] []
|
||||
]
|
||||
|
||||
let VirtualNumpadButton (text: string) =
|
||||
a [_href "#"; Value (text.ToLower()); _class "posButton virtualNumpadButton"] [str text]
|
||||
|
||||
let VirtualNumpadRow (buttons:string[]) =
|
||||
div [_class "virtualNumpadRow"] [
|
||||
yield! Array.map VirtualNumpadButton buttons
|
||||
]
|
||||
|
||||
let VirtualNumpad =
|
||||
div [_id "virtualNumpad"] [
|
||||
div [_class "headingRow"] [
|
||||
h3 [_id "virtualNumpadHeading"] []
|
||||
a [_class "posButton closeKeyboards"] [str "X"]
|
||||
]
|
||||
div [_id "virtualNumpadInput"] []
|
||||
div [_id "virtualNumpadButtons"] [
|
||||
VirtualNumpadRow [|"1"; "2"; "3"|]
|
||||
VirtualNumpadRow [|"4"; "5"; "6"|]
|
||||
VirtualNumpadRow [|"7"; "8"; "9"|]
|
||||
VirtualNumpadRow [|"0"; "."; "Clear"|]
|
||||
VirtualNumpadRow [|"Submit"|]
|
||||
]
|
||||
]
|
||||
|
||||
let alert =
|
||||
div [_id "alert"] [
|
||||
div [_id "alertHeading"] []
|
||||
div [_id "alertMessage"] []
|
||||
div [_id "alertButtons"] [
|
||||
a [_class "posButton"; _id "alertOk"] [lang "alert_ok"]
|
||||
a [_class "posButton"; _id "alertYes"] [lang "alert_yes"]
|
||||
a [_class "posButton"; _id "alertNo"] [lang "alert_no"]
|
||||
]
|
||||
]
|
||||
let keyboards = [|
|
||||
VirtualKeyboard
|
||||
VirtualNumpad
|
||||
alert
|
||||
|]
|
||||
|
||||
let HtmlPage pageTitle scripts styles tags content =
|
||||
html [] [
|
||||
head [] [
|
||||
title [] [innerText pageTitle]
|
||||
link [_rel "manifest" ; _href "/manifest.webmanifest"]
|
||||
yield! styles
|
||||
yield! scripts
|
||||
yield! tags
|
||||
]
|
||||
body [] [
|
||||
yield! content
|
||||
yield! keyboards
|
||||
]
|
||||
]
|
||||
|
||||
let HTMLPageWithScripts pageTitle scripts content = HtmlPage pageTitle scripts [||] content
|
||||
let HTMLPageWithStyles pageTitle styles content = HtmlPage pageTitle [||] styles content
|
||||
let HTMLPageWithNoScriptsOrStyles pageTitle content = HtmlPage pageTitle [||] [||] content
|
||||
32
Installer/Controller.fs
Normal file
@@ -0,0 +1,32 @@
|
||||
module DredgePos.Installer.Controller
|
||||
|
||||
open System.Reflection
|
||||
open DredgePos.Types
|
||||
open FSharp.Reflection
|
||||
|
||||
let RunMigration (fsModule: System.Type) =
|
||||
fsModule
|
||||
.GetMethod("run")
|
||||
.Invoke(null, [||])
|
||||
|> ignore
|
||||
Entity.Create {name=fsModule.FullName; timestamp=DredgeFramework.CurrentTime(); id=0} |> ignore
|
||||
fsModule.FullName + " ran Successfully"
|
||||
|
||||
let RunAllMigrations () =
|
||||
let completedMigrations =
|
||||
try
|
||||
Entity.GetAll<migration>
|
||||
with
|
||||
| _ -> [||]
|
||||
|> Array.map (fun migration -> migration.name)
|
||||
|
||||
Assembly
|
||||
.GetExecutingAssembly()
|
||||
.GetTypes()
|
||||
|> Array.filter FSharpType.IsModule
|
||||
|> Array.filter (fun fsModule -> fsModule.Namespace = "DredgePos.Migrations")
|
||||
|> Array.filter (fun fsModule -> not (completedMigrations |> Array.contains fsModule.FullName))
|
||||
|> Array.sortBy (fun fsModule -> fsModule.Name)
|
||||
|> Array.map RunMigration
|
||||
|> (fun arr -> if arr.Length > 0 then arr else [|"No Migrations Were Run"|])
|
||||
|> String.concat "<br/><hr/>"
|
||||
2
Installer/Model.fs
Normal file
@@ -0,0 +1,2 @@
|
||||
module DredgePos.Installer.Model
|
||||
|
||||
10
Installer/Router.fs
Normal file
@@ -0,0 +1,10 @@
|
||||
module DredgePos.Installer.Router
|
||||
|
||||
open DredgePos
|
||||
open Saturn
|
||||
open Giraffe
|
||||
|
||||
let router = router {
|
||||
pipe_through Ajax.Router.pipeline
|
||||
get "/" (warbler (fun _ -> htmlString (Controller.RunAllMigrations ())))
|
||||
}
|
||||
131
Migrations/CreateDatabaseSchema.fs
Normal file
@@ -0,0 +1,131 @@
|
||||
module DredgePos.Migrations.CreateDatabaseSchema
|
||||
|
||||
open DredgePos.Types
|
||||
open Database
|
||||
open Dapper.FSharp
|
||||
open Dapper.FSharp.PostgreSQL
|
||||
|
||||
let CreateDatabase (db: db_config) connectionString =
|
||||
let connection = connect connectionString
|
||||
connection
|
||||
|> NonDbSpecificQuery $"""
|
||||
CREATE DATABASE {db.db_name};
|
||||
"""
|
||||
|
||||
let addTables () =
|
||||
CreateTable "sessions" [
|
||||
"session_id", "varchar(200)"
|
||||
"clerk_json", "text"
|
||||
"clerk_id", "int"
|
||||
"expires", "int"
|
||||
]
|
||||
|
||||
CreateTable "grids" [
|
||||
"name", "varchar(60)"
|
||||
"rows", "int"
|
||||
"cols", "int"
|
||||
"data", "text"
|
||||
]
|
||||
|
||||
CreateTable "reservations" [
|
||||
"name", "varchar(100)"
|
||||
"time", "int"
|
||||
"covers", "int"
|
||||
"floorplan_table_id", "int"
|
||||
"created_at", "int"
|
||||
]
|
||||
|
||||
CreateTable "venues" [
|
||||
"name", "varchar(60)"
|
||||
]
|
||||
|
||||
CreateTable "floorplan_tables" [
|
||||
"table_number", "int"
|
||||
"room_id", "int"
|
||||
"venue_id", "int"
|
||||
"pos_x", "int"
|
||||
"pos_y", "int"
|
||||
"shape", "varchar(12)"
|
||||
"width", "int"
|
||||
"height", "int"
|
||||
"default_covers", "int"
|
||||
"rotation", "int"
|
||||
"merged_children", "text"
|
||||
"previous_state", "text"
|
||||
"status", "int"
|
||||
]
|
||||
|
||||
CreateTable "print_groups" [
|
||||
"name", "varchar(20)"
|
||||
"printer_id", "int"
|
||||
"venue_id", "int"
|
||||
]
|
||||
|
||||
CreateTable "sales_categories" [
|
||||
"parent", "int"
|
||||
"name", "varchar(20)"
|
||||
"print_group_id", "int"
|
||||
"venue_id", "int"
|
||||
]
|
||||
|
||||
CreateTable "rooms" [
|
||||
"name", "varchar(20)"
|
||||
"background_image", "varchar(100)"
|
||||
"venue_id", "int"
|
||||
]
|
||||
|
||||
CreateTable "floorplan_decorations" [
|
||||
"room_id", "int"
|
||||
"pos_x", "int"
|
||||
"pos_y", "int"
|
||||
"rotation", "int"
|
||||
"width", "int"
|
||||
"height", "int"
|
||||
"image", "varchar(100)"
|
||||
"venue_id", "int"
|
||||
]
|
||||
|
||||
CreateTable "clerks" [
|
||||
"name", "varchar(20)"
|
||||
"login_code", "int"
|
||||
"user_group_id", "int"
|
||||
]
|
||||
|
||||
CreateTable "order_screen_page_groups" [
|
||||
"order", "int"
|
||||
"venue_id", "int"
|
||||
"label", "varchar(40)"
|
||||
"grid_id", "int"
|
||||
]
|
||||
|
||||
CreateTable "buttons" [
|
||||
"text", "varchar(60)"
|
||||
"primary_action", "varchar(15)"
|
||||
"primary_action_value", "varchar(20)"
|
||||
"secondary_action", "varchar(15)"
|
||||
"secondary_action_value", "varchar(20)"
|
||||
"image", "varchar(60)"
|
||||
"extra_classes", "text"
|
||||
"extra_styles", "text"
|
||||
]
|
||||
|
||||
CreateTable "items" [
|
||||
"code", "varchar(40)"
|
||||
"sales_category_id", "int"
|
||||
"name", "varchar(60)"
|
||||
"item_type", "varchar(12)"
|
||||
"price1", "int"
|
||||
]
|
||||
|
||||
CreateTable "migrations" [
|
||||
"name", "varchar(100)"
|
||||
"timestamp", "int"
|
||||
]
|
||||
|
||||
let run () =
|
||||
let db = getDatabaseSettings ()
|
||||
|
||||
$"Server={db.host};Port={db.port};User Id={db.username};Password={db.password};Include Error Detail=true"
|
||||
|> CreateDatabase db
|
||||
|> ignore
|
||||
|> addTables
|
||||
345
Migrations/PopulateTestData.fs
Normal file
@@ -0,0 +1,345 @@
|
||||
module DredgePos.Migrations.PopulateTestData
|
||||
|
||||
open DredgeFramework
|
||||
open DredgePos.Types
|
||||
open System.IO
|
||||
|
||||
let CreatePageFromDirectory index (dir: string) =
|
||||
let dirName = DirectoryInfo(dir).Name
|
||||
|
||||
let printGroup =
|
||||
match dirName.ToLower() with
|
||||
| "beer" | "wine" -> (Entity.GetFirstByColumn<print_group> "name" "Beverage").id
|
||||
| _ -> (Entity.GetFirstByColumn<print_group> "name" "Food").id
|
||||
|
||||
let parentName =
|
||||
match dirName.ToLower() with
|
||||
| "beer" | "wine" -> "Beverage"
|
||||
| _ -> "Food"
|
||||
let parentCategory = Entity.GetFirstByColumn<sales_category> "name" parentName
|
||||
|
||||
if dirName.ToLower() <> "dips" && dirName.ToLower() <> "Steak Temperatures" then
|
||||
let NewGrid = Entity.Create {
|
||||
id=0
|
||||
name=dirName
|
||||
rows=8
|
||||
cols=6
|
||||
data=""
|
||||
}
|
||||
|
||||
Entity.Create {
|
||||
id=0
|
||||
order=index
|
||||
venue_id=1
|
||||
label=dirName
|
||||
grid_id=NewGrid.id
|
||||
} |> ignore
|
||||
else ()
|
||||
|
||||
Entity.Create {
|
||||
id=0
|
||||
parent=parentCategory.id
|
||||
name=dirName
|
||||
print_group_id=printGroup
|
||||
venue_id=1
|
||||
} |> ignore
|
||||
|
||||
dir
|
||||
|
||||
let CreateDefaultPrintGroups (path: string) =
|
||||
Entity.Create {
|
||||
id=0
|
||||
name="Food"
|
||||
printer_id=1
|
||||
venue_id=1
|
||||
} |> ignore
|
||||
|
||||
Entity.Create {
|
||||
id=0
|
||||
name="Beverage"
|
||||
printer_id=1
|
||||
venue_id=1
|
||||
} |> ignore
|
||||
|
||||
|
||||
path
|
||||
|
||||
let CreateDefaultVenue (path: string) =
|
||||
let venue: venue = {
|
||||
id=0
|
||||
name="Megalomania"
|
||||
}
|
||||
Entity.Create venue
|
||||
|>ignore
|
||||
path
|
||||
|
||||
let CreateDefaultClerk (path: string) =
|
||||
let venue: clerk = {
|
||||
id=0
|
||||
name="Josh"
|
||||
login_code=1408
|
||||
user_group_id=1
|
||||
}
|
||||
Entity.Create venue
|
||||
|>ignore
|
||||
path
|
||||
|
||||
let CreateDefaultSalesCategories (path: string) =
|
||||
Entity.Create {
|
||||
id=0
|
||||
parent=0
|
||||
name="Food"
|
||||
print_group_id=(Entity.GetFirstByColumn<print_group> "name" "Food").id
|
||||
venue_id=1
|
||||
} |> ignore
|
||||
|
||||
Entity.Create {
|
||||
id=0
|
||||
parent=0
|
||||
name="Beverage"
|
||||
print_group_id=(Entity.GetFirstByColumn<print_group> "name" "Beverage").id
|
||||
venue_id=1
|
||||
} |> ignore
|
||||
|
||||
path
|
||||
|
||||
let CreateRooms () =
|
||||
"wwwroot/images/rooms"
|
||||
|> Directory.GetFiles
|
||||
|> Array.filter (fun file -> Path.GetExtension file = ".png" || Path.GetExtension file = ".jpg")
|
||||
|> Array.iter (fun image ->
|
||||
let roomName = Path.GetFileNameWithoutExtension image
|
||||
Entity.Create {
|
||||
id=0
|
||||
name=roomName
|
||||
background_image= Path.GetFileName image
|
||||
venue_id=1
|
||||
} |> ignore
|
||||
)
|
||||
|
||||
let populateEntreeGrid () =
|
||||
let SalesCategory = Entity.GetFirstByColumn<sales_category> "name" "Entrees"
|
||||
let DipSalesCategory = Entity.GetFirstByColumn<sales_category> "name" "Dips"
|
||||
let Entrees = Entity.GetAllByColumn<item> "sales_category_id" SalesCategory.id
|
||||
let Dips = Entity.GetAllByColumn<item> "sales_category_id" DipSalesCategory.id
|
||||
let GridData =
|
||||
[|
|
||||
0; 0; 0; 0; 0; 0;
|
||||
0; 0; 0; 0; 0; 0;
|
||||
0; 0; 0; 0; 0; 0;
|
||||
0; 0; 0; 0; 0; 0;
|
||||
0; 0; 0; 0; 0; 0;
|
||||
0; 0; 0; 0; 0; 0;
|
||||
0; 0; 0; 0; 0; 0;
|
||||
0; 0; 0; 0; 0; 0;
|
||||
|]
|
||||
|> Array.mapi (fun index current ->
|
||||
let isFirstColumn = (index % 6) = 0
|
||||
if not isFirstColumn then current else
|
||||
let entree = Entrees |> Array.tryItem (index/6)
|
||||
match entree with
|
||||
| None -> 0
|
||||
| Some x -> x.id
|
||||
)
|
||||
|> Array.mapi (fun index current ->
|
||||
let isSecondRow = index > 6 && index < 12
|
||||
if not isSecondRow then current else
|
||||
let entree = Dips |> Array.tryItem (index-7)
|
||||
match entree with
|
||||
| None -> 0
|
||||
| Some x -> x.id
|
||||
)
|
||||
|
||||
let grid =
|
||||
Entity.GetFirstByColumn<order_screen_page_group> "label" "Entrees"
|
||||
|> Entity.GetRelated<grid, order_screen_page_group>
|
||||
|
||||
let newGrid = {grid with data=(jsonEncode {|page1=GridData|})}
|
||||
Entity.Update newGrid |> ignore
|
||||
|
||||
()
|
||||
|
||||
let populateMainGrid (category: string) () =
|
||||
let SalesCategory = Entity.GetFirstByColumn<sales_category> "name" category
|
||||
let Mains = Entity.GetAllByColumn<item> "sales_category_id" SalesCategory.id
|
||||
let getId index =
|
||||
match Mains |> Array.tryItem index with
|
||||
| None -> 0
|
||||
| Some x -> x.id
|
||||
let GridData =
|
||||
[|
|
||||
getId 0; 0; getId 1; 0; getId 2; 0;
|
||||
0; 0; 0; 0; 0; 0;
|
||||
getId 3; 0; getId 4; 0; getId 5; 0;
|
||||
0; 0; 0; 0; 0; 0;
|
||||
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 grid =
|
||||
Entity.GetFirstByColumn<order_screen_page_group> "label" category
|
||||
|> Entity.GetRelated<grid, order_screen_page_group>
|
||||
|
||||
let newGrid = {grid with data=(jsonEncode {|page1=GridData|})}
|
||||
Entity.Update newGrid |> ignore
|
||||
|
||||
let populateDessertGrid () =
|
||||
let SalesCategory = Entity.GetFirstByColumn<sales_category> "name" "Dessert"
|
||||
let Desserts = Entity.GetAllByColumn<item> "sales_category_id" SalesCategory.id
|
||||
let getId index =
|
||||
match Desserts |> Array.tryItem index with
|
||||
| None -> 0
|
||||
| Some x -> x.id
|
||||
let GridData =
|
||||
[|
|
||||
getId 0; 0; getId 1; 0; 0 ; 0;
|
||||
0; 0; 0; 0; 0; 0;
|
||||
0; getId 2; 0; getId 4; 0; 0;
|
||||
0; 0; 0; 0; 0; 0;
|
||||
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 grid =
|
||||
Entity.GetFirstByColumn<order_screen_page_group> "label" "Dessert"
|
||||
|> Entity.GetRelated<grid, order_screen_page_group>
|
||||
|
||||
let newGrid = {grid with data=(jsonEncode {|page1=GridData|})}
|
||||
Entity.Update newGrid |> ignore
|
||||
|
||||
let populateBeerGrid () =
|
||||
let SalesCategory = Entity.GetFirstByColumn<sales_category> "name" "Beer"
|
||||
let Beers = Entity.GetAllByColumn<item> "sales_category_id" SalesCategory.id
|
||||
let grid =
|
||||
Entity.GetFirstByColumn<order_screen_page_group> "label" "Beer"
|
||||
|> Entity.GetRelated<grid, order_screen_page_group>
|
||||
|
||||
let GridData =
|
||||
Beers
|
||||
|> Array.chunkBySize 24
|
||||
|> Array.map (fun beerPage ->
|
||||
let getId index =
|
||||
match beerPage |> Array.tryItem index with
|
||||
| None -> 0
|
||||
| Some x -> x.id
|
||||
[|
|
||||
getId 0; getId 1; getId 2; getId 3; getId 4 ; getId 5;
|
||||
0; 0; 0; 0; 0 ;0;
|
||||
getId 6; getId 7; getId 8; getId 9; getId 10 ; getId 11;
|
||||
0; 0; 0; 0; 0 ;0;
|
||||
getId 12; getId 13; getId 14; getId 15; getId 16 ; getId 17;
|
||||
0; 0; 0; 0; 0 ;0;
|
||||
getId 18; getId 19; getId 20; getId 21; getId 22 ; getId 23;
|
||||
0; 0; 0; 0; 0 ;0;
|
||||
|]
|
||||
)
|
||||
|> Array.mapi (fun index beerpage -> (map [$"page{index+1}", beerpage]))
|
||||
|> jsonEncode
|
||||
|
||||
let newGrid = {grid with data=GridData}
|
||||
Entity.Update newGrid |> ignore
|
||||
|
||||
let populateSteakTemperaturesGrid () =
|
||||
let SalesCategory = Entity.GetFirstByColumn<sales_category> "name" "Steak Temperatures"
|
||||
let Temps = Entity.GetAllByColumn<item> "sales_category_id" SalesCategory.id
|
||||
let grid =
|
||||
Entity.GetFirstByColumn<order_screen_page_group> "label" "Steak Temperatures"
|
||||
|> Entity.GetRelated<grid, order_screen_page_group>
|
||||
|
||||
let getId index =
|
||||
match Temps |> Array.tryItem index with
|
||||
| None -> 0
|
||||
| Some x -> x.id
|
||||
let GridData =
|
||||
[|
|
||||
getId 0; 0; getId 1; 0; getId 2; 0;
|
||||
0; 0; 0; 0; 0; 0;
|
||||
getId 3; 0; getId 4; 0; getId 5; 0;
|
||||
0; 0; 0; 0; 0; 0;
|
||||
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}
|
||||
Entity.Update newGrid |> ignore
|
||||
|
||||
let steakButtons = Entity.GetAllByColumn<button> "text" "Venison Wellington"
|
||||
steakButtons |> Array.iter (fun button ->
|
||||
Entity.Update {button with secondary_action="grid"; secondary_action_value=newGrid.id.ToString()} |> ignore
|
||||
)
|
||||
|
||||
let PopulateGrids () =
|
||||
populateEntreeGrid ()
|
||||
|> populateMainGrid "Mains"
|
||||
|> populateMainGrid "Wine"
|
||||
|> populateDessertGrid
|
||||
|> populateBeerGrid
|
||||
|> populateSteakTemperaturesGrid
|
||||
|
||||
let CreateItemFromFileName (index: int) (dirName: string) (file: string) =
|
||||
let extension = Path.GetExtension file
|
||||
let fileName = Path.GetFileNameWithoutExtension file
|
||||
let itemType =
|
||||
match dirName.ToLower() with
|
||||
| "dips" -> "instruction"
|
||||
| "steak temperatures" -> "instruction"
|
||||
| _ -> "item"
|
||||
|
||||
let categories = (Entity.GetAllByColumn<sales_category> "name" dirName)
|
||||
let categoryID =
|
||||
if categories.Length > 0 then categories[0].id
|
||||
else 1
|
||||
|
||||
let newItem = Entity.Create {
|
||||
id = 0
|
||||
code = $"{dirName}0{index+1}" |> StringReplace " " ""
|
||||
sales_category_id=categoryID
|
||||
name=fileName
|
||||
item_type=itemType
|
||||
price1=10
|
||||
}
|
||||
|
||||
let classes =
|
||||
match dirName.ToLower() with
|
||||
| "beer" | "dessert" -> "doubleHeight"
|
||||
| "mains" | "wine" | "steak temperatures" -> "doubleHeight doubleWidth"
|
||||
| "entrees" -> "doubleWidth"
|
||||
| _ -> ""
|
||||
|
||||
Entity.Create {
|
||||
id=0
|
||||
text=fileName
|
||||
primary_action="item"
|
||||
primary_action_value=newItem.code
|
||||
secondary_action="None"
|
||||
secondary_action_value=""
|
||||
image= $"{dirName}/{fileName}{extension}"
|
||||
extra_classes=classes
|
||||
extra_styles=""
|
||||
} |> ignore
|
||||
|
||||
|
||||
let CreateItemsAndButtons (dir: string) =
|
||||
let dirName = DirectoryInfo(dir).Name
|
||||
dir
|
||||
|> Directory.GetFiles
|
||||
|> Array.filter (fun file -> Path.GetExtension file = ".png" || Path.GetExtension file = ".jpg")
|
||||
|> Array.iteri (fun index -> CreateItemFromFileName index dirName)
|
||||
|
||||
let run () =
|
||||
"wwwroot/images/items"
|
||||
|> CreateDefaultVenue
|
||||
|> CreateDefaultClerk
|
||||
|> CreateDefaultPrintGroups
|
||||
|> CreateDefaultSalesCategories
|
||||
|> Directory.GetDirectories
|
||||
|> Array.mapi CreatePageFromDirectory
|
||||
|> Array.iter CreateItemsAndButtons
|
||||
|> CreateRooms
|
||||
|> PopulateGrids
|
||||
@@ -1,46 +1,35 @@
|
||||
module PageController
|
||||
module DredgePos.OrderScreen.Controller
|
||||
|
||||
open System
|
||||
open DredgePos.Types
|
||||
open FSharp.Data
|
||||
open Microsoft.AspNetCore.Http
|
||||
open Floorplan
|
||||
open Giraffe
|
||||
open DredgePos
|
||||
open DredgeFramework
|
||||
open DredgePos.Types
|
||||
open Giraffe
|
||||
open Microsoft.AspNetCore.Http
|
||||
|
||||
let loadHomePage(): HttpHandler =
|
||||
let variables = map ["title", "Log In"]
|
||||
let scripts = ["dredgepos.authenticate.js"]
|
||||
let styles = ["dredgepos.authenticate.css"]
|
||||
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 = Floorplan.Model.getTable tableNumber
|
||||
|}
|
||||
|> ajaxSuccess
|
||||
|> json
|
||||
|
||||
Theme.loadTemplateWithVarsScriptsAndStyles "authenticate" variables scripts styles
|
||||
|> htmlString
|
||||
|
||||
let loadFloorplan (ctx: HttpContext) : HttpHandler =
|
||||
Session.RequireClerkAuthentication ctx
|
||||
|
||||
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 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 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 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 =
|
||||
if tableNumber > 0 then
|
||||
map ["data-table", jsonEncode (getTable tableNumber)]
|
||||
map ["data-table", jsonEncode table]
|
||||
|> Theme.htmlAttributes
|
||||
else ""
|
||||
|
||||
@@ -67,8 +56,8 @@ let loadOrderScreen (ctx: HttpContext) (tableNumber: int) : HttpHandler =
|
||||
|> joinWithNewLine
|
||||
|
||||
let grids =
|
||||
OrderScreen.getAllPageGrids ()
|
||||
|> Array.map OrderScreen.getPagesHTML
|
||||
Model.getAllPageGrids ()
|
||||
|> Array.map Model.getPagesHTML
|
||||
|> joinWithNewLine
|
||||
|
||||
let coverSelectorButtons =
|
||||
@@ -87,26 +76,14 @@ let loadOrderScreen (ctx: HttpContext) (tableNumber: int) : HttpHandler =
|
||||
"orderNumber", orderNumber
|
||||
"changeCoverNumberButton", changeCoverNumberButton
|
||||
"covers", coverString
|
||||
"salesCategoryOverrideButtons", OrderScreen.generateSalesCategoryOverrideButtons ()
|
||||
"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 <| Session.getCurrentClerk ctx
|
||||
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
|
||||
|
||||
let getOpenTables() =
|
||||
let rows = openTables()
|
||||
rows |> jsonEncode
|
||||
|
||||
let mergeTables parent child =
|
||||
mergeTables parent child |> ignore
|
||||
"done"
|
||||
|
||||
let unmergeTables table =
|
||||
unmergeTable table |> ignore
|
||||
"done"
|
||||
@@ -1,4 +1,5 @@
|
||||
module OrderScreen
|
||||
module DredgePos.OrderScreen.Model
|
||||
|
||||
open DredgeFramework
|
||||
open DredgePos
|
||||
open DredgePos.Types
|
||||
@@ -26,7 +27,7 @@ let getImageButtonData (button: button) =
|
||||
|
||||
{|
|
||||
extra_data = extraData
|
||||
text = item.item_name
|
||||
text = item.name
|
||||
|}
|
||||
|
||||
let getGridButtonData (button: button) =
|
||||
@@ -38,7 +39,7 @@ let getGridButtonData (button: button) =
|
||||
let grid = Entity.GetById<grid> gridId
|
||||
{|
|
||||
extra_data = map ["data-grid", jsonEncode gridId] |> htmlAttributes
|
||||
text = grid.grid_name
|
||||
text = grid.name
|
||||
|}
|
||||
|
||||
let getActionData (button: button) (action: string) =
|
||||
@@ -92,7 +93,7 @@ let renderButton (buttonId: int) =
|
||||
loadTemplateWithVars "orderScreen/grid_button" vars
|
||||
|
||||
let renderPage (grid: grid) (buttonHTML: string) =
|
||||
let vars = map ["pageButtons", buttonHTML; "rows", string grid.grid_rows; "cols", string grid.grid_cols]
|
||||
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) =
|
||||
@@ -113,7 +114,7 @@ let generateSalesCategoryOverrideButtons () =
|
||||
|
||||
|
||||
let renderGrid (grid: grid) =
|
||||
let gridData = grid.grid_data |> Decode.Auto.fromString<Map<string, int[]>>
|
||||
let gridData = grid.data |> Decode.Auto.fromString<Map<string, int[]>>
|
||||
|
||||
match gridData with
|
||||
| Error _ -> "Error"
|
||||
@@ -133,5 +134,3 @@ let getPagesHTML (gridInfo: grid * order_screen_page_group) =
|
||||
|
||||
renderGrid grid
|
||||
|> renderPageGroup pageGroup
|
||||
|
||||
|
||||
15
OrderScreen/Router.fs
Normal 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)))
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
module Orders
|
||||
|
||||
let getHighestOrderNumber () = 6
|
||||
64
Program.fs
@@ -1,71 +1,27 @@
|
||||
namespace WebApplication
|
||||
|
||||
namespace DredgePos
|
||||
|
||||
open DredgePos
|
||||
open DredgePos.Types
|
||||
open Microsoft.AspNetCore.Server.Kestrel.Core
|
||||
open Reservations
|
||||
open Saturn
|
||||
open Giraffe
|
||||
open Types
|
||||
|
||||
module Program =
|
||||
|
||||
let handlePostRoute<'a> handlerFunction post next ctx =
|
||||
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
|
||||
let router = router {
|
||||
pipe_through Ajax.Router.pipeline
|
||||
not_found_handler (setStatusCode 404 >=> text "404")
|
||||
get "/" (redirectTo true "/login")
|
||||
get "/login" (warbler (fun _ -> PageController.loadHomePage() ))
|
||||
get "/floorplan" (warbler (fun ctx -> PageController.loadFloorplan (snd ctx)))
|
||||
get "/order" (warbler (fun ctx -> PageController.loadOrderScreen (snd ctx) 0))
|
||||
getf "/order/%i" (fun number -> (warbler (fun ctx -> PageController.loadOrderScreen (snd ctx) number)))
|
||||
forward "/ajax" floorplanRouter
|
||||
forward "/orderScreen" orderScreenRouter
|
||||
forward "/ajax" Ajax.Router.router
|
||||
forward "/floorplan" DredgePos.Floorplan.Router.router
|
||||
forward "/order" DredgePos.OrderScreen.Router.router
|
||||
forward "/login" DredgePos.Authenticate.Router.router
|
||||
forward "/reservations" DredgePos.Reservations.Router.router
|
||||
forward "/install" DredgePos.Installer.Router.router
|
||||
}
|
||||
|
||||
let app = application {
|
||||
use_mime_types [(".woff", "application/font-woff")]
|
||||
use_static "wwwroot"
|
||||
use_router pageRouter
|
||||
use_router router
|
||||
url "http://0.0.0.0:5001"
|
||||
}
|
||||
|
||||
|
||||
run app
|
||||
|
||||
29
Reservations/Controller.fs
Normal 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
|
||||
@@ -1,29 +1,20 @@
|
||||
module Reservations
|
||||
module DredgePos.Reservations.Model
|
||||
|
||||
open System
|
||||
open DredgeFramework
|
||||
open Dapper.FSharp
|
||||
open DredgePos
|
||||
open Types
|
||||
|
||||
let GetReservationById (id: int) =
|
||||
select {
|
||||
table "reservations"
|
||||
where (eq "id" id)
|
||||
}
|
||||
|> db.Select<reservation>
|
||||
|> first
|
||||
|
||||
let updateReservation (reservation: reservation) =
|
||||
update{
|
||||
table "reservations"
|
||||
set reservation
|
||||
where(eq "id" reservation.id)
|
||||
} |> db.Update |> ignore
|
||||
} |> Database.Update |> ignore
|
||||
reservation
|
||||
|
||||
let DeleteReservation (tableId: int) =
|
||||
delete {
|
||||
table "reservations"
|
||||
where (eq "reservation_table_id" tableId)
|
||||
} |> db.Delete |> ignore
|
||||
where (eq "floorplan_table_id" tableId)
|
||||
} |> Database.Delete |> ignore
|
||||
13
Reservations/Router.fs
Normal 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 )
|
||||
}
|
||||
9
config.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"database": {
|
||||
"db_name": "dredgepos",
|
||||
"username": "postgres",
|
||||
"password": "root",
|
||||
"host": "localhost",
|
||||
"port": 5432
|
||||
}
|
||||
}
|
||||
5
package-lock.json
generated
@@ -578,6 +578,11 @@
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
|
||||
},
|
||||
"tsc": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/tsc/-/tsc-2.0.4.tgz",
|
||||
"integrity": "sha512-fzoSieZI5KKJVBYGvwbVZs/J5za84f2lSTLPYf6AGiIf43tZ3GNrI1QzTLcjtyDDP4aLxd46RTZq1nQxe7+k5Q=="
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.4.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz",
|
||||
|
||||
@@ -7,9 +7,15 @@
|
||||
"currency.js": "^2.0.4",
|
||||
"konva": "^8.2.2",
|
||||
"sass": "^1.43.4",
|
||||
"tsc": "^2.0.4",
|
||||
"typescript": "^4.4.4"
|
||||
},
|
||||
"description": "",
|
||||
"license": "",
|
||||
"repository": ""
|
||||
"repository": "",
|
||||
"scripts": {
|
||||
"sass": "sass sass:wwwroot/styles",
|
||||
"typescript": "tsc",
|
||||
"build": "npm run sass && npm run typescript"
|
||||
}
|
||||
}
|
||||
|
||||
10
sql.log
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
create table if not exists migrations
|
||||
(
|
||||
id serial
|
||||
constraint migrations_pk
|
||||
primary key,
|
||||
"name" varchar(100) not null,
|
||||
"timestamp" int not null
|
||||
);
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
"noImplicitAny":true,
|
||||
"removeComments":false,
|
||||
"preserveConstEnums":true,
|
||||
"outDir":"../js",
|
||||
"outDir":"wwwroot/scripts",
|
||||
"target":"ES2016",
|
||||
"sourceMap":true,
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"include":[
|
||||
"*"
|
||||
"typescript"
|
||||
]
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
let showLoginBox = () => showVirtualNumpad('Enter Login Code', 6, true, false, false, authenticate)
|
||||
|
||||
let authenticate = (input : string) => {
|
||||
let login = ajaxSync('/ajax/authenticateClerk', input)
|
||||
let login = ajaxSync('/login/authenticateClerk', input)
|
||||
if(login === 'success'){
|
||||
location.assign('/floorplan')
|
||||
location.assign('/floorplan/')
|
||||
}
|
||||
else
|
||||
showLoginBox()
|
||||
@@ -11,7 +11,7 @@ interface floorplan{
|
||||
tableLayer: Konva.Layer
|
||||
rooms: room[]
|
||||
tables: floorplan_table[]
|
||||
decorations: decoration[]
|
||||
decorations: floorplan_decoration[]
|
||||
activeTableNumbers: number[]
|
||||
selectedTableNumber: number
|
||||
selectedDecorationId: number
|
||||
@@ -25,7 +25,7 @@ interface floorplan{
|
||||
|
||||
interface floorplan_data{
|
||||
tables: floorplan_table[]
|
||||
decorations: decoration[]
|
||||
decorations: floorplan_decoration[]
|
||||
activeTableNumbers: number[]
|
||||
rooms: room[]
|
||||
reservations:reservation[]
|
||||
@@ -50,7 +50,7 @@ const Floorplan: floorplan = {
|
||||
selectedDecorationId: 0
|
||||
};
|
||||
|
||||
$(() => ajax('/ajax/getFloorplanData/1', null, 'get', setupFloorplan, null, null) )
|
||||
$(() => ajax('/floorplan/getFloorplanData/1', null, 'get', setupFloorplan, null, null) )
|
||||
|
||||
|
||||
const setupFloorplanEvents = () => {
|
||||
@@ -122,7 +122,7 @@ const loadRoom = (roomToLoad: room) => {
|
||||
button.addClass('active')
|
||||
|
||||
const tablesInRoom = Floorplan.tables.filter(table => table.room_id == roomToLoad.id)
|
||||
const decorationsInRoom = Floorplan.decorations.filter(decoration => decoration.decoration_room == roomToLoad.id)
|
||||
const decorationsInRoom = Floorplan.decorations.filter(decoration => decoration.room_id == roomToLoad.id)
|
||||
decorationsInRoom.forEach(decoration => createDecorationShape(decoration, false))
|
||||
tablesInRoom.forEach(createTableShape)
|
||||
if(!isInMode('transfer')) {
|
||||
@@ -173,7 +173,7 @@ const createTableShape = (table: floorplan_table) => {
|
||||
stroke: "black",
|
||||
strokeWidth: 4,
|
||||
draggable: false,
|
||||
listening: true
|
||||
listening: true,
|
||||
});
|
||||
break;
|
||||
default:
|
||||
@@ -276,7 +276,7 @@ const saveTable = (tableToUpdate: floorplan_table) => {
|
||||
tables.push(tableToUpdate)
|
||||
|
||||
Floorplan.tables = tables
|
||||
ajax("/ajax/transformTable", tableToUpdate, 'post', null,null,null)
|
||||
ajax("/floorplan/transformTable", tableToUpdate, 'post', null,null,null)
|
||||
}
|
||||
|
||||
const setTransformerNodes = (nodes: Konva.Shape[]) => {
|
||||
@@ -347,7 +347,7 @@ const createEmptyReservation = (covers: number) => {
|
||||
time: 0,
|
||||
}
|
||||
|
||||
ajax('/ajax/newEmptyReservation', newReservation,'post', emptyReservationCreated, null, null )
|
||||
ajax('/reservations/newEmptyReservation', newReservation,'post', emptyReservationCreated, null, null )
|
||||
}
|
||||
|
||||
const emptyReservationCreated = (reservation: reservation) => {
|
||||
@@ -366,7 +366,7 @@ const addReservationName = (name: string) => {
|
||||
hideVirtualKeyboard()
|
||||
const reservation = Floorplan.reservations.filter(reservation => reservation.floorplan_table_id == getSelectedTableData().id)[0]
|
||||
reservation.name = name
|
||||
ajax('/ajax/updateReservation', reservation, 'post', reservationNameAdded, null, null)
|
||||
ajax('/reservations/updateReservation', reservation, 'post', reservationNameAdded, null, null)
|
||||
}
|
||||
|
||||
const reservationNameAdded = (updatedReservation: reservation) => {
|
||||
@@ -386,7 +386,7 @@ const updateTableData = (tableToRemove: floorplan_table) => {
|
||||
const unreserveTable = () => {
|
||||
const selectedTable = getSelectedTableData()
|
||||
selectedTable.status = 0
|
||||
ajax('/ajax/unreserveTable', selectedTable, 'post', tableUnreserved, null, null)
|
||||
ajax('/reservations/unreserveTable', selectedTable, 'post', tableUnreserved, null, null)
|
||||
}
|
||||
|
||||
const tableUnreserved = (table: floorplan_table) => {
|
||||
@@ -469,21 +469,21 @@ const tableDblClicked = (event: Konva.KonvaEventObject<any>) => {
|
||||
|
||||
}
|
||||
|
||||
const createDecorationShape = (decoration:decoration, select?: boolean) => {
|
||||
const createDecorationShape = (decoration:floorplan_decoration, select?: boolean) => {
|
||||
const draggable = isInMode('edit')
|
||||
const decorationShape = new Image()
|
||||
|
||||
decorationShape.onload = () => {
|
||||
const decorationImage = new Konva.Image({
|
||||
id: decoration.id.toString(),
|
||||
x: decoration.decoration_pos_x * Floorplan.visualScale,
|
||||
y: decoration.decoration_pos_y * Floorplan.visualScale,
|
||||
x: decoration.pos_x * Floorplan.visualScale,
|
||||
y: decoration.pos_y * Floorplan.visualScale,
|
||||
image: decorationShape,
|
||||
offsetX: decoration.decoration_width * 0.5 * Floorplan.visualScale,
|
||||
offsetY: decoration.decoration_height * 0.5 * Floorplan.visualScale,
|
||||
rotation: decoration.decoration_rotation,
|
||||
width: decoration.decoration_width * Floorplan.visualScale,
|
||||
height: decoration.decoration_height * Floorplan.visualScale,
|
||||
offsetX: decoration.width * 0.5 * Floorplan.visualScale,
|
||||
offsetY: decoration.height * 0.5 * Floorplan.visualScale,
|
||||
rotation: decoration.rotation,
|
||||
width: decoration.width * Floorplan.visualScale,
|
||||
height: decoration.height * Floorplan.visualScale,
|
||||
draggable: draggable,
|
||||
});
|
||||
|
||||
@@ -500,7 +500,7 @@ const createDecorationShape = (decoration:decoration, select?: boolean) => {
|
||||
}
|
||||
}
|
||||
|
||||
decorationShape.src = 'images/decorations/' + decoration.decoration_image
|
||||
decorationShape.src = '/images/decorations/' + decoration.image
|
||||
}
|
||||
|
||||
const setupDecorationEvents = (decorationShape: Konva.Image) => {
|
||||
@@ -541,22 +541,22 @@ const getDecorationDataById = (id: number) => {
|
||||
const decorationTransformed = (event: Konva.KonvaEventObject<MouseEvent>|Konva.KonvaEventObject<TouchEvent|DragEvent|MouseEvent>) => {
|
||||
let decorationShape = event.currentTarget as Konva.Image
|
||||
const oldDecorationData = getDecorationDataById(Number(decorationShape.id()))
|
||||
const newDecoration: decoration = {
|
||||
const newDecoration: floorplan_decoration = {
|
||||
id: oldDecorationData.id,
|
||||
decoration_room: oldDecorationData.decoration_room,
|
||||
decoration_pos_x: Math.round(decorationShape.x() / Floorplan.visualScale),
|
||||
decoration_pos_y: Math.round(decorationShape.y() / Floorplan.visualScale),
|
||||
decoration_rotation: Math.round(decorationShape.rotation()),
|
||||
decoration_width: Math.round((decorationShape.scaleX() * decorationShape.width()) / Floorplan.visualScale),
|
||||
decoration_height: Math.round((decorationShape.scaleY() * decorationShape.height()) / Floorplan.visualScale),
|
||||
decoration_image: oldDecorationData.decoration_image,
|
||||
room_id: oldDecorationData.room_id,
|
||||
pos_x: Math.round(decorationShape.x() / Floorplan.visualScale),
|
||||
pos_y: Math.round(decorationShape.y() / Floorplan.visualScale),
|
||||
rotation: Math.round(decorationShape.rotation()),
|
||||
width: Math.round((decorationShape.scaleX() * decorationShape.width()) / Floorplan.visualScale),
|
||||
height: Math.round((decorationShape.scaleY() * decorationShape.height()) / Floorplan.visualScale),
|
||||
image: oldDecorationData.image,
|
||||
venue_id: oldDecorationData.venue_id,
|
||||
}
|
||||
|
||||
saveDecoration(newDecoration)
|
||||
}
|
||||
|
||||
const saveDecoration = (decorationToUpdate: decoration) => {
|
||||
const saveDecoration = (decorationToUpdate: floorplan_decoration) => {
|
||||
const decorations =
|
||||
Floorplan
|
||||
.decorations
|
||||
@@ -567,7 +567,7 @@ const saveDecoration = (decorationToUpdate: decoration) => {
|
||||
decorations.push(decorationToUpdate)
|
||||
|
||||
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')
|
||||
@@ -576,22 +576,22 @@ const hideDecorator = () => $('#decorator').css('display', 'flex').hide()
|
||||
const addDecoration = (e: Event) => {
|
||||
const button = $(e.currentTarget)
|
||||
|
||||
const newDecoration: decoration = {
|
||||
const newDecoration: floorplan_decoration = {
|
||||
id: 0,
|
||||
decoration_room: Floorplan.currentRoom.id,
|
||||
decoration_pos_x: Floorplan.visualScaleBasis / 2,
|
||||
decoration_pos_y: Floorplan.visualScaleBasis / 2,
|
||||
decoration_rotation: 0,
|
||||
decoration_width: 200,
|
||||
decoration_height: 200,
|
||||
decoration_image: button.data('image'),
|
||||
room_id: Floorplan.currentRoom.id,
|
||||
pos_x: Floorplan.visualScaleBasis / 2,
|
||||
pos_y: Floorplan.visualScaleBasis / 2,
|
||||
rotation: 0,
|
||||
width: 200,
|
||||
height: 200,
|
||||
image: button.data('image'),
|
||||
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: floorplan_decoration) => {
|
||||
Floorplan.decorations.push(decoration)
|
||||
createDecorationShape(decoration, true)
|
||||
|
||||
@@ -600,11 +600,11 @@ const decorationAdded = (decoration: decoration) => {
|
||||
|
||||
|
||||
const deleteDecoration = () => ajax(
|
||||
'/ajax/deleteDecoration',
|
||||
'/floorplan/deleteDecoration',
|
||||
getDecorationDataById(Floorplan.selectedDecorationId),
|
||||
'post', decorationDeleted, null, null)
|
||||
|
||||
const decorationDeleted = (deletedDecoration:decoration) => {
|
||||
const decorationDeleted = (deletedDecoration:floorplan_decoration) => {
|
||||
Floorplan.decorations = Floorplan.decorations.filter(decoration => decoration.id != deletedDecoration.id)
|
||||
const decorationShape = Floorplan.stage.findOne(`#${deletedDecoration.id}`)
|
||||
decorationShape.destroy()
|
||||
@@ -616,8 +616,10 @@ const setRoomBackground = (roomToLoad: room) => {
|
||||
const height = Floorplan.floorplanDiv.height()
|
||||
|
||||
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`)
|
||||
} else {
|
||||
Floorplan.floorplanDiv.css("background-image", "none")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -735,7 +737,7 @@ const addTable = (tableNumber: number) => {
|
||||
venue_id: 1
|
||||
};
|
||||
|
||||
ajax('/ajax/createTable', newTable, 'post', tableAdded, tableNotAdded, null)
|
||||
ajax('/floorplan/createTable', newTable, 'post', tableAdded, tableNotAdded, null)
|
||||
}
|
||||
|
||||
const tableAdded = (table: floorplan_table) => {
|
||||
@@ -763,7 +765,7 @@ const deleteTable = (tableNumber: number) => {
|
||||
return false
|
||||
}
|
||||
|
||||
ajax(`/ajax/deleteTable`, tableToDelete, 'post', tableDeleted, null, null);
|
||||
ajax(`/floorplan/deleteTable`, tableToDelete, 'post', tableDeleted, null, null);
|
||||
}
|
||||
|
||||
const tableDeleted = (deletedTable: floorplan_table) => {
|
||||
@@ -782,7 +784,7 @@ const mergeTables = (table1: floorplan_table, table2: floorplan_table ) => {
|
||||
posAlert(lang('error_self_merge'))
|
||||
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>) => {
|
||||
@@ -795,7 +797,7 @@ const tablesMerged = (tables: Record<'child'|'parent'|'merged', floorplan_table>
|
||||
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 parentTable = tables['parent']
|
||||
@@ -815,7 +817,7 @@ const transferTables = (origin: floorplan_table, destination: floorplan_table) =
|
||||
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>) => {
|
||||
@@ -123,7 +123,7 @@ const addItemToOrderBox = (orderItem:orderItem) => {
|
||||
const existingRow = orderBox
|
||||
.find('tr')
|
||||
.filterByData('item', orderItem.item)
|
||||
.filterByData('print_group', orderItem.print_group)
|
||||
.filterByData('print_group', orderItem.print_group_id)
|
||||
.filterByData('cover', orderItem.cover)
|
||||
.last()
|
||||
|
||||
@@ -186,13 +186,13 @@ const addInstructionToOrderBox = (instruction: orderItem) => {
|
||||
|
||||
|
||||
const addNewItem = (item: item, qty = 1) => {
|
||||
const salesCategory = OrderScreen.sales_categories.where('id', item.item_category)
|
||||
const printGroup = OrderScreen.print_group_override ?? OrderScreen.print_groups.where('id', salesCategory.print_group)
|
||||
const salesCategory = OrderScreen.sales_categories.where('id', item.category)
|
||||
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,
|
||||
item: item,
|
||||
qty: qty,
|
||||
print_group: printGroup,
|
||||
print_group_id: printGroup,
|
||||
cover: OrderScreen.selected_cover,
|
||||
}
|
||||
|
||||
@@ -258,17 +258,17 @@ const renderOrderBox = () => {
|
||||
const createOrderRow = (orderItem: orderItem) => {
|
||||
const row = $('.orderBoxTable').EmptyRow()
|
||||
const price = money(orderItem.item.price1)
|
||||
const itemCellText = $('<span/>').text(orderItem.item.item_name)
|
||||
const itemCellText = $('<span/>').text(orderItem.item.name)
|
||||
row
|
||||
.addClass(`${orderItem.item.item_type}Row`)
|
||||
.setColumnValue(lang('qty_header'), orderItem.qty)
|
||||
.setColumnValue(lang('price_header'), price)
|
||||
.setColumnValue(lang('id_header'), orderItem.item.id)
|
||||
.setColumnValue(lang('total_price_header'), price.multiply(orderItem.qty))
|
||||
.setColumnValue(lang('printgroup_header'), orderItem.print_group?.name)
|
||||
.setColumnValue(lang('printgroup_header'), orderItem.print_group_id?.name)
|
||||
.data('order-item-id', orderItem.id)
|
||||
.data('order-item-id', orderItem.id)
|
||||
.data('print_group', orderItem.print_group)
|
||||
.data('print_group', orderItem.print_group_id)
|
||||
.data('cover', orderItem.cover)
|
||||
.data('item', orderItem.item)
|
||||
.find('td.itemCell')
|
||||
@@ -303,7 +303,7 @@ const itemButtonClicked = (e: JQuery.TriggeredEvent) => {
|
||||
const gridButtonClicked = (e: JQuery.TriggeredEvent) => {
|
||||
const button = $(e.target).closest('.posButton')
|
||||
const grid : number = button.data('grid')
|
||||
ajax(`/orderScreen/getGridHtml/${grid}`, null, null,gridHtmlGenerated, null, null)
|
||||
ajax(`/order/getGridHtml/${grid}`, null, null,gridHtmlGenerated, null, null)
|
||||
}
|
||||
|
||||
|
||||
@@ -319,17 +319,17 @@ const gridHtmlGenerated = (gridData: {gridHtml:string, grid: grid}) => {
|
||||
|
||||
gridContainer
|
||||
.show()
|
||||
.width(gridCellWidth * grid.grid_cols)
|
||||
.width(gridCellWidth * grid.cols)
|
||||
.children('.gridContainerHeader')
|
||||
.children('span')
|
||||
.text(grid.grid_name)
|
||||
.text(grid.name)
|
||||
.parent()
|
||||
.parent()
|
||||
.find('.pageGroup')
|
||||
.html(gridHtml)
|
||||
.show()
|
||||
.parent()
|
||||
.height(gridCellHeight * grid.grid_rows)
|
||||
.height(gridCellHeight * grid.rows)
|
||||
.closest('.gridContainer')
|
||||
.find('.pageNavigation')
|
||||
.toggle(gridContainer.find('.gridPage').length > 1)
|
||||
@@ -495,7 +495,7 @@ const freetextSubmitted = (text: string) => {
|
||||
|
||||
const item = Object.assign({}, OrderScreen.custom_item)
|
||||
item.item_type = 'instruction'
|
||||
item.item_name = text
|
||||
item.name = text
|
||||
|
||||
addNewItem(item)
|
||||
|
||||
@@ -509,7 +509,7 @@ const customItemTextSubmitted = (text: string) => {
|
||||
|
||||
const item = Object.assign({}, OrderScreen.custom_item)
|
||||
item.item_type = 'item'
|
||||
item.item_name = text
|
||||
item.name = text
|
||||
item.price1 = price.intValue
|
||||
|
||||
addNewItem(item)
|
||||
@@ -571,7 +571,7 @@ const changeCoverNumberPromptSubmitted = (value: string) => updateCoverNumbers(N
|
||||
const updateCoverNumbers = (covers: number) => {
|
||||
let newTable = Object.assign({}, OrderScreen.table)
|
||||
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) => {
|
||||
@@ -600,5 +600,5 @@ const generateCoverSelector = () => {
|
||||
|
||||
$(() => {
|
||||
OrderScreen.table = $('#pageContainer').data('table') || null
|
||||
ajax('/orderScreen/getOrderScreenData/1', null, 'get', setupOrderScreen, null, null)
|
||||
ajax('/order/getOrderScreenData/1', null, 'get', setupOrderScreen, null, null)
|
||||
})
|
||||
@@ -228,7 +228,6 @@ let showVirtualNumpad = (heading: string, maxlength = 4, isPassword: boolean, al
|
||||
index = index + 1
|
||||
|
||||
let currentRow : string[] = layoutToLoad[`row${index}${modifier}`]
|
||||
|
||||
$(row).children('a').each((keyIndex, button) => {
|
||||
let key = $(button);
|
||||
let keyValue: string = currentRow[keyIndex];
|
||||
@@ -10,7 +10,7 @@ interface order {
|
||||
interface orderItem {
|
||||
id: number
|
||||
qty: number
|
||||
print_group: print_group
|
||||
print_group_id: print_group
|
||||
item: item
|
||||
cover: number
|
||||
}
|
||||
@@ -18,7 +18,7 @@ interface orderItem {
|
||||
interface print_group {
|
||||
id: number,
|
||||
name: string,
|
||||
printer: number,
|
||||
printer_id: number,
|
||||
venue_id: number,
|
||||
}
|
||||
|
||||
@@ -50,21 +50,21 @@ interface floorplan_table {
|
||||
id: number
|
||||
}
|
||||
|
||||
interface decoration {
|
||||
interface floorplan_decoration {
|
||||
id: number
|
||||
decoration_room: number
|
||||
decoration_pos_x: number
|
||||
decoration_pos_y: number
|
||||
decoration_rotation: number
|
||||
decoration_width: number
|
||||
decoration_height: number
|
||||
decoration_image: string
|
||||
room_id: number
|
||||
pos_x: number
|
||||
pos_y: number
|
||||
rotation: number
|
||||
width: number
|
||||
height: number
|
||||
image: string
|
||||
venue_id: number
|
||||
}
|
||||
|
||||
interface room {
|
||||
id: number
|
||||
room_name: string
|
||||
name: string
|
||||
background_image: string
|
||||
venue_id: number
|
||||
}
|
||||
@@ -87,26 +87,22 @@ interface keyboard {
|
||||
}
|
||||
|
||||
interface order_screen_page{id: number; order_screen_page_group_id: number; grid_id: number}
|
||||
interface grid {id: number; grid_name: string; grid_rows: number; grid_cols: number; grid_data: string}
|
||||
interface grid {id: number; name: string; rows: number; cols: number; data: string}
|
||||
|
||||
interface item {
|
||||
id: number
|
||||
item_code: string
|
||||
item_category: number
|
||||
item_name: string
|
||||
code: string
|
||||
category: number
|
||||
name: string
|
||||
item_type: string
|
||||
price1: number
|
||||
price2: number
|
||||
price3: number
|
||||
price4: number
|
||||
price5: number
|
||||
}
|
||||
|
||||
type sales_category = {
|
||||
id: number
|
||||
parent: number
|
||||
name: string
|
||||
print_group: string
|
||||
print_group_id: string
|
||||
venue_id: number
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |