Compare commits
13 Commits
npm_script
...
orderscree
| Author | SHA1 | Date | |
|---|---|---|---|
| 6c7bb9eff4 | |||
| 905adcd7bd | |||
| 5e78701b0b | |||
| 420c6530e0 | |||
| 100a772297 | |||
| a587423d3e | |||
| cc7d06e78b | |||
| 05a1a71e6b | |||
|
|
b6aadc072f | ||
| 207edf0de3 | |||
|
|
6439b4326c | ||
| cb58262507 | |||
|
|
b5a2514495 |
@@ -1,16 +1,15 @@
|
|||||||
module DredgePos.Authenticate.Controller
|
module DredgePos.Authenticate.Controller
|
||||||
|
|
||||||
open Giraffe
|
|
||||||
open DredgeFramework
|
open DredgeFramework
|
||||||
open Microsoft.AspNetCore.Http
|
open Microsoft.AspNetCore.Http
|
||||||
|
open DredgePos.Global.Controller
|
||||||
|
|
||||||
let loadAuthenticatePage (): HttpHandler =
|
let loadAuthenticatePage =
|
||||||
let variables = map ["title", "Log In"]
|
let scripts = [|"dredgepos.authenticate.js"|] |> addDefaultScripts
|
||||||
let scripts = ["dredgepos.authenticate.js"]
|
let styles = [|"dredgepos.authenticate.css"|] |> addDefaultStyles
|
||||||
let styles = ["dredgepos.authenticate.css"]
|
let metaTags = [|"viewport", "user-scalable = no, initial-scale=0.8,maximum-scale=0.8 ,shrink-to-fit=yes"|] |> addDefaultMetaTags
|
||||||
|
|
||||||
Theme.loadTemplateWithVarsScriptsAndStyles "authenticate" variables scripts styles
|
View.index scripts styles metaTags
|
||||||
|> htmlString
|
|
||||||
|
|
||||||
let loginWithLoginCode (context: HttpContext) (login_code: int) =
|
let loginWithLoginCode (context: HttpContext) (login_code: int) =
|
||||||
if Model.clerkLogin login_code context then ajaxSuccess "success"
|
if Model.clerkLogin login_code context then ajaxSuccess "success"
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ let getClerkByLoginCode (loginCode: int) =
|
|||||||
let clerk =
|
let clerk =
|
||||||
select {
|
select {
|
||||||
table "clerks"
|
table "clerks"
|
||||||
where (eq "clerk_login_code" loginCode)
|
where (eq "login_code" loginCode)
|
||||||
take 1
|
take 1
|
||||||
}
|
}
|
||||||
|> db.Select<clerk>
|
|> Database.Select<clerk>
|
||||||
|> EnumerableToArray
|
|> EnumerableToArray
|
||||||
|
|
||||||
if (clerk |> length) > 0 then
|
if (clerk |> length) > 0 then
|
||||||
@@ -26,19 +26,19 @@ let deleteSession sessionId context =
|
|||||||
delete {
|
delete {
|
||||||
table "sessions"
|
table "sessions"
|
||||||
where (eq "session_id" sessionId)
|
where (eq "session_id" sessionId)
|
||||||
} |> db.Delete |> ignore
|
} |> Database.Delete |> ignore
|
||||||
Browser.deleteCookie "dredgepos_clerk_logged_in" context
|
Browser.deleteCookie "dredgepos_clerk_logged_in" context
|
||||||
|
|
||||||
let deleteSessionByClerkId clerk_id context =
|
let deleteSessionByClerkId clerk_id context =
|
||||||
delete {
|
delete {
|
||||||
table "sessions"
|
table "sessions"
|
||||||
where (eq "clerk_id" clerk_id)
|
where (eq "clerk_id" clerk_id)
|
||||||
} |> db.Delete |> ignore
|
} |> Database.Delete |> ignore
|
||||||
|
|
||||||
Browser.deleteCookie "dredgepos_clerk_logged_in" context
|
Browser.deleteCookie "dredgepos_clerk_logged_in" context
|
||||||
|
|
||||||
let createNewSession (clerk: clerk) 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
|
deleteSessionByClerkId clerk.id context
|
||||||
let newSessionId = (Guid.NewGuid().ToString "N") + (Guid.NewGuid().ToString "N")
|
let newSessionId = (Guid.NewGuid().ToString "N") + (Guid.NewGuid().ToString "N")
|
||||||
|
|
||||||
@@ -53,18 +53,14 @@ let createNewSession (clerk: clerk) context =
|
|||||||
table "sessions"
|
table "sessions"
|
||||||
value newSession
|
value newSession
|
||||||
}
|
}
|
||||||
|> db.Insert
|
|> Database.Insert
|
||||||
|> ignore
|
|> ignore
|
||||||
|
|
||||||
Browser.setCookie "dredgepos_clerk_logged_in" newSessionId (DateTimeOffset.UtcNow.AddHours(24.0)) context
|
Browser.setCookie "dredgepos_clerk_logged_in" newSessionId (DateTimeOffset.UtcNow.AddHours(24.0)) context
|
||||||
|
|
||||||
|
|
||||||
let sessionExists (sessionId: string) context =
|
let sessionExists (sessionId: string) context =
|
||||||
let sessions =
|
let sessions = Entity.GetAllByColumn<session> "session_id" sessionId
|
||||||
select {
|
|
||||||
table "sessions"
|
|
||||||
where (eq "session_id" sessionId)
|
|
||||||
} |> db.Select<session>
|
|
||||||
|
|
||||||
match sessions |> length with
|
match sessions |> length with
|
||||||
| 0 -> false
|
| 0 -> false
|
||||||
@@ -78,11 +74,11 @@ let sessionExists (sessionId: string) context =
|
|||||||
false
|
false
|
||||||
|
|
||||||
let checkAuthentication clerk =
|
let checkAuthentication clerk =
|
||||||
let existingClerk = getClerkByLoginCode clerk.clerk_login_code
|
let existingClerk = getClerkByLoginCode clerk.login_code
|
||||||
existingClerk.IsSome
|
existingClerk.IsSome
|
||||||
&& existingClerk.Value.id = clerk.id
|
&& existingClerk.Value.id = clerk.id
|
||||||
&& existingClerk.Value.clerk_name = clerk.clerk_name
|
&& existingClerk.Value.name = clerk.name
|
||||||
&& existingClerk.Value.clerk_login_code = clerk.clerk_login_code
|
&& existingClerk.Value.login_code = clerk.login_code
|
||||||
|
|
||||||
let getLoginCookie context = Browser.getCookie "dredgepos_clerk_logged_in" context
|
let getLoginCookie context = Browser.getCookie "dredgepos_clerk_logged_in" context
|
||||||
|
|
||||||
@@ -91,7 +87,7 @@ let getSession (sessionId: string) =
|
|||||||
select {
|
select {
|
||||||
table "sessions"
|
table "sessions"
|
||||||
where (eq "session_id" sessionId)
|
where (eq "session_id" sessionId)
|
||||||
} |> db.Select<session>
|
} |> Database.Select<session>
|
||||||
|
|
||||||
match sessions |> length with
|
match sessions |> length with
|
||||||
| 0 -> {session_id = ""; clerk_json = ""; clerk_id= 0; expires= 0; id=0}
|
| 0 -> {session_id = ""; clerk_json = ""; clerk_id= 0; expires= 0; id=0}
|
||||||
@@ -99,7 +95,7 @@ let getSession (sessionId: string) =
|
|||||||
|
|
||||||
let getCurrentClerk context =
|
let getCurrentClerk context =
|
||||||
let cookie = getLoginCookie 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
|
match cookie with
|
||||||
| "" ->
|
| "" ->
|
||||||
Browser.redirect "/login" context
|
Browser.redirect "/login" context
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
open Saturn
|
open Saturn
|
||||||
open Giraffe
|
open Giraffe
|
||||||
|
|
||||||
let homepage = (warbler (fun _ -> Controller.loadAuthenticatePage() ))
|
let homepage = (warbler (fun _ -> htmlView Controller.loadAuthenticatePage ))
|
||||||
let handlePostRoute<'a> handlerFunction post next ctx = json (handlerFunction ctx post) next ctx
|
let handlePostRoute<'a> handlerFunction post next ctx = json (handlerFunction ctx post) next ctx
|
||||||
|
|
||||||
let pipeline = pipeline{
|
let pipeline = pipeline{
|
||||||
|
|||||||
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|]
|
||||||
|
|
||||||
|
|
||||||
@@ -25,5 +25,4 @@ let setCookie name value (expiry: DateTimeOffset) (context: HttpContext) =
|
|||||||
options.Expires <- expiry
|
options.Expires <- expiry
|
||||||
context.Response.Cookies.Append(name, value, options);
|
context.Response.Cookies.Append(name, value, options);
|
||||||
|
|
||||||
let redirect url (context: HttpContext) =
|
let redirect url (context: HttpContext) = context.Response.Redirect url
|
||||||
context.Response.Redirect url
|
|
||||||
@@ -1,46 +1,98 @@
|
|||||||
module db
|
module Database
|
||||||
|
|
||||||
open Dapper
|
open Dapper
|
||||||
open Dapper.FSharp
|
|
||||||
open Dapper.FSharp.PostgreSQL
|
open Dapper.FSharp.PostgreSQL
|
||||||
|
|
||||||
|
|
||||||
open DredgeFramework
|
open DredgeFramework
|
||||||
|
open DredgePos.Types
|
||||||
|
open Npgsql
|
||||||
|
|
||||||
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 connect connectionString = new NpgsqlConnection(connectionString)
|
||||||
let connection = new Npgsql.NpgsqlConnection(connString)
|
|
||||||
|
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 Select<'a> asyncQuery =
|
||||||
|
let connection = connectToDatabase ()
|
||||||
asyncQuery
|
asyncQuery
|
||||||
|> connection.SelectAsync<'a>
|
|> connection.SelectAsync<'a>
|
||||||
|> RunSynchronously
|
|> RunSynchronously
|
||||||
|> EnumerableToArray
|
|> EnumerableToArray
|
||||||
|
|> closeAndReturn connection
|
||||||
|
|
||||||
let SelectJoin<'a, 'b> asyncQuery =
|
let SelectJoin<'a, 'b> asyncQuery =
|
||||||
|
let connection = connectToDatabase ()
|
||||||
asyncQuery
|
asyncQuery
|
||||||
|> connection.SelectAsync<'a, 'b>
|
|> connection.SelectAsync<'a, 'b>
|
||||||
|> RunSynchronously
|
|> RunSynchronously
|
||||||
|> EnumerableToArray
|
|> EnumerableToArray
|
||||||
|
|> closeAndReturn connection
|
||||||
|
|
||||||
|
|
||||||
let Insert<'a> asyncQuery =
|
let Insert<'a> asyncQuery =
|
||||||
|
let connection = connectToDatabase ()
|
||||||
asyncQuery
|
asyncQuery
|
||||||
|> connection.InsertAsync<'a>
|
|> connection.InsertAsync<'a>
|
||||||
|> RunSynchronously
|
|> RunSynchronously
|
||||||
|
|> closeAndReturn connection
|
||||||
|
|
||||||
|
|
||||||
let InsertOutput<'a> asyncQuery =
|
let InsertOutput<'a> asyncQuery =
|
||||||
|
let connection = connectToDatabase ()
|
||||||
asyncQuery
|
asyncQuery
|
||||||
|> connection.InsertOutputAsync<'a, 'a>
|
|> connection.InsertOutputAsync<'a, 'a>
|
||||||
|> RunSynchronously
|
|> RunSynchronously
|
||||||
|> EnumerableToArray
|
|> EnumerableToArray
|
||||||
|
|> closeAndReturn connection
|
||||||
|
|
||||||
let Update<'a> asyncQuery =
|
let Update<'a> asyncQuery =
|
||||||
|
let connection = connectToDatabase ()
|
||||||
asyncQuery
|
asyncQuery
|
||||||
|> connection.UpdateOutputAsync<'a, 'a>
|
|> connection.UpdateOutputAsync<'a, 'a>
|
||||||
|> RunSynchronously
|
|> RunSynchronously
|
||||||
|> EnumerableToArray
|
|> EnumerableToArray
|
||||||
|
|> closeAndReturn connection
|
||||||
|
|
||||||
let Delete<'a> asyncQuery =
|
let Delete<'a> asyncQuery =
|
||||||
|
let connection = connectToDatabase ()
|
||||||
asyncQuery
|
asyncQuery
|
||||||
|> connection.DeleteAsync
|
|> connection.DeleteAsync
|
||||||
|> RunSynchronously
|
|> 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.Collections.Generic
|
||||||
open System.Globalization
|
open System.Globalization
|
||||||
open FSharp.Data.Sql
|
|
||||||
open System
|
open System
|
||||||
open System.Drawing
|
open System.Drawing
|
||||||
open System.IO
|
open System.IO
|
||||||
open System.Linq
|
open System.Linq
|
||||||
open System.Xml;
|
open System.Xml;
|
||||||
open System.Xml.XPath;
|
|
||||||
open System.Xml.Xsl
|
open System.Xml.Xsl
|
||||||
|
open DredgePos.Types
|
||||||
open FSharp.Reflection
|
open FSharp.Reflection
|
||||||
|
|
||||||
open Thoth.Json.Net
|
open Thoth.Json.Net
|
||||||
@@ -35,8 +34,9 @@ let EnumerableToArray (enumerable: IEnumerable<'T>) = enumerable.ToArray()
|
|||||||
|
|
||||||
let getFileExtension (file: string) = Path.GetExtension file
|
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 GetFileName (file: string) = Path.GetFileName file
|
||||||
|
let FileExists = File.Exists
|
||||||
|
|
||||||
let length (variable: 'T[]) = variable.Length
|
let length (variable: 'T[]) = variable.Length
|
||||||
let first (array: 'a[]) = array[0]
|
let first (array: 'a[]) = array[0]
|
||||||
@@ -101,3 +101,13 @@ let GetImageSize image =
|
|||||||
loadedImage.Width, loadedImage.Height
|
loadedImage.Width, loadedImage.Height
|
||||||
|
|
||||||
let CurrentTime() = DateTimeOffset.Now.ToUnixTimeSeconds() |> int
|
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
|
module Entity
|
||||||
|
open Dapper
|
||||||
open Dapper.FSharp
|
open Dapper.FSharp
|
||||||
open DredgeFramework
|
open DredgeFramework
|
||||||
open Pluralize.NET.Core
|
open Pluralize.NET.Core
|
||||||
@@ -15,7 +16,7 @@ let Create (record: 'x)=
|
|||||||
value record
|
value record
|
||||||
excludeColumn "id"
|
excludeColumn "id"
|
||||||
}
|
}
|
||||||
|> db.InsertOutput
|
|> Database.InsertOutput
|
||||||
|> first
|
|> first
|
||||||
|
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ let inline Update (record: ^x) =
|
|||||||
where (eq "id" id)
|
where (eq "id" id)
|
||||||
excludeColumn "id"
|
excludeColumn "id"
|
||||||
}
|
}
|
||||||
|> db.Update
|
|> Database.Update
|
||||||
|
|
||||||
let GetAll<'x> =
|
let GetAll<'x> =
|
||||||
let tableName = GetDatabaseTable<'x>
|
let tableName = GetDatabaseTable<'x>
|
||||||
@@ -36,7 +37,7 @@ let GetAll<'x> =
|
|||||||
select {
|
select {
|
||||||
table tableName
|
table tableName
|
||||||
}
|
}
|
||||||
|> db.Select<'x>
|
|> Database.Select<'x>
|
||||||
|
|
||||||
let GetAllByColumn<'x> (column: string) (value: obj) =
|
let GetAllByColumn<'x> (column: string) (value: obj) =
|
||||||
let tableName = GetDatabaseTable<'x>
|
let tableName = GetDatabaseTable<'x>
|
||||||
@@ -44,7 +45,9 @@ let GetAllByColumn<'x> (column: string) (value: obj) =
|
|||||||
select {
|
select {
|
||||||
table tableName
|
table tableName
|
||||||
where (eq column value)
|
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 GetAllInVenue<'x> = GetAllByColumn<'x> "venue_id" (getCurrentVenue ())
|
||||||
let GetById<'x> (id: int) = GetAllByColumn<'x> "id" id |> first
|
let GetById<'x> (id: int) = GetAllByColumn<'x> "id" id |> first
|
||||||
@@ -67,7 +70,7 @@ let DeleteById<'x> id =
|
|||||||
delete {
|
delete {
|
||||||
table tableName
|
table tableName
|
||||||
where (eq "id" id)
|
where (eq "id" id)
|
||||||
} |> db.Delete |> ignore
|
} |> Database.Delete |> ignore
|
||||||
|
|
||||||
entity
|
entity
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ type reservation = {
|
|||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type venue = {
|
type venue = {
|
||||||
id: int
|
id: int
|
||||||
venue_name: string
|
name: string
|
||||||
}
|
}
|
||||||
|
|
||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
@@ -38,7 +38,7 @@ type floorplan_table = {
|
|||||||
type print_group = {
|
type print_group = {
|
||||||
id: int
|
id: int
|
||||||
name: string
|
name: string
|
||||||
printer: int
|
printer_id: int
|
||||||
venue_id: int
|
venue_id: int
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,14 +47,14 @@ type sales_category = {
|
|||||||
id: int
|
id: int
|
||||||
parent: int
|
parent: int
|
||||||
name: string
|
name: string
|
||||||
print_group: int
|
print_group_id: int
|
||||||
venue_id: int
|
venue_id: int
|
||||||
}
|
}
|
||||||
|
|
||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type floorplan_room = {
|
type room = {
|
||||||
id: int
|
id: int
|
||||||
room_name: string
|
name: string
|
||||||
background_image: string
|
background_image: string
|
||||||
venue_id: int
|
venue_id: int
|
||||||
}
|
}
|
||||||
@@ -62,18 +62,23 @@ type floorplan_room = {
|
|||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type floorplan_decoration = {
|
type floorplan_decoration = {
|
||||||
id: int
|
id: int
|
||||||
decoration_room: int
|
room_id: int
|
||||||
decoration_pos_x: int
|
pos_x: int
|
||||||
decoration_pos_y: int
|
pos_y: int
|
||||||
decoration_rotation: int
|
rotation: int
|
||||||
decoration_width: int
|
width: int
|
||||||
decoration_height: int
|
height: int
|
||||||
decoration_image: string
|
image: string
|
||||||
venue_id: int
|
venue_id: int
|
||||||
}
|
}
|
||||||
|
|
||||||
[<CLIMutable>]
|
[<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>]
|
[<CLIMutable>]
|
||||||
type session = {id: int; session_id: string; clerk_json: string; clerk_id: int; expires: int}
|
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}
|
type order_screen_page_group = {id: int; order: int; venue_id: int; label: string; grid_id: int}
|
||||||
|
|
||||||
[<CLIMutable>]
|
[<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>]
|
[<CLIMutable>]
|
||||||
type button = {
|
type button = {
|
||||||
@@ -100,13 +105,30 @@ type button = {
|
|||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type item = {
|
type item = {
|
||||||
id: int
|
id: int
|
||||||
item_code: string
|
code: string
|
||||||
item_category: int
|
sales_category_id: int
|
||||||
item_name: string
|
name: string
|
||||||
item_type: string
|
item_type: string
|
||||||
price1: int
|
price1: int
|
||||||
price2: int
|
}
|
||||||
price3: int
|
|
||||||
price4: int
|
[<CLIMutable>]
|
||||||
price5: int
|
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
|
||||||
}
|
}
|
||||||
168
DredgePos.fsproj
@@ -13,18 +13,31 @@
|
|||||||
<Compile Include="Core\Language.module.fs" />
|
<Compile Include="Core\Language.module.fs" />
|
||||||
<Compile Include="Core\Theme.module.fs" />
|
<Compile Include="Core\Theme.module.fs" />
|
||||||
<Compile Include="Printer.module.fs" />
|
<Compile Include="Printer.module.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\Model.fs" />
|
||||||
|
<Compile Include="Entities\Floorplan_Decorations\View.fs" />
|
||||||
<Compile Include="Entities\Floorplan_Decorations\Controller.fs" />
|
<Compile Include="Entities\Floorplan_Decorations\Controller.fs" />
|
||||||
<Compile Include="Entities\Floorplan_Decorations\Router.fs" />
|
<Compile Include="Entities\Floorplan_Decorations\Router.fs" />
|
||||||
|
<Compile Include="Entities\Buttons\Model.fs" />
|
||||||
<Compile Include="Authenticate\Model.fs" />
|
<Compile Include="Authenticate\Model.fs" />
|
||||||
|
<Compile Include="Authenticate\View.fs" />
|
||||||
<Compile Include="Authenticate\Controller.fs" />
|
<Compile Include="Authenticate\Controller.fs" />
|
||||||
<Compile Include="Authenticate\Router.fs" />
|
<Compile Include="Authenticate\Router.fs" />
|
||||||
<Compile Include="Ajax\Controller.fs" />
|
<Compile Include="Ajax\Controller.fs" />
|
||||||
<Compile Include="Ajax\Router.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\Model.fs" />
|
||||||
|
<Compile Include="Floorplan\View.fs" />
|
||||||
<Compile Include="Floorplan\Controller.fs" />
|
<Compile Include="Floorplan\Controller.fs" />
|
||||||
<Compile Include="Floorplan\Router.fs" />
|
<Compile Include="Floorplan\Router.fs" />
|
||||||
<Compile Include="OrderScreen\Model.fs" />
|
<Compile Include="OrderScreen\Model.fs" />
|
||||||
|
<Compile Include="OrderScreen\View.fs" />
|
||||||
<Compile Include="OrderScreen\Controller.fs" />
|
<Compile Include="OrderScreen\Controller.fs" />
|
||||||
<Compile Include="OrderScreen\Router.fs" />
|
<Compile Include="OrderScreen\Router.fs" />
|
||||||
<Compile Include="Reservations\Model.fs" />
|
<Compile Include="Reservations\Model.fs" />
|
||||||
@@ -106,168 +119,15 @@
|
|||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="views\restaurant\alert.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\authenticate.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\backupPayentsplitter.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\button.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\buttonWithImage.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\categories\BeerPage1.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\categories\BeerPage2.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\categories\DessertsPage1.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\categories\MainsPage1.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\categories\StartersPage1.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\categories\WinePage1.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\categoryButton.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\categoryMenu.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\components\posButton.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\decoratorItem.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\decoratorRow.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\floorplan.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\keyboards.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\orderBox.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\orderBoxTable.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\orderScreen.tpl - Copy.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\orderScreen.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\orderScreen\button_image.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\orderScreen\change_cover_number_button.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\orderScreen\cover_selector.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\orderScreen\grid_button.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\orderScreen\grid_container.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\orderScreen\page.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\orderScreen\page_group.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\orderScreen\page_group_button.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\paymentSplitter.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\popupBoxItems.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\roomButton.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\virtualKeyboard.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="views\restaurant\virtualNumpad.tpl.htm">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Folder Include="wwwroot\styles" />
|
<Folder Include="wwwroot\styles" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<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="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="Giraffe" Version="6.0.0-alpha-2" />
|
||||||
<PackageReference Include="Npgsql" Version="6.0.0" />
|
<PackageReference Include="Npgsql" Version="6.0.0" />
|
||||||
<PackageReference Include="Pluralize.NET.Core" Version="1.0.0" />
|
<PackageReference Include="Pluralize.NET.Core" Version="1.0.0" />
|
||||||
<PackageReference Include="Saturn" Version="0.15.0-preview03" />
|
<PackageReference Include="Saturn" Version="0.15.0" />
|
||||||
<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="System.Drawing.Common" Version="6.0.0-preview.5.21301.5" />
|
<PackageReference Include="System.Drawing.Common" Version="6.0.0-preview.5.21301.5" />
|
||||||
<PackageReference Include="Thoth.Json.Net" Version="5.0.0" />
|
<PackageReference Include="Thoth.Json.Net" Version="5.0.0" />
|
||||||
<PackageReference Update="FSharp.Core" Version="6.0.2-beta.21631.1" />
|
<PackageReference Update="FSharp.Core" Version="6.0.2-beta.21631.1" />
|
||||||
|
|||||||
19
Entities/Buttons/Model.fs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
module DredgePos.Entities.Buttons.Model
|
||||||
|
|
||||||
|
open DredgePos.Types
|
||||||
|
open DredgeFramework
|
||||||
|
|
||||||
|
let attr = Giraffe.ViewEngine.HtmlElements.attr
|
||||||
|
|
||||||
|
let getItemActionAttributes (itemCode: string) =
|
||||||
|
let item = Entity.GetFirstByColumn<item> "code" (StringTrim itemCode)
|
||||||
|
[(attr "data-item") <| jsonEncode item]
|
||||||
|
|
||||||
|
let getGridActionAttributes (gridId: int) = [(attr "data-grid") <| jsonEncode gridId]
|
||||||
|
|
||||||
|
let getActionAttributes (action: string) (actionValue: string) =
|
||||||
|
|
||||||
|
match action with
|
||||||
|
| "item" -> getItemActionAttributes actionValue
|
||||||
|
| "grid" -> actionValue |> int |> getGridActionAttributes
|
||||||
|
| _ -> []
|
||||||
@@ -1,27 +1,13 @@
|
|||||||
module DredgePos.Entities.Floorplan_Decorations.Controller
|
module DredgePos.Entities.Floorplan_Decorations.Controller
|
||||||
|
|
||||||
open DredgeFramework
|
|
||||||
open System
|
|
||||||
open System.IO
|
open System.IO
|
||||||
|
|
||||||
let getImageHTML (imageName: string, imageUrl: string) =
|
|
||||||
let vars = map [
|
|
||||||
"image_name", imageName
|
|
||||||
"image_url", imageUrl
|
|
||||||
]
|
|
||||||
Theme.loadTemplateWithVars "decoratorItem" vars
|
|
||||||
|
|
||||||
let getImageRowHtml (imagesInRow: string[]) =
|
|
||||||
let vars = map ["decorations", String.Join("", imagesInRow)]
|
|
||||||
Theme.loadTemplateWithVars "decoratorRow" vars
|
|
||||||
|
|
||||||
let generateDecorator () =
|
let generateDecorator () =
|
||||||
"wwwroot/images/decorations"
|
"wwwroot/images/decorations"
|
||||||
|> Directory.GetFiles
|
|> Directory.GetFiles
|
||||||
|> Array.filter Model.isImageFile
|
|> Array.filter Model.isImageFile
|
||||||
|> Array.map Model.GetFileNameWithoutExtension
|
|> Array.map Model.GetFileNameWithoutExtension
|
||||||
|> Array.map Model.getImageName
|
|> Array.map Model.getImageName
|
||||||
|> Array.map getImageHTML
|
|> Array.map View.decoratorItem
|
||||||
|> Array.chunkBySize 4
|
|> Array.chunkBySize 4
|
||||||
|> Array.map getImageRowHtml
|
|> Array.map View.decoratorRow
|
||||||
|> JoinArray ""
|
|
||||||
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
|
||||||
|
]
|
||||||
|
]
|
||||||
@@ -2,15 +2,18 @@
|
|||||||
|
|
||||||
open DredgeFramework
|
open DredgeFramework
|
||||||
open DredgePos
|
open DredgePos
|
||||||
|
open DredgePos.Global.Controller
|
||||||
|
open DredgePos.Entities
|
||||||
open DredgePos.Types
|
open DredgePos.Types
|
||||||
open Giraffe
|
open Giraffe
|
||||||
open Microsoft.AspNetCore.Http
|
open Microsoft.AspNetCore.Http
|
||||||
open Model
|
open Model
|
||||||
|
open System.IO
|
||||||
|
|
||||||
let makeRoomButton (room: floorplan_room) =
|
let makeRoomButton (room: room) =
|
||||||
let vars = map [
|
let vars = map [
|
||||||
"roomId", room.id |> string
|
"roomId", room.id |> string
|
||||||
"roomName", room.room_name
|
"roomName", room.name
|
||||||
]
|
]
|
||||||
|
|
||||||
Theme.loadTemplateWithVars "roomButton" vars
|
Theme.loadTemplateWithVars "roomButton" vars
|
||||||
@@ -47,7 +50,7 @@ let getFloorplanData (id: int) =
|
|||||||
tables = tableList
|
tables = tableList
|
||||||
decorations = Entity.GetAllInVenue<floorplan_decoration>
|
decorations = Entity.GetAllInVenue<floorplan_decoration>
|
||||||
activeTableNumbers = Model.getActiveTables (getCurrentVenue())
|
activeTableNumbers = Model.getActiveTables (getCurrentVenue())
|
||||||
rooms = Entity.GetAllInVenue<floorplan_room>
|
rooms = Entity.GetAllInVenue<room>
|
||||||
reservations = reservationList
|
reservations = reservationList
|
||||||
|}
|
|}
|
||||||
|> ajaxSuccess
|
|> ajaxSuccess
|
||||||
@@ -70,24 +73,24 @@ let deleteTable (table: floorplan_table) =
|
|||||||
table |> ajaxSuccess |> json
|
table |> ajaxSuccess |> json
|
||||||
|
|
||||||
let transferTable (origin, destination) =
|
let transferTable (origin, destination) =
|
||||||
Model.transferTable origin destination
|
transferTable origin destination
|
||||||
let data = map ["origin", getTable origin ; "destination", getTable destination]
|
let data = map ["origin", getTable origin ; "destination", getTable destination]
|
||||||
ajaxSuccess data |> json
|
ajaxSuccess data |> json
|
||||||
|
|
||||||
let AddDecoration (data: floorplan_decoration) =
|
let AddDecoration (data: floorplan_decoration) =
|
||||||
let image = "wwwroot/images/decorations/" + data.decoration_image
|
let image = "wwwroot/images/decorations/" + data.image
|
||||||
let width, height = image |> GetImageSize
|
let width, height = image |> GetImageSize
|
||||||
let aspectRatio = decimal width / decimal height
|
let aspectRatio = decimal width / decimal height
|
||||||
|
|
||||||
let decoration : floorplan_decoration = {
|
let decoration : floorplan_decoration = {
|
||||||
id = 0
|
id = 0
|
||||||
decoration_height = (200m / aspectRatio) |> int
|
height = (200m / aspectRatio) |> int
|
||||||
decoration_width = 200
|
width = 200
|
||||||
decoration_rotation = 0
|
rotation = 0
|
||||||
decoration_image = data.decoration_image
|
image = data.image
|
||||||
decoration_pos_x = data.decoration_pos_x
|
pos_x = data.pos_x
|
||||||
decoration_pos_y = data.decoration_pos_y
|
pos_y = data.pos_y
|
||||||
decoration_room = data.decoration_room
|
room_id = data.room_id
|
||||||
venue_id = data.venue_id
|
venue_id = data.venue_id
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,23 +108,12 @@ let DeleteDecoration (decorationToDelete: floorplan_decoration) =
|
|||||||
|> ajaxSuccess
|
|> ajaxSuccess
|
||||||
|> json
|
|> json
|
||||||
|
|
||||||
let loadFloorplan (ctx: HttpContext) : HttpHandler =
|
let loadFloorplanView (ctx: HttpContext) =
|
||||||
Authenticate.Model.RequireClerkAuthentication ctx
|
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
|
||||||
|
|
||||||
let roomMenu =
|
View.index styles scripts metaTags currentClerk (Floorplan_Decorations.Controller.generateDecorator ()) roomMenu
|
||||||
Entity.GetAllInVenue<floorplan_room>
|
|
||||||
|> Array.map makeRoomButton
|
|
||||||
|> joinWithNewLine
|
|
||||||
|
|
||||||
let variables = map [
|
|
||||||
"title", "Floorplan"
|
|
||||||
"roomMenu", roomMenu
|
|
||||||
"decorator", Entities.Floorplan_Decorations.Controller.generateDecorator()
|
|
||||||
]
|
|
||||||
let styles = ["dredgepos.floorplan.css"]
|
|
||||||
let scripts = ["./external/konva.min.js" ; "dredgepos.floorplan.js"]
|
|
||||||
let currentClerk = recordToMap <| Authenticate.Model.getCurrentClerk ctx
|
|
||||||
|
|
||||||
let arrays = map ["clerk", currentClerk]
|
|
||||||
|
|
||||||
htmlString <| Theme.loadTemplateWithVarsArraysScriptsAndStyles "floorplan" variables arrays scripts styles
|
|
||||||
@@ -39,7 +39,7 @@ let tablesInRoom (roomId: int) = //Get a list of all tables in a particular room
|
|||||||
table "floorplan_tables"
|
table "floorplan_tables"
|
||||||
where (eq "room_id" roomId)
|
where (eq "room_id" roomId)
|
||||||
}
|
}
|
||||||
|> db.Select<floorplan_table>
|
|> Database.Select<floorplan_table>
|
||||||
|
|
||||||
|
|
||||||
let getActiveTables (venueId: int) =
|
let getActiveTables (venueId: int) =
|
||||||
@@ -47,7 +47,7 @@ let getActiveTables (venueId: int) =
|
|||||||
table "floorplan_tables"
|
table "floorplan_tables"
|
||||||
where (eq "venue_id" venueId)
|
where (eq "venue_id" venueId)
|
||||||
}
|
}
|
||||||
|> db.Select
|
|> Database.Select
|
||||||
|> Array.filter tableIsOpen
|
|> Array.filter tableIsOpen
|
||||||
|> Array.map (fun table -> table.table_number)
|
|> Array.map (fun table -> table.table_number)
|
||||||
|
|
||||||
@@ -87,28 +87,34 @@ let saveOrderToTable orderXML tableNumber =
|
|||||||
|
|
||||||
File.WriteAllText(tableFile, tableXML)
|
File.WriteAllText(tableFile, tableXML)
|
||||||
|
|
||||||
let getTable (tableNumber : int) =
|
let getTableSafely (tableNumber: int) =
|
||||||
let query = select {
|
let query = select {
|
||||||
table "floorplan_tables"
|
table "floorplan_tables"
|
||||||
where (eq "table_number" tableNumber + eq "venue_id" (getCurrentVenue()))
|
where (eq "table_number" tableNumber + eq "venue_id" (getCurrentVenue()))
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = query |> db.Select<floorplan_table>
|
query
|
||||||
result |> first
|
|> Database.Select<floorplan_table>
|
||||||
|
|> Array.tryItem 0
|
||||||
|
|
||||||
|
let getTable (tableNumber : int) =
|
||||||
|
match getTableSafely tableNumber with
|
||||||
|
| None -> failwith $"Table {tableNumber} not found in current venue"
|
||||||
|
| Some table -> table
|
||||||
|
|
||||||
let getTableById (id : int) =
|
let getTableById (id : int) =
|
||||||
select {
|
select {
|
||||||
table "floorplan_tables"
|
table "floorplan_tables"
|
||||||
where (eq "id" id)
|
where (eq "id" id)
|
||||||
}
|
}
|
||||||
|> db.Select<floorplan_table>
|
|> Database.Select<floorplan_table>
|
||||||
|> first
|
|> first
|
||||||
|
|
||||||
let getRoom (roomId: int) =
|
let getRoom (roomId: int) =
|
||||||
select {
|
select {
|
||||||
table "floorplan_rooms"
|
table "floorplan_rooms"
|
||||||
where (eq "id" roomId)
|
where (eq "id" roomId)
|
||||||
} |> db.Select<floorplan_room> |> first
|
} |> Database.Select<room> |> first
|
||||||
|
|
||||||
let updateTablePosition (floorplanTable: floorplan_table) = Entity.Update floorplanTable
|
let updateTablePosition (floorplanTable: floorplan_table) = Entity.Update floorplanTable
|
||||||
|
|
||||||
@@ -117,7 +123,7 @@ let createEmptyReservation (reservation: reservation) =
|
|||||||
table "floorplan_tables"
|
table "floorplan_tables"
|
||||||
set {| status = 2 |}
|
set {| status = 2 |}
|
||||||
where(eq "id" reservation.floorplan_table_id)
|
where(eq "id" reservation.floorplan_table_id)
|
||||||
} |> db.Update |> ignore
|
} |> Database.Update |> ignore
|
||||||
|
|
||||||
Entity.Create reservation
|
Entity.Create reservation
|
||||||
|
|
||||||
@@ -154,7 +160,7 @@ let tableExists (tableNumber: int) =
|
|||||||
select{
|
select{
|
||||||
table "floorplan_tables"
|
table "floorplan_tables"
|
||||||
where (eq "table_number" tableNumber + eq "venue_id" (getCurrentVenue()))
|
where (eq "table_number" tableNumber + eq "venue_id" (getCurrentVenue()))
|
||||||
} |> db.Select<floorplan_table> |> length
|
} |> Database.Select<floorplan_table> |> length
|
||||||
|
|
||||||
match numberOfResults with
|
match numberOfResults with
|
||||||
| 0 ->
|
| 0 ->
|
||||||
@@ -169,14 +175,14 @@ let tableExists (tableNumber: int) =
|
|||||||
| _ ->
|
| _ ->
|
||||||
let parentTableData = getTable allTables[0]
|
let parentTableData = getTable allTables[0]
|
||||||
let parentRoom = getRoom parentTableData.room_id
|
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()]
|
language.getAndReplace "error_table_exists_merged" [parentRoomName; parentTableData.table_number.ToString()]
|
||||||
|
|
||||||
|
|
||||||
| _ ->
|
| _ ->
|
||||||
let tableData = getTable tableNumber
|
let tableData = getTable tableNumber
|
||||||
let room = getRoom tableData.room_id
|
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) =
|
let addNewTableWithoutOutput (newTable: floorplan_table) =
|
||||||
@@ -184,7 +190,7 @@ let addNewTableWithoutOutput (newTable: floorplan_table) =
|
|||||||
table "floorplan_tables"
|
table "floorplan_tables"
|
||||||
value newTable
|
value newTable
|
||||||
}
|
}
|
||||||
|> db.Insert
|
|> Database.Insert
|
||||||
|
|
||||||
let addNewTable (newTable: floorplan_table) = Entity.Create newTable
|
let addNewTable (newTable: floorplan_table) = Entity.Create newTable
|
||||||
|
|
||||||
@@ -238,7 +244,7 @@ let mergeTables parent child = //Merge two tables together
|
|||||||
default_covers = parentTable.default_covers + childTable.default_covers
|
default_covers = parentTable.default_covers + childTable.default_covers
|
||||||
|}
|
|}
|
||||||
where (eq "table_number" parent + eq "venue_id" (getCurrentVenue()))
|
where (eq "table_number" parent + eq "venue_id" (getCurrentVenue()))
|
||||||
} |> db.Update |> ignore
|
} |> Database.Update |> ignore
|
||||||
|
|
||||||
Entity.DeleteById<floorplan_table> newChildTable.id
|
Entity.DeleteById<floorplan_table> newChildTable.id
|
||||||
|> ignore
|
|> ignore
|
||||||
@@ -251,7 +257,7 @@ let updateUnmergedTables parentTable childTable =
|
|||||||
table "floorplan_tables"
|
table "floorplan_tables"
|
||||||
set parentTable
|
set parentTable
|
||||||
where(eq "table_number" parentTable.table_number + eq "venue_id" (getCurrentVenue()))
|
where(eq "table_number" parentTable.table_number + eq "venue_id" (getCurrentVenue()))
|
||||||
} |> db.Update |> ignore
|
} |> Database.Update |> ignore
|
||||||
|
|
||||||
addNewTableWithoutOutput childTable |> ignore
|
addNewTableWithoutOutput childTable |> ignore
|
||||||
true
|
true
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
module DredgePos.Floorplan.Router
|
module DredgePos.Floorplan.Router
|
||||||
|
|
||||||
open DredgePos
|
open DredgePos
|
||||||
|
open DredgePos.Global.Router
|
||||||
open DredgePos.Types
|
open DredgePos.Types
|
||||||
open Saturn
|
open Saturn
|
||||||
open Giraffe
|
open Giraffe
|
||||||
|
|
||||||
let floorplan = (warbler (fun ctx -> DredgePos.Floorplan.Controller.loadFloorplan (snd ctx)))
|
let floorplan = (htmlViewWithContext Controller.loadFloorplanView)
|
||||||
|
|
||||||
let router = router {
|
let router = router {
|
||||||
pipe_through Ajax.Router.pipeline
|
pipe_through Ajax.Router.pipeline
|
||||||
get "/" floorplan
|
|
||||||
get "" floorplan
|
get "" floorplan
|
||||||
|
get "/" floorplan
|
||||||
post "/mergeTables" (bindJson<floorplan_table[]> Controller.mergeTables)
|
post "/mergeTables" (bindJson<floorplan_table[]> Controller.mergeTables)
|
||||||
post "/transformTable" (bindJson<floorplan_table> Controller.transformTable)
|
post "/transformTable" (bindJson<floorplan_table> Controller.transformTable)
|
||||||
post "/createTable" (bindJson<floorplan_table> Controller.createTable)
|
post "/createTable" (bindJson<floorplan_table> Controller.createTable)
|
||||||
|
|||||||
86
Floorplan/View.fs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
module DredgePos.Floorplan.View
|
||||||
|
|
||||||
|
open DredgePos.Global
|
||||||
|
open DredgePos.Global.View
|
||||||
|
open DredgePos.Entities
|
||||||
|
open DredgePos.Types
|
||||||
|
open Giraffe.ViewEngine
|
||||||
|
open DredgeFramework
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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"|]
|
||||||
18
Global/Router.fs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
module DredgePos.Global.Router
|
||||||
|
|
||||||
|
open Saturn
|
||||||
|
open Giraffe
|
||||||
|
|
||||||
|
let htmlViewWithContext func =
|
||||||
|
(fun ctx ->
|
||||||
|
func (snd ctx)
|
||||||
|
|> htmlView
|
||||||
|
)
|
||||||
|
|> warbler
|
||||||
|
|
||||||
|
let htmlViewWithContextAndId (id: int) func =
|
||||||
|
(fun ctx ->
|
||||||
|
func (snd ctx) id
|
||||||
|
|> htmlView
|
||||||
|
)
|
||||||
|
|> warbler
|
||||||
134
Global/View.fs
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
module DredgePos.Global.View
|
||||||
|
|
||||||
|
open DredgeFramework
|
||||||
|
open DredgePos.Types
|
||||||
|
open Giraffe.ViewEngine
|
||||||
|
|
||||||
|
let Value = attr "data-value"
|
||||||
|
let _table (value: floorplan_table) = value |> jsonEncode |> (attr "data-table")
|
||||||
|
|
||||||
|
let VisibleInMode (value: string list) = value |> jsonEncode |> (attr "data-visible-in-mode")
|
||||||
|
let InvisibleInMode (value: string list) = value |> jsonEncode |> (attr "data-invisible-in-mode")
|
||||||
|
let ActiveInMode (value: string) = value |> (attr "data-active-in-mode")
|
||||||
|
let innerText = str
|
||||||
|
let lang key = language.get key |> str
|
||||||
|
|
||||||
|
let template = tag "template"
|
||||||
|
|
||||||
|
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 posButton (extraClasses: string) attrs content =
|
||||||
|
let allAttrs = [_class $"posButton {extraClasses}"] |> List.append attrs
|
||||||
|
a allAttrs content
|
||||||
|
|
||||||
|
let PosButton classes (attrs: Map<string, 'x>) text =
|
||||||
|
let attrArray =
|
||||||
|
attrs
|
||||||
|
|> Map.map (fun key value ->
|
||||||
|
(attr key) (string value)
|
||||||
|
)
|
||||||
|
|> Map.values
|
||||||
|
|> Array.ofSeq
|
||||||
|
|
||||||
|
posButton classes [
|
||||||
|
yield! attrArray
|
||||||
|
] [str text]
|
||||||
|
|
||||||
|
let HtmlPage pageTitle scripts styles tags content =
|
||||||
|
html [] [
|
||||||
|
head [] [
|
||||||
|
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
|
||||||
380
Migrations/PopulateTestData.fs
Normal file
@@ -0,0 +1,380 @@
|
|||||||
|
module DredgePos.Migrations.PopulateTestData
|
||||||
|
|
||||||
|
open DredgeFramework
|
||||||
|
open DredgePos.Types
|
||||||
|
open System.IO
|
||||||
|
|
||||||
|
let spaceButton () = (Entity.GetFirstByColumn<button> "primary_action" "spacer").id
|
||||||
|
|
||||||
|
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 CreateDefaultButtons (path: string) =
|
||||||
|
Entity.Create {
|
||||||
|
id = 0
|
||||||
|
text = ""
|
||||||
|
primary_action = "spacer"
|
||||||
|
secondary_action = ""
|
||||||
|
primary_action_value = ""
|
||||||
|
secondary_action_value = ""
|
||||||
|
image = ""
|
||||||
|
extra_classes = "invisible"
|
||||||
|
extra_styles = ""
|
||||||
|
}
|
||||||
|
|> ignore
|
||||||
|
path
|
||||||
|
|
||||||
|
let CreateDefaultItems (path: string) =
|
||||||
|
Entity.Create {
|
||||||
|
id = 0
|
||||||
|
name = "Custom Item"
|
||||||
|
code = "OPEN000"
|
||||||
|
sales_category_id = (Entity.GetFirstByColumn<sales_category> "name" "Food").id
|
||||||
|
item_type = "item"
|
||||||
|
price1 = 0
|
||||||
|
}
|
||||||
|
|> ignore
|
||||||
|
path
|
||||||
|
|
||||||
|
let CreateRooms () =
|
||||||
|
"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 space = spaceButton()
|
||||||
|
let GridData =
|
||||||
|
[|
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
|]
|
||||||
|
|> 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 -> space
|
||||||
|
| 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 -> space
|
||||||
|
| 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 space = spaceButton()
|
||||||
|
let getId index =
|
||||||
|
match Mains |> Array.tryItem index with
|
||||||
|
| None -> space
|
||||||
|
| Some x -> x.id
|
||||||
|
let GridData =
|
||||||
|
[|
|
||||||
|
getId 0; space; getId 1; space; getId 2; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
getId 3; space; getId 4; space; getId 5; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
|]
|
||||||
|
|
||||||
|
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 space = spaceButton()
|
||||||
|
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 -> space
|
||||||
|
| Some x -> x.id
|
||||||
|
let GridData =
|
||||||
|
[|
|
||||||
|
getId 0; space; getId 1; space; space ; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; getId 2; space; getId 4; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
|]
|
||||||
|
|
||||||
|
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 space = spaceButton()
|
||||||
|
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 mutable buttonMap = Map.empty<string, int[]>
|
||||||
|
Beers
|
||||||
|
|> Array.chunkBySize 24
|
||||||
|
|> Array.map (fun beerPage ->
|
||||||
|
let getId index =
|
||||||
|
match beerPage |> Array.tryItem index with
|
||||||
|
| None -> space
|
||||||
|
| Some x -> x.id
|
||||||
|
[|
|
||||||
|
getId 0; getId 1; getId 2; getId 3; getId 4 ; getId 5;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
getId 6; getId 7; getId 8; getId 9; getId 10 ; getId 11;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
getId 12; getId 13; getId 14; getId 15; getId 16 ; getId 17;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
getId 18; getId 19; getId 20; getId 21; getId 22 ; getId 23;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
|]
|
||||||
|
)
|
||||||
|
|> Array.iteri (fun index buttonIds ->
|
||||||
|
buttonMap <- buttonMap |> Map.add $"page{index+1}" buttonIds
|
||||||
|
)
|
||||||
|
|
||||||
|
let GridData = buttonMap |> jsonEncode
|
||||||
|
|
||||||
|
let newGrid = {grid with data=GridData}
|
||||||
|
Entity.Update newGrid |> ignore
|
||||||
|
|
||||||
|
let populateSteakTemperaturesGrid () =
|
||||||
|
let space = spaceButton()
|
||||||
|
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 -> space
|
||||||
|
| Some x -> x.id
|
||||||
|
let GridData =
|
||||||
|
[|
|
||||||
|
getId 0; space; getId 1; space; getId 2; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
getId 3; space; getId 4; space; getId 5; space;
|
||||||
|
space; space; space; space; space; space;
|
||||||
|
|]
|
||||||
|
|
||||||
|
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"
|
||||||
|
| _ -> "normal"
|
||||||
|
|
||||||
|
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
|
||||||
|
|> CreateDefaultItems
|
||||||
|
|> CreateDefaultButtons
|
||||||
|
|> Directory.GetDirectories
|
||||||
|
|> Array.mapi CreatePageFromDirectory
|
||||||
|
|> Array.iter CreateItemsAndButtons
|
||||||
|
|> CreateRooms
|
||||||
|
|> PopulateGrids
|
||||||
@@ -3,87 +3,88 @@
|
|||||||
open DredgePos
|
open DredgePos
|
||||||
open DredgeFramework
|
open DredgeFramework
|
||||||
open DredgePos.Types
|
open DredgePos.Types
|
||||||
|
open DredgePos.Global.Controller
|
||||||
|
open Saturn.CSRF
|
||||||
|
open Thoth.Json.Net
|
||||||
open Giraffe
|
open Giraffe
|
||||||
open Microsoft.AspNetCore.Http
|
open Microsoft.AspNetCore.Http
|
||||||
|
open FSharp.Collections
|
||||||
|
|
||||||
let getOrderScreenData (tableNumber: int) =
|
let getOrderScreenData (tableNumber: int) =
|
||||||
{|
|
{|
|
||||||
order_screen_pages = Entity.GetAllInVenue<order_screen_page_group>
|
order_screen_pages = Entity.GetAllInVenue<order_screen_page_group>
|
||||||
sales_categories = Entity.GetAllInVenue<sales_category>
|
sales_categories = Entity.GetAllInVenue<sales_category>
|
||||||
print_groups = Entity.GetAllInVenue<print_group>
|
print_groups = Entity.GetAllInVenue<print_group>
|
||||||
custom_item = Entity.GetAllByColumn<item> "item_code" "OPEN000" |> first
|
custom_item = Entity.GetFirstByColumn<item> "code" "OPEN000"
|
||||||
table = Floorplan.Model.getTable tableNumber
|
table = Floorplan.Model.getTable tableNumber
|
||||||
|}
|
|}
|
||||||
|> ajaxSuccess
|
|> ajaxSuccess
|
||||||
|> json
|
|> json
|
||||||
|
|
||||||
|
let renderGrid (grid: grid) =
|
||||||
|
let gridData = grid.data |> Decode.Auto.fromString<Map<string, int[]>>
|
||||||
|
match gridData with
|
||||||
|
| Error message -> failwith message
|
||||||
|
| Ok data ->
|
||||||
|
data
|
||||||
|
|> Map.toArray
|
||||||
|
|> Array.map snd
|
||||||
|
|> Array.map(
|
||||||
|
fun buttonIds ->
|
||||||
|
buttonIds
|
||||||
|
|> Array.map Entity.GetById<button>
|
||||||
|
|> Array.map View.itemButton
|
||||||
|
|> View.gridPage grid
|
||||||
|
)
|
||||||
|
|
||||||
let loadGrid (gridId: int) =
|
let loadGrid (gridId: int) =
|
||||||
let grid = Entity.GetById<grid> gridId
|
let grid = Entity.GetById<grid> gridId
|
||||||
let gridHtml = Model.loadGrid gridId
|
let gridNodes = (renderGrid grid) |> List.ofArray
|
||||||
|
let gridHtml = Giraffe.ViewEngine.RenderView.AsString.htmlNodes gridNodes
|
||||||
|
|
||||||
if gridHtml = "Error" then ajaxFail gridHtml
|
if gridHtml = "Error" then ajaxFail gridHtml
|
||||||
else ajaxSuccess {|grid=grid;gridHtml=gridHtml|}
|
else ajaxSuccess {|grid=grid;gridHtml=gridHtml|}
|
||||||
|> json
|
|> json
|
||||||
|
|
||||||
let loadOrderScreen (ctx: HttpContext) (tableNumber: int) : HttpHandler =
|
let loadOrderScreenView (ctx: HttpContext) (tableNumber: int) =
|
||||||
Authenticate.Model.RequireClerkAuthentication ctx
|
Authenticate.Model.RequireClerkAuthentication ctx
|
||||||
|
let tableOption = DredgePos.Floorplan.Model.getTableSafely tableNumber
|
||||||
|
let attr = Giraffe.ViewEngine.HtmlElements.attr
|
||||||
|
|
||||||
let table = Floorplan.Model.getTable tableNumber
|
match tableOption with
|
||||||
|
| None ->
|
||||||
|
Browser.redirect "/" ctx
|
||||||
|
View.posButtonTemplate
|
||||||
|
| Some table ->
|
||||||
|
let currentClerk = Authenticate.Model.getCurrentClerk ctx
|
||||||
|
let styles = [|"dredgepos.orderScreen.css"|] |> addDefaultStyles
|
||||||
|
let scripts = [|"dredgepos.tables.js";"./external/currency.min.js";"dredgepos.orderScreen.js"; |] |> addDefaultScripts
|
||||||
|
let metaTags = [|"viewport", "user-scalable = no, initial-scale=0.8,maximum-scale=0.8 ,shrink-to-fit=yes"|] |> addDefaultMetaTags
|
||||||
|
|
||||||
let covers = if tableNumber > 0 then table.default_covers else 0
|
let printGroupButtons =
|
||||||
let coverString = language.getAndReplace "covers" [covers]
|
Entity.GetAllInVenue<sales_category>
|
||||||
|
|> Array.map View.printGroupButton
|
||||||
|
|
||||||
let changeCoverNumberButton = if tableNumber > 0 then Theme.loadTemplateWithVars "orderScreen/change_cover_number_button" (map ["covers", coverString]) else ""
|
let orderScreenPageGroupButtons =
|
||||||
|
|
||||||
let orderNumber =
|
|
||||||
if tableNumber > 0 then language.getAndReplace "active_table" [tableNumber]
|
|
||||||
else language.get "new_order"
|
|
||||||
|
|
||||||
let containerAttributes =
|
|
||||||
if tableNumber > 0 then
|
|
||||||
map ["data-table", jsonEncode table]
|
|
||||||
|> Theme.htmlAttributes
|
|
||||||
else ""
|
|
||||||
|
|
||||||
let categoryList =
|
|
||||||
Entity.GetAllInVenue<order_screen_page_group>
|
Entity.GetAllInVenue<order_screen_page_group>
|
||||||
|> Array.filter (fun page_group -> page_group.id <> 0)
|
|> Array.filter (fun page_group -> page_group.id <> 0)
|
||||||
|> Array.sortBy (fun {order=order} -> order)
|
|> Array.sortBy (fun {order=order} -> order)
|
||||||
|> Array.map (fun category ->
|
|> Array.map View.pageGroupButton
|
||||||
let categoryMap = recordToMap category
|
|
||||||
let categoryArray = map ["page", categoryMap]
|
|
||||||
Theme.loadTemplateWithArrays "orderScreen/page_group_button" categoryArray
|
|
||||||
)
|
|
||||||
|> joinWithNewLine
|
|
||||||
|
|
||||||
let grids =
|
let grids = Model.getAllPageGridsInVenue ()
|
||||||
Model.getAllPageGrids ()
|
let pageGroupNodes =
|
||||||
|> Array.map Model.getPagesHTML
|
grids
|
||||||
|> joinWithNewLine
|
|> Array.map(fun (grid, page_group) ->
|
||||||
|
renderGrid grid
|
||||||
|
|> View.pageGroup page_group
|
||||||
|
)
|
||||||
|
|
||||||
let coverSelectorButtons =
|
let coverSelectorButtons =
|
||||||
Array.init (covers+1) id
|
Array.init (table.default_covers + 1) id
|
||||||
|> Array.map(fun coverNumber ->
|
|> Array.map(fun coverNumber ->
|
||||||
let text = if coverNumber > 0 then language.getAndReplace "selected_cover" [coverNumber]
|
let text = if coverNumber > 0 then language.getAndReplace "selected_cover" [coverNumber]
|
||||||
else language.get "cover_zero"
|
else language.get "cover_zero"
|
||||||
Theme.PosButton text "coverSelectorButton" $"""data-cover="{coverNumber}" """)
|
Global.View.PosButton "coverSelectorButton" (map ["data-cover", coverNumber]) text
|
||||||
|> String.concat "\n"
|
)
|
||||||
|
|
||||||
let variables = map [
|
View.index tableNumber styles scripts metaTags currentClerk printGroupButtons orderScreenPageGroupButtons pageGroupNodes coverSelectorButtons
|
||||||
"title", "Order"
|
|
||||||
"containerAttributes", containerAttributes
|
|
||||||
"categoryList", categoryList
|
|
||||||
"pageGroups", grids
|
|
||||||
"orderNumber", orderNumber
|
|
||||||
"changeCoverNumberButton", changeCoverNumberButton
|
|
||||||
"covers", coverString
|
|
||||||
"salesCategoryOverrideButtons", Model.generateSalesCategoryOverrideButtons ()
|
|
||||||
"coverSelectorButtons", coverSelectorButtons
|
|
||||||
]
|
|
||||||
|
|
||||||
let styles = ["dredgepos.orderScreen.css"]
|
|
||||||
let scripts = ["dredgepos.tables.js";"./external/currency.min.js";"dredgepos.orderScreen.js"; ]
|
|
||||||
let currentClerk = recordToMap <| Authenticate.Model.getCurrentClerk ctx
|
|
||||||
let arrays = map ["clerk", currentClerk]
|
|
||||||
|
|
||||||
Theme.loadTemplateWithVarsArraysScriptsAndStyles "orderScreen" variables arrays scripts styles
|
|
||||||
|> htmlString
|
|
||||||
@@ -8,129 +8,11 @@ open Thoth.Json.Net
|
|||||||
open Theme
|
open Theme
|
||||||
|
|
||||||
|
|
||||||
let getAllPageGrids () = Entity.GetAllInVenue<order_screen_page_group>
|
let getAllPageGridsInVenue () =
|
||||||
|
Entity.GetAllInVenue<order_screen_page_group>
|
||||||
|> Array.filter(fun pageGroup -> pageGroup.grid_id <> 0)
|
|> Array.filter(fun pageGroup -> pageGroup.grid_id <> 0)
|
||||||
|> Array.map(fun pageGroup -> (Entity.GetById<grid> pageGroup.grid_id), pageGroup)
|
|> Array.map(fun pageGroup -> (Entity.GetById<grid> pageGroup.grid_id), pageGroup)
|
||||||
|
|
||||||
let getImageButtonData (button: button) =
|
|
||||||
let itemCode =
|
|
||||||
if button.primary_action = "item" then button.primary_action_value
|
|
||||||
else button.secondary_action_value
|
|
||||||
|
|
||||||
let item = Entity.GetAllByColumn<item> "item_code" itemCode
|
|
||||||
|> first
|
|
||||||
|
|
||||||
let extraData =
|
|
||||||
map [
|
|
||||||
"data-item", jsonEncode item
|
|
||||||
] |> htmlAttributes
|
|
||||||
|
|
||||||
{|
|
|
||||||
extra_data = extraData
|
|
||||||
text = item.item_name
|
|
||||||
|}
|
|
||||||
|
|
||||||
let getGridButtonData (button: button) =
|
|
||||||
let gridId =
|
|
||||||
if button.primary_action = "grid" then button.primary_action_value
|
|
||||||
else button.secondary_action_value
|
|
||||||
|> int
|
|
||||||
|
|
||||||
let grid = Entity.GetById<grid> gridId
|
|
||||||
{|
|
|
||||||
extra_data = map ["data-grid", jsonEncode gridId] |> htmlAttributes
|
|
||||||
text = grid.grid_name
|
|
||||||
|}
|
|
||||||
|
|
||||||
let getActionData (button: button) (action: string) =
|
|
||||||
let actionValue =
|
|
||||||
if action = "primary" then button.primary_action
|
|
||||||
else button.secondary_action
|
|
||||||
|
|
||||||
match actionValue with
|
|
||||||
| "item" -> getImageButtonData button
|
|
||||||
| "grid" -> getGridButtonData button
|
|
||||||
| "spacer" -> {|extra_data=""; text=""|}
|
|
||||||
| _ -> {|extra_data=""; text=""|}
|
|
||||||
|
|
||||||
let renderButton (buttonId: int) =
|
|
||||||
let button = Entity.GetById<button> buttonId
|
|
||||||
|
|
||||||
let extra_styles =
|
|
||||||
match button.extra_styles.Length with
|
|
||||||
| 0 -> ""
|
|
||||||
| _ -> $""" style="{button.extra_styles}" """
|
|
||||||
|
|
||||||
let imageClass = if button.image.Length > 0 then "hasImage" else ""
|
|
||||||
let spacerClass = if button.primary_action = "spacer" || button.secondary_action = "spacer"
|
|
||||||
then "invisible"
|
|
||||||
else ""
|
|
||||||
|
|
||||||
let image = if button.image.Length > 0 then loadTemplateWithVars "orderScreen/button_image" (map ["image", button.image]) else ""
|
|
||||||
|
|
||||||
let extraClasses = [|imageClass; spacerClass|] |> String.concat " "
|
|
||||||
|
|
||||||
let primary_action_data = getActionData button "primary"
|
|
||||||
let secondary_action_data = getActionData button "secondary"
|
|
||||||
|
|
||||||
let action_extra_data = primary_action_data.extra_data + " " + secondary_action_data.extra_data
|
|
||||||
let button_text =
|
|
||||||
if button.text.Length > 0 then button.text
|
|
||||||
else
|
|
||||||
if primary_action_data.text.Length > 0 then primary_action_data.text
|
|
||||||
else secondary_action_data.text
|
|
||||||
|
|
||||||
let vars = map [
|
|
||||||
"extra_classes", button.extra_classes + " " + extraClasses
|
|
||||||
"extra_styles", extra_styles
|
|
||||||
"primary_action", button.primary_action
|
|
||||||
"secondary_action", button.secondary_action
|
|
||||||
"text", button_text
|
|
||||||
"image", image
|
|
||||||
"extra_data", action_extra_data
|
|
||||||
]
|
|
||||||
|
|
||||||
loadTemplateWithVars "orderScreen/grid_button" vars
|
|
||||||
|
|
||||||
let renderPage (grid: grid) (buttonHTML: string) =
|
|
||||||
let vars = map ["pageButtons", buttonHTML; "rows", string grid.grid_rows; "cols", string grid.grid_cols]
|
|
||||||
loadTemplateWithVars "orderScreen/page" vars
|
|
||||||
|
|
||||||
let renderPageGroup (pageGroup: order_screen_page_group) (pageHTML: string) =
|
|
||||||
let vars = map [
|
|
||||||
"pages", pageHTML
|
|
||||||
"page_group_id", string pageGroup.id
|
|
||||||
]
|
|
||||||
loadTemplateWithVars "orderScreen/page_group" vars
|
|
||||||
|
|
||||||
let printGroupPosButton (printGroup: print_group) =
|
let printGroupPosButton (printGroup: print_group) =
|
||||||
PosButton (language.getAndReplace "print_with" [printGroup.name]) "printGroupOverrideButton toggle" $"""data-value="{printGroup.id}" """
|
PosButton (language.getAndReplace "print_with" [printGroup.name]) "printGroupOverrideButton toggle" $"""data-value="{printGroup.id}" """
|
||||||
|
|
||||||
let generateSalesCategoryOverrideButtons () =
|
|
||||||
Entity.GetAllInVenue<print_group>
|
|
||||||
|> Array.map printGroupPosButton
|
|
||||||
|> Array.append [|PosButton (language.getAndReplace "print_with" ["default"]) "printGroupOverrideButton toggle default active" """data-value="0" """|]
|
|
||||||
|> joinWithNewLine
|
|
||||||
|
|
||||||
|
|
||||||
let renderGrid (grid: grid) =
|
|
||||||
let gridData = grid.grid_data |> Decode.Auto.fromString<Map<string, int[]>>
|
|
||||||
|
|
||||||
match gridData with
|
|
||||||
| Error _ -> "Error"
|
|
||||||
| Ok pages ->
|
|
||||||
pages
|
|
||||||
|> Map.toArray
|
|
||||||
|> Array.map snd
|
|
||||||
|> Array.map(fun row -> row |> Array.map renderButton |> String.concat "\n")
|
|
||||||
|> Array.map (renderPage grid)
|
|
||||||
|> joinWithNewLine
|
|
||||||
|
|
||||||
let loadGrid gridId = renderGrid (Entity.GetById<grid> gridId)
|
|
||||||
|
|
||||||
|
|
||||||
let getPagesHTML (gridInfo: grid * order_screen_page_group) =
|
|
||||||
let grid, pageGroup = gridInfo
|
|
||||||
|
|
||||||
renderGrid grid
|
|
||||||
|> renderPageGroup pageGroup
|
|
||||||
|
|||||||
@@ -10,6 +10,5 @@ let router = router {
|
|||||||
getf "/getOrderScreenData/%i" Controller.getOrderScreenData
|
getf "/getOrderScreenData/%i" Controller.getOrderScreenData
|
||||||
getf "/getGridHtml/%i" Controller.loadGrid
|
getf "/getGridHtml/%i" Controller.loadGrid
|
||||||
post "/updateCovers" (bindJson<floorplan_table> (fun table -> Entity.Update table |> Array.head |> DredgeFramework.ajaxSuccess |> json))
|
post "/updateCovers" (bindJson<floorplan_table> (fun table -> Entity.Update table |> Array.head |> DredgeFramework.ajaxSuccess |> json))
|
||||||
get "/" (warbler (fun ctx -> Controller.loadOrderScreen (snd ctx) 0))
|
getf "/%i" (fun number -> (warbler (fun ctx -> htmlView <| Controller.loadOrderScreenView (snd ctx) number)))
|
||||||
getf "/%i" (fun number -> (warbler (fun ctx -> Controller.loadOrderScreen (snd ctx) number)))
|
|
||||||
}
|
}
|
||||||
159
OrderScreen/View.fs
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
module DredgePos.OrderScreen.View
|
||||||
|
|
||||||
|
open DredgeFramework
|
||||||
|
open DredgePos.Types
|
||||||
|
open DredgePos.Global.View
|
||||||
|
open DredgePos.Entities.Buttons.Model
|
||||||
|
open Thoth.Json.Net
|
||||||
|
open Giraffe.ViewEngine
|
||||||
|
open language
|
||||||
|
|
||||||
|
let coverSelector buttons = div [_class "coverSelector"] [
|
||||||
|
yield! buttons
|
||||||
|
]
|
||||||
|
|
||||||
|
let pageContainer floorplanTable (clerk: clerk) printGroupButtons orderScreenPageGroupButtons pageGroups =
|
||||||
|
div [_id "pageContainer" ; _table floorplanTable] [
|
||||||
|
div [_id "leftColumn"] [
|
||||||
|
h1 [_class "tableHeading"] [str (getAndReplace "active_table" [floorplanTable.table_number])]
|
||||||
|
div [_class "tableInfo"] [
|
||||||
|
posButton "changeCoverNumberButton" [] [str (getAndReplace "covers" [floorplanTable.default_covers])]
|
||||||
|
posButton "" [] [str (getAndReplace "logged_in_as" [clerk.name])]
|
||||||
|
]
|
||||||
|
div [_class "orderBox"] [
|
||||||
|
table [_class "orderBoxTable"] [
|
||||||
|
thead [] [
|
||||||
|
tr [] [
|
||||||
|
th [_class "orderBoxCell qtyCell"] [str (get "qty_header")]
|
||||||
|
th [_class "orderBoxCell itemIdCell"] [str (get "id_header")]
|
||||||
|
th [_class "orderBoxCell itemCell"] [str (get "item_header")]
|
||||||
|
th [_class "orderBoxCell unitPriceCell"] [str (get "price_header")]
|
||||||
|
th [_class "orderBoxCell totalPriceCell"] [str (get "total_price_header")]
|
||||||
|
th [_class "orderBoxCell printGroupCell"] [str (get "printgroup_header")]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
tbody [] []
|
||||||
|
]
|
||||||
|
]
|
||||||
|
div [_class "orderBoxInfo"] [
|
||||||
|
span [_class "voidModeWarning"; VisibleInMode ["void"]] [str (get "void_mode")]
|
||||||
|
]
|
||||||
|
div [_class "orderBoxFooter"] [
|
||||||
|
span [_class "totalPrice"] [str (getAndReplace "totalPrice" ["0.00"])]
|
||||||
|
small [_class "selectedPrice"] [str (getAndReplace "selectedPrice" ["0.00"])]
|
||||||
|
|
||||||
|
]
|
||||||
|
]
|
||||||
|
div [_id "rightColumn"] [
|
||||||
|
div [_id "topHalf"] [
|
||||||
|
div [_class "functionButtons"] [
|
||||||
|
div [_class "printGroupButtons toggleGroup"] [
|
||||||
|
input [_type "hidden"; _class "value"]
|
||||||
|
yield! printGroupButtons
|
||||||
|
]
|
||||||
|
div [_class "functionColumn"] [
|
||||||
|
posButton "accumulateButton" [ActiveInMode "accumulate"] [str (get "accumulate_function")]
|
||||||
|
posButton "showCoverSelectorButton" [] [str (get "select_covers")]
|
||||||
|
]
|
||||||
|
div [_class "functionColumn"] [
|
||||||
|
posButton "voidButton" [ActiveInMode "void"] [str (get "void")]
|
||||||
|
posButton "openItemButton" [] [str (get "custom_item_button")]
|
||||||
|
posButton "freetextButton" [] [str (get "freetext_button")]
|
||||||
|
posButton "numpadButton" [] [str (get "numpad_button")]
|
||||||
|
]
|
||||||
|
div [_class "functionColumn"] [
|
||||||
|
posButton "" [] ["pay_function" |> get |> str]
|
||||||
|
posButton "" [] ["print_function" |> get |> str]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
div [_id "pageList"] [
|
||||||
|
yield! orderScreenPageGroupButtons
|
||||||
|
]
|
||||||
|
div [_id "pageGroupContainer"] [
|
||||||
|
yield! pageGroups
|
||||||
|
]
|
||||||
|
div [_class "pageNavigation"] [
|
||||||
|
posButton "prevButton" [] ["prev_page" |> get |> str]
|
||||||
|
posButton "nextButton" [] ["next_page" |> get |> str]
|
||||||
|
]
|
||||||
|
|
||||||
|
]
|
||||||
|
]
|
||||||
|
(* Grid Container, Cover Selector *)
|
||||||
|
|
||||||
|
let posButtonTemplate =
|
||||||
|
template [_id "posButtonTemplate"] [
|
||||||
|
posButton "" [] []
|
||||||
|
]
|
||||||
|
|
||||||
|
let gridContainer =
|
||||||
|
div [_class "gridContainer"] [
|
||||||
|
div [_class "gridContainerHeader"] [
|
||||||
|
span [] []
|
||||||
|
div [_class "posButton closeGrid"] [str "×"]
|
||||||
|
]
|
||||||
|
div [_class "gridContainerGrid"] [
|
||||||
|
div [_class "pageGroup"] []
|
||||||
|
]
|
||||||
|
div [_class "pageNavigation"] [
|
||||||
|
posButton "prevButton" [] ["prev_page" |> get |> str]
|
||||||
|
posButton "nextButton" [] ["next_page" |> get |> str]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
let pageGroupButton (pageGroup: order_screen_page_group) = posButton "loadPageGroup" [(attr "data-page-group-id") (string pageGroup.id)] [str pageGroup.label]
|
||||||
|
let printGroupButton (printGroup: sales_category) = posButton "" [(attr "data-print-group-id") (string printGroup.id)] [str printGroup.name]
|
||||||
|
|
||||||
|
let itemButtonImage (button: button) =
|
||||||
|
span [
|
||||||
|
_class "buttonImg"
|
||||||
|
_style $"background-image:url(\"/images/items/{button.image}\");"
|
||||||
|
] []
|
||||||
|
|
||||||
|
let itemButton (button: button) =
|
||||||
|
let extraClasses =
|
||||||
|
if button.image.Length > 0 then button.extra_classes + " hasImage"
|
||||||
|
else button.extra_classes
|
||||||
|
|
||||||
|
let primaryAttributes = getActionAttributes button.primary_action button.primary_action_value
|
||||||
|
let secondaryAttributes = getActionAttributes button.secondary_action button.secondary_action_value
|
||||||
|
|
||||||
|
posButton extraClasses [
|
||||||
|
yield! primaryAttributes
|
||||||
|
yield! secondaryAttributes
|
||||||
|
_style button.extra_styles
|
||||||
|
(attr "data-primary-action") button.primary_action
|
||||||
|
(attr "data-secondary-action") button.secondary_action
|
||||||
|
] [
|
||||||
|
if button.image.Length > 0 then itemButtonImage button
|
||||||
|
span [_class "text "] [str button.text]
|
||||||
|
]
|
||||||
|
|
||||||
|
let _dataPageGroup = attr "data-page-group"
|
||||||
|
let _dataPageGroupId = attr "data-page-group-id"
|
||||||
|
|
||||||
|
let pageGroup (page_group: order_screen_page_group) gridNodes =
|
||||||
|
div [_class "pageGroup"; _dataPageGroupId (string page_group.id); ] [
|
||||||
|
yield! gridNodes
|
||||||
|
]
|
||||||
|
|
||||||
|
let gridPage (grid: grid) buttonNodes =
|
||||||
|
div [
|
||||||
|
_class "gridPage"
|
||||||
|
_style $"
|
||||||
|
grid-template-columns: repeat({grid.cols}, 1fr);
|
||||||
|
grid-template-rows: repeat({grid.rows}, 1fr);"
|
||||||
|
] [
|
||||||
|
yield! buttonNodes
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
let index orderNumber styles scripts tags clerk printGroupButtons orderScreenPageGroupButtons pageGroupNodes coverSelectorButtons =
|
||||||
|
[|
|
||||||
|
pageContainer (DredgePos.Floorplan.Model.getTable orderNumber) clerk printGroupButtons orderScreenPageGroupButtons pageGroupNodes
|
||||||
|
posButtonTemplate
|
||||||
|
gridContainer
|
||||||
|
coverSelector coverSelectorButtons
|
||||||
|
|]
|
||||||
|
|> HtmlPage "Order" (GetScripts scripts) (GetStyles styles) (GetMetaTags tags)
|
||||||
@@ -14,6 +14,7 @@ module Program =
|
|||||||
forward "/order" DredgePos.OrderScreen.Router.router
|
forward "/order" DredgePos.OrderScreen.Router.router
|
||||||
forward "/login" DredgePos.Authenticate.Router.router
|
forward "/login" DredgePos.Authenticate.Router.router
|
||||||
forward "/reservations" DredgePos.Reservations.Router.router
|
forward "/reservations" DredgePos.Reservations.Router.router
|
||||||
|
forward "/install" DredgePos.Installer.Router.router
|
||||||
}
|
}
|
||||||
|
|
||||||
let app = application {
|
let app = application {
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ let updateReservation (reservation: reservation) =
|
|||||||
table "reservations"
|
table "reservations"
|
||||||
set reservation
|
set reservation
|
||||||
where(eq "id" reservation.id)
|
where(eq "id" reservation.id)
|
||||||
} |> db.Update |> ignore
|
} |> Database.Update |> ignore
|
||||||
reservation
|
reservation
|
||||||
|
|
||||||
let DeleteReservation (tableId: int) =
|
let DeleteReservation (tableId: int) =
|
||||||
delete {
|
delete {
|
||||||
table "reservations"
|
table "reservations"
|
||||||
where (eq "floorplan_table_id" tableId)
|
where (eq "floorplan_table_id" tableId)
|
||||||
} |> db.Delete |> ignore
|
} |> Database.Delete |> ignore
|
||||||
9
config.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"database": {
|
||||||
|
"db_name": "dredgepos",
|
||||||
|
"username": "postgres",
|
||||||
|
"password": "root",
|
||||||
|
"host": "localhost",
|
||||||
|
"port": 5432
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,6 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"sass": "sass sass:wwwroot/styles",
|
"sass": "sass sass:wwwroot/styles",
|
||||||
"typescript": "tsc",
|
"typescript": "tsc",
|
||||||
"build" : "npm run sass && npm run typescript"
|
"build": "npm run sass && npm run typescript"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -268,6 +268,9 @@
|
|||||||
text-align: center
|
text-align: center
|
||||||
width: 60%
|
width: 60%
|
||||||
|
|
||||||
|
.itemIdCell
|
||||||
|
display: none
|
||||||
|
|
||||||
.qtyCell
|
.qtyCell
|
||||||
width: 10%
|
width: 10%
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ interface floorplan{
|
|||||||
tableLayer: Konva.Layer
|
tableLayer: Konva.Layer
|
||||||
rooms: room[]
|
rooms: room[]
|
||||||
tables: floorplan_table[]
|
tables: floorplan_table[]
|
||||||
decorations: decoration[]
|
decorations: floorplan_decoration[]
|
||||||
activeTableNumbers: number[]
|
activeTableNumbers: number[]
|
||||||
selectedTableNumber: number
|
selectedTableNumber: number
|
||||||
selectedDecorationId: number
|
selectedDecorationId: number
|
||||||
@@ -25,7 +25,7 @@ interface floorplan{
|
|||||||
|
|
||||||
interface floorplan_data{
|
interface floorplan_data{
|
||||||
tables: floorplan_table[]
|
tables: floorplan_table[]
|
||||||
decorations: decoration[]
|
decorations: floorplan_decoration[]
|
||||||
activeTableNumbers: number[]
|
activeTableNumbers: number[]
|
||||||
rooms: room[]
|
rooms: room[]
|
||||||
reservations:reservation[]
|
reservations:reservation[]
|
||||||
@@ -122,7 +122,7 @@ const loadRoom = (roomToLoad: room) => {
|
|||||||
button.addClass('active')
|
button.addClass('active')
|
||||||
|
|
||||||
const tablesInRoom = Floorplan.tables.filter(table => table.room_id == roomToLoad.id)
|
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))
|
decorationsInRoom.forEach(decoration => createDecorationShape(decoration, false))
|
||||||
tablesInRoom.forEach(createTableShape)
|
tablesInRoom.forEach(createTableShape)
|
||||||
if(!isInMode('transfer')) {
|
if(!isInMode('transfer')) {
|
||||||
@@ -173,7 +173,7 @@ const createTableShape = (table: floorplan_table) => {
|
|||||||
stroke: "black",
|
stroke: "black",
|
||||||
strokeWidth: 4,
|
strokeWidth: 4,
|
||||||
draggable: false,
|
draggable: false,
|
||||||
listening: true
|
listening: true,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -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 draggable = isInMode('edit')
|
||||||
const decorationShape = new Image()
|
const decorationShape = new Image()
|
||||||
|
|
||||||
decorationShape.onload = () => {
|
decorationShape.onload = () => {
|
||||||
const decorationImage = new Konva.Image({
|
const decorationImage = new Konva.Image({
|
||||||
id: decoration.id.toString(),
|
id: decoration.id.toString(),
|
||||||
x: decoration.decoration_pos_x * Floorplan.visualScale,
|
x: decoration.pos_x * Floorplan.visualScale,
|
||||||
y: decoration.decoration_pos_y * Floorplan.visualScale,
|
y: decoration.pos_y * Floorplan.visualScale,
|
||||||
image: decorationShape,
|
image: decorationShape,
|
||||||
offsetX: decoration.decoration_width * 0.5 * Floorplan.visualScale,
|
offsetX: decoration.width * 0.5 * Floorplan.visualScale,
|
||||||
offsetY: decoration.decoration_height * 0.5 * Floorplan.visualScale,
|
offsetY: decoration.height * 0.5 * Floorplan.visualScale,
|
||||||
rotation: decoration.decoration_rotation,
|
rotation: decoration.rotation,
|
||||||
width: decoration.decoration_width * Floorplan.visualScale,
|
width: decoration.width * Floorplan.visualScale,
|
||||||
height: decoration.decoration_height * Floorplan.visualScale,
|
height: decoration.height * Floorplan.visualScale,
|
||||||
draggable: draggable,
|
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) => {
|
const setupDecorationEvents = (decorationShape: Konva.Image) => {
|
||||||
@@ -541,22 +541,22 @@ const getDecorationDataById = (id: number) => {
|
|||||||
const decorationTransformed = (event: Konva.KonvaEventObject<MouseEvent>|Konva.KonvaEventObject<TouchEvent|DragEvent|MouseEvent>) => {
|
const decorationTransformed = (event: Konva.KonvaEventObject<MouseEvent>|Konva.KonvaEventObject<TouchEvent|DragEvent|MouseEvent>) => {
|
||||||
let decorationShape = event.currentTarget as Konva.Image
|
let decorationShape = event.currentTarget as Konva.Image
|
||||||
const oldDecorationData = getDecorationDataById(Number(decorationShape.id()))
|
const oldDecorationData = getDecorationDataById(Number(decorationShape.id()))
|
||||||
const newDecoration: decoration = {
|
const newDecoration: floorplan_decoration = {
|
||||||
id: oldDecorationData.id,
|
id: oldDecorationData.id,
|
||||||
decoration_room: oldDecorationData.decoration_room,
|
room_id: oldDecorationData.room_id,
|
||||||
decoration_pos_x: Math.round(decorationShape.x() / Floorplan.visualScale),
|
pos_x: Math.round(decorationShape.x() / Floorplan.visualScale),
|
||||||
decoration_pos_y: Math.round(decorationShape.y() / Floorplan.visualScale),
|
pos_y: Math.round(decorationShape.y() / Floorplan.visualScale),
|
||||||
decoration_rotation: Math.round(decorationShape.rotation()),
|
rotation: Math.round(decorationShape.rotation()),
|
||||||
decoration_width: Math.round((decorationShape.scaleX() * decorationShape.width()) / Floorplan.visualScale),
|
width: Math.round((decorationShape.scaleX() * decorationShape.width()) / Floorplan.visualScale),
|
||||||
decoration_height: Math.round((decorationShape.scaleY() * decorationShape.height()) / Floorplan.visualScale),
|
height: Math.round((decorationShape.scaleY() * decorationShape.height()) / Floorplan.visualScale),
|
||||||
decoration_image: oldDecorationData.decoration_image,
|
image: oldDecorationData.image,
|
||||||
venue_id: oldDecorationData.venue_id,
|
venue_id: oldDecorationData.venue_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
saveDecoration(newDecoration)
|
saveDecoration(newDecoration)
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveDecoration = (decorationToUpdate: decoration) => {
|
const saveDecoration = (decorationToUpdate: floorplan_decoration) => {
|
||||||
const decorations =
|
const decorations =
|
||||||
Floorplan
|
Floorplan
|
||||||
.decorations
|
.decorations
|
||||||
@@ -576,22 +576,22 @@ const hideDecorator = () => $('#decorator').css('display', 'flex').hide()
|
|||||||
const addDecoration = (e: Event) => {
|
const addDecoration = (e: Event) => {
|
||||||
const button = $(e.currentTarget)
|
const button = $(e.currentTarget)
|
||||||
|
|
||||||
const newDecoration: decoration = {
|
const newDecoration: floorplan_decoration = {
|
||||||
id: 0,
|
id: 0,
|
||||||
decoration_room: Floorplan.currentRoom.id,
|
room_id: Floorplan.currentRoom.id,
|
||||||
decoration_pos_x: Floorplan.visualScaleBasis / 2,
|
pos_x: Floorplan.visualScaleBasis / 2,
|
||||||
decoration_pos_y: Floorplan.visualScaleBasis / 2,
|
pos_y: Floorplan.visualScaleBasis / 2,
|
||||||
decoration_rotation: 0,
|
rotation: 0,
|
||||||
decoration_width: 200,
|
width: 200,
|
||||||
decoration_height: 200,
|
height: 200,
|
||||||
decoration_image: button.data('image'),
|
image: button.data('image'),
|
||||||
venue_id: Floorplan.currentRoom.venue_id
|
venue_id: Floorplan.currentRoom.venue_id
|
||||||
}
|
}
|
||||||
|
|
||||||
ajax('/floorplan/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)
|
Floorplan.decorations.push(decoration)
|
||||||
createDecorationShape(decoration, true)
|
createDecorationShape(decoration, true)
|
||||||
|
|
||||||
@@ -604,7 +604,7 @@ const deleteDecoration = () => ajax(
|
|||||||
getDecorationDataById(Floorplan.selectedDecorationId),
|
getDecorationDataById(Floorplan.selectedDecorationId),
|
||||||
'post', decorationDeleted, null, null)
|
'post', decorationDeleted, null, null)
|
||||||
|
|
||||||
const decorationDeleted = (deletedDecoration:decoration) => {
|
const decorationDeleted = (deletedDecoration:floorplan_decoration) => {
|
||||||
Floorplan.decorations = Floorplan.decorations.filter(decoration => decoration.id != deletedDecoration.id)
|
Floorplan.decorations = Floorplan.decorations.filter(decoration => decoration.id != deletedDecoration.id)
|
||||||
const decorationShape = Floorplan.stage.findOne(`#${deletedDecoration.id}`)
|
const decorationShape = Floorplan.stage.findOne(`#${deletedDecoration.id}`)
|
||||||
decorationShape.destroy()
|
decorationShape.destroy()
|
||||||
@@ -615,9 +615,11 @@ const setRoomBackground = (roomToLoad: room) => {
|
|||||||
const width = Floorplan.floorplanDiv.width()
|
const width = Floorplan.floorplanDiv.width()
|
||||||
const height = Floorplan.floorplanDiv.height()
|
const height = Floorplan.floorplanDiv.height()
|
||||||
|
|
||||||
if(roomToLoad.background_image) {
|
if(roomToLoad.background_image != "") {
|
||||||
Floorplan.floorplanDiv.css("background-image", `url(/images/rooms/${roomToLoad?.background_image})`)
|
Floorplan.floorplanDiv.css("background-image", `url('/images/rooms/${roomToLoad.background_image}')`)
|
||||||
Floorplan.floorplanDiv.css("background-size", `${width}px ${height}px`)
|
Floorplan.floorplanDiv.css("background-size", `${width}px ${height}px`)
|
||||||
|
} else {
|
||||||
|
Floorplan.floorplanDiv.css("background-image", "none")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ const loadPageGroup = (e: Event) => {
|
|||||||
button.addClass('active')
|
button.addClass('active')
|
||||||
|
|
||||||
let pageGroupId = button.data('page-group-id')
|
let pageGroupId = button.data('page-group-id')
|
||||||
|
|
||||||
container.find('.pageGroup').hide()
|
container.find('.pageGroup').hide()
|
||||||
|
|
||||||
let activeGrid = $(`.pageGroup[data-page-group-id=${pageGroupId}]`)
|
let activeGrid = $(`.pageGroup[data-page-group-id=${pageGroupId}]`)
|
||||||
@@ -59,7 +58,6 @@ const loadPageGroup = (e: Event) => {
|
|||||||
|
|
||||||
const setupOrderScreen = (data: OrderScreenData) => {
|
const setupOrderScreen = (data: OrderScreenData) => {
|
||||||
|
|
||||||
$('.coverSelector, .gridContainer').hide()
|
|
||||||
|
|
||||||
OrderScreen.order_screen_pages = data.order_screen_pages
|
OrderScreen.order_screen_pages = data.order_screen_pages
|
||||||
OrderScreen.sales_categories = data.sales_categories
|
OrderScreen.sales_categories = data.sales_categories
|
||||||
@@ -123,7 +121,7 @@ const addItemToOrderBox = (orderItem:orderItem) => {
|
|||||||
const existingRow = orderBox
|
const existingRow = orderBox
|
||||||
.find('tr')
|
.find('tr')
|
||||||
.filterByData('item', orderItem.item)
|
.filterByData('item', orderItem.item)
|
||||||
.filterByData('print_group', orderItem.print_group)
|
.filterByData('print_group', orderItem.print_group_id)
|
||||||
.filterByData('cover', orderItem.cover)
|
.filterByData('cover', orderItem.cover)
|
||||||
.last()
|
.last()
|
||||||
|
|
||||||
@@ -186,13 +184,13 @@ const addInstructionToOrderBox = (instruction: orderItem) => {
|
|||||||
|
|
||||||
|
|
||||||
const addNewItem = (item: item, qty = 1) => {
|
const addNewItem = (item: item, qty = 1) => {
|
||||||
const salesCategory = OrderScreen.sales_categories.where('id', item.item_category)
|
const salesCategory = OrderScreen.sales_categories.where('id', item.sales_category_id)
|
||||||
const printGroup = OrderScreen.print_group_override ?? OrderScreen.print_groups.where('id', salesCategory.print_group)
|
const printGroup = OrderScreen.print_group_override ?? OrderScreen.print_groups.where('id', salesCategory.print_group_id)
|
||||||
const orderItem : orderItem = {
|
const orderItem : orderItem = {
|
||||||
id: OrderScreen.order_item_id_generator.next().value,
|
id: OrderScreen.order_item_id_generator.next().value,
|
||||||
item: item,
|
item: item,
|
||||||
qty: qty,
|
qty: qty,
|
||||||
print_group: printGroup,
|
print_group_id: printGroup,
|
||||||
cover: OrderScreen.selected_cover,
|
cover: OrderScreen.selected_cover,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,11 +221,11 @@ const getLastInstructionRow = (row: JQuery) => {
|
|||||||
return $(finalRow)
|
return $(finalRow)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getParentRow = (row: JQuery) => {
|
const getParentRow = (row: JQuery) =>
|
||||||
return row.hasClass('instructionRow')
|
row.hasClass('instructionRow')
|
||||||
? row.prevAll('.itemRow').first()
|
? row.prevAll('.itemRow').first()
|
||||||
: row
|
: row
|
||||||
}
|
|
||||||
|
|
||||||
const incrementRowQty = (row: JQuery, qty: number) => {
|
const incrementRowQty = (row: JQuery, qty: number) => {
|
||||||
const existingQty = Number(row.getColumnValue(lang('qty_header')))
|
const existingQty = Number(row.getColumnValue(lang('qty_header')))
|
||||||
@@ -258,17 +256,17 @@ const renderOrderBox = () => {
|
|||||||
const createOrderRow = (orderItem: orderItem) => {
|
const createOrderRow = (orderItem: orderItem) => {
|
||||||
const row = $('.orderBoxTable').EmptyRow()
|
const row = $('.orderBoxTable').EmptyRow()
|
||||||
const price = money(orderItem.item.price1)
|
const price = money(orderItem.item.price1)
|
||||||
const itemCellText = $('<span/>').text(orderItem.item.item_name)
|
const itemCellText = $('<span/>').text(orderItem.item.name)
|
||||||
row
|
row
|
||||||
.addClass(`${orderItem.item.item_type}Row`)
|
.addClass(`${orderItem.item.item_type}Row`)
|
||||||
.setColumnValue(lang('qty_header'), orderItem.qty)
|
.setColumnValue(lang('qty_header'), orderItem.qty)
|
||||||
.setColumnValue(lang('price_header'), price)
|
.setColumnValue(lang('price_header'), price)
|
||||||
.setColumnValue(lang('id_header'), orderItem.item.id)
|
.setColumnValue(lang('id_header'), orderItem.item.id)
|
||||||
.setColumnValue(lang('total_price_header'), price.multiply(orderItem.qty))
|
.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('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('cover', orderItem.cover)
|
||||||
.data('item', orderItem.item)
|
.data('item', orderItem.item)
|
||||||
.find('td.itemCell')
|
.find('td.itemCell')
|
||||||
@@ -306,7 +304,6 @@ const gridButtonClicked = (e: JQuery.TriggeredEvent) => {
|
|||||||
ajax(`/order/getGridHtml/${grid}`, null, null,gridHtmlGenerated, null, null)
|
ajax(`/order/getGridHtml/${grid}`, null, null,gridHtmlGenerated, null, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const hideGrids = () => $('.gridContainer').hide()
|
const hideGrids = () => $('.gridContainer').hide()
|
||||||
|
|
||||||
|
|
||||||
@@ -319,17 +316,17 @@ const gridHtmlGenerated = (gridData: {gridHtml:string, grid: grid}) => {
|
|||||||
|
|
||||||
gridContainer
|
gridContainer
|
||||||
.show()
|
.show()
|
||||||
.width(gridCellWidth * grid.grid_cols)
|
.width(gridCellWidth * grid.cols)
|
||||||
.children('.gridContainerHeader')
|
.children('.gridContainerHeader')
|
||||||
.children('span')
|
.children('span')
|
||||||
.text(grid.grid_name)
|
.text(grid.name)
|
||||||
.parent()
|
.parent()
|
||||||
.parent()
|
.parent()
|
||||||
.find('.pageGroup')
|
.find('.pageGroup')
|
||||||
.html(gridHtml)
|
.html(gridHtml)
|
||||||
.show()
|
.show()
|
||||||
.parent()
|
.parent()
|
||||||
.height(gridCellHeight * grid.grid_rows)
|
.height(gridCellHeight * grid.rows)
|
||||||
.closest('.gridContainer')
|
.closest('.gridContainer')
|
||||||
.find('.pageNavigation')
|
.find('.pageNavigation')
|
||||||
.toggle(gridContainer.find('.gridPage').length > 1)
|
.toggle(gridContainer.find('.gridPage').length > 1)
|
||||||
@@ -426,6 +423,7 @@ const getTotalOfRows = (rows: JQuery) => {
|
|||||||
|
|
||||||
const getQty = (row: JQuery) => Number(row.getColumnValue(lang('qty_header')))
|
const getQty = (row: JQuery) => Number(row.getColumnValue(lang('qty_header')))
|
||||||
const getUnitPrice = (row: JQuery) => moneyFromString(row.getColumnValue(lang('price_header')))
|
const getUnitPrice = (row: JQuery) => moneyFromString(row.getColumnValue(lang('price_header')))
|
||||||
|
|
||||||
const calculateRowTotal = (row: JQuery) => {
|
const calculateRowTotal = (row: JQuery) => {
|
||||||
let price = getUnitPrice(row)
|
let price = getUnitPrice(row)
|
||||||
let qty = getQty(row)
|
let qty = getQty(row)
|
||||||
@@ -495,7 +493,7 @@ const freetextSubmitted = (text: string) => {
|
|||||||
|
|
||||||
const item = Object.assign({}, OrderScreen.custom_item)
|
const item = Object.assign({}, OrderScreen.custom_item)
|
||||||
item.item_type = 'instruction'
|
item.item_type = 'instruction'
|
||||||
item.item_name = text
|
item.name = text
|
||||||
|
|
||||||
addNewItem(item)
|
addNewItem(item)
|
||||||
|
|
||||||
@@ -509,7 +507,7 @@ const customItemTextSubmitted = (text: string) => {
|
|||||||
|
|
||||||
const item = Object.assign({}, OrderScreen.custom_item)
|
const item = Object.assign({}, OrderScreen.custom_item)
|
||||||
item.item_type = 'item'
|
item.item_type = 'item'
|
||||||
item.item_name = text
|
item.name = text
|
||||||
item.price1 = price.intValue
|
item.price1 = price.intValue
|
||||||
|
|
||||||
addNewItem(item)
|
addNewItem(item)
|
||||||
@@ -600,5 +598,7 @@ const generateCoverSelector = () => {
|
|||||||
|
|
||||||
$(() => {
|
$(() => {
|
||||||
OrderScreen.table = $('#pageContainer').data('table') || null
|
OrderScreen.table = $('#pageContainer').data('table') || null
|
||||||
ajax('/order/getOrderScreenData/1', null, 'get', setupOrderScreen, null, null)
|
$('.coverSelector, .gridContainer').hide()
|
||||||
|
if(OrderScreen.table)
|
||||||
|
ajax(`/order/getOrderScreenData/${OrderScreen.table.table_number}`, null, 'get', setupOrderScreen, null, null)
|
||||||
})
|
})
|
||||||
@@ -228,7 +228,6 @@ let showVirtualNumpad = (heading: string, maxlength = 4, isPassword: boolean, al
|
|||||||
index = index + 1
|
index = index + 1
|
||||||
|
|
||||||
let currentRow : string[] = layoutToLoad[`row${index}${modifier}`]
|
let currentRow : string[] = layoutToLoad[`row${index}${modifier}`]
|
||||||
|
|
||||||
$(row).children('a').each((keyIndex, button) => {
|
$(row).children('a').each((keyIndex, button) => {
|
||||||
let key = $(button);
|
let key = $(button);
|
||||||
let keyValue: string = currentRow[keyIndex];
|
let keyValue: string = currentRow[keyIndex];
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ interface order {
|
|||||||
interface orderItem {
|
interface orderItem {
|
||||||
id: number
|
id: number
|
||||||
qty: number
|
qty: number
|
||||||
print_group: print_group
|
print_group_id: print_group
|
||||||
item: item
|
item: item
|
||||||
cover: number
|
cover: number
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ interface orderItem {
|
|||||||
interface print_group {
|
interface print_group {
|
||||||
id: number,
|
id: number,
|
||||||
name: string,
|
name: string,
|
||||||
printer: number,
|
printer_id: number,
|
||||||
venue_id: number,
|
venue_id: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,21 +50,21 @@ interface floorplan_table {
|
|||||||
id: number
|
id: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface decoration {
|
interface floorplan_decoration {
|
||||||
id: number
|
id: number
|
||||||
decoration_room: number
|
room_id: number
|
||||||
decoration_pos_x: number
|
pos_x: number
|
||||||
decoration_pos_y: number
|
pos_y: number
|
||||||
decoration_rotation: number
|
rotation: number
|
||||||
decoration_width: number
|
width: number
|
||||||
decoration_height: number
|
height: number
|
||||||
decoration_image: string
|
image: string
|
||||||
venue_id: number
|
venue_id: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface room {
|
interface room {
|
||||||
id: number
|
id: number
|
||||||
room_name: string
|
name: string
|
||||||
background_image: string
|
background_image: string
|
||||||
venue_id: number
|
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 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 {
|
interface item {
|
||||||
id: number
|
id: number
|
||||||
item_code: string
|
code: string
|
||||||
item_category: number
|
sales_category_id: number
|
||||||
item_name: string
|
name: string
|
||||||
item_type: string
|
item_type: string
|
||||||
price1: number
|
price1: number
|
||||||
price2: number
|
|
||||||
price3: number
|
|
||||||
price4: number
|
|
||||||
price5: number
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type sales_category = {
|
type sales_category = {
|
||||||
id: number
|
id: number
|
||||||
parent: number
|
parent: number
|
||||||
name: string
|
name: string
|
||||||
print_group: string
|
print_group_id: string
|
||||||
venue_id: number
|
venue_id: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
<div id="alert" >
|
|
||||||
<div id="alertHeading"></div>
|
|
||||||
<div id="alertMessage"></div>
|
|
||||||
<div id="alertButtons">
|
|
||||||
<a class="posButton" id="alertOk"><!--[lang:alert_ok]--></a>
|
|
||||||
<a class="posButton" id="alertYes"><!--[lang:alert_yes]--></a>
|
|
||||||
<a class="posButton" id="alertNo"><!--[lang:alert_no]--></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title><!--[var:title]--></title>
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
||||||
<meta name = "viewport" content = "user-scalable = no, initial-scale=0.8,maximum-scale=0.8 ,shrink-to-fit=yes" />
|
|
||||||
<link rel="manifest" href="/manifest.webmanifest">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="authenticator">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!--[template:keyboards]-->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>DredgePOS</title>
|
|
||||||
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
|
|
||||||
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="themes/restaurant/theme.css?id=ax" media="screen" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="themes/restaurant/paymentSplitter.css?id=ax" media="screen" />
|
|
||||||
<meta name = "viewport" content = "width=1280, initial-scale = 0.8, user-scalable = no, shrink-to-fit=no" />
|
|
||||||
<script type="text/javascript" src="currency.min.js"></script>
|
|
||||||
<script type="text/javascript" src="posFunctions.js"></script>
|
|
||||||
<script type="text/javascript" src="paymentFunctions.js"></script>
|
|
||||||
</head>
|
|
||||||
<body class="darkMode">
|
|
||||||
<div id="pageContainer">
|
|
||||||
<div id="flexWrapper">
|
|
||||||
<div id="header">
|
|
||||||
<h1>Paying Table</h2>
|
|
||||||
</div>
|
|
||||||
<div id="stucture">
|
|
||||||
<div id="leftColumn">
|
|
||||||
<h2>Whole Table</h2>
|
|
||||||
<table id="first" cellspacing="0">
|
|
||||||
<thead>
|
|
||||||
<th class="hide">Item Code</th>
|
|
||||||
<th>Qty</th>
|
|
||||||
<th>Item</th>
|
|
||||||
<th class="hide">Unit Price</th>
|
|
||||||
<th class="hide">Print Group</th>
|
|
||||||
<th class="totalpriceCell">Total Price</th>
|
|
||||||
<th class="hide">Cover</th>
|
|
||||||
<th class="clerkCell">Clerk</th>
|
|
||||||
<th class="hide">Selected Qty</th>
|
|
||||||
<th class="hide">Original Qty</th>
|
|
||||||
<th class="hide">Category</th>
|
|
||||||
<th class="hide">Department</th>
|
|
||||||
<th class="hide"><!--[lang:has_split_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:orig_tprice_header]--></th>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<!--[var:tableHTML]-->
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div id="controlColumn">
|
|
||||||
<a class="posButton" onclick="moveItems('#first', '#second')">></a>
|
|
||||||
<a class="posButton" onclick="moveItems('#second', '#first')"><</a>
|
|
||||||
</div>
|
|
||||||
<div id="centerColumn">
|
|
||||||
<h2>Partial Table</h2>
|
|
||||||
<table id="second" cellspacing="0">
|
|
||||||
<thead>
|
|
||||||
<th class="hide">Item Code</th>
|
|
||||||
<th>Qty</th>
|
|
||||||
<th>Item</th>
|
|
||||||
<th class="hide">Unit Price</th>
|
|
||||||
<th class="hide">Print Group</th>
|
|
||||||
<th class="totalpriceCell">Total Price</th>
|
|
||||||
<th class="hide">Cover</th>
|
|
||||||
<th class="clerkCell hide">Clerk</th>
|
|
||||||
<th class="hide">Selected Qty</th>
|
|
||||||
<th class="hide">Category</th>
|
|
||||||
<th class="hide">Department</th>
|
|
||||||
<th class="hide"><!--[lang:has_split_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:orig_tprice_header]--></th>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div id="rightColumn">
|
|
||||||
<h2>Controls</h2>
|
|
||||||
<div id="rightColumnContainer">
|
|
||||||
<a class="posButton heading" onclick="">Selection Tools</a>
|
|
||||||
<a class="posButton qtySelector" onclick="overrideQuantitySelect()">Select Quantity</a>
|
|
||||||
<a class="posButton" onclick="overrideQuantitySelect()">Select Amount</a>
|
|
||||||
<a class="selectDepartment posButton">Select By Department</a>
|
|
||||||
<a class="selectCategory posButton">Select By Category</a>
|
|
||||||
<a class="selectCovers posButton">Select by Cover #</a>
|
|
||||||
<a class="selectPrintGroup posButton">Select by Printed With</a>
|
|
||||||
<a class="selectAll posButton">Select All</a>
|
|
||||||
<a class="posButton heading">Select By Fraction</a>
|
|
||||||
<a class="posButton selectFraction" data-value="2">Select 1⁄2</a>
|
|
||||||
<a class="posButton selectFraction" data-value="3">Select 1⁄3</a>
|
|
||||||
<a class="posButton selectFraction" data-value="4">Select 1⁄4</a>
|
|
||||||
<a class="posButton selectFraction" data-value="5">Select 1⁄5</a>
|
|
||||||
<a class="posButton selectFraction" data-value="6">Select 1⁄6</a>
|
|
||||||
<a class="posButton selectFraction" data-value="7">Select 1⁄7</a>
|
|
||||||
<a class="posButton selectFraction" data-value="8">Select 1⁄8</a>
|
|
||||||
<a class="posButton selectFraction" data-value="<!--[var:uniqueCovers]-->" posButton">Select 1⁄covers</a>
|
|
||||||
|
|
||||||
<a class="posButton heading" onclick="loadScreen('tableMap')">Exit</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="coverControls" class="popupBox"><!--[var:coverButtons]--></div>
|
|
||||||
<div id="departmentControl" class="popupBox"><!--[var:departmentButtons]--></div>
|
|
||||||
<div id="categoryControl" class="popupBox"><!--[var:categoryButtons]--></div>
|
|
||||||
<div id="printGroupControl" class="popupBox"><!--[var:printGroupButtons]--></div>
|
|
||||||
<!--[template:keyboards]-->
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(document).ready( function () {
|
|
||||||
covers = '<!--[var:covers]-->'
|
|
||||||
dredgePosSetup('#pageContainer');
|
|
||||||
setupPaymentSplitter();
|
|
||||||
} );
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<div class="itemCellWrapper">
|
|
||||||
<div
|
|
||||||
class="definedButton item <!--[arr:item|button_classes]--> posButton"
|
|
||||||
data-type="<!--[arr:item|type]-->"
|
|
||||||
data-id="<!--[arr:item|itemid]-->"
|
|
||||||
data-grid="<!--[arr:item|button_grid_id]-->"
|
|
||||||
data-name="<!--[arr:item|itemname]-->"
|
|
||||||
data-price="<!--[arr:item|price]-->"
|
|
||||||
data-category="<!--[arr:item|c_name]-->"
|
|
||||||
data-department="<!--[arr:item|dep_name]-->"
|
|
||||||
data-printgroup="<!--[arr:item|pg_name]-->">
|
|
||||||
<a><!--[arr:item|itemname]--></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<div class="itemCellWrapper"> <div
|
|
||||||
class="definedButton item hasImage <!--[arr:item|button_classes]--> posButton"
|
|
||||||
data-type="<!--[arr:item|type]-->"
|
|
||||||
data-id="<!--[arr:item|itemid]-->"
|
|
||||||
data-name="<!--[arr:item|itemname]-->"
|
|
||||||
data-price="<!--[arr:item|price]-->"
|
|
||||||
data-grid="<!--[arr:item|button_grid_id]-->"
|
|
||||||
data-category="<!--[arr:item|c_name]-->"
|
|
||||||
data-department="<!--[arr:item|dep_name]-->"
|
|
||||||
data-printgroup="<!--[arr:item|pg_name]-->">
|
|
||||||
<a style="background-image:url('images/<!--[arr:item|image]-->')"></a>
|
|
||||||
<a><!--[arr:item|itemname]--></a>
|
|
||||||
|
|
||||||
</div></div>
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
<div class="itemPage">
|
|
||||||
<table cellspacing="0" cellpadding="0">
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:CRAFTBEER001]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER002]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER003]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER004]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER005]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER006]--></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:CRAFTBEER007]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER008]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER009]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER010]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER012]--></td>
|
|
||||||
<td><!--[button:INSTRUCTION005]--></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td><!--[button:INSTRUCTION006]--></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:CRAFTBEER013]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER014]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER015]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER016]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER017]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER018]--></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:CRAFTBEER019]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER020]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER021]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER022]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER023]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER024]--></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
</table></div>
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
<div class="itemPage">
|
|
||||||
<table cellspacing="0" cellpadding="0">
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:CRAFTBEER025]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER026]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER027]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER028]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER029]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER030]--></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:CRAFTBEER031]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER032]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER033]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER034]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER035]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER036]--></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:CRAFTBEER037]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER038]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER039]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER040]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER041]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER042]--></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:CRAFTBEER043]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER044]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER045]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER046]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER047]--></td>
|
|
||||||
<td><!--[button:CRAFTBEER048]--></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
</table></div>
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
<div class="itemPage"><table cellspacing="0" cellpadding="0">
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:DESSERT001]--></td>
|
|
||||||
<td></td>
|
|
||||||
<td><!--[button:DESSERT002]--></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td><!--[button:DESSERT004]--></td>
|
|
||||||
<td></td>
|
|
||||||
<td><!--[button:DESSERT003]--></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
</table></div>
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
<div class="itemPage"><table cellspacing="0" cellpadding="0">
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:MAIN001]--></td>
|
|
||||||
<td></td>
|
|
||||||
<td><!--[button:MAIN003]--></td>
|
|
||||||
<td></td>
|
|
||||||
<td><!--[button:MAIN004]--></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:MAIN005]--></td>
|
|
||||||
<td></td>
|
|
||||||
<td><!--[button:MAIN006]--></td>
|
|
||||||
<td></td>
|
|
||||||
<td><!--[button:MAIN007]--></td>
|
|
||||||
<td></td>
|
|
||||||
</td>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</table></div>
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
<div class="itemPage">
|
|
||||||
<table cellspacing="0" cellpadding="0">
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:STARTER001]--></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:STARTER002]--></td>
|
|
||||||
<td></td>
|
|
||||||
<td><!--[button:DIP002]--></td>
|
|
||||||
<td><!--[button:DIP003]--></td>
|
|
||||||
<td><!--[button:DIP004]--></td>
|
|
||||||
<td><!--[button:DIP005]--></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:STARTER003]--></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:STARTER004]--></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><!--[button:STARTER005]--></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</table></div>
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
<div class="itemPage"><table cellspacing="0" cellpadding="0">
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td><!--[button:WINE002]--></td>
|
|
||||||
<td><!--[button:WINE001]--></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td><!--[button:WINE004]--></td>
|
|
||||||
<td><!--[button:WINE003]--></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</td>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</table></div>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<a onclick="loadCategory('<!--[arr:cat|c_name]-->')" class="posButton categoryButton">
|
|
||||||
<!--[arr:cat|c_name]-->
|
|
||||||
</a>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<!--[categoryButton:1]-->
|
|
||||||
<!--[categoryButton:2]-->
|
|
||||||
<!--[categoryButton:4]-->
|
|
||||||
<!--[categoryButton:3]-->
|
|
||||||
<!--[categoryButton:5]-->
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<a class="posButton <!--[var:classes]-->" <!--[var: attributes]-->>
|
|
||||||
<!--[var:text]-->
|
|
||||||
</a>
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<div class="decoratorItem" data-image="<!--[var:image_url]-->">
|
|
||||||
<a style="background-image:url('/images/decorations/<!--[var:image_url]-->')"></a>
|
|
||||||
<a><!--[var:image_name]--></a>
|
|
||||||
</div>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<div class="decoratorRow">
|
|
||||||
<!--[var:decorations]-->
|
|
||||||
</div>
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>DredgePOS</title>
|
|
||||||
<script src="https://unpkg.com/current-device/umd/current-device.min.js"></script>
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
||||||
<meta name = "viewport" content = "user-scalable = no, initial-scale=0.8,maximum-scale=0.8 ,shrink-to-fit=yes" />
|
|
||||||
<link rel="manifest" href="/manifest.webmanifest">
|
|
||||||
</head>
|
|
||||||
<body class="darkMode">
|
|
||||||
<div id="pageContainer">
|
|
||||||
<div id="floorplanLeftColumn">
|
|
||||||
<div class="topCell">
|
|
||||||
<a class="posHeader">Logged in as <!--[arr:clerk|clerk_name]--></a>
|
|
||||||
</div>
|
|
||||||
<div class="middleCell">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="bottomCell">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="floorplanCenterColumn">
|
|
||||||
<div class="topCell">
|
|
||||||
<!--[var:roomMenu]-->
|
|
||||||
</div>
|
|
||||||
<div class="middleCell">
|
|
||||||
<div id="floorplanCanvas"></div>
|
|
||||||
</div>
|
|
||||||
<div class="bottomCell">
|
|
||||||
<div class="editControls" data-visible-in-mode='["tableSelected"]'>
|
|
||||||
<div class="posHeader currentTable">
|
|
||||||
<b class="selectedTableNumber"></b>
|
|
||||||
<a class="reservationStatus" data-visible-in-mode='["reservedTableSelected"]'></a>
|
|
||||||
<small class="selectedTableCovers"></small>
|
|
||||||
</div>
|
|
||||||
<a class="posButton placeOrderButton"><!--[lang:order_table]--></a>
|
|
||||||
<a class="posButton reserveTableButton" data-invisible-in-mode='["reservedTableSelected", "activeTableSelected"]'><!--[lang:reserve_table]--></a>
|
|
||||||
<a class="posButton unreserveTableButton" data-visible-in-mode='["reservedTableSelected"]'><!--[lang:unreserve_table]--></a>
|
|
||||||
<a class="posButton payTableButton" data-visible-in-mode='["activeTableSelected"]'><!--[lang:pay_table]--></a>
|
|
||||||
<a class="posButton viewTableButton" data-visible-in-mode='["activeTableSelected"]'><!--[lang:view_table]--></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="floorplanRightColumn">
|
|
||||||
<div class="topCell">
|
|
||||||
<a class="posButton logOut" onclick="logout()">×</a>
|
|
||||||
</div>
|
|
||||||
<div class="middleCell">
|
|
||||||
<a class="posButton editModeButton"><!--[lang:edit_floorplan]--></a>
|
|
||||||
<div class="floorplanControls useVisibility" data-visible-in-mode='["edit"]'>
|
|
||||||
<a class="posButton addTableButton" ><!--[lang:add_table]--></a>
|
|
||||||
<a class="posButton addDecoration"><!--[lang:add_decoration]--></a>
|
|
||||||
<a class="posButton deleteDecoration useVisibility" data-visible-in-mode='["decorationSelected", "edit"]'><!--[lang:delete_decoration]--></a>
|
|
||||||
<a class="posButton deleteTableButton useVisibility" data-visible-in-mode='["tableSelected", "edit"]'><!--[lang:delete_table]--></a>
|
|
||||||
<a class="posButton changeShapeButton useVisibility" data-visible-in-mode='["tableSelected", "edit"]'><!--[lang:change_shape]--></a>
|
|
||||||
</div>
|
|
||||||
<div class="mergeControls useVisibility" data-visible-in-mode='["tableSelected"]'>
|
|
||||||
<a class="posButton mergeButton" data-active-in-mode="merge"><!--[lang:merge_table]--></a>
|
|
||||||
<a class="posButton unmergeButton" data-visible-in-mode='["tableSelected"]'><!--[lang:unmerge_table]--></a>
|
|
||||||
<a class="transferTableButton posButton" data-active-in-mode="transfer" data-visible-in-mode='["activeTableSelected"]'><!--[lang:transfer_table]--></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bottomCell">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!--[template:keyboards]-->
|
|
||||||
<div id="decorator">
|
|
||||||
<div id="decoratorHeader">
|
|
||||||
<h2><!--[lang:choose_decoration]--></h2>
|
|
||||||
<a class="posButton" onclick="$('#decorator').css('display','none')">×</a>
|
|
||||||
</div>
|
|
||||||
<div id="decoratorContent"><!--[var:decorator]--></div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<!--[template:alert]-->
|
|
||||||
<!--[template:virtualNumpad]-->
|
|
||||||
<!--[template:virtualKeyboard]-->
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<b>OrderBox Loaded</b>
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<table cellspacing="0" id="orderBox" data-tablenumber="<!--[var:tableNumber]-->" data-covers="<!--[var:covers]-->" data-clerk="<!--[arr:clerk|clerk_name]-->" class="">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="idCell hide"><!--[lang:id_header]--></th>
|
|
||||||
<th class="qtyCell"><!--[lang:qty_header]--></th>
|
|
||||||
<th class="itemCell"><!--[lang:item_header]--></th>
|
|
||||||
<th class="totalPriceCell"><!--[lang:total_price_header]--></th>
|
|
||||||
<th class="printGroupCell"><!--[lang:printgroup_header]--></th>
|
|
||||||
<th class="unitPriceCell hide"><!--[lang:individual_price_header]--></th>
|
|
||||||
<th class="sortkeyCell hide"><!--[lang:sortkey_header]--></th>
|
|
||||||
<th class="typeCell hide"><!--[lang:type_header]--></th>
|
|
||||||
<th class="coverCell hide"><!--[lang:cover_header]--></th>
|
|
||||||
<th class="departmentCell hide"><!--[lang:department_header]--></th>
|
|
||||||
<th class="categoryCell hide"><!--[lang:category_header]--></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>DredgePOS</title>
|
|
||||||
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
|
|
||||||
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="themes/restaurant/theme.css?id=ax" media="screen" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="themes/restaurant/screen.css?id=ax" media="screen" />
|
|
||||||
<meta name = "viewport" content = "width=1280, initial-scale = 0.8, user-scalable = no, shrink-to-fit=no" />
|
|
||||||
<script type="text/javascript" src="posFunctions.js"></script>
|
|
||||||
</head>
|
|
||||||
<body class="darkMode">
|
|
||||||
<div id="pageContainer">
|
|
||||||
<div id="leftColumn">
|
|
||||||
<div id="tableDetails">
|
|
||||||
<h2><span id="activeTable"><!--[var:activeTable]--></span></h2>
|
|
||||||
<p class="posButton coverNumbers"><span id="covers"><!--[var:covers]--></span> covers </p>
|
|
||||||
<p class="clerk"><!--[var:loggedInAs]--></p>
|
|
||||||
</div>
|
|
||||||
<div id="orderBoxContainer">
|
|
||||||
<!--[template:orderBoxTable]-->
|
|
||||||
</div>
|
|
||||||
<div id="leftColumnFooter">
|
|
||||||
<p class="messageBox"></p>
|
|
||||||
<h2>Total Price: <span class="orderBoxTotals">$0.00</span></h2>
|
|
||||||
<p class="selectedTotal">($0.00 Selected)</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="rightColumn">
|
|
||||||
<div id="topHalf">
|
|
||||||
<div id="courseSelect" class="posButtonGroup">
|
|
||||||
<h2><!--[lang:print_with]--></h2>
|
|
||||||
<a onclick="setPrintGroupOverride(false, this)" class="toggle default posButton active"><!--[lang:print_with_category|default]--></a>
|
|
||||||
<a onclick="setPrintGroupOverride('Starters',this)" class="posButton toggle"><!--[lang:print_with_category|Starters]--></a>
|
|
||||||
<a onclick="setPrintGroupOverride('Mains',this)" class="posButton toggle"><!--[lang:print_with_category|Mains]--></a>
|
|
||||||
<a onclick="setPrintGroupOverride('Desserts',this)" class="posButton toggle"><!--[lang:print_with_category|Desserts]--></a>
|
|
||||||
<a onclick="setPrintGroupOverride('Drinks',this)" class="posButton toggle"><!--[lang:print_with_category|Drinks]--></a>
|
|
||||||
</div>
|
|
||||||
<div id="functions">
|
|
||||||
<h2><!--[lang:functions_header]--></h2>
|
|
||||||
<a onclick="loadScreen('tableMap')" class="posButton"><!--[lang:close_order_function]--></a>
|
|
||||||
<a class="posButton accumulateButton"><!--[lang:accumulate_function]--></a>
|
|
||||||
<a class="posButton void"><!--[lang:void]--></a>
|
|
||||||
<a class="posButton"><!--[lang:pay_function]--></a>
|
|
||||||
<a class="posButton saveOrder"><!--[lang:print_function]--></a>
|
|
||||||
</div>
|
|
||||||
<div id="positionControl">
|
|
||||||
<a class="posButton freeText" data-type="instruction" data-id="freetext"
|
|
||||||
data-name=""
|
|
||||||
data-price="0"
|
|
||||||
data-category="0"
|
|
||||||
data-department="0"
|
|
||||||
data-printgroup="0"><!--[lang:freetext_button]--></a>
|
|
||||||
<div type="text" class="positionInput"><!--[lang:select_covers]--></div>
|
|
||||||
<div id="positions">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="topNumPad" class="numPad">
|
|
||||||
<a class="posButton numberButton">1</a>
|
|
||||||
<a class="posButton numberButton">2</a>
|
|
||||||
<a class="posButton numberButton">3</a>
|
|
||||||
<a class="posButton numberButton">4</a>
|
|
||||||
<a class="posButton numberButton">5</a>
|
|
||||||
<a class="posButton numberButton">6</a>
|
|
||||||
<a class="posButton numberButton">7</a>
|
|
||||||
<a class="posButton numberButton">8</a>
|
|
||||||
<a class="posButton numberButton">9</a>
|
|
||||||
<a class="posButton numberButton">0</a>
|
|
||||||
<a class="posButton numberButton">.</a>
|
|
||||||
<a class="posButton multiplier">×</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="bottomHalf">
|
|
||||||
<!--[template:categoryMenu]-->
|
|
||||||
<div id="itemGrid">
|
|
||||||
<div id="itemWrapper">
|
|
||||||
<!--[template:categories/StartersPage1]-->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="innerNavigation">
|
|
||||||
<a class="posButton" onclick="scrollPage('left')"><</a>
|
|
||||||
<a class="posButton" onclick="scrollPage('right')">></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--[template:keyboards]-->
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(document).ready( function () {
|
|
||||||
//Base grid width must be defined for multipage functionality to work.
|
|
||||||
baseGridWidth = 850;
|
|
||||||
dredgePosSetup();
|
|
||||||
|
|
||||||
$("#orderBox tbody tr").on( 'click', function ( e ) {
|
|
||||||
selectRow($(this));
|
|
||||||
} )
|
|
||||||
} );
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>DredgePOS</title>
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
||||||
<meta name = "viewport" content = "user-scalable = no ,shrink-to-fit=yes" />
|
|
||||||
<link rel="manifest" href="/manifest.webmanifest">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div id="pageContainer" <!--[var: containerAttributes]-->>
|
|
||||||
<div id="leftColumn">
|
|
||||||
<h1 class="tableHeading"><!--[var: orderNumber]--></h1>
|
|
||||||
<div class="tableInfo">
|
|
||||||
<!--[var: changeCoverNumberButton]-->
|
|
||||||
<a class="posButton">Logged in as <!--[arr:clerk|clerk_name]--></a>
|
|
||||||
</div>
|
|
||||||
<div class="orderBox">
|
|
||||||
<table class="orderBoxTable">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="orderBoxCell qtyCell"><!--[lang:qty_header]--></th>
|
|
||||||
<th class="orderBoxCell itemIdCell hidden"><!--[lang:id_header]--></th>
|
|
||||||
<th class="orderBoxCell itemCell"><!--[lang:item_header]--></th>
|
|
||||||
<th class="orderBoxCell unitPriceCell hidden"><!--[lang:price_header]--></th>
|
|
||||||
<th class="orderBoxCell totalPriceCell"><!--[lang:total_price_header]--></th>
|
|
||||||
<th class="orderBoxCell printGroupCell"><!--[lang:printgroup_header]--></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody></tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="orderBoxInfo">
|
|
||||||
<span class="voidModeWarning" data-visible-in-mode='["void"]'><!--[lang:void_mode]--></span>
|
|
||||||
</div>
|
|
||||||
<div class="orderBoxFooter">
|
|
||||||
<span class="orderBoxTotal"><!--[lang:totalPrice|0.00]--></span>
|
|
||||||
<small class="orderBoxSelectedTotal"><!--[lang:selectedPrice|0.00]--></small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="rightColumn">
|
|
||||||
<div id="topHalf">
|
|
||||||
<div class="functionButtons">
|
|
||||||
<div class="printGroupButtons toggleGroup">
|
|
||||||
<input type="hidden" name="print_override" class="value" />
|
|
||||||
<!--[var:salesCategoryOverrideButtons]-->
|
|
||||||
</div>
|
|
||||||
<div class="functionColumn">
|
|
||||||
<a class="posButton accumulateButton" data-active-in-mode="accumulate"><!--[lang:accumulate_function]--></a>
|
|
||||||
<a class="showCoverSelectorButton posButton"><!--[lang:select_covers]--></a>
|
|
||||||
</div>
|
|
||||||
<div class="functionColumn">
|
|
||||||
<a class="posButton voidButton" data-active-in-mode="void"><!--[lang:void]--></a>
|
|
||||||
<a class="posButton openItemButton"><!--[lang:custom_item_button]--></a>
|
|
||||||
<a class="freetextButton posButton"><!--[lang:freetext_button]--></a>
|
|
||||||
<a class="numpadButton posButton"><!--[lang:numpad_button]--></a>
|
|
||||||
</div>
|
|
||||||
<div class="functionColumn">
|
|
||||||
<a class="posButton"><!--[lang:pay_function]--></a>
|
|
||||||
<a class="posButton"><!--[lang:print_function]--></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="pageList">
|
|
||||||
<!--[var:categoryList]-->
|
|
||||||
</div>
|
|
||||||
<div id="pageGroupContainer">
|
|
||||||
<!--[var:pageGroups]-->
|
|
||||||
</div>
|
|
||||||
<div class="pageNavigation">
|
|
||||||
<a class="posButton prevButton"><!--[lang:prev_page]--></a>
|
|
||||||
<a class="posButton nextButton"><!--[lang:next_page]--></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--[template:keyboards]-->
|
|
||||||
<!--[template:orderScreen/grid_container]-->
|
|
||||||
<!--[template:orderScreen/cover_selector]-->
|
|
||||||
<template id="posButtonTemplate">
|
|
||||||
<!--[template:components/posButton]-->
|
|
||||||
</template>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<span class="buttonImg" style="background-image:url(/images/items/<!--[var:image]-->);"></span>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<a href="#" class="posButton changeCoverNumberButton"><!--[var:covers]--></a>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<div class="coverSelector">
|
|
||||||
<!--[var:coverSelectorButtons]-->
|
|
||||||
</div>
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<a href="#" class="posButton <!--[var:extra_classes]-->"
|
|
||||||
data-primary-action="<!--[var:primary_action]-->"
|
|
||||||
data-secondary-action="<!--[var:secondary_action]-->" <!--[var: extra_data]--> <!--[var: extra_styles]-->>
|
|
||||||
<!--[var:image]-->
|
|
||||||
<span class="text"><!--[var:text]--></span>
|
|
||||||
</a>
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
<div class="gridContainer">
|
|
||||||
<div class="gridContainerHeader">
|
|
||||||
<span></span>
|
|
||||||
<div class="posButton closeGrid">×</div>
|
|
||||||
</div>
|
|
||||||
<div class="gridContainerGrid">
|
|
||||||
<div class="pageGroup"></div>
|
|
||||||
</div>
|
|
||||||
<div class="pageNavigation">
|
|
||||||
<a class="posButton prevButton"><!--[lang:prev_page]--></a>
|
|
||||||
<a class="posButton nextButton"><!--[lang:next_page]--></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<div class="gridPage" style="
|
|
||||||
grid-template-columns: repeat(<!--[var:cols]-->, 1fr);
|
|
||||||
grid-template-rows: repeat(<!--[var:rows]-->, 1fr);
|
|
||||||
">
|
|
||||||
<!--[var:pageButtons]-->
|
|
||||||
</div>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<div class="pageGroup" data-page-group-id="<!--[var:page_group_id]-->">
|
|
||||||
<!--[var:pages]-->
|
|
||||||
</div>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<a data-page-group-id="<!--[arr:page|id]-->" class="posButton loadPageGroup">
|
|
||||||
<!--[arr:page|label]-->
|
|
||||||
</a>
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>DredgePOS</title>
|
|
||||||
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
|
|
||||||
<script src="https://unpkg.com/current-device/umd/current-device.min.js"></script>
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="themes/restaurant/theme.css?id=ax" media="screen" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="themes/restaurant/paymentSplitter.css?id=ax" media="screen" />
|
|
||||||
<meta name = "viewport" content = "user-scalable = no, initial-scale=0.8 ,shrink-to-fit=yes" />
|
|
||||||
<script type="text/javascript" src="currency.min.js"></script>
|
|
||||||
<script type="text/javascript" src="posFunctions.js"></script>
|
|
||||||
<script type="text/javascript" src="paymentFunctions.js"></script>
|
|
||||||
</head>
|
|
||||||
<body class="darkMode" data-tablenumber="<!--[var:activeTable]-->">
|
|
||||||
<div id="pageContainer">
|
|
||||||
<div id="flexWrapper">
|
|
||||||
<div id="header">
|
|
||||||
<a class="posButton"><!--[var:loggedInAs]--></a>
|
|
||||||
<h1><!--[lang:paying_table|<!--[var:activeTable]-->]--></h1>
|
|
||||||
<a class="posButton exit" onclick="loadScreen('tableMap')">×</a>
|
|
||||||
</div>
|
|
||||||
<div id="pageStructure">
|
|
||||||
<div id="leftColumn">
|
|
||||||
|
|
||||||
<h2>Whole Table</h2>
|
|
||||||
<div class="tableWrapper">
|
|
||||||
<table id="first" cellspacing="0">
|
|
||||||
<thead>
|
|
||||||
<th class="hide"><!--[lang:id_header]--></th>
|
|
||||||
<th><!--[lang:qty_header]--></th>
|
|
||||||
<th><!--[lang:item_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:individual_price_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:printgroup_header]--></th>
|
|
||||||
<th class="totalpriceCell"><!--[lang:total_price_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:cover_header]--></th>
|
|
||||||
<th class="clerkCell"><!--[lang:clerk_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:orig_qty_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:category_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:department_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:orig_tprice_header]--></th>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<!--[var:tableHTML]-->
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="tableFooter">
|
|
||||||
<div class="totalsRow">
|
|
||||||
<h3 class="firstTotal"></h3>
|
|
||||||
<p class="firstSelectedTotal"></p>
|
|
||||||
</div>
|
|
||||||
<div class="controlRow">
|
|
||||||
<a class="posButton payAll"><!--[lang:pay_all]--></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="controlColumn">
|
|
||||||
<a class="posButton" onclick="moveItems('#first', '#second')">></a>
|
|
||||||
<a class="posButton" onclick="moveItems('#second', '#first')"><</a>
|
|
||||||
</div>
|
|
||||||
<div id="centerColumn">
|
|
||||||
<h2>Partial Table</h2>
|
|
||||||
<div class="tableWrapper">
|
|
||||||
<table id="second" cellspacing="0">
|
|
||||||
<thead>
|
|
||||||
<th class="hide"><!--[lang:id_header]--></th>
|
|
||||||
<th><!--[lang:qty_header]--></th>
|
|
||||||
<th><!--[lang:item_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:individual_price_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:printgroup_header]--></th>
|
|
||||||
<th class="totalpriceCell"><!--[lang:total_price_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:cover_header]--></th>
|
|
||||||
<th class="clerkCell"><!--[lang:clerk_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:orig_qty_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:category_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:department_header]--></th>
|
|
||||||
<th class="hide"><!--[lang:orig_tprice_header]--></th>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="tableFooter">
|
|
||||||
<div class="totalsRow">
|
|
||||||
<h3 class="secondTotal"></h3>
|
|
||||||
<p class="secondSelectedTotal"></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="controlRow">
|
|
||||||
<a class="posButton payPartial"><!--[lang:pay_table]--></a>
|
|
||||||
<a class="posButton transferPartial">Transfer to Another Table</a>
|
|
||||||
<a class="posButton selectAllSecond">Select All</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="rightColumn">
|
|
||||||
<h2>Controls</h2>
|
|
||||||
<div id="rightColumnContainer">
|
|
||||||
<div class="row">
|
|
||||||
<a class="heading" onclick="">Selection Tools</a>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<a class="posButton qtySelector">Select Quantity</a>
|
|
||||||
<a class="posButton selectAmount">Select Amount</a>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<a class="selectDepartment posButton">Select By Department</a>
|
|
||||||
<a class="selectCategory posButton">Select By Category</a>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<a class="selectCovers posButton">Select by Cover #</a>
|
|
||||||
<a class="selectPrintGroup posButton">Select by Printed With</a>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<a class="selectAll posButton">Select All</a>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<a class="heading">Select By Fraction</a>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<a class="posButton selectFraction" data-value="2">Select 1⁄2</a>
|
|
||||||
<a class="posButton selectFraction" data-value="3">Select 1⁄3</a>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<a class="posButton selectFraction" data-value="4">Select 1⁄4</a>
|
|
||||||
<a class="posButton selectFraction" data-value="5">Select 1⁄5</a>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<a class="posButton selectFraction" data-value="6">Select 1⁄6</a>
|
|
||||||
<a class="posButton selectFraction" data-value="7">Select 1⁄7</a>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<a class="posButton selectFraction" data-value="8">Select 1⁄8</a>
|
|
||||||
<a class="posButton selectFraction" data-value="<!--[var:covers]-->">Select 1⁄covers</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="coverControls" class="popupBox"><!--[var:coverButtons]--></div>
|
|
||||||
<div id="departmentControl" class="popupBox"><!--[var:departmentButtons]--></div>
|
|
||||||
<div id="categoryControl" class="popupBox"><!--[var:categoryButtons]--></div>
|
|
||||||
<div id="printGroupControl" class="popupBox"><!--[var:printGroupButtons]--></div>
|
|
||||||
<!--[template:keyboards]-->
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(document).ready( function () {
|
|
||||||
covers = '<!--[var:covers]-->'
|
|
||||||
dredgePosSetup('#pageContainer');
|
|
||||||
setupPaymentSplitter();
|
|
||||||
} );
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<a data-value="<!--[var:value]-->" class="posButton <!--[var:class]-->"><!--[var:text]--></a>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<a class="posButton roomButton" data-value="<!--[var:roomId]-->"><!--[var:roomName]--></a>
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
<div id="virtualKeyboard">
|
|
||||||
<div class="headingRow">
|
|
||||||
<h3 id="virtualKeyboardHeading"></h3>
|
|
||||||
<a class="posButton closeKeyboards">X</a>
|
|
||||||
</div>
|
|
||||||
<input type="text" name="virtualKeyboardInput" id="virtualKeyboardInput" />
|
|
||||||
<div id="virtualKeyboardButtons">
|
|
||||||
<div class="virtualKeyboardRow">
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
</div>
|
|
||||||
<div class="virtualKeyboardRow">
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
</div>
|
|
||||||
<div class="virtualKeyboardRow">
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
</div>
|
|
||||||
<div class="virtualKeyboardRow">
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
<a></a>
|
|
||||||
</div>
|
|
||||||
<div class="virtualKeyboardRow">
|
|
||||||
<a></a>
|
|
||||||
</div>
|
|
||||||
<span class="forceFocus"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
<div id="virtualNumpad">
|
|
||||||
<div class="headingRow">
|
|
||||||
<h3 id="virtualNumpadHeading"></h3>
|
|
||||||
<a class="posButton closeKeyboards">X</a>
|
|
||||||
</div>
|
|
||||||
<div id="virtualNumpadInput"></div>
|
|
||||||
<div id="virtualNumpadButtons">
|
|
||||||
<div class="virtualNumpadRow">
|
|
||||||
<a href="#" data-value="1" class="posButton virtualNumpadButton">1</a>
|
|
||||||
<a href="#" data-value="2" class="posButton virtualNumpadButton">2</a>
|
|
||||||
<a href="#" data-value="3" class="posButton virtualNumpadButton">3</a>
|
|
||||||
</div><div class="virtualNumpadRow">
|
|
||||||
<a href="#" data-value="4" class="posButton virtualNumpadButton">4</a>
|
|
||||||
<a href="#" data-value="5" class="posButton virtualNumpadButton">5</a>
|
|
||||||
<a href="#" data-value="6" class="posButton virtualNumpadButton">6</a>
|
|
||||||
</div><div class="virtualNumpadRow">
|
|
||||||
<a href="#" data-value="7" class="posButton virtualNumpadButton">7</a>
|
|
||||||
<a href="#" data-value="8" class="posButton virtualNumpadButton">8</a>
|
|
||||||
<a href="#" data-value="9" class="posButton virtualNumpadButton">9</a>
|
|
||||||
</div><div class="virtualNumpadRow">
|
|
||||||
<a href="#" data-value="0" class="posButton virtualNumpadButton">0</a>
|
|
||||||
<a href="#" data-value="." class="posButton virtualNumpadButton">.</a>
|
|
||||||
<a href="#" data-value="clear" class="posButton virtualNumpadButton virtualNumpadClear">Clear</a>
|
|
||||||
</div><div class="virtualNumpadRow">
|
|
||||||
<a href="#" data-value="submit" class="posButton virtualNumpadButton virtualNumpadSubmit">Enter</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
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 |