Version 8 #43
|
@ -6,7 +6,7 @@ open PrayerTracker.ViewModels
|
||||||
|
|
||||||
/// View for the church edit page
|
/// View for the church edit page
|
||||||
let edit (m : EditChurch) ctx vi =
|
let edit (m : EditChurch) ctx vi =
|
||||||
let pageTitle = match m.IsNew with true -> "Add a New Church" | false -> "Edit Church"
|
let pageTitle = if m.IsNew then "Add a New Church" else "Edit Church"
|
||||||
let s = I18N.localizer.Force ()
|
let s = I18N.localizer.Force ()
|
||||||
[ form [ _action "/church/save"; _method "post"; _class "pt-center-columns" ] [
|
[ form [ _action "/church/save"; _method "post"; _class "pt-center-columns" ] [
|
||||||
style [ _scoped ] [
|
style [ _scoped ] [
|
||||||
|
|
|
@ -27,7 +27,7 @@ let space = rawText " "
|
||||||
let icon name = i [ _class "material-icons" ] [ rawText name ]
|
let icon name = i [ _class "material-icons" ] [ rawText name ]
|
||||||
|
|
||||||
/// Generate a Material Design icon, specifying the point size (must be defined in CSS)
|
/// Generate a Material Design icon, specifying the point size (must be defined in CSS)
|
||||||
let iconSized size name = i [ _class $"material-icons md-{size}" ] [ rawText name ]
|
let iconSized size name = i [ _class $"material-icons md-%i{size}" ] [ rawText name ]
|
||||||
|
|
||||||
/// Generate a CSRF prevention token
|
/// Generate a CSRF prevention token
|
||||||
let csrfToken (ctx : HttpContext) =
|
let csrfToken (ctx : HttpContext) =
|
||||||
|
@ -80,13 +80,11 @@ let namedColorList name selected attrs (s : IStringLocalizer) =
|
||||||
|
|
||||||
/// Generate an input[type=radio] that is selected if its value is the current value
|
/// Generate an input[type=radio] that is selected if its value is the current value
|
||||||
let radio name domId value current =
|
let radio name domId value current =
|
||||||
input
|
input [ _type "radio"
|
||||||
[ _type "radio"
|
_name name
|
||||||
_name name
|
_id domId
|
||||||
_id domId
|
_value value
|
||||||
_value value
|
if value = current then _checked ]
|
||||||
if value = current then _checked
|
|
||||||
]
|
|
||||||
|
|
||||||
/// Generate a select list with the current value selected
|
/// Generate a select list with the current value selected
|
||||||
let selectList name selected attrs items =
|
let selectList name selected attrs items =
|
||||||
|
@ -100,7 +98,7 @@ let selectList name selected attrs items =
|
||||||
|> select (List.concat [ [ _name name; _id name ]; attrs ])
|
|> select (List.concat [ [ _name name; _id name ]; attrs ])
|
||||||
|
|
||||||
/// Generate the text for a default entry at the top of a select list
|
/// Generate the text for a default entry at the top of a select list
|
||||||
let selectDefault text = $"— {text} —"
|
let selectDefault text = $"— %s{text} —"
|
||||||
|
|
||||||
/// Generate a standard submit button with icon and text
|
/// Generate a standard submit button with icon and text
|
||||||
let submit attrs ico text = button (_type "submit" :: attrs) [ icon ico; rawText " "; locStr text ]
|
let submit attrs ico text = button (_type "submit" :: attrs) [ icon ico; rawText " "; locStr text ]
|
||||||
|
@ -108,29 +106,13 @@ let submit attrs ico text = button (_type "submit" :: attrs) [ icon ico; rawText
|
||||||
|
|
||||||
open System
|
open System
|
||||||
|
|
||||||
|
// TODO: this is where to implement issue #1
|
||||||
/// Format a GUID with no dashes (used for URLs and forms)
|
/// Format a GUID with no dashes (used for URLs and forms)
|
||||||
let flatGuid (x : Guid) = x.ToString "N"
|
let flatGuid (x : Guid) = x.ToString "N"
|
||||||
|
|
||||||
/// An empty GUID string (used for "add" actions)
|
/// An empty GUID string (used for "add" actions)
|
||||||
let emptyGuid = flatGuid Guid.Empty
|
let emptyGuid = flatGuid Guid.Empty
|
||||||
|
|
||||||
|
|
||||||
/// blockquote tag
|
|
||||||
let blockquote = tag "blockquote"
|
|
||||||
|
|
||||||
/// role attribute
|
|
||||||
let _role = attr "role"
|
|
||||||
/// aria-* attribute
|
|
||||||
let _aria typ = attr $"aria-{typ}"
|
|
||||||
/// onclick attribute
|
|
||||||
let _onclick = attr "onclick"
|
|
||||||
/// onsubmit attribute
|
|
||||||
let _onsubmit = attr "onsubmit"
|
|
||||||
|
|
||||||
/// scoped flag (used for <style> tag)
|
|
||||||
let _scoped = flag "scoped"
|
|
||||||
|
|
||||||
|
|
||||||
/// The name this function used to have when the view engine was part of Giraffe
|
/// The name this function used to have when the view engine was part of Giraffe
|
||||||
let renderHtmlNode = RenderView.AsString.htmlNode
|
let renderHtmlNode = RenderView.AsString.htmlNode
|
||||||
|
|
||||||
|
|
|
@ -13,32 +13,32 @@ let error code vi =
|
||||||
let raw = rawLocText sw
|
let raw = rawLocText sw
|
||||||
let is404 = "404" = code
|
let is404 = "404" = code
|
||||||
let pageTitle = if is404 then "Page Not Found" else "Server Error"
|
let pageTitle = if is404 then "Page Not Found" else "Server Error"
|
||||||
[ yield!
|
[ yield!
|
||||||
if is404 then
|
if is404 then
|
||||||
[ p [] [
|
[ p [] [
|
||||||
raw l["The page you requested cannot be found."]
|
raw l["The page you requested cannot be found."]
|
||||||
raw l["Please use your “Back” button to return to {0}.", s["PrayerTracker"]]
|
raw l["Please use your “Back” button to return to {0}.", s["PrayerTracker"]]
|
||||||
]
|
]
|
||||||
p [] [
|
p [] [
|
||||||
raw l["If you reached this page from a link within {0}, please copy the link from the browser's address bar, and send it to support, along with the group for which you were currently authenticated (if any).",
|
raw l["If you reached this page from a link within {0}, please copy the link from the browser's address bar, and send it to support, along with the group for which you were currently authenticated (if any).",
|
||||||
s["PrayerTracker"]]
|
s["PrayerTracker"]]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
else
|
else
|
||||||
[ p [] [
|
[ p [] [
|
||||||
raw l["An error ({0}) has occurred.", code]
|
raw l["An error ({0}) has occurred.", code]
|
||||||
raw l["Please use your “Back” button to return to {0}.", s["PrayerTracker"]]
|
raw l["Please use your “Back” button to return to {0}.", s["PrayerTracker"]]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
br []
|
br []
|
||||||
hr []
|
hr []
|
||||||
div [ _style "font-size:70%;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen-Sans,Ubuntu,Cantarell,'Helvetica Neue',sans-serif" ] [
|
div [ _style "font-size:70%;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen-Sans,Ubuntu,Cantarell,'Helvetica Neue',sans-serif" ] [
|
||||||
img [ _src $"""/img/%A{s["footer_en"]}.png"""
|
img [ _src $"""/img/%A{s["footer_en"]}.png"""
|
||||||
_alt $"""%A{s["PrayerTracker"]} %A{s["from Bit Badger Solutions"]}"""
|
_alt $"""%A{s["PrayerTracker"]} %A{s["from Bit Badger Solutions"]}"""
|
||||||
_title $"""%A{s["PrayerTracker"]} %A{s["from Bit Badger Solutions"]}"""
|
_title $"""%A{s["PrayerTracker"]} %A{s["from Bit Badger Solutions"]}"""
|
||||||
_style "vertical-align:text-bottom;" ]
|
_style "vertical-align:text-bottom;" ]
|
||||||
str vi.Version
|
str vi.Version
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|> div []
|
|> div []
|
||||||
|> Layout.bare pageTitle
|
|> Layout.bare pageTitle
|
||||||
|
@ -51,72 +51,72 @@ let index vi =
|
||||||
use sw = new StringWriter ()
|
use sw = new StringWriter ()
|
||||||
let raw = rawLocText sw
|
let raw = rawLocText sw
|
||||||
|
|
||||||
[ p [] [
|
[ p [] [
|
||||||
raw l["Welcome to <strong>{0}</strong>!", s["PrayerTracker"]]
|
raw l["Welcome to <strong>{0}</strong>!", s["PrayerTracker"]]
|
||||||
space
|
space
|
||||||
raw l["{0} is an interactive website that provides churches, Sunday School classes, and other organizations an easy way to keep up with their prayer requests.",
|
raw l["{0} is an interactive website that provides churches, Sunday School classes, and other organizations an easy way to keep up with their prayer requests.",
|
||||||
s["PrayerTracker"]]
|
s["PrayerTracker"]]
|
||||||
space
|
space
|
||||||
raw l["It is provided at no charge, as a ministry and a community service."]
|
raw l["It is provided at no charge, as a ministry and a community service."]
|
||||||
]
|
]
|
||||||
h4 [] [ raw l["What Does It Do?"] ]
|
h4 [] [ raw l["What Does It Do?"] ]
|
||||||
p [] [
|
p [] [
|
||||||
raw l["{0} has what you need to make maintaining a prayer request list a breeze.", s["PrayerTracker"]]
|
raw l["{0} has what you need to make maintaining a prayer request list a breeze.", s["PrayerTracker"]]
|
||||||
space
|
space
|
||||||
raw l["Some of the things it can do..."]
|
raw l["Some of the things it can do..."]
|
||||||
]
|
]
|
||||||
ul [] [
|
ul [] [
|
||||||
li [] [
|
li [] [
|
||||||
raw l["It drops old requests off the list automatically."]
|
raw l["It drops old requests off the list automatically."]
|
||||||
space
|
space
|
||||||
raw l["Requests other than “{0}” requests will expire at 14 days, though this can be changed by the organization.",
|
raw l["Requests other than “{0}” requests will expire at 14 days, though this can be changed by the organization.",
|
||||||
s["Long-Term Requests"]]
|
s["Long-Term Requests"]]
|
||||||
space
|
space
|
||||||
raw l["This expiration is based on the last update, not the initial request."]
|
raw l["This expiration is based on the last update, not the initial request."]
|
||||||
space
|
space
|
||||||
raw l["(And, once requests do “drop off”, they are not gone - they may be recovered if needed.)"]
|
raw l["(And, once requests do “drop off”, they are not gone - they may be recovered if needed.)"]
|
||||||
]
|
]
|
||||||
li [] [
|
li [] [
|
||||||
raw l["Requests can be viewed any time."]
|
raw l["Requests can be viewed any time."]
|
||||||
space
|
space
|
||||||
raw l["Lists can be made public, or they can be secured with a password, if desired."]
|
raw l["Lists can be made public, or they can be secured with a password, if desired."]
|
||||||
]
|
]
|
||||||
li [] [
|
li [] [
|
||||||
raw l["Lists can be e-mailed to a pre-defined list of members."]
|
raw l["Lists can be e-mailed to a pre-defined list of members."]
|
||||||
space
|
space
|
||||||
raw l["This can be useful for folks who may not be able to write down all the requests during class, but want a list so that they can pray for them the rest of week."]
|
raw l["This can be useful for folks who may not be able to write down all the requests during class, but want a list so that they can pray for them the rest of week."]
|
||||||
space
|
space
|
||||||
raw l["E-mails are sent individually to each person, which keeps the e-mail list private and keeps the messages from being flagged as spam."]
|
raw l["E-mails are sent individually to each person, which keeps the e-mail list private and keeps the messages from being flagged as spam."]
|
||||||
]
|
]
|
||||||
li [] [
|
li [] [
|
||||||
raw l["The look and feel of the list can be configured for each group."]
|
raw l["The look and feel of the list can be configured for each group."]
|
||||||
space
|
space
|
||||||
raw l["All fonts, colors, and sizes can be customized."]
|
raw l["All fonts, colors, and sizes can be customized."]
|
||||||
space
|
space
|
||||||
raw l["This allows for configuration of large-print lists, among other things."]
|
raw l["This allows for configuration of large-print lists, among other things."]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
h4 [] [ raw l["How Can Your Organization Use {0}?", s["PrayerTracker"]] ]
|
h4 [] [ raw l["How Can Your Organization Use {0}?", s["PrayerTracker"]] ]
|
||||||
p [] [
|
p [] [
|
||||||
raw l["Like God’s gift of salvation, {0} is free for the asking for any church, Sunday School class, or other organization who wishes to use it.",
|
raw l["Like God’s gift of salvation, {0} is free for the asking for any church, Sunday School class, or other organization who wishes to use it.",
|
||||||
s["PrayerTracker"]]
|
s["PrayerTracker"]]
|
||||||
space
|
space
|
||||||
raw l["If your organization would like to get set up, just <a href=\"mailto:daniel@djs-consulting.com?subject=New%20{0}%20Class\">e-mail</a> Daniel and let him know.",
|
raw l["If your organization would like to get set up, just <a href=\"mailto:daniel@djs-consulting.com?subject=New%20{0}%20Class\">e-mail</a> Daniel and let him know.",
|
||||||
s["PrayerTracker"]]
|
s["PrayerTracker"]]
|
||||||
]
|
]
|
||||||
h4 [] [ raw l["Do I Have to Register to See the Requests?"] ]
|
h4 [] [ raw l["Do I Have to Register to See the Requests?"] ]
|
||||||
p [] [
|
p [] [
|
||||||
raw l["This depends on the group."]
|
raw l["This depends on the group."]
|
||||||
space
|
space
|
||||||
raw l["Lists can be configured to be password-protected, but they do not have to be."]
|
raw l["Lists can be configured to be password-protected, but they do not have to be."]
|
||||||
space
|
space
|
||||||
raw l["If you click on the “{0}” link above, you will see a list of groups - those that do not indicate that they require logging in are publicly viewable.",
|
raw l["If you click on the “{0}” link above, you will see a list of groups - those that do not indicate that they require logging in are publicly viewable.",
|
||||||
s["View Request List"]]
|
s["View Request List"]]
|
||||||
]
|
]
|
||||||
h4 [] [ raw l["How Does It Work?"] ]
|
h4 [] [ raw l["How Does It Work?"] ]
|
||||||
p [] [
|
p [] [
|
||||||
raw l["Check out the “{0}” link above - it details each of the processes and how they work.", s["Help"]]
|
raw l["Check out the “{0}” link above - it details each of the processes and how they work.", s["Help"]]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|> Layout.Content.standard
|
|> Layout.Content.standard
|
||||||
|> Layout.standard vi "Welcome!"
|
|> Layout.standard vi "Welcome!"
|
||||||
|
@ -129,68 +129,68 @@ let privacyPolicy vi =
|
||||||
use sw = new StringWriter ()
|
use sw = new StringWriter ()
|
||||||
let raw = rawLocText sw
|
let raw = rawLocText sw
|
||||||
|
|
||||||
[ p [ _class "pt-right-text" ] [ small [] [ em [] [ raw l["(as of July 31, 2018)"] ] ] ]
|
[ p [ _class "pt-right-text" ] [ small [] [ em [] [ raw l["(as of July 31, 2018)"] ] ] ]
|
||||||
p [] [
|
p [] [
|
||||||
raw l["The nature of the service is one where privacy is a must."]
|
raw l["The nature of the service is one where privacy is a must."]
|
||||||
space
|
space
|
||||||
raw l["The items below will help you understand the data we collect, access, and store on your behalf as you use this service."]
|
raw l["The items below will help you understand the data we collect, access, and store on your behalf as you use this service."]
|
||||||
]
|
]
|
||||||
h3 [] [ raw l["What We Collect"] ]
|
h3 [] [ raw l["What We Collect"] ]
|
||||||
ul [] [
|
ul [] [
|
||||||
li [] [
|
li [] [
|
||||||
strong [] [ raw l["Identifying Data"] ]
|
strong [] [ raw l["Identifying Data"] ]
|
||||||
rawText " – "
|
rawText " – "
|
||||||
raw l["{0} stores the first and last names, e-mail addresses, and hashed passwords of all authorized users.",
|
raw l["{0} stores the first and last names, e-mail addresses, and hashed passwords of all authorized users.",
|
||||||
s["PrayerTracker"]]
|
s["PrayerTracker"]]
|
||||||
space
|
space
|
||||||
raw l["Users are also associated with one or more small groups."]
|
raw l["Users are also associated with one or more small groups."]
|
||||||
]
|
]
|
||||||
li [] [
|
li [] [
|
||||||
strong [] [ raw l["User Provided Data"] ]
|
strong [] [ raw l["User Provided Data"] ]
|
||||||
rawText " – "
|
rawText " – "
|
||||||
raw l["{0} stores the text of prayer requests.", s["PrayerTracker"]]
|
raw l["{0} stores the text of prayer requests.", s["PrayerTracker"]]
|
||||||
space
|
space
|
||||||
raw l["It also stores names and e-mail addreses of small group members, and plain-text passwords for small groups with password-protected lists."]
|
raw l["It also stores names and e-mail addreses of small group members, and plain-text passwords for small groups with password-protected lists."]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
h3 [] [ raw l["How Your Data Is Accessed / Secured"] ]
|
h3 [] [ raw l["How Your Data Is Accessed / Secured"] ]
|
||||||
ul [] [
|
ul [] [
|
||||||
li [] [
|
li [] [
|
||||||
raw l["While you are signed in, {0} utilizes a session cookie, and transmits that cookie to the server to establish your identity.",
|
raw l["While you are signed in, {0} utilizes a session cookie, and transmits that cookie to the server to establish your identity.",
|
||||||
s["PrayerTracker"]]
|
s["PrayerTracker"]]
|
||||||
space
|
space
|
||||||
raw l["If you utilize the “{0}” box on sign in, a second cookie is stored, and transmitted to establish a session; this cookie is removed by clicking the “{1}” link.",
|
raw l["If you utilize the “{0}” box on sign in, a second cookie is stored, and transmitted to establish a session; this cookie is removed by clicking the “{1}” link.",
|
||||||
s["Remember Me"], s["Log Off"]]
|
s["Remember Me"], s["Log Off"]]
|
||||||
space
|
space
|
||||||
raw l["Both of these cookies are encrypted, both in your browser and in transit."]
|
raw l["Both of these cookies are encrypted, both in your browser and in transit."]
|
||||||
space
|
space
|
||||||
raw l["Finally, a third cookie is used to maintain your currently selected language, so that this selection is maintained across browser sessions."]
|
raw l["Finally, a third cookie is used to maintain your currently selected language, so that this selection is maintained across browser sessions."]
|
||||||
]
|
]
|
||||||
li [] [
|
li [] [
|
||||||
raw l["Data for your small group is returned to you, as required, to display and edit."]
|
raw l["Data for your small group is returned to you, as required, to display and edit."]
|
||||||
space
|
space
|
||||||
raw l["{0} also sends e-mails on behalf of the configured owner of a small group; these e-mails are sent from prayer@djs-consulting.com, with the “Reply To” header set to the configured owner of the small group.",
|
raw l["{0} also sends e-mails on behalf of the configured owner of a small group; these e-mails are sent from prayer@djs-consulting.com, with the “Reply To” header set to the configured owner of the small group.",
|
||||||
s["PrayerTracker"]]
|
s["PrayerTracker"]]
|
||||||
space
|
space
|
||||||
raw l["Distinct e-mails are sent to each user, as to not disclose the other recipients."]
|
raw l["Distinct e-mails are sent to each user, as to not disclose the other recipients."]
|
||||||
space
|
space
|
||||||
raw l["On the server, all data is stored in a controlled-access database."]
|
raw l["On the server, all data is stored in a controlled-access database."]
|
||||||
]
|
]
|
||||||
li [] [
|
li [] [
|
||||||
raw l["Your data is backed up, along with other Bit Badger Solutions hosted systems, in a rolling manner; backups are preserved for the prior 7 days, and backups from the 1st and 15th are preserved for 3 months."]
|
raw l["Your data is backed up, along with other Bit Badger Solutions hosted systems, in a rolling manner; backups are preserved for the prior 7 days, and backups from the 1st and 15th are preserved for 3 months."]
|
||||||
space
|
space
|
||||||
raw l["These backups are stored in a private cloud data repository."]
|
raw l["These backups are stored in a private cloud data repository."]
|
||||||
]
|
]
|
||||||
li [] [
|
li [] [
|
||||||
raw l["Access to servers and backups is strictly controlled and monitored for unauthorized access attempts."]
|
raw l["Access to servers and backups is strictly controlled and monitored for unauthorized access attempts."]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
h3 [] [ raw l["Removing Your Data"] ]
|
h3 [] [ raw l["Removing Your Data"] ]
|
||||||
p [] [
|
p [] [
|
||||||
raw l["At any time, you may choose to discontinue using {0}; just e-mail Daniel, as you did to register, and request deletion of your small group.",
|
raw l["At any time, you may choose to discontinue using {0}; just e-mail Daniel, as you did to register, and request deletion of your small group.",
|
||||||
s["PrayerTracker"]]
|
s["PrayerTracker"]]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|> Layout.Content.standard
|
|> Layout.Content.standard
|
||||||
|> Layout.standard vi "Privacy Policy"
|
|> Layout.standard vi "Privacy Policy"
|
||||||
|
|
||||||
|
@ -205,38 +205,38 @@ let termsOfService vi =
|
||||||
a [ _href "/legal/privacy-policy" ] [ str (s["Privacy Policy"].Value.ToLower ()) ]
|
a [ _href "/legal/privacy-policy" ] [ str (s["Privacy Policy"].Value.ToLower ()) ]
|
||||||
|> renderHtmlString
|
|> renderHtmlString
|
||||||
|
|
||||||
[ p [ _class "pt-right-text" ] [ small [] [ em [] [ raw l["(as of May 24, 2018)"] ] ] ]
|
[ p [ _class "pt-right-text" ] [ small [] [ em [] [ raw l["(as of May 24, 2018)"] ] ] ]
|
||||||
h3 [] [ str "1. "; raw l["Acceptance of Terms"] ]
|
h3 [] [ str "1. "; raw l["Acceptance of Terms"] ]
|
||||||
p [] [
|
p [] [
|
||||||
raw l["By accessing this web site, you are agreeing to be bound by these Terms and Conditions, and that you are responsible to ensure that your use of this site complies with all applicable laws."]
|
raw l["By accessing this web site, you are agreeing to be bound by these Terms and Conditions, and that you are responsible to ensure that your use of this site complies with all applicable laws."]
|
||||||
space
|
space
|
||||||
raw l["Your continued use of this site implies your acceptance of these terms."]
|
raw l["Your continued use of this site implies your acceptance of these terms."]
|
||||||
]
|
]
|
||||||
h3 [] [ str "2. "; raw l["Description of Service and Registration"] ]
|
h3 [] [ str "2. "; raw l["Description of Service and Registration"] ]
|
||||||
p [] [
|
p [] [
|
||||||
raw l["{0} is a service that allows individuals to enter and amend prayer requests on behalf of organizations.",
|
raw l["{0} is a service that allows individuals to enter and amend prayer requests on behalf of organizations.",
|
||||||
s["PrayerTracker"]]
|
s["PrayerTracker"]]
|
||||||
space
|
space
|
||||||
raw l["Registration is accomplished via e-mail to Daniel Summers (daniel at bitbadger dot solutions, substituting punctuation)."]
|
raw l["Registration is accomplished via e-mail to Daniel Summers (daniel at bitbadger dot solutions, substituting punctuation)."]
|
||||||
space
|
space
|
||||||
raw l["See our {0} for details on the personal (user) information we maintain.", ppLink]
|
raw l["See our {0} for details on the personal (user) information we maintain.", ppLink]
|
||||||
]
|
]
|
||||||
h3 [] [ str "3. "; raw l["Liability"] ]
|
h3 [] [ str "3. "; raw l["Liability"] ]
|
||||||
p [] [
|
p [] [
|
||||||
raw l["This service is provided “as is”, and no warranty (express or implied) exists."]
|
raw l["This service is provided “as is”, and no warranty (express or implied) exists."]
|
||||||
space
|
space
|
||||||
raw l["The service and its developers may not be held liable for any damages that may arise through the use of this service."]
|
raw l["The service and its developers may not be held liable for any damages that may arise through the use of this service."]
|
||||||
]
|
]
|
||||||
h3 [] [ str "4. "; raw l["Updates to Terms"] ]
|
h3 [] [ str "4. "; raw l["Updates to Terms"] ]
|
||||||
p [] [
|
p [] [
|
||||||
raw l["These terms and conditions may be updated at any time."]
|
raw l["These terms and conditions may be updated at any time."]
|
||||||
space
|
space
|
||||||
raw l["When these terms are updated, users will be notified by a system-generated announcement."]
|
raw l["When these terms are updated, users will be notified by a system-generated announcement."]
|
||||||
space
|
space
|
||||||
raw l["Additionally, the date at the top of this page will be updated."]
|
raw l["Additionally, the date at the top of this page will be updated."]
|
||||||
]
|
]
|
||||||
hr []
|
hr []
|
||||||
p [] [ raw l["You may also wish to review our {0} to learn how we handle your data.", ppLink] ]
|
p [] [ raw l["You may also wish to review our {0} to learn how we handle your data.", ppLink] ]
|
||||||
]
|
]
|
||||||
|> Layout.Content.standard
|
|> Layout.Content.standard
|
||||||
|> Layout.standard vi "Terms of Service"
|
|> Layout.standard vi "Terms of Service"
|
||||||
|
@ -248,14 +248,14 @@ let unauthorized vi =
|
||||||
let l = I18N.forView "Home/Unauthorized"
|
let l = I18N.forView "Home/Unauthorized"
|
||||||
use sw = new StringWriter ()
|
use sw = new StringWriter ()
|
||||||
let raw = rawLocText sw
|
let raw = rawLocText sw
|
||||||
[ p [] [
|
[ p [] [
|
||||||
raw l["If you feel you have reached this page in error, please <a href=\"mailto:daniel@djs-consulting.com?Subject={0}%20Unauthorized%20Access\">contact Daniel</a> and provide the details as to what you were doing (i.e., what link did you click, where had you been, etc.).",
|
raw l["If you feel you have reached this page in error, please <a href=\"mailto:daniel@djs-consulting.com?Subject={0}%20Unauthorized%20Access\">contact Daniel</a> and provide the details as to what you were doing (i.e., what link did you click, where had you been, etc.).",
|
||||||
s["PrayerTracker"]]
|
s["PrayerTracker"]]
|
||||||
]
|
]
|
||||||
p [] [
|
p [] [
|
||||||
raw l["Otherwise, you may select one of the links above to get back into an authorized portion of {0}.",
|
raw l["Otherwise, you may select one of the links above to get back into an authorized portion of {0}.",
|
||||||
s["PrayerTracker"]]
|
s["PrayerTracker"]]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|> Layout.Content.standard
|
|> Layout.Content.standard
|
||||||
|> Layout.standard vi "Unauthorized Access"
|
|> Layout.standard vi "Unauthorized Access"
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
module PrayerTracker.Views.Layout
|
module PrayerTracker.Views.Layout
|
||||||
|
|
||||||
open Giraffe.ViewEngine
|
open Giraffe.ViewEngine
|
||||||
|
open Giraffe.ViewEngine.Accessibility
|
||||||
|
open Giraffe.ViewEngine.Htmx
|
||||||
open PrayerTracker
|
open PrayerTracker
|
||||||
open PrayerTracker.ViewModels
|
open PrayerTracker.ViewModels
|
||||||
open System
|
open System
|
||||||
|
@ -12,6 +14,16 @@ open System.Globalization
|
||||||
let langCode () = if CultureInfo.CurrentCulture.Name.StartsWith "es" then "es" else "en"
|
let langCode () = if CultureInfo.CurrentCulture.Name.StartsWith "es" then "es" else "en"
|
||||||
|
|
||||||
|
|
||||||
|
/// Known htmx targets
|
||||||
|
module Target =
|
||||||
|
|
||||||
|
/// htmx links target the body element
|
||||||
|
let body = _hxTarget "body"
|
||||||
|
|
||||||
|
/// htmx links target the #pt-body element
|
||||||
|
let content = _hxTarget "#pt-body"
|
||||||
|
|
||||||
|
|
||||||
/// Navigation items
|
/// Navigation items
|
||||||
module Navigation =
|
module Navigation =
|
||||||
|
|
||||||
|
@ -23,103 +35,119 @@ module Navigation =
|
||||||
match m.User with
|
match m.User with
|
||||||
| Some u ->
|
| Some u ->
|
||||||
li [ _class "dropdown" ] [
|
li [ _class "dropdown" ] [
|
||||||
a [ _class "dropbtn"
|
a [ _class "dropbtn"; _ariaLabel s["Requests"].Value; _title s["Requests"].Value; _roleButton ] [
|
||||||
_role "button"
|
icon "question_answer"; space; locStr s["Requests"]; space; icon "keyboard_arrow_down"
|
||||||
_aria "label" s["Requests"].Value
|
]
|
||||||
_title s["Requests"].Value ]
|
div [ _class "dropdown-content"; _roleMenuBar ] [
|
||||||
[ icon "question_answer"; space; locStr s["Requests"]; space; icon "keyboard_arrow_down" ]
|
a [ _href "/prayer-requests"; _roleMenuItem ] [
|
||||||
div [ _class "dropdown-content"; _role "menu" ] [
|
icon "compare_arrows"; menuSpacer; locStr s["Maintain"]
|
||||||
a [ _href "/prayer-requests" ] [ icon "compare_arrows"; menuSpacer; locStr s["Maintain"] ]
|
]
|
||||||
a [ _href "/prayer-requests/view" ] [ icon "list"; menuSpacer; locStr s["View List"] ]
|
a [ _href "/prayer-requests/view"; _roleMenuItem ] [
|
||||||
|
icon "list"; menuSpacer; locStr s["View List"]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
li [ _class "dropdown" ] [
|
li [ _class "dropdown" ] [
|
||||||
a [ _class "dropbtn"; _role "button"; _aria "label" s["Group"].Value; _title s["Group"].Value ]
|
a [ _class "dropbtn"; _ariaLabel s["Group"].Value; _title s["Group"].Value; _roleButton ] [
|
||||||
[ icon "group"; space; locStr s["Group"]; space; icon "keyboard_arrow_down" ]
|
icon "group"; space; locStr s["Group"]; space; icon "keyboard_arrow_down"
|
||||||
div [ _class "dropdown-content"; _role "menu" ] [
|
]
|
||||||
a [ _href "/small-group/members" ]
|
div [ _class "dropdown-content"; _roleMenuBar ] [
|
||||||
[ icon "email"; menuSpacer; locStr s["Maintain Group Members"] ]
|
a [ _href "/small-group/members"; _roleMenuItem ] [
|
||||||
a [ _href "/small-group/announcement" ]
|
icon "email"; menuSpacer; locStr s["Maintain Group Members"]
|
||||||
[ icon "send"; menuSpacer; locStr s["Send Announcement"] ]
|
]
|
||||||
a [ _href "/small-group/preferences" ]
|
a [ _href "/small-group/announcement"; _roleMenuItem ] [
|
||||||
[ icon "build"; menuSpacer; locStr s["Change Preferences"] ]
|
icon "send"; menuSpacer; locStr s["Send Announcement"]
|
||||||
|
]
|
||||||
|
a [ _href "/small-group/preferences"; _roleMenuItem ] [
|
||||||
|
icon "build"; menuSpacer; locStr s["Change Preferences"]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
if u.isAdmin then
|
if u.isAdmin then
|
||||||
li [ _class "dropdown" ] [
|
li [ _class "dropdown" ] [
|
||||||
a [ _class "dropbtn"
|
a [ _class "dropbtn"
|
||||||
_role "button"
|
_ariaLabel s["Administration"].Value
|
||||||
_aria "label" s["Administration"].Value
|
_title s["Administration"].Value
|
||||||
_title s["Administration"].Value
|
_roleButton ] [
|
||||||
] [ icon "settings"; space; locStr s["Administration"]; space; icon "keyboard_arrow_down" ]
|
icon "settings"; space; locStr s["Administration"]; space; icon "keyboard_arrow_down"
|
||||||
div [ _class "dropdown-content"; _role "menu" ] [
|
]
|
||||||
a [ _href "/churches" ] [ icon "home"; menuSpacer; locStr s["Churches"] ]
|
div [ _class "dropdown-content"; _roleMenuBar ] [
|
||||||
a [ _href "/small-groups" ] [ icon "send"; menuSpacer; locStr s["Groups"] ]
|
a [ _href "/churches"; _roleMenuItem ] [ icon "home"; menuSpacer; locStr s["Churches"] ]
|
||||||
a [ _href "/users" ] [ icon "build"; menuSpacer; locStr s["Users"] ]
|
a [ _href "/small-groups"; _roleMenuItem ] [ icon "send"; menuSpacer; locStr s["Groups"] ]
|
||||||
|
a [ _href "/users"; _roleMenuItem ] [ icon "build"; menuSpacer; locStr s["Users"] ]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
| None ->
|
| None ->
|
||||||
match m.Group with
|
match m.Group with
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
li [] [
|
li [] [
|
||||||
a [ _href "/prayer-requests/view"
|
a [ _href "/prayer-requests/view"
|
||||||
_aria "label" s["View Request List"].Value
|
_ariaLabel s["View Request List"].Value
|
||||||
_title s["View Request List"].Value
|
_title s["View Request List"].Value ] [
|
||||||
] [ icon "list"; space; locStr s["View Request List"] ]
|
icon "list"; space; locStr s["View Request List"]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
| None ->
|
| None ->
|
||||||
li [ _class "dropdown" ] [
|
li [ _class "dropdown" ] [
|
||||||
a [ _class "dropbtn"
|
a [ _class "dropbtn"; _ariaLabel s["Log On"].Value; _title s["Log On"].Value; _roleButton ] [
|
||||||
_role "button"
|
icon "security"; space; locStr s["Log On"]; space; icon "keyboard_arrow_down"
|
||||||
_aria "label" s["Log On"].Value
|
]
|
||||||
_title s["Log On"].Value
|
div [ _class "dropdown-content"; _roleMenuBar ] [
|
||||||
] [ icon "security"; space; locStr s["Log On"]; space; icon "keyboard_arrow_down" ]
|
a [ _href "/user/log-on"; _roleMenuItem ] [ icon "person"; menuSpacer; locStr s["User"] ]
|
||||||
div [ _class "dropdown-content"; _role "menu" ] [
|
a [ _href "/small-group/log-on"; _roleMenuItem ] [
|
||||||
a [ _href "/user/log-on" ] [ icon "person"; menuSpacer; locStr s["User"] ]
|
icon "group"; menuSpacer; locStr s["Group"]
|
||||||
a [ _href "/small-group/log-on" ] [ icon "group"; menuSpacer; locStr s["Group"] ]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
li [] [
|
li [] [
|
||||||
a [ _href "/prayer-requests/lists"
|
a [ _href "/prayer-requests/lists"
|
||||||
_aria "label" s["View Request List"].Value
|
_ariaLabel s["View Request List"].Value
|
||||||
_title s["View Request List"].Value
|
_title s["View Request List"].Value ] [
|
||||||
] [ icon "list"; space; locStr s["View Request List"] ]
|
icon "list"; space; locStr s["View Request List"]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
li [] [
|
li [] [
|
||||||
a [ _href $"https://docs.prayer.bitbadger.solutions/{langCode ()}"
|
a [ _href $"https://docs.prayer.bitbadger.solutions/{langCode ()}"
|
||||||
_aria "label" s["Help"].Value;
|
_ariaLabel s["Help"].Value
|
||||||
_title s["View Help"].Value
|
_title s["View Help"].Value
|
||||||
_target "_blank"
|
_target "_blank"
|
||||||
] [ icon "help"; space; locStr s["Help"] ]
|
_rel "noopener" ] [
|
||||||
|
icon "help"; space; locStr s["Help"]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
let rightLinks =
|
let rightLinks =
|
||||||
match m.Group with
|
match m.Group with
|
||||||
| Some _ -> [
|
| Some _ ->
|
||||||
match m.User with
|
[ match m.User with
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
|
li [] [
|
||||||
|
a [ _href "/user/password"
|
||||||
|
_ariaLabel s["Change Your Password"].Value
|
||||||
|
_title s["Change Your Password"].Value ] [
|
||||||
|
icon "lock"; space; locStr s["Change Your Password"]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
| None -> ()
|
||||||
li [] [
|
li [] [
|
||||||
a [ _href "/user/password"
|
a [ _href "/log-off"
|
||||||
_aria "label" s["Change Your Password"].Value
|
_ariaLabel s["Log Off"].Value
|
||||||
_title s["Change Your Password"].Value
|
_title s["Log Off"].Value
|
||||||
] [ icon "lock"; space; locStr s["Change Your Password"] ]
|
_hxTarget "body" ] [
|
||||||
|
icon "power_settings_new"; space; locStr s["Log Off"]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
| None -> ()
|
|
||||||
li [] [
|
|
||||||
a [ _href "/log-off"; _aria "label" s["Log Off"].Value; _title s["Log Off"].Value ]
|
|
||||||
[ icon "power_settings_new"; space; locStr s["Log Off"] ]
|
|
||||||
]
|
]
|
||||||
]
|
|
||||||
| None -> []
|
| None -> []
|
||||||
header [ _class "pt-title-bar" ] [
|
header [ _class "pt-title-bar"; Target.content ] [
|
||||||
section [ _class "pt-title-bar-left" ] [
|
section [ _class "pt-title-bar-left"; _ariaLabel "Left side of top menu" ] [
|
||||||
span [ _class "pt-title-bar-home" ] [
|
span [ _class "pt-title-bar-home" ] [
|
||||||
a [ _href "/"; _title s["Home"].Value ] [ locStr s["PrayerTracker"] ]
|
a [ _href "/"; _title s["Home"].Value ] [ locStr s["PrayerTracker"] ]
|
||||||
]
|
]
|
||||||
ul [] leftLinks
|
ul [] leftLinks
|
||||||
]
|
]
|
||||||
section [ _class "pt-title-bar-center" ] []
|
section [ _class "pt-title-bar-center"; _ariaLabel "Empty center space in top menu" ] []
|
||||||
section [ _class "pt-title-bar-right"; _role "toolbar" ] [
|
section [ _class "pt-title-bar-right"; _roleToolBar; _ariaLabel "Right side of top menu" ] [
|
||||||
ul [] rightLinks
|
ul [] rightLinks
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
@ -127,7 +155,7 @@ module Navigation =
|
||||||
/// Identity bar (below top nav)
|
/// Identity bar (below top nav)
|
||||||
let identity m =
|
let identity m =
|
||||||
let s = I18N.localizer.Force ()
|
let s = I18N.localizer.Force ()
|
||||||
header [ _id "pt-language" ] [
|
header [ _id "pt-language"; Target.body ] [
|
||||||
div [] [
|
div [] [
|
||||||
span [ _class "u" ] [ locStr s["Language"]; rawText ": " ]
|
span [ _class "u" ] [ locStr s["Language"]; rawText ": " ]
|
||||||
match langCode () with
|
match langCode () with
|
||||||
|
@ -141,24 +169,24 @@ module Navigation =
|
||||||
a [ _href "/language/es" ] [ locStr s["Cambie a Español"] ]
|
a [ _href "/language/es" ] [ locStr s["Cambie a Español"] ]
|
||||||
]
|
]
|
||||||
match m.Group with
|
match m.Group with
|
||||||
| Some g ->[
|
| Some g ->
|
||||||
match m.User with
|
[ match m.User with
|
||||||
| Some u ->
|
| Some u ->
|
||||||
span [ _class "u" ] [ locStr s["Currently Logged On"] ]
|
span [ _class "u" ] [ locStr s["Currently Logged On"] ]
|
||||||
rawText " "
|
rawText " "
|
||||||
icon "person"
|
icon "person"
|
||||||
strong [] [ str u.fullName ]
|
strong [] [ str u.fullName ]
|
||||||
rawText " "
|
rawText " "
|
||||||
| None ->
|
| None ->
|
||||||
locStr s["Logged On as a Member of"]
|
locStr s["Logged On as a Member of"]
|
||||||
rawText " "
|
rawText " "
|
||||||
icon "group"
|
icon "group"
|
||||||
space
|
space
|
||||||
match m.User with
|
match m.User with
|
||||||
| Some _ -> a [ _href "/small-group" ] [ strong [] [ str g.name ] ]
|
| Some _ -> a [ _href "/small-group"; Target.content ] [ strong [] [ str g.name ] ]
|
||||||
| None -> strong [] [ str g.name ]
|
| None -> strong [] [ str g.name ]
|
||||||
rawText " "
|
rawText " "
|
||||||
]
|
]
|
||||||
| None -> []
|
| None -> []
|
||||||
|> div []
|
|> div []
|
||||||
]
|
]
|
||||||
|
@ -178,13 +206,12 @@ module Content =
|
||||||
let private titleSep = rawText " « "
|
let private titleSep = rawText " « "
|
||||||
|
|
||||||
/// Common HTML head tag items
|
/// Common HTML head tag items
|
||||||
let private commonHead =
|
let private commonHead = [
|
||||||
[ meta [ _name "viewport"; _content "width=device-width, initial-scale=1" ]
|
meta [ _name "viewport"; _content "width=device-width, initial-scale=1" ]
|
||||||
meta [ _name "generator"; _content "Giraffe" ]
|
meta [ _name "generator"; _content "Giraffe" ]
|
||||||
link [ _rel "stylesheet"; _href "https://fonts.googleapis.com/icon?family=Material+Icons" ]
|
link [ _rel "stylesheet"; _href "https://fonts.googleapis.com/icon?family=Material+Icons" ]
|
||||||
link [ _rel "stylesheet"; _href "/css/app.css" ]
|
link [ _rel "stylesheet"; _href "/css/app.css" ]
|
||||||
script [ _src "/js/app.js" ] []
|
]
|
||||||
]
|
|
||||||
|
|
||||||
/// Render the <head> portion of the page
|
/// Render the <head> portion of the page
|
||||||
let private htmlHead m pageTitle =
|
let private htmlHead m pageTitle =
|
||||||
|
@ -203,8 +230,12 @@ let private htmlHead m pageTitle =
|
||||||
let private helpLink link =
|
let private helpLink link =
|
||||||
let s = I18N.localizer.Force ()
|
let s = I18N.localizer.Force ()
|
||||||
sup [] [
|
sup [] [
|
||||||
a [ _href link; _title s["Click for Help on This Page"].Value; _onclick $"return PT.showHelp('{link}')" ]
|
a [ _href link
|
||||||
[ icon "help_outline" ]
|
_title s["Click for Help on This Page"].Value
|
||||||
|
_onclick $"return PT.showHelp('{link}')"
|
||||||
|
_hxNoBoost ] [
|
||||||
|
icon "help_outline"
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
/// Render the page title, and optionally a help link
|
/// Render the page title, and optionally a help link
|
||||||
|
@ -239,8 +270,8 @@ let private messages m =
|
||||||
|
|
||||||
/// Render the <footer> at the bottom of the page
|
/// Render the <footer> at the bottom of the page
|
||||||
let private htmlFooter m =
|
let private htmlFooter m =
|
||||||
let s = I18N.localizer.Force ()
|
let s = I18N.localizer.Force ()
|
||||||
let imgText = sprintf "%O %O" s["PrayerTracker"] s["from Bit Badger Solutions"]
|
let imgText = $"""%O{s["PrayerTracker"]} %O{s["from Bit Badger Solutions"]}"""
|
||||||
let resultTime = TimeSpan(DateTime.Now.Ticks - m.RequestStart).TotalSeconds
|
let resultTime = TimeSpan(DateTime.Now.Ticks - m.RequestStart).TotalSeconds
|
||||||
footer [] [
|
footer [] [
|
||||||
div [ _id "pt-legal" ] [
|
div [ _id "pt-legal" ] [
|
||||||
|
@ -248,30 +279,34 @@ let private htmlFooter m =
|
||||||
rawText " • "
|
rawText " • "
|
||||||
a [ _href "/legal/terms-of-service" ] [ locStr s["Terms of Service"] ]
|
a [ _href "/legal/terms-of-service" ] [ locStr s["Terms of Service"] ]
|
||||||
rawText " • "
|
rawText " • "
|
||||||
a [ _href "https://github.com/bit-badger/PrayerTracker"
|
a [ _href "https://github.com/bit-badger/PrayerTracker"
|
||||||
_title s["View source code and get technical support"].Value
|
_title s["View source code and get technical support"].Value
|
||||||
_target "_blank"
|
_target "_blank"
|
||||||
_rel "noopener"
|
_rel "noopener" ] [
|
||||||
] [ locStr s["Source & Support"]
|
locStr s["Source & Support"]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
div [ _id "pt-footer" ] [
|
div [ _id "pt-footer" ] [
|
||||||
a [ _href "/"; _style "line-height:28px;" ]
|
a [ _href "/"; _style "line-height:28px;" ] [
|
||||||
[ img [ _src $"""/img/%O{s["footer_en"]}.png"""; _alt imgText; _title imgText ] ]
|
img [ _src $"""/img/%O{s["footer_en"]}.png"""; _alt imgText; _title imgText ]
|
||||||
|
]
|
||||||
str m.Version
|
str m.Version
|
||||||
space
|
space
|
||||||
i [ _title s["This page loaded in {0:N3} seconds", resultTime].Value; _class "material-icons md-18" ]
|
i [ _title s["This page loaded in {0:N3} seconds", resultTime].Value; _class "material-icons md-18" ] [
|
||||||
[ str "schedule" ]
|
str "schedule"
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
Script.minified
|
||||||
|
script [ _src "/js/app.js" ] []
|
||||||
]
|
]
|
||||||
|
|
||||||
/// The standard layout for PrayerTracker
|
/// The standard layout for PrayerTracker
|
||||||
let standard m pageTitle (content : XmlNode) =
|
let standard m pageTitle (content : XmlNode) =
|
||||||
let s = I18N.localizer.Force ()
|
let s = I18N.localizer.Force ()
|
||||||
let ttl = s[pageTitle]
|
let ttl = s[pageTitle]
|
||||||
html [ _lang "" ] [
|
html [ _lang (langCode ()) ] [
|
||||||
htmlHead m ttl
|
htmlHead m ttl
|
||||||
body [] [
|
body [ _hxBoost ] [
|
||||||
Navigation.top m
|
Navigation.top m
|
||||||
div [ _id "pt-body" ] [
|
div [ _id "pt-body" ] [
|
||||||
Navigation.identity m
|
Navigation.identity m
|
||||||
|
@ -287,7 +322,7 @@ let standard m pageTitle (content : XmlNode) =
|
||||||
let bare pageTitle content =
|
let bare pageTitle content =
|
||||||
let s = I18N.localizer.Force ()
|
let s = I18N.localizer.Force ()
|
||||||
let ttl = s[pageTitle]
|
let ttl = s[pageTitle]
|
||||||
html [ _lang "" ] [
|
html [ _lang (langCode ()) ] [
|
||||||
head [] [
|
head [] [
|
||||||
meta [ _charset "UTF-8" ]
|
meta [ _charset "UTF-8" ]
|
||||||
title [] [ locStr ttl; titleSep; locStr s["PrayerTracker"] ]
|
title [] [ locStr ttl; titleSep; locStr s["PrayerTracker"] ]
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Giraffe" Version="6.0.0" />
|
<PackageReference Include="Giraffe" Version="6.0.0" />
|
||||||
<PackageReference Include="Giraffe.ViewEngine" Version="1.4.0" />
|
<PackageReference Include="Giraffe.ViewEngine" Version="1.4.0" />
|
||||||
|
<PackageReference Include="Giraffe.ViewEngine.Htmx" Version="1.8.0" />
|
||||||
<PackageReference Include="MailKit" Version="3.3.0" />
|
<PackageReference Include="MailKit" Version="3.3.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="2.2.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
|
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
|
||||||
|
|
Loading…
Reference in New Issue
Block a user