Interim commit

Nowhere close to executable (though everything builds)
This commit is contained in:
Daniel J. Summers 2016-07-07 22:57:14 -05:00
parent 99b3c14ec6
commit b86ba7b6f6
27 changed files with 1478 additions and 0 deletions

63
.gitattributes vendored Normal file
View File

@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

View File

@ -0,0 +1,21 @@
namespace myWebLog.Data.AssemblyInfo
open System.Reflection
open System.Runtime.CompilerServices
open System.Runtime.InteropServices
[<assembly: AssemblyTitle("myWebLog.Data")>]
[<assembly: AssemblyDescription("Data access for myWebLog")>]
[<assembly: AssemblyConfiguration("")>]
[<assembly: AssemblyCompany("DJS Consulting")>]
[<assembly: AssemblyProduct("myWebLog.Data")>]
[<assembly: AssemblyCopyright("Copyright © 2016")>]
[<assembly: AssemblyTrademark("")>]
[<assembly: AssemblyCulture("")>]
[<assembly: ComVisible(false)>]
[<assembly: Guid("1fba0b84-b09e-4b16-b9b6-5730dea27192")>]
[<assembly: AssemblyVersion("0.9.1.0")>]
[<assembly: AssemblyFileVersion("1.0.0.0")>]
do
()

View File

@ -0,0 +1,9 @@
namespace myWebLog.Data
open RethinkDb.Driver.Net
type DataConfig = {
database : string
conn : IConnection
}

View File

@ -0,0 +1,265 @@
namespace myWebLog.Entities
open Newtonsoft.Json
// ---- Constants ----
/// Constants to use for revision source language
module RevisionSource =
let Markdown = "markdown"
let HTML = "html"
/// Constants to use for authorization levels
module AuthorizationLevel =
let Administrator = "Administrator"
let User = "User"
/// Constants to use for post statuses
module PostStatus =
let Draft = "Draft"
let Published = "Published"
// ---- Entities ----
/// A revision of a post or page
type Revision = {
/// The instant which this revision was saved
asOf : int64
/// The source language
sourceType : string
/// The text
text : string
}
/// A page with static content
type Page = {
/// The Id
id : string
/// The Id of the web log to which this page belongs
webLogId : string
/// The Id of the author of this page
authorId : string
/// The title of the page
title : string
/// The link at which this page is displayed
permalink : string
/// The instant this page was published
publishedOn : int64
/// The instant this page was last updated
lastUpdatedOn : int64
/// Whether this page shows as part of the web log's navigation
showInPageList : bool
/// The current text of the page
text : string
/// Revisions of this page
revisions : Revision list
}
with
static member empty =
{ id = ""
webLogId = ""
authorId = ""
title = ""
permalink = ""
publishedOn = int64 0
lastUpdatedOn = int64 0
showInPageList = false
text = ""
revisions = List.empty
}
/// A web log
type WebLog = {
/// The Id
id : string
/// The name
name : string
/// The subtitle
subtitle : string option
/// The default page ("posts" or a page Id)
defaultPage : string
/// The path of the theme (within /views)
themePath : string
/// The URL base
urlBase : string
/// The time zone in which dates/times should be displayed
timeZone : string
/// A list of pages to be rendered as part of the site navigation
[<JsonIgnore>]
pageList : Page list
}
with
/// An empty web log
static member empty =
{ id = ""
name = ""
subtitle = None
defaultPage = ""
themePath = "default"
urlBase = ""
timeZone = "America/New_York"
pageList = List.empty
}
/// An authorization between a user and a web log
type Authorization = {
/// The Id of the web log to which this authorization grants access
webLogId : string
/// The level of access granted by this authorization
level : string
}
/// A user of myWebLog
type User = {
/// The Id
id : string
/// The user name (e-mail address)
userName : string
/// The first name
firstName : string
/// The last name
lastName : string
/// The user's preferred name
preferredName : string
/// The hash of the user's password
passwordHash : string
/// The URL of the user's personal site
url : string option
/// The user's authorizations
authorizations : Authorization list
}
with
/// An empty user
static member empty =
{ id = ""
userName = ""
firstName = ""
lastName = ""
preferredName = ""
passwordHash = ""
url = None
authorizations = List.empty
}
/// Claims for this user
[<JsonIgnore>]
member this.claims = this.authorizations
|> List.map (fun auth -> sprintf "%s|%s" auth.webLogId auth.level)
/// A category to which posts may be assigned
type Category = {
/// The Id
id : string
/// The displayed name
name : string
/// The slug (used in category URLs)
slug : string
/// A longer description of the category
description : string option
/// The parent Id of this category (if a subcategory)
parentId : string option
/// The categories for which this category is the parent
children : string list
}
with
/// An empty category
static member empty =
{ id = ""
name = ""
slug = ""
description = None
parentId = None
children = List.empty
}
/// A comment (applies to a post)
type Comment = {
/// The Id
id : string
/// The Id of the post to which this comment applies
postId : string
/// The Id of the comment to which this comment is a reply
inReplyToId : string option
/// The name of the commentor
name : string
/// The e-mail address of the commentor
email : string
/// The URL of the commentor's personal website
url : string option
/// The instant the comment was posted
postedOn : int64
/// The text of the comment
text : string
}
with
static member empty =
{ id = ""
postId = ""
inReplyToId = None
name = ""
email = ""
url = None
postedOn = int64 0
text = ""
}
/// A post
type Post = {
/// The Id
id : string
/// The Id of the web log to which this post belongs
webLogId : string
/// The Id of the author of this post
authorId : string
/// The status
status : string
/// The title
title : string
/// The link at which the post resides
permalink : string
/// The instant on which the post was originally published
publishedOn : int64
/// The instant on which the post was last updated
updatedOn : int64
/// The text of the post
text : string
/// The Ids of the categories to which this is assigned
categoryIds : string list
/// The tags for the post
tags : string list
/// The permalinks at which this post may have once resided
priorPermalinks : string list
/// Revisions of this post
revisions : Revision list
/// The categories to which this is assigned
[<JsonIgnore>]
categories : Category list
/// The comments
[<JsonIgnore>]
comments : Comment list
}
with
static member empty =
{ id = ""
webLogId = ""
authorId = ""
status = PostStatus.Draft
title = ""
permalink = ""
publishedOn = int64 0
updatedOn = int64 0
text = ""
categoryIds = List.empty
tags = List.empty
priorPermalinks = List.empty
revisions = List.empty
categories = List.empty
comments = List.empty
}

View File

@ -0,0 +1,23 @@
module myWebLog.Data.Rethink
open RethinkDb.Driver.Ast
open RethinkDb.Driver.Net
let private r = RethinkDb.Driver.RethinkDB.R
let private await task = task |> Async.AwaitTask |> Async.RunSynchronously
let delete (expr : ReqlExpr) = expr.Delete ()
let get (expr : obj) (table : Table) = table.Get expr
let getAll (exprs : obj[]) (table : Table) = table.GetAll exprs
let insert (expr : obj) (table : Table) = table.Insert expr
let optArg key (value : obj) (expr : GetAll) = expr.OptArg (key, value)
let orderBy (exprA : obj) (expr : ReqlExpr) = expr.OrderBy exprA
let replace (exprA : obj) (expr : ReqlExpr) = expr.Replace exprA
let runAtomAsync<'T> (conn : IConnection) (ast : ReqlAst) = ast.RunAtomAsync<'T> conn |> await
let runCursorAsync<'T> (conn : IConnection) (ast : ReqlAst) = ast.RunCursorAsync<'T> conn |> await
let runListAsync<'T> (conn : IConnection) (ast : ReqlAst) = ast.RunAtomAsync<System.Collections.Generic.List<'T>> conn
|> await
let runResultAsync (conn : IConnection) (ast : ReqlAst) = ast.RunResultAsync conn |> await
let table (expr : obj) = r.Table expr
let update (exprA : obj) (expr : ReqlExpr) = expr.Update exprA
let without (exprs : obj[]) (expr : ReqlExpr) = expr.Without exprs

154
src/myWebLog.Data/SetUp.fs Normal file
View File

@ -0,0 +1,154 @@
module myWebLog.Data.SetUp
open RethinkDb.Driver
open System
open Rethink
open RethinkDb.Driver.Ast
let private r = RethinkDB.R
let private logStep step = Console.Out.WriteLine(sprintf "[myWebLog] %s" step)
let private logStepStart text = Console.Out.Write (sprintf "[myWebLog] %s..." text)
let private logStepDone () = Console.Out.WriteLine(" done.")
let private result task = task |> Async.AwaitTask |> Async.RunSynchronously
let checkDatabase (cfg : DataConfig) =
logStep "|> Checking database"
let dbs = r.DbList()
|> runListAsync<string> cfg.conn
match dbs.Contains cfg.database with
| true -> ()
| _ -> logStepStart (sprintf " %s database not found - creating" cfg.database)
r.DbCreate cfg.database
|> runResultAsync cfg.conn
|> ignore
logStepDone ()
let checkTables cfg =
logStep "|> Checking tables"
let tables = r.Db(cfg.database).TableList()
|> runListAsync<string> cfg.conn
[ Table.Category; Table.Comment; Table.Page; Table.Post; Table.User; Table.WebLog ]
|> List.map (fun tbl -> match tables.Contains tbl with
| true -> None
| _ -> Some (tbl, r.TableCreate tbl))
|> List.filter (fun create -> create.IsSome)
|> List.map (fun create -> create.Value)
|> List.iter (fun (tbl, create) -> logStepStart (sprintf " Creating table %s" tbl)
create
|> runResultAsync cfg.conn
|> ignore
logStepDone ())
let tbl cfg table = r.Db(cfg.database).Table(table)
let createIndex cfg table index =
logStepStart (sprintf """ Creating index "%s" on table %s""" index table)
(tbl cfg table).IndexCreate(index)
|> runResultAsync cfg.conn
|> ignore
(tbl cfg table).IndexWait(index)
|> runResultAsync cfg.conn
|> ignore
logStepDone ()
let chkIndexes cfg table (indexes : string list) =
let idx = (tbl cfg table).IndexList()
|> runListAsync<string> cfg.conn
indexes
|> List.iter (fun index -> match idx.Contains index with
| true -> ()
| _ -> createIndex cfg table index)
idx
let checkCategoryIndexes cfg =
chkIndexes cfg Table.Category [ "webLogId"; "slug" ]
|> ignore
let checkCommentIndexes cfg =
chkIndexes cfg Table.Comment [ "postId" ]
|> ignore
let checkPageIndexes cfg =
let idx = chkIndexes cfg Table.Page [ "webLogId" ]
match idx.Contains "permalink" with
| true -> ()
| _ -> logStepStart (sprintf """ Creating index "permalink" on table %s""" Table.Page)
(tbl cfg Table.Page)
.IndexCreate("permalink", ReqlFunction1(fun row -> upcast r.Array(row.["webLogId"], row.["permalink"])))
|> runResultAsync cfg.conn
|> ignore
(tbl cfg Table.Page).IndexWait "permalink"
|> runResultAsync cfg.conn
|> ignore
logStepDone ()
match idx.Contains "pageList" with
| true -> ()
| _ -> logStepStart (sprintf """ Creating index "pageList" on table %s""" Table.Page)
(tbl cfg Table.Page)
.IndexCreate("pageList", ReqlFunction1(fun row -> upcast r.Array(row.["webLogId"], row.["showInPageList"])))
|> runResultAsync cfg.conn
|> ignore
(tbl cfg Table.Page).IndexWait "pageList"
|> runResultAsync cfg.conn
|> ignore
logStepDone ()
let checkPostIndexes cfg =
let idx = chkIndexes cfg Table.Post [ "webLogId" ]
match idx.Contains "webLogAndStatus" with
| true -> ()
| _ -> logStepStart (sprintf """ Creating index "webLogAndStatus" on table %s""" Table.Post)
(tbl cfg Table.Post)
.IndexCreate("webLogAndStatus", ReqlFunction1(fun row -> upcast r.Array(row.["webLogId"], row.["status"])))
|> runResultAsync cfg.conn
|> ignore
(tbl cfg Table.Post).IndexWait "webLogAndStatus"
|> runResultAsync cfg.conn
|> ignore
logStepDone ()
match idx.Contains "permalink" with
| true -> ()
| _ -> logStepStart (sprintf """ Creating index "permalink" on table %s""" Table.Post)
(tbl cfg Table.Post)
.IndexCreate("permalink", ReqlFunction1(fun row -> upcast r.Array(row.["webLogId"], row.["permalink"])))
|> runResultAsync cfg.conn
|> ignore
(tbl cfg Table.Post).IndexWait "permalink"
|> runResultAsync cfg.conn
|> ignore
logStepDone ()
let checkUserIndexes cfg =
let idx = chkIndexes cfg Table.User [ ]
match idx.Contains "logOn" with
| true -> ()
| _ -> logStepStart (sprintf """ Creating index "logOn" on table %s""" Table.User)
(tbl cfg Table.User)
.IndexCreate("logOn", ReqlFunction1(fun row -> upcast r.Array(row.["userName"], row.["passwordHash"])))
|> runResultAsync cfg.conn
|> ignore
(tbl cfg Table.User).IndexWait "logOn"
|> runResultAsync cfg.conn
|> ignore
logStepDone ()
let checkWebLogIndexes cfg =
chkIndexes cfg Table.WebLog [ "urlBase" ]
|> ignore
let checkIndexes cfg =
logStep "|> Checking indexes"
checkCategoryIndexes cfg
checkCommentIndexes cfg
checkPageIndexes cfg
checkPostIndexes cfg
checkUserIndexes cfg
checkWebLogIndexes cfg
let startUpCheck cfg =
logStep "Database Start Up Checks Starting"
checkDatabase cfg
checkTables cfg
checkIndexes cfg
logStep "Database Start Up Checks Complete"

View File

@ -0,0 +1,19 @@
module myWebLog.Data.Table
/// The Category table
let Category = "Category"
/// The Comment table
let Comment = "Comment"
/// The Page table
let Page = "Page"
/// The Post table
let Post = "Post"
/// The WebLog table
let WebLog = "WebLog"
/// The User table
let User = "User"

View File

@ -0,0 +1,20 @@
module myWebLog.Data.WebLog
open myWebLog.Entities
open Rethink
open RethinkDb.Driver
let private r = RethinkDB.R
type PageList = { pageList : Ast.CoerceTo }
/// Detemine the web log by the URL base
let tryFindWebLogByUrlBase (cfg : DataConfig) (urlBase : string) =
r.Table(Table.WebLog).GetAll([| urlBase |]).OptArg("index", "urlBase")
.Merge(fun webLog -> { pageList = r.Table(Table.Page)
.GetAll([| webLog.["id"], true |]).OptArg("index", "pageList")
.OrderBy("title")
.Pluck([| "title", "permalink" |])
.CoerceTo("array") })
|> runCursorAsync<WebLog> cfg.conn
|> Seq.tryHead

View File

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>1fba0b84-b09e-4b16-b9b6-5730dea27192</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>myWebLog.Data</RootNamespace>
<AssemblyName>myWebLog.Data</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<TargetFSharpCoreVersion>4.4.0.0</TargetFSharpCoreVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Name>myWebLog.Data</Name>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<Tailcalls>false</Tailcalls>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<DocumentationFile>bin\Debug\myWebLog.Data.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Tailcalls>true</Tailcalls>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<DocumentationFile>bin\Release\myWebLog.Data.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
</PropertyGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '11.0'">
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</Otherwise>
</Choose>
<Import Project="$(FSharpTargetsPath)" />
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="Entities.fs" />
<Compile Include="Table.fs" />
<Compile Include="DataConfig.fs" />
<Compile Include="Rethink.fs" />
<Compile Include="SetUp.fs" />
<Compile Include="WebLog.fs" />
<Content Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="Common.Logging">
<HintPath>..\packages\Common.Logging.3.3.0\lib\net40\Common.Logging.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Common.Logging.Core">
<HintPath>..\packages\Common.Logging.Core.3.3.0\lib\net40\Common.Logging.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="RethinkDb.Driver">
<HintPath>..\packages\RethinkDb.Driver.2.3.8\lib\net45\RethinkDb.Driver.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
</ItemGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Common.Logging" version="3.3.0" targetFramework="net452" />
<package id="Common.Logging.Core" version="3.3.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
<package id="RethinkDb.Driver" version="2.3.8" targetFramework="net452" />
</packages>

View File

@ -0,0 +1,17 @@
using System.Resources;
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("myWebLog.Resources")]
[assembly: AssemblyDescription("Resources for the myWebLog package")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("myWebLog.Resources")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("a12ea8da-88bc-4447-90cb-a0e2dcc37523")]
[assembly: AssemblyVersion("0.9.1.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: NeutralResourcesLanguage("en-US")]

View File

@ -0,0 +1,72 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace myWebLog {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("myWebLog.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Log On.
/// </summary>
public static string LogOn {
get {
return ResourceManager.GetString("LogOn", resourceCulture);
}
}
}
}

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="LogOn" xml:space="preserve">
<value>Log On</value>
</data>
</root>

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A12EA8DA-88BC-4447-90CB-A0E2DCC37523}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>myWebLog</RootNamespace>
<AssemblyName>myWebLog.Resources</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

127
src/myWebLog.Web/App.fs Normal file
View File

@ -0,0 +1,127 @@
module myWebLog.App
open myWebLog
open myWebLog.Data
open myWebLog.Data.SetUp
open myWebLog.Data.WebLog
open myWebLog.Entities
open Nancy
open Nancy.Authentication.Forms
open Nancy.Bootstrapper
open Nancy.Cryptography
open Nancy.Owin
open Nancy.Security
open Nancy.Session
open Nancy.Session.Persistable
open Nancy.Session.RethinkDb
open Nancy.TinyIoc
open Nancy.ViewEngines.SuperSimpleViewEngine
open RethinkDb.Driver
open RethinkDb.Driver.Net
open Suave
open Suave.Owin
open System.Text.RegularExpressions
/// Set up a database connection
let cfg =
{ database = "myWebLog"
conn = RethinkDB.R.Connection()
.Hostname(RethinkDBConstants.DefaultHostname)
.Port(RethinkDBConstants.DefaultPort)
.AuthKey(RethinkDBConstants.DefaultAuthkey)
.Db("myWebLog")
.Timeout(RethinkDBConstants.DefaultTimeout)
.Connect() }
do
startUpCheck cfg
type TranslateTokenViewEngineMatcher() =
static let regex = Regex("@Translate\.(?<TranslationKey>[a-zA-Z0-9-_]+);?", RegexOptions.Compiled)
interface ISuperSimpleViewEngineMatcher with
member this.Invoke (content, model, host) =
regex.Replace(content, fun m -> let key = m.Groups.["TranslationKey"].Value
match Resources.ResourceManager.GetString key with
| null -> key
| xlat -> xlat)
/// Handle forms authentication
type MyWebLogUser(name, claims) =
interface IUserIdentity with
member this.UserName with get() = name
member this.Claims with get() = claims
member this.UserName with get() = (this :> IUserIdentity).UserName
member this.Claims with get() = (this :> IUserIdentity).Claims
type MyWebLogUserMapper(container : TinyIoCContainer) =
interface IUserMapper with
member this.GetUserFromIdentifier (identifier, context) =
match context.Request.PersistableSession.GetOrDefault(Keys.User, User.empty) with
| user when user.id = string identifier -> upcast MyWebLogUser(user.preferredName, user.claims)
| _ -> null
/// Set up the RethinkDB connection instance to be used by the IoC container
type ApplicationBootstrapper() =
inherit DefaultNancyBootstrapper()
override this.ConfigureRequestContainer (container, context) =
base.ConfigureRequestContainer (container, context)
container.Register<IUserMapper, MyWebLogUserMapper>()
|> ignore
override this.ApplicationStartup (container, pipelines) =
base.ApplicationStartup (container, pipelines)
// Data configuration
container.Register<DataConfig>(cfg)
|> ignore
// I18N in SSVE
container.Register<seq<ISuperSimpleViewEngineMatcher>>(fun _ _ ->
Seq.singleton (TranslateTokenViewEngineMatcher() :> ISuperSimpleViewEngineMatcher))
|> ignore
// Forms authentication configuration
let salt = (System.Text.ASCIIEncoding()).GetBytes "NoneOfYourBeesWax"
let auth =
FormsAuthenticationConfiguration(
CryptographyConfiguration = CryptographyConfiguration
(RijndaelEncryptionProvider(PassphraseKeyGenerator("Secrets", salt)),
DefaultHmacProvider(PassphraseKeyGenerator("Clandestine", salt))),
RedirectUrl = "~/user/logon",
UserMapper = container.Resolve<IUserMapper>())
FormsAuthentication.Enable (pipelines, auth)
// CSRF
Csrf.Enable pipelines
// Sessions
let sessions = RethinkDbSessionConfiguration(cfg.conn)
sessions.Database <- cfg.database
PersistableSessions.Enable (pipelines, sessions)
()
let version =
let v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version
match v.Build with
| 0 -> match v.Minor with
| 0 -> string v.Major
| _ -> sprintf "%d.%d" v.Major v.Minor
| _ -> sprintf "%d.%d.%d" v.Major v.Minor v.Build
|> sprintf "v%s"
/// Set up the request environment
type RequestEnvironment() =
interface IRequestStartup with
member this.Initialize (pipelines, context) =
pipelines.BeforeRequest.AddItemToStartOfPipeline
(fun ctx -> ctx.Items.["requestStart"] <- System.DateTime.Now.Ticks
match tryFindWebLogByUrlBase cfg ctx.Request.Url.HostName with
| Some webLog -> ctx.Items.["webLog"] <- webLog
| None -> System.ApplicationException
(sprintf "%s is not properly configured for myWebLog" ctx.Request.Url.HostName)
|> raise
ctx.Items.["version"] <- version
null)
let app = OwinApp.ofMidFunc "/" (NancyMiddleware.UseNancy (NancyOptions()))
let run () = startWebServer defaultConfig app // webPart

View File

@ -0,0 +1,21 @@
namespace myWebLog.Web.AssemblyInfo
open System.Reflection
open System.Runtime.CompilerServices
open System.Runtime.InteropServices
[<assembly: AssemblyTitle("myWebLog.Web")>]
[<assembly: AssemblyDescription("Main Nancy assembly for myWebLog")>]
[<assembly: AssemblyConfiguration("")>]
[<assembly: AssemblyCompany("DJS Consulting")>]
[<assembly: AssemblyProduct("myWebLog.Web")>]
[<assembly: AssemblyCopyright("Copyright © 2016")>]
[<assembly: AssemblyTrademark("")>]
[<assembly: AssemblyCulture("")>]
[<assembly: ComVisible(false)>]
[<assembly: Guid("e6ee110a-27a6-4a19-b0cb-d24f48f71b53")>]
[<assembly: AssemblyVersion("0.9.1.0")>]
[<assembly: AssemblyFileVersion("1.0.0.0")>]
do
()

3
src/myWebLog.Web/Keys.fs Normal file
View File

@ -0,0 +1,3 @@
module myWebLog.Keys
let User = "user"

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>e6ee110a-27a6-4a19-b0cb-d24f48f71b53</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>myWebLog.Web</RootNamespace>
<AssemblyName>myWebLog.Web</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<TargetFSharpCoreVersion>4.4.0.0</TargetFSharpCoreVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Name>myWebLog.Web</Name>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<Tailcalls>false</Tailcalls>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<DocumentationFile>bin\Debug\myWebLog.Web.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Tailcalls>true</Tailcalls>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<DocumentationFile>bin\Release\myWebLog.Web.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
</PropertyGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '11.0'">
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</Otherwise>
</Choose>
<Import Project="$(FSharpTargetsPath)" />
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="Keys.fs" />
<Compile Include="App.fs" />
<Content Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="Common.Logging">
<HintPath>..\packages\Common.Logging.3.3.1\lib\net40\Common.Logging.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Common.Logging.Core">
<HintPath>..\packages\Common.Logging.Core.3.3.1\lib\net40\Common.Logging.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="FSharp.Core">
<HintPath>..\packages\FSharp.Core.4.0.0.1\lib\net40\FSharp.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="Nancy">
<HintPath>..\packages\Nancy.1.4.3\lib\net40\Nancy.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Nancy.Authentication.Forms">
<HintPath>..\packages\Nancy.Authentication.Forms.1.4.1\lib\net40\Nancy.Authentication.Forms.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Nancy.Session.Persistable">
<HintPath>..\packages\Nancy.Session.Persistable.0.8.6\lib\net452\Nancy.Session.Persistable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Nancy.Session.RethinkDb">
<HintPath>..\packages\Nancy.Session.RethinkDB.0.8.6\lib\net452\Nancy.Session.RethinkDb.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="RethinkDb.Driver">
<HintPath>..\packages\RethinkDb.Driver.2.3.8\lib\net45\RethinkDb.Driver.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Suave">
<HintPath>..\packages\Suave.1.1.3\lib\net40\Suave.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\myWebLog.Data\myWebLog.Data.fsproj">
<Name>myWebLog.Data</Name>
<Project>{1fba0b84-b09e-4b16-b9b6-5730dea27192}</Project>
<Private>True</Private>
</ProjectReference>
<ProjectReference Include="..\myWebLog.Resources\myWebLog.Resources.csproj">
<Name>myWebLog.Resources</Name>
<Project>{a12ea8da-88bc-4447-90cb-a0e2dcc37523}</Project>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Common.Logging" version="3.3.1" targetFramework="net452" />
<package id="Common.Logging.Core" version="3.3.1" targetFramework="net452" />
<package id="FSharp.Core" version="4.0.0.1" targetFramework="net452" />
<package id="Nancy" version="1.4.3" targetFramework="net452" />
<package id="Nancy.Authentication.Forms" version="1.4.1" targetFramework="net452" />
<package id="Nancy.Session.Persistable" version="0.8.6" targetFramework="net452" />
<package id="Nancy.Session.RethinkDB" version="0.8.6" targetFramework="net452" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
<package id="RethinkDb.Driver" version="2.3.8" targetFramework="net452" />
<package id="Suave" version="1.1.3" targetFramework="net452" />
</packages>

40
src/myWebLog.sln Normal file
View File

@ -0,0 +1,40 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "myWebLog", "myWebLog\myWebLog.csproj", "{B9F6DB52-65A1-4C2A-8C97-739E08A1D4FB}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "myWebLog.Web", "myWebLog.Web\myWebLog.Web.fsproj", "{E6EE110A-27A6-4A19-B0CB-D24F48F71B53}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "myWebLog.Data", "myWebLog.Data\myWebLog.Data.fsproj", "{1FBA0B84-B09E-4B16-B9B6-5730DEA27192}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "myWebLog.Resources", "myWebLog.Resources\myWebLog.Resources.csproj", "{A12EA8DA-88BC-4447-90CB-A0E2DCC37523}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B9F6DB52-65A1-4C2A-8C97-739E08A1D4FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B9F6DB52-65A1-4C2A-8C97-739E08A1D4FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B9F6DB52-65A1-4C2A-8C97-739E08A1D4FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B9F6DB52-65A1-4C2A-8C97-739E08A1D4FB}.Release|Any CPU.Build.0 = Release|Any CPU
{E6EE110A-27A6-4A19-B0CB-D24F48F71B53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E6EE110A-27A6-4A19-B0CB-D24F48F71B53}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E6EE110A-27A6-4A19-B0CB-D24F48F71B53}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E6EE110A-27A6-4A19-B0CB-D24F48F71B53}.Release|Any CPU.Build.0 = Release|Any CPU
{1FBA0B84-B09E-4B16-B9B6-5730DEA27192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1FBA0B84-B09E-4B16-B9B6-5730DEA27192}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1FBA0B84-B09E-4B16-B9B6-5730DEA27192}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1FBA0B84-B09E-4B16-B9B6-5730DEA27192}.Release|Any CPU.Build.0 = Release|Any CPU
{A12EA8DA-88BC-4447-90CB-A0E2DCC37523}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A12EA8DA-88BC-4447-90CB-A0E2DCC37523}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A12EA8DA-88BC-4447-90CB-A0E2DCC37523}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A12EA8DA-88BC-4447-90CB-A0E2DCC37523}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

6
src/myWebLog/App.config Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>

10
src/myWebLog/Program.cs Normal file
View File

@ -0,0 +1,10 @@
namespace myWebLog
{
class Program
{
static void Main(string[] args)
{
App.run();
}
}
}

View File

@ -0,0 +1,15 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("myWebLog")]
[assembly: AssemblyDescription("A lightweight blogging platform built on Nancy and RethinkDB")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("myWebLog")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("b9f6db52-65a1-4c2a-8c97-739e08a1d4fb")]
[assembly: AssemblyVersion("0.9.1.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B9F6DB52-65A1-4C2A-8C97-739E08A1D4FB}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>myWebLog</RootNamespace>
<AssemblyName>myWebLog</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\myWebLog.Data\myWebLog.Data.fsproj">
<Project>{1fba0b84-b09e-4b16-b9b6-5730dea27192}</Project>
<Name>myWebLog.Data</Name>
</ProjectReference>
<ProjectReference Include="..\myWebLog.Resources\myWebLog.Resources.csproj">
<Project>{a12ea8da-88bc-4447-90cb-a0e2dcc37523}</Project>
<Name>myWebLog.Resources</Name>
</ProjectReference>
<ProjectReference Include="..\myWebLog.Web\myWebLog.Web.fsproj">
<Project>{e6ee110a-27a6-4a19-b0cb-d24f48f71b53}</Project>
<Name>myWebLog.Web</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Content Include="views\default\index-content.html" />
<Content Include="views\default\index.html" />
<Content Include="views\default\layout.html" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,38 @@
@If.subTitle
<h2>
<span class="label label-info">@Model.subTitle</span>
</h2>
@EndIf
@Each.posts
<div class="row">
<div class="col-xs-12">
<article>
<h1>
<a href="/@Current.permalink" title="Permanent Link to &quot;@Current.title@quot;">@Current.title</a>
</h1>
<!-- var pubDate = moment(post.publishedDate) -->
<p>
<i class="fa fa-calendar" title="@Translate.Date" /> &nbsp; @Current.publishedDate <!-- #{pubDate.format('MMMM Do, YYYY')} -->
<i class="fa fa-clock-o" title="@Translate.Time" /> &nbsp; @Current.publishedTime <!-- #{pubDate.format('h:mma')} -->
</p>
@Current.text
</article>
<hr />
</div>
</div>
@EndEach
<div class="row">
<div class="col-xs-3 col-xs-offset-3">
// TODO: stopped here
if hasNext
- var nextLink = (2 < page) ? '/page/' + (page - 1) : '/'
if '/posts' == extraUrl && 2 == page
//- Leave the "next" link at '/'
else
- nextLink = extraUrl + nextLink
p: a.btn.btn-primary(href="#{nextLink}")= __("Newer Posts")
</div>
.col-xs-3.text-right
if hasPrior
p: a.btn.btn-primary(href=extraUrl + '/page/' + (page + 1))= __("Older Posts")
</div>

View File

@ -0,0 +1,5 @@
@Master['default/layout']
@Section['Content']
@Partial['default/index-content', Model]
@EndSection

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<meta name="generator" content="@Model.generator" />
<title>@Model.pageTitle | @Model.webLog.name</title>
<link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="/styles/bootstrap-theme.min.css" />
<link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" />
@Section['Head'];
</head>
<body>
<header>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="/">@Model.webLog.name</a>
</div>
<p class="navbar-text">@Model.webLog.subtitle</p>
<ul class="nav navbar-nav navbar-left">
@Each.webLog.pageList
<li>
<a href="/@Current.permalink">@Current.title</a>
@EndEach
</ul>
<ul class="nav navbar-nav navbar-right">
@If.isAuthenticated
<li><a href="/admin">@Translate.Dashboard</a></li>
<li><a href="/user/logoff">@Translate.LogOff</a></li>
@EndIf
@IfNot.isAuthenticated
<li><a href="/user/logon">@Translate.LogOn</a></li>
@EndIf
</ul>
</div>
</nav>
</header>
<div class="container">
@Section['Content'];
</div>
@Section['Footer'];
<script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
@Section['Scripts'];
</body>
</html>