Huge repo reorganization
In no particular order... - Created projects using F# generator, using Paket and FAKE - Split "entities" into their own project, and created interface for data functions required on those entities - Renamed "data" project and used it as an implementation of data access - Created "logic" layer that takes the data interface, and does the non-persistence-related manipulation of items - Moved "web" project to "app", and modified Nancy modules to utilize Logic project and data interface instead of Data project and RethinkDB connection - Created test placeholder project; will be filling that out shortly (TAD?)
This commit is contained in:
parent
8194649018
commit
710004dfc4
4
.gitignore
vendored
4
.gitignore
vendored
@ -21,6 +21,8 @@ bld/
|
|||||||
[Bb]in/
|
[Bb]in/
|
||||||
[Oo]bj/
|
[Oo]bj/
|
||||||
[Ll]og/
|
[Ll]og/
|
||||||
|
[Bb]uild/
|
||||||
|
[Dd]eploy/
|
||||||
|
|
||||||
# Visual Studio 2015 cache/options directory
|
# Visual Studio 2015 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
@ -241,7 +243,7 @@ FakesAssemblies/
|
|||||||
_Pvt_Extensions
|
_Pvt_Extensions
|
||||||
|
|
||||||
# Paket dependency manager
|
# Paket dependency manager
|
||||||
.paket/paket.exe
|
**/.paket/paket.exe
|
||||||
paket-files/
|
paket-files/
|
||||||
|
|
||||||
# FAKE - F# Make
|
# FAKE - F# Make
|
||||||
|
BIN
src/.paket/paket.bootstrapper.exe
Normal file
BIN
src/.paket/paket.bootstrapper.exe
Normal file
Binary file not shown.
@ -1,12 +1,13 @@
|
|||||||
namespace MyWebLog
|
namespace MyWebLog
|
||||||
|
|
||||||
open MyWebLog.Data.WebLog
|
open MyWebLog.Data
|
||||||
open MyWebLog.Entities
|
open MyWebLog.Entities
|
||||||
|
open MyWebLog.Logic.WebLog
|
||||||
open Nancy
|
open Nancy
|
||||||
open RethinkDb.Driver.Net
|
open RethinkDb.Driver.Net
|
||||||
|
|
||||||
/// Handle /admin routes
|
/// Handle /admin routes
|
||||||
type AdminModule(conn : IConnection) as this =
|
type AdminModule(data : IMyWebLogData) as this =
|
||||||
inherit NancyModule("/admin")
|
inherit NancyModule("/admin")
|
||||||
|
|
||||||
do
|
do
|
||||||
@ -15,6 +16,6 @@ type AdminModule(conn : IConnection) as this =
|
|||||||
/// Admin dashboard
|
/// Admin dashboard
|
||||||
member this.Dashboard () =
|
member this.Dashboard () =
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let model = DashboardModel(this.Context, this.WebLog, findDashboardCounts conn this.WebLog.Id)
|
let model = DashboardModel(this.Context, this.WebLog, findDashboardCounts data this.WebLog.Id)
|
||||||
model.PageTitle <- Resources.Dashboard
|
model.PageTitle <- Resources.Dashboard
|
||||||
upcast this.View.["admin/dashboard", model]
|
upcast this.View.["admin/dashboard", model]
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
open MyWebLog
|
open MyWebLog
|
||||||
open MyWebLog.Data
|
open MyWebLog.Data
|
||||||
open MyWebLog.Data.SetUp
|
open MyWebLog.Data.RethinkDB
|
||||||
open MyWebLog.Data.WebLog
|
|
||||||
open MyWebLog.Entities
|
open MyWebLog.Entities
|
||||||
|
open MyWebLog.Logic.WebLog
|
||||||
open Nancy
|
open Nancy
|
||||||
open Nancy.Authentication.Forms
|
open Nancy.Authentication.Forms
|
||||||
open Nancy.Bootstrapper
|
open Nancy.Bootstrapper
|
||||||
@ -13,6 +13,7 @@ open Nancy.Cryptography
|
|||||||
open Nancy.Owin
|
open Nancy.Owin
|
||||||
open Nancy.Security
|
open Nancy.Security
|
||||||
open Nancy.Session.Persistable
|
open Nancy.Session.Persistable
|
||||||
|
//open Nancy.Session.Relational
|
||||||
open Nancy.Session.RethinkDb
|
open Nancy.Session.RethinkDb
|
||||||
open Nancy.TinyIoc
|
open Nancy.TinyIoc
|
||||||
open Nancy.ViewEngines.SuperSimpleViewEngine
|
open Nancy.ViewEngines.SuperSimpleViewEngine
|
||||||
@ -21,6 +22,7 @@ open RethinkDb.Driver.Net
|
|||||||
open Suave
|
open Suave
|
||||||
open Suave.Owin
|
open Suave.Owin
|
||||||
open System
|
open System
|
||||||
|
open System.Configuration
|
||||||
open System.IO
|
open System.IO
|
||||||
open System.Text.RegularExpressions
|
open System.Text.RegularExpressions
|
||||||
|
|
||||||
@ -28,8 +30,10 @@ open System.Text.RegularExpressions
|
|||||||
let cfg = try AppConfig.FromJson (System.IO.File.ReadAllText "config.json")
|
let cfg = try AppConfig.FromJson (System.IO.File.ReadAllText "config.json")
|
||||||
with ex -> raise <| ApplicationException(Resources.ErrBadAppConfig, ex)
|
with ex -> raise <| ApplicationException(Resources.ErrBadAppConfig, ex)
|
||||||
|
|
||||||
|
let data : IMyWebLogData = upcast RethinkMyWebLogData(cfg.DataConfig.Conn, cfg.DataConfig)
|
||||||
|
|
||||||
do
|
do
|
||||||
startUpCheck cfg.DataConfig
|
data.SetUp ()
|
||||||
|
|
||||||
/// Support RESX lookup via the @Translate SSVE alias
|
/// Support RESX lookup via the @Translate SSVE alias
|
||||||
type TranslateTokenViewEngineMatcher() =
|
type TranslateTokenViewEngineMatcher() =
|
||||||
@ -83,10 +87,10 @@ type MyWebLogBootstrapper() =
|
|||||||
|
|
||||||
override this.ApplicationStartup (container, pipelines) =
|
override this.ApplicationStartup (container, pipelines) =
|
||||||
base.ApplicationStartup (container, pipelines)
|
base.ApplicationStartup (container, pipelines)
|
||||||
// Data configuration (both config and the connection; Nancy modules just need the connection)
|
// Application configuration
|
||||||
container.Register<AppConfig>(cfg)
|
container.Register<AppConfig>(cfg)
|
||||||
|> ignore
|
|> ignore
|
||||||
container.Register<IConnection>(cfg.DataConfig.Conn)
|
container.Register<IMyWebLogData>(data)
|
||||||
|> ignore
|
|> ignore
|
||||||
// NodaTime
|
// NodaTime
|
||||||
container.Register<IClock>(SystemClock.Instance)
|
container.Register<IClock>(SystemClock.Instance)
|
||||||
@ -110,6 +114,7 @@ type MyWebLogBootstrapper() =
|
|||||||
// Sessions
|
// Sessions
|
||||||
let sessions = RethinkDbSessionConfiguration(cfg.DataConfig.Conn)
|
let sessions = RethinkDbSessionConfiguration(cfg.DataConfig.Conn)
|
||||||
sessions.Database <- cfg.DataConfig.Database
|
sessions.Database <- cfg.DataConfig.Database
|
||||||
|
//let sessions = RelationalSessionConfiguration(ConfigurationManager.ConnectionStrings.["SessionStore"].ConnectionString)
|
||||||
PersistableSessions.Enable (pipelines, sessions)
|
PersistableSessions.Enable (pipelines, sessions)
|
||||||
()
|
()
|
||||||
|
|
||||||
@ -127,7 +132,7 @@ type RequestEnvironment() =
|
|||||||
member this.Initialize (pipelines, context) =
|
member this.Initialize (pipelines, context) =
|
||||||
let establishEnv (ctx : NancyContext) =
|
let establishEnv (ctx : NancyContext) =
|
||||||
ctx.Items.[Keys.RequestStart] <- DateTime.Now.Ticks
|
ctx.Items.[Keys.RequestStart] <- DateTime.Now.Ticks
|
||||||
match tryFindWebLogByUrlBase cfg.DataConfig.Conn ctx.Request.Url.HostName with
|
match tryFindWebLogByUrlBase data ctx.Request.Url.HostName with
|
||||||
| Some webLog -> ctx.Items.[Keys.WebLog] <- webLog
|
| Some webLog -> ctx.Items.[Keys.WebLog] <- webLog
|
||||||
| None -> // TODO: redirect to domain set up page
|
| None -> // TODO: redirect to domain set up page
|
||||||
ApplicationException (sprintf "%s %s" ctx.Request.Url.HostName Resources.ErrNotConfigured)
|
ApplicationException (sprintf "%s %s" ctx.Request.Url.HostName Resources.ErrNotConfigured)
|
@ -1,6 +1,6 @@
|
|||||||
namespace MyWebLog
|
namespace MyWebLog
|
||||||
|
|
||||||
open MyWebLog.Data
|
open MyWebLog.Data.RethinkDB
|
||||||
open Newtonsoft.Json
|
open Newtonsoft.Json
|
||||||
open System.Text
|
open System.Text
|
||||||
|
|
@ -1,6 +1,7 @@
|
|||||||
namespace MyWebLog
|
namespace MyWebLog
|
||||||
|
|
||||||
open MyWebLog.Data.Category
|
open MyWebLog.Data
|
||||||
|
open MyWebLog.Logic.Category
|
||||||
open MyWebLog.Entities
|
open MyWebLog.Entities
|
||||||
open Nancy
|
open Nancy
|
||||||
open Nancy.ModelBinding
|
open Nancy.ModelBinding
|
||||||
@ -8,7 +9,7 @@ open Nancy.Security
|
|||||||
open RethinkDb.Driver.Net
|
open RethinkDb.Driver.Net
|
||||||
|
|
||||||
/// Handle /category and /categories URLs
|
/// Handle /category and /categories URLs
|
||||||
type CategoryModule(conn : IConnection) as this =
|
type CategoryModule(data : IMyWebLogData) as this =
|
||||||
inherit NancyModule()
|
inherit NancyModule()
|
||||||
|
|
||||||
do
|
do
|
||||||
@ -21,7 +22,7 @@ type CategoryModule(conn : IConnection) as this =
|
|||||||
member this.CategoryList () =
|
member this.CategoryList () =
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let model = CategoryListModel(this.Context, this.WebLog,
|
let model = CategoryListModel(this.Context, this.WebLog,
|
||||||
(getAllCategories conn this.WebLog.Id
|
(findAllCategories data this.WebLog.Id
|
||||||
|> List.map (fun cat -> IndentedCategory.Create cat (fun _ -> false))))
|
|> List.map (fun cat -> IndentedCategory.Create cat (fun _ -> false))))
|
||||||
upcast this.View.["/admin/category/list", model]
|
upcast this.View.["/admin/category/list", model]
|
||||||
|
|
||||||
@ -31,13 +32,13 @@ type CategoryModule(conn : IConnection) as this =
|
|||||||
let catId = parameters.["id"].ToString ()
|
let catId = parameters.["id"].ToString ()
|
||||||
match (match catId with
|
match (match catId with
|
||||||
| "new" -> Some Category.Empty
|
| "new" -> Some Category.Empty
|
||||||
| _ -> tryFindCategory conn this.WebLog.Id catId) with
|
| _ -> tryFindCategory data this.WebLog.Id catId) with
|
||||||
| Some cat -> let model = CategoryEditModel(this.Context, this.WebLog, cat)
|
| Some cat -> let model = CategoryEditModel(this.Context, this.WebLog, cat)
|
||||||
model.Categories <- getAllCategories conn this.WebLog.Id
|
model.Categories <- findAllCategories data this.WebLog.Id
|
||||||
|> List.map (fun cat -> IndentedCategory.Create cat
|
|> List.map (fun cat -> IndentedCategory.Create cat
|
||||||
(fun c -> c = defaultArg (fst cat).ParentId ""))
|
(fun c -> c = defaultArg (fst cat).ParentId ""))
|
||||||
upcast this.View.["admin/category/edit", model]
|
upcast this.View.["admin/category/edit", model]
|
||||||
| None -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Save a category
|
/// Save a category
|
||||||
member this.SaveCategory (parameters : DynamicDictionary) =
|
member this.SaveCategory (parameters : DynamicDictionary) =
|
||||||
@ -45,41 +46,43 @@ type CategoryModule(conn : IConnection) as this =
|
|||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let catId = parameters.["id"].ToString ()
|
let catId = parameters.["id"].ToString ()
|
||||||
let form = this.Bind<CategoryForm> ()
|
let form = this.Bind<CategoryForm> ()
|
||||||
let oldCat = match catId with "new" -> Some Category.Empty | _ -> tryFindCategory conn this.WebLog.Id catId
|
let oldCat = match catId with
|
||||||
|
| "new" -> Some { Category.Empty with WebLogId = this.WebLog.Id }
|
||||||
|
| _ -> tryFindCategory data this.WebLog.Id catId
|
||||||
match oldCat with
|
match oldCat with
|
||||||
| Some old -> let cat = { old with Name = form.Name
|
| Some old -> let cat = { old with Name = form.Name
|
||||||
Slug = form.Slug
|
Slug = form.Slug
|
||||||
Description = match form.Description with "" -> None | d -> Some d
|
Description = match form.Description with "" -> None | d -> Some d
|
||||||
ParentId = match form.ParentId with "" -> None | p -> Some p }
|
ParentId = match form.ParentId with "" -> None | p -> Some p }
|
||||||
let newCatId = saveCategory conn this.WebLog.Id cat
|
let newCatId = saveCategory data cat
|
||||||
match old.ParentId = cat.ParentId with
|
match old.ParentId = cat.ParentId with
|
||||||
| true -> ()
|
| true -> ()
|
||||||
| _ -> match old.ParentId with
|
| _ -> match old.ParentId with
|
||||||
| Some parentId -> removeCategoryFromParent conn this.WebLog.Id parentId newCatId
|
| Some parentId -> removeCategoryFromParent data this.WebLog.Id parentId newCatId
|
||||||
| None -> ()
|
| _ -> ()
|
||||||
match cat.ParentId with
|
match cat.ParentId with
|
||||||
| Some parentId -> addCategoryToParent conn this.WebLog.Id parentId newCatId
|
| Some parentId -> addCategoryToParent data this.WebLog.Id parentId newCatId
|
||||||
| None -> ()
|
| _ -> ()
|
||||||
let model = MyWebLogModel(this.Context, this.WebLog)
|
let model = MyWebLogModel(this.Context, this.WebLog)
|
||||||
{ UserMessage.Empty with
|
{ UserMessage.Empty with
|
||||||
Level = Level.Info
|
Level = Level.Info
|
||||||
Message = System.String.Format
|
Message = System.String.Format
|
||||||
(Resources.MsgCategoryEditSuccess,
|
(Resources.MsgCategoryEditSuccess,
|
||||||
(match catId with | "new" -> Resources.Added | _ -> Resources.Updated)) }
|
(match catId with "new" -> Resources.Added | _ -> Resources.Updated)) }
|
||||||
|> model.AddMessage
|
|> model.AddMessage
|
||||||
this.Redirect (sprintf "/category/%s/edit" newCatId) model
|
this.Redirect (sprintf "/category/%s/edit" newCatId) model
|
||||||
| None -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Delete a category
|
/// Delete a category
|
||||||
member this.DeleteCategory (parameters : DynamicDictionary) =
|
member this.DeleteCategory (parameters : DynamicDictionary) =
|
||||||
this.ValidateCsrfToken ()
|
this.ValidateCsrfToken ()
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let catId = parameters.["id"].ToString ()
|
let catId = parameters.["id"].ToString ()
|
||||||
match tryFindCategory conn this.WebLog.Id catId with
|
match tryFindCategory data this.WebLog.Id catId with
|
||||||
| Some cat -> deleteCategory conn cat
|
| Some cat -> deleteCategory data cat
|
||||||
let model = MyWebLogModel(this.Context, this.WebLog)
|
let model = MyWebLogModel(this.Context, this.WebLog)
|
||||||
{ UserMessage.Empty with Level = Level.Info
|
{ UserMessage.Empty with Level = Level.Info
|
||||||
Message = System.String.Format(Resources.MsgCategoryDeleted, cat.Name) }
|
Message = System.String.Format(Resources.MsgCategoryDeleted, cat.Name) }
|
||||||
|> model.AddMessage
|
|> model.AddMessage
|
||||||
this.Redirect "/categories" model
|
this.Redirect "/categories" model
|
||||||
| None -> this.NotFound ()
|
| _ -> this.NotFound ()
|
302
src/MyWebLog.App/MyWebLog.App.fsproj
Normal file
302
src/MyWebLog.App/MyWebLog.App.fsproj
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="12.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>9cea3a8b-e8aa-44e6-9f5f-2095ceed54eb</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<RootNamespace>MyWebLog.App</RootNamespace>
|
||||||
|
<AssemblyName>MyWebLog.App</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||||
|
<TargetFSharpCoreVersion>4.4.0.0</TargetFSharpCoreVersion>
|
||||||
|
<Name>MyWebLog.App</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.App.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.App.xml</DocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="mscorlib" />
|
||||||
|
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Numerics" />
|
||||||
|
<Reference Include="System.ServiceModel" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="AssemblyInfo.fs" />
|
||||||
|
<Compile Include="Keys.fs" />
|
||||||
|
<Compile Include="AppConfig.fs" />
|
||||||
|
<Compile Include="ViewModels.fs" />
|
||||||
|
<Compile Include="ModuleExtensions.fs" />
|
||||||
|
<Compile Include="AdminModule.fs" />
|
||||||
|
<Compile Include="CategoryModule.fs" />
|
||||||
|
<Compile Include="PageModule.fs" />
|
||||||
|
<Compile Include="PostModule.fs" />
|
||||||
|
<Compile Include="UserModule.fs" />
|
||||||
|
<Compile Include="App.fs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MyWebLog.Data.RethinkDB\MyWebLog.Data.RethinkDB.fsproj">
|
||||||
|
<Name>MyWebLog.Data.RethinkDB</Name>
|
||||||
|
<Project>{d6c2be5e-883a-4f34-9905-b730543ca380}</Project>
|
||||||
|
<Private>True</Private>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\MyWebLog.Entities\MyWebLog.Entities.fsproj">
|
||||||
|
<Name>MyWebLog.Entities</Name>
|
||||||
|
<Project>{a87f3cf5-2189-442b-8acf-929f5153ac22}</Project>
|
||||||
|
<Private>True</Private>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\MyWebLog.Logic\MyWebLog.Logic.fsproj">
|
||||||
|
<Name>MyWebLog.Logic</Name>
|
||||||
|
<Project>{29f6eda3-4f43-4bb3-9c63-ae238a9b7f12}</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>
|
||||||
|
<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)" Condition="Exists('$(FSharpTargetsPath)')" />
|
||||||
|
<!-- 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>
|
||||||
|
-->
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Common.Logging">
|
||||||
|
<HintPath>..\packages\Common.Logging\lib\net40\Common.Logging.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Common.Logging.Core">
|
||||||
|
<HintPath>..\packages\Common.Logging.Core\lib\net40\Common.Logging.Core.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v4.0'">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="FSharp.Compiler.Service">
|
||||||
|
<HintPath>..\packages\FSharp.Compiler.Service\lib\net40\FSharp.Compiler.Service.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="FSharp.Compiler.Service">
|
||||||
|
<HintPath>..\packages\FSharp.Compiler.Service\lib\net45\FSharp.Compiler.Service.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="CSharpFormat">
|
||||||
|
<HintPath>..\packages\FSharp.Formatting\lib\net40\CSharpFormat.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="FSharp.CodeFormat">
|
||||||
|
<HintPath>..\packages\FSharp.Formatting\lib\net40\FSharp.CodeFormat.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="FSharp.Formatting.Common">
|
||||||
|
<HintPath>..\packages\FSharp.Formatting\lib\net40\FSharp.Formatting.Common.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="FSharp.Literate">
|
||||||
|
<HintPath>..\packages\FSharp.Formatting\lib\net40\FSharp.Literate.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="FSharp.Markdown">
|
||||||
|
<HintPath>..\packages\FSharp.Formatting\lib\net40\FSharp.Markdown.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="FSharp.MetadataFormat">
|
||||||
|
<HintPath>..\packages\FSharp.Formatting\lib\net40\FSharp.MetadataFormat.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="RazorEngine">
|
||||||
|
<HintPath>..\packages\FSharp.Formatting\lib\net40\RazorEngine.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Web.Razor">
|
||||||
|
<HintPath>..\packages\FSharp.Formatting\lib\net40\System.Web.Razor.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="FSharpVSPowerTools.Core">
|
||||||
|
<HintPath>..\packages\FSharpVSPowerTools.Core\lib\net45\FSharpVSPowerTools.Core.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Nancy">
|
||||||
|
<HintPath>..\packages\Nancy\lib\net40\Nancy.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Nancy.Authentication.Forms">
|
||||||
|
<HintPath>..\packages\Nancy.Authentication.Forms\lib\net40\Nancy.Authentication.Forms.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v4.5.2'">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Nancy.Session.Persistable">
|
||||||
|
<HintPath>..\packages\Nancy.Session.Persistable\lib\net452\Nancy.Session.Persistable.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v4.5.2'">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Nancy.Session.RethinkDb">
|
||||||
|
<HintPath>..\packages\Nancy.Session.RethinkDB\lib\net452\Nancy.Session.RethinkDb.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v4.0'">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
<HintPath>..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
<HintPath>..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="NodaTime">
|
||||||
|
<HintPath>..\packages\NodaTime\lib\net35-Client\NodaTime.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Xml">
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="RethinkDb.Driver">
|
||||||
|
<HintPath>..\packages\RethinkDb.Driver\lib\net45\RethinkDb.Driver.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Suave">
|
||||||
|
<HintPath>..\packages\Suave\lib\net40\Suave.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
</Project>
|
@ -1,8 +1,9 @@
|
|||||||
namespace MyWebLog
|
namespace MyWebLog
|
||||||
|
|
||||||
open FSharp.Markdown
|
open FSharp.Markdown
|
||||||
open MyWebLog.Data.Page
|
open MyWebLog.Data
|
||||||
open MyWebLog.Entities
|
open MyWebLog.Entities
|
||||||
|
open MyWebLog.Logic.Page
|
||||||
open Nancy
|
open Nancy
|
||||||
open Nancy.ModelBinding
|
open Nancy.ModelBinding
|
||||||
open Nancy.Security
|
open Nancy.Security
|
||||||
@ -10,7 +11,7 @@ open NodaTime
|
|||||||
open RethinkDb.Driver.Net
|
open RethinkDb.Driver.Net
|
||||||
|
|
||||||
/// Handle /pages and /page URLs
|
/// Handle /pages and /page URLs
|
||||||
type PageModule(conn : IConnection, clock : IClock) as this =
|
type PageModule(data : IMyWebLogData, clock : IClock) as this =
|
||||||
inherit NancyModule()
|
inherit NancyModule()
|
||||||
|
|
||||||
do
|
do
|
||||||
@ -22,7 +23,7 @@ type PageModule(conn : IConnection, clock : IClock) as this =
|
|||||||
/// List all pages
|
/// List all pages
|
||||||
member this.PageList () =
|
member this.PageList () =
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let model = PagesModel(this.Context, this.WebLog, (findAllPages conn this.WebLog.Id
|
let model = PagesModel(this.Context, this.WebLog, (findAllPages data this.WebLog.Id
|
||||||
|> List.map (fun p -> PageForDisplay(this.WebLog, p))))
|
|> List.map (fun p -> PageForDisplay(this.WebLog, p))))
|
||||||
model.PageTitle <- Resources.Pages
|
model.PageTitle <- Resources.Pages
|
||||||
upcast this.View.["admin/page/list", model]
|
upcast this.View.["admin/page/list", model]
|
||||||
@ -33,16 +34,16 @@ type PageModule(conn : IConnection, clock : IClock) as this =
|
|||||||
let pageId = parameters.["id"].ToString ()
|
let pageId = parameters.["id"].ToString ()
|
||||||
match (match pageId with
|
match (match pageId with
|
||||||
| "new" -> Some Page.Empty
|
| "new" -> Some Page.Empty
|
||||||
| _ -> tryFindPage conn this.WebLog.Id pageId) with
|
| _ -> tryFindPage data this.WebLog.Id pageId) with
|
||||||
| Some page -> let rev = match page.Revisions
|
| Some page -> let rev = match page.Revisions
|
||||||
|> List.sortByDescending (fun r -> r.AsOf)
|
|> List.sortByDescending (fun r -> r.AsOf)
|
||||||
|> List.tryHead with
|
|> List.tryHead with
|
||||||
| Some r -> r
|
| Some r -> r
|
||||||
| None -> Revision.Empty
|
| _ -> Revision.Empty
|
||||||
let model = EditPageModel(this.Context, this.WebLog, page, rev)
|
let model = EditPageModel(this.Context, this.WebLog, page, rev)
|
||||||
model.PageTitle <- match pageId with "new" -> Resources.AddNewPage | _ -> Resources.EditPage
|
model.PageTitle <- match pageId with "new" -> Resources.AddNewPage | _ -> Resources.EditPage
|
||||||
upcast this.View.["admin/page/edit", model]
|
upcast this.View.["admin/page/edit", model]
|
||||||
| None -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Save a page
|
/// Save a page
|
||||||
member this.SavePage (parameters : DynamicDictionary) =
|
member this.SavePage (parameters : DynamicDictionary) =
|
||||||
@ -51,7 +52,7 @@ type PageModule(conn : IConnection, clock : IClock) as this =
|
|||||||
let pageId = parameters.["id"].ToString ()
|
let pageId = parameters.["id"].ToString ()
|
||||||
let form = this.Bind<EditPageForm> ()
|
let form = this.Bind<EditPageForm> ()
|
||||||
let now = clock.Now.Ticks
|
let now = clock.Now.Ticks
|
||||||
match (match pageId with "new" -> Some Page.Empty | _ -> tryFindPage conn this.WebLog.Id pageId) with
|
match (match pageId with "new" -> Some Page.Empty | _ -> tryFindPage data this.WebLog.Id pageId) with
|
||||||
| Some p -> let page = match pageId with "new" -> { p with WebLogId = this.WebLog.Id } | _ -> p
|
| Some p -> let page = match pageId with "new" -> { p with WebLogId = this.WebLog.Id } | _ -> p
|
||||||
let pId = { p with
|
let pId = { p with
|
||||||
Title = form.Title
|
Title = form.Title
|
||||||
@ -64,7 +65,7 @@ type PageModule(conn : IConnection, clock : IClock) as this =
|
|||||||
Revisions = { AsOf = now
|
Revisions = { AsOf = now
|
||||||
SourceType = form.Source
|
SourceType = form.Source
|
||||||
Text = form.Text } :: page.Revisions }
|
Text = form.Text } :: page.Revisions }
|
||||||
|> savePage conn
|
|> savePage data
|
||||||
let model = MyWebLogModel(this.Context, this.WebLog)
|
let model = MyWebLogModel(this.Context, this.WebLog)
|
||||||
{ UserMessage.Empty with
|
{ UserMessage.Empty with
|
||||||
Level = Level.Info
|
Level = Level.Info
|
||||||
@ -73,18 +74,18 @@ type PageModule(conn : IConnection, clock : IClock) as this =
|
|||||||
(match pageId with "new" -> Resources.Added | _ -> Resources.Updated)) }
|
(match pageId with "new" -> Resources.Added | _ -> Resources.Updated)) }
|
||||||
|> model.AddMessage
|
|> model.AddMessage
|
||||||
this.Redirect (sprintf "/page/%s/edit" pId) model
|
this.Redirect (sprintf "/page/%s/edit" pId) model
|
||||||
| None -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Delete a page
|
/// Delete a page
|
||||||
member this.DeletePage (parameters : DynamicDictionary) =
|
member this.DeletePage (parameters : DynamicDictionary) =
|
||||||
this.ValidateCsrfToken ()
|
this.ValidateCsrfToken ()
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let pageId = parameters.["id"].ToString ()
|
let pageId = parameters.["id"].ToString ()
|
||||||
match tryFindPageWithoutRevisions conn this.WebLog.Id pageId with
|
match tryFindPageWithoutRevisions data this.WebLog.Id pageId with
|
||||||
| Some page -> deletePage conn page.WebLogId page.Id
|
| Some page -> deletePage data page.WebLogId page.Id
|
||||||
let model = MyWebLogModel(this.Context, this.WebLog)
|
let model = MyWebLogModel(this.Context, this.WebLog)
|
||||||
{ UserMessage.Empty with Level = Level.Info
|
{ UserMessage.Empty with Level = Level.Info
|
||||||
Message = Resources.MsgPageDeleted }
|
Message = Resources.MsgPageDeleted }
|
||||||
|> model.AddMessage
|
|> model.AddMessage
|
||||||
this.Redirect "/pages" model
|
this.Redirect "/pages" model
|
||||||
| None -> this.NotFound ()
|
| _ -> this.NotFound ()
|
@ -1,10 +1,11 @@
|
|||||||
namespace MyWebLog
|
namespace MyWebLog
|
||||||
|
|
||||||
open FSharp.Markdown
|
open FSharp.Markdown
|
||||||
open MyWebLog.Data.Category
|
open MyWebLog.Data
|
||||||
open MyWebLog.Data.Page
|
|
||||||
open MyWebLog.Data.Post
|
|
||||||
open MyWebLog.Entities
|
open MyWebLog.Entities
|
||||||
|
open MyWebLog.Logic.Category
|
||||||
|
open MyWebLog.Logic.Page
|
||||||
|
open MyWebLog.Logic.Post
|
||||||
open Nancy
|
open Nancy
|
||||||
open Nancy.ModelBinding
|
open Nancy.ModelBinding
|
||||||
open Nancy.Security
|
open Nancy.Security
|
||||||
@ -15,7 +16,7 @@ open System
|
|||||||
open System.ServiceModel.Syndication
|
open System.ServiceModel.Syndication
|
||||||
|
|
||||||
/// Routes dealing with posts (including the home page, /tag, /category, RSS, and catch-all routes)
|
/// Routes dealing with posts (including the home page, /tag, /category, RSS, and catch-all routes)
|
||||||
type PostModule(conn : IConnection, clock : IClock) as this =
|
type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
||||||
inherit NancyModule()
|
inherit NancyModule()
|
||||||
|
|
||||||
/// Get the page number from the dictionary
|
/// Get the page number from the dictionary
|
||||||
@ -27,14 +28,14 @@ type PostModule(conn : IConnection, clock : IClock) as this =
|
|||||||
|
|
||||||
/// Generate an RSS/Atom feed of the latest posts
|
/// Generate an RSS/Atom feed of the latest posts
|
||||||
let generateFeed format : obj =
|
let generateFeed format : obj =
|
||||||
let posts = findFeedPosts conn this.WebLog.Id 10
|
let posts = findFeedPosts data this.WebLog.Id 10
|
||||||
let feed =
|
let feed =
|
||||||
SyndicationFeed(
|
SyndicationFeed(
|
||||||
this.WebLog.Name, defaultArg this.WebLog.Subtitle null,
|
this.WebLog.Name, defaultArg this.WebLog.Subtitle null,
|
||||||
Uri(sprintf "%s://%s" this.Request.Url.Scheme this.WebLog.UrlBase), null,
|
Uri(sprintf "%s://%s" this.Request.Url.Scheme this.WebLog.UrlBase), null,
|
||||||
(match posts |> List.tryHead with
|
(match posts |> List.tryHead with
|
||||||
| Some (post, _) -> Instant(post.UpdatedOn).ToDateTimeOffset ()
|
| Some (post, _) -> Instant(post.UpdatedOn).ToDateTimeOffset ()
|
||||||
| _ -> System.DateTimeOffset(System.DateTime.MinValue)),
|
| _ -> System.DateTimeOffset(System.DateTime.MinValue)),
|
||||||
posts
|
posts
|
||||||
|> List.map (fun (post, user) ->
|
|> List.map (fun (post, user) ->
|
||||||
let item =
|
let item =
|
||||||
@ -76,15 +77,15 @@ type PostModule(conn : IConnection, clock : IClock) as this =
|
|||||||
member this.PublishedPostsPage pageNbr =
|
member this.PublishedPostsPage pageNbr =
|
||||||
let model = PostsModel(this.Context, this.WebLog)
|
let model = PostsModel(this.Context, this.WebLog)
|
||||||
model.PageNbr <- pageNbr
|
model.PageNbr <- pageNbr
|
||||||
model.Posts <- findPageOfPublishedPosts conn this.WebLog.Id pageNbr 10 |> forDisplay
|
model.Posts <- findPageOfPublishedPosts data this.WebLog.Id pageNbr 10 |> forDisplay
|
||||||
model.HasNewer <- match pageNbr with
|
model.HasNewer <- match pageNbr with
|
||||||
| 1 -> false
|
| 1 -> false
|
||||||
| _ -> match List.isEmpty model.Posts with
|
| _ -> match List.isEmpty model.Posts with
|
||||||
| true -> false
|
| true -> false
|
||||||
| _ -> Option.isSome <| tryFindNewerPost conn (List.last model.Posts).Post
|
| _ -> Option.isSome <| tryFindNewerPost data (List.last model.Posts).Post
|
||||||
model.HasOlder <- match List.isEmpty model.Posts with
|
model.HasOlder <- match List.isEmpty model.Posts with
|
||||||
| true -> false
|
| true -> false
|
||||||
| _ -> Option.isSome <| tryFindOlderPost conn (List.head model.Posts).Post
|
| _ -> Option.isSome <| tryFindOlderPost data (List.head model.Posts).Post
|
||||||
model.UrlPrefix <- "/posts"
|
model.UrlPrefix <- "/posts"
|
||||||
model.PageTitle <- match pageNbr with 1 -> "" | _ -> sprintf "%s%i" Resources.PageHash pageNbr
|
model.PageTitle <- match pageNbr with 1 -> "" | _ -> sprintf "%s%i" Resources.PageHash pageNbr
|
||||||
this.ThemedView "index" model
|
this.ThemedView "index" model
|
||||||
@ -93,59 +94,59 @@ type PostModule(conn : IConnection, clock : IClock) as this =
|
|||||||
member this.HomePage () =
|
member this.HomePage () =
|
||||||
match this.WebLog.DefaultPage with
|
match this.WebLog.DefaultPage with
|
||||||
| "posts" -> this.PublishedPostsPage 1
|
| "posts" -> this.PublishedPostsPage 1
|
||||||
| pageId -> match tryFindPageWithoutRevisions conn this.WebLog.Id pageId with
|
| pageId -> match tryFindPageWithoutRevisions data this.WebLog.Id pageId with
|
||||||
| Some page -> let model = PageModel(this.Context, this.WebLog, page)
|
| Some page -> let model = PageModel(this.Context, this.WebLog, page)
|
||||||
model.PageTitle <- page.Title
|
model.PageTitle <- page.Title
|
||||||
this.ThemedView "page" model
|
this.ThemedView "page" model
|
||||||
| None -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Derive a post or page from the URL, or redirect from a prior URL to the current one
|
/// Derive a post or page from the URL, or redirect from a prior URL to the current one
|
||||||
member this.CatchAll (parameters : DynamicDictionary) =
|
member this.CatchAll (parameters : DynamicDictionary) =
|
||||||
let url = parameters.["permalink"].ToString ()
|
let url = parameters.["permalink"].ToString ()
|
||||||
match tryFindPostByPermalink conn this.WebLog.Id url with
|
match tryFindPostByPermalink data this.WebLog.Id url with
|
||||||
| Some post -> // Hopefully the most common result; the permalink is a permalink!
|
| Some post -> // Hopefully the most common result; the permalink is a permalink!
|
||||||
let model = PostModel(this.Context, this.WebLog, post)
|
let model = PostModel(this.Context, this.WebLog, post)
|
||||||
model.NewerPost <- tryFindNewerPost conn post
|
model.NewerPost <- tryFindNewerPost data post
|
||||||
model.OlderPost <- tryFindOlderPost conn post
|
model.OlderPost <- tryFindOlderPost data post
|
||||||
model.PageTitle <- post.Title
|
model.PageTitle <- post.Title
|
||||||
this.ThemedView "single" model
|
this.ThemedView "single" model
|
||||||
| None -> // Maybe it's a page permalink instead...
|
| _ -> // Maybe it's a page permalink instead...
|
||||||
match tryFindPageByPermalink conn this.WebLog.Id url with
|
match tryFindPageByPermalink data this.WebLog.Id url with
|
||||||
| Some page -> // ...and it is!
|
| Some page -> // ...and it is!
|
||||||
let model = PageModel(this.Context, this.WebLog, page)
|
let model = PageModel(this.Context, this.WebLog, page)
|
||||||
model.PageTitle <- page.Title
|
model.PageTitle <- page.Title
|
||||||
this.ThemedView "page" model
|
this.ThemedView "page" model
|
||||||
| None -> // Maybe it's an old permalink for a post
|
| _ -> // Maybe it's an old permalink for a post
|
||||||
match tryFindPostByPriorPermalink conn this.WebLog.Id url with
|
match tryFindPostByPriorPermalink data this.WebLog.Id url with
|
||||||
| Some post -> // Redirect them to the proper permalink
|
| Some post -> // Redirect them to the proper permalink
|
||||||
upcast this.Response.AsRedirect(sprintf "/%s" post.Permalink)
|
upcast this.Response.AsRedirect(sprintf "/%s" post.Permalink)
|
||||||
.WithStatusCode HttpStatusCode.MovedPermanently
|
.WithStatusCode HttpStatusCode.MovedPermanently
|
||||||
| None -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Display categorized posts
|
/// Display categorized posts
|
||||||
member this.CategorizedPosts (parameters : DynamicDictionary) =
|
member this.CategorizedPosts (parameters : DynamicDictionary) =
|
||||||
let slug = parameters.["slug"].ToString ()
|
let slug = parameters.["slug"].ToString ()
|
||||||
match tryFindCategoryBySlug conn this.WebLog.Id slug with
|
match tryFindCategoryBySlug data this.WebLog.Id slug with
|
||||||
| Some cat -> let pageNbr = getPage parameters
|
| Some cat -> let pageNbr = getPage parameters
|
||||||
let model = PostsModel(this.Context, this.WebLog)
|
let model = PostsModel(this.Context, this.WebLog)
|
||||||
model.PageNbr <- pageNbr
|
model.PageNbr <- pageNbr
|
||||||
model.Posts <- findPageOfCategorizedPosts conn this.WebLog.Id cat.Id pageNbr 10 |> forDisplay
|
model.Posts <- findPageOfCategorizedPosts data this.WebLog.Id cat.Id pageNbr 10 |> forDisplay
|
||||||
model.HasNewer <- match List.isEmpty model.Posts with
|
model.HasNewer <- match List.isEmpty model.Posts with
|
||||||
| true -> false
|
| true -> false
|
||||||
| _ -> Option.isSome <| tryFindNewerCategorizedPost conn cat.Id
|
| _ -> Option.isSome <| tryFindNewerCategorizedPost data cat.Id
|
||||||
(List.head model.Posts).Post
|
(List.head model.Posts).Post
|
||||||
model.HasOlder <- match List.isEmpty model.Posts with
|
model.HasOlder <- match List.isEmpty model.Posts with
|
||||||
| true -> false
|
| true -> false
|
||||||
| _ -> Option.isSome <| tryFindOlderCategorizedPost conn cat.Id
|
| _ -> Option.isSome <| tryFindOlderCategorizedPost data cat.Id
|
||||||
(List.last model.Posts).Post
|
(List.last model.Posts).Post
|
||||||
model.UrlPrefix <- sprintf "/category/%s" slug
|
model.UrlPrefix <- sprintf "/category/%s" slug
|
||||||
model.PageTitle <- sprintf "\"%s\" Category%s" cat.Name
|
model.PageTitle <- sprintf "\"%s\" Category%s" cat.Name
|
||||||
(match pageNbr with | 1 -> "" | n -> sprintf " | Page %i" n)
|
(match pageNbr with | 1 -> "" | n -> sprintf " | Page %i" n)
|
||||||
model.Subtitle <- Some <| match cat.Description with
|
model.Subtitle <- Some <| match cat.Description with
|
||||||
| Some desc -> desc
|
| Some desc -> desc
|
||||||
| None -> sprintf "Posts in the \"%s\" category" cat.Name
|
| _ -> sprintf "Posts in the \"%s\" category" cat.Name
|
||||||
this.ThemedView "index" model
|
this.ThemedView "index" model
|
||||||
| None -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Display tagged posts
|
/// Display tagged posts
|
||||||
member this.TaggedPosts (parameters : DynamicDictionary) =
|
member this.TaggedPosts (parameters : DynamicDictionary) =
|
||||||
@ -153,13 +154,13 @@ type PostModule(conn : IConnection, clock : IClock) as this =
|
|||||||
let pageNbr = getPage parameters
|
let pageNbr = getPage parameters
|
||||||
let model = PostsModel(this.Context, this.WebLog)
|
let model = PostsModel(this.Context, this.WebLog)
|
||||||
model.PageNbr <- pageNbr
|
model.PageNbr <- pageNbr
|
||||||
model.Posts <- findPageOfTaggedPosts conn this.WebLog.Id tag pageNbr 10 |> forDisplay
|
model.Posts <- findPageOfTaggedPosts data this.WebLog.Id tag pageNbr 10 |> forDisplay
|
||||||
model.HasNewer <- match List.isEmpty model.Posts with
|
model.HasNewer <- match List.isEmpty model.Posts with
|
||||||
| true -> false
|
| true -> false
|
||||||
| _ -> Option.isSome <| tryFindNewerTaggedPost conn tag (List.head model.Posts).Post
|
| _ -> Option.isSome <| tryFindNewerTaggedPost data tag (List.head model.Posts).Post
|
||||||
model.HasOlder <- match List.isEmpty model.Posts with
|
model.HasOlder <- match List.isEmpty model.Posts with
|
||||||
| true -> false
|
| true -> false
|
||||||
| _ -> Option.isSome <| tryFindOlderTaggedPost conn tag (List.last model.Posts).Post
|
| _ -> Option.isSome <| tryFindOlderTaggedPost data tag (List.last model.Posts).Post
|
||||||
model.UrlPrefix <- sprintf "/tag/%s" tag
|
model.UrlPrefix <- sprintf "/tag/%s" tag
|
||||||
model.PageTitle <- sprintf "\"%s\" Tag%s" tag (match pageNbr with 1 -> "" | n -> sprintf " | Page %i" n)
|
model.PageTitle <- sprintf "\"%s\" Tag%s" tag (match pageNbr with 1 -> "" | n -> sprintf " | Page %i" n)
|
||||||
model.Subtitle <- Some <| sprintf "Posts tagged \"%s\"" tag
|
model.Subtitle <- Some <| sprintf "Posts tagged \"%s\"" tag
|
||||||
@ -182,7 +183,7 @@ type PostModule(conn : IConnection, clock : IClock) as this =
|
|||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let model = PostsModel(this.Context, this.WebLog)
|
let model = PostsModel(this.Context, this.WebLog)
|
||||||
model.PageNbr <- pageNbr
|
model.PageNbr <- pageNbr
|
||||||
model.Posts <- findPageOfAllPosts conn this.WebLog.Id pageNbr 25 |> forDisplay
|
model.Posts <- findPageOfAllPosts data this.WebLog.Id pageNbr 25 |> forDisplay
|
||||||
model.HasNewer <- pageNbr > 1
|
model.HasNewer <- pageNbr > 1
|
||||||
model.HasOlder <- List.length model.Posts > 24
|
model.HasOlder <- List.length model.Posts > 24
|
||||||
model.UrlPrefix <- "/posts/list"
|
model.UrlPrefix <- "/posts/list"
|
||||||
@ -193,21 +194,21 @@ type PostModule(conn : IConnection, clock : IClock) as this =
|
|||||||
member this.EditPost (parameters : DynamicDictionary) =
|
member this.EditPost (parameters : DynamicDictionary) =
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let postId = parameters.["postId"].ToString ()
|
let postId = parameters.["postId"].ToString ()
|
||||||
match (match postId with "new" -> Some Post.Empty | _ -> tryFindPost conn this.WebLog.Id postId) with
|
match (match postId with "new" -> Some Post.Empty | _ -> tryFindPost data this.WebLog.Id postId) with
|
||||||
| Some post -> let rev = match post.Revisions
|
| Some post -> let rev = match post.Revisions
|
||||||
|> List.sortByDescending (fun r -> r.AsOf)
|
|> List.sortByDescending (fun r -> r.AsOf)
|
||||||
|> List.tryHead with
|
|> List.tryHead with
|
||||||
| Some r -> r
|
| Some r -> r
|
||||||
| None -> Revision.Empty
|
| None -> Revision.Empty
|
||||||
let model = EditPostModel(this.Context, this.WebLog, post, rev)
|
let model = EditPostModel(this.Context, this.WebLog, post, rev)
|
||||||
model.Categories <- getAllCategories conn this.WebLog.Id
|
model.Categories <- findAllCategories data this.WebLog.Id
|
||||||
|> List.map (fun cat -> string (fst cat).Id,
|
|> List.map (fun cat -> string (fst cat).Id,
|
||||||
sprintf "%s%s"
|
sprintf "%s%s"
|
||||||
(String.replicate (snd cat) " ")
|
(String.replicate (snd cat) " ")
|
||||||
(fst cat).Name)
|
(fst cat).Name)
|
||||||
model.PageTitle <- match post.Id with "new" -> Resources.AddNewPost | _ -> Resources.EditPost
|
model.PageTitle <- match post.Id with "new" -> Resources.AddNewPost | _ -> Resources.EditPost
|
||||||
upcast this.View.["admin/post/edit"]
|
upcast this.View.["admin/post/edit"]
|
||||||
| None -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Save a post
|
/// Save a post
|
||||||
member this.SavePost (parameters : DynamicDictionary) =
|
member this.SavePost (parameters : DynamicDictionary) =
|
||||||
@ -216,7 +217,7 @@ type PostModule(conn : IConnection, clock : IClock) as this =
|
|||||||
let postId = parameters.["postId"].ToString ()
|
let postId = parameters.["postId"].ToString ()
|
||||||
let form = this.Bind<EditPostForm>()
|
let form = this.Bind<EditPostForm>()
|
||||||
let now = clock.Now.Ticks
|
let now = clock.Now.Ticks
|
||||||
match (match postId with "new" -> Some Post.Empty | _ -> tryFindPost conn this.WebLog.Id postId) with
|
match (match postId with "new" -> Some Post.Empty | _ -> tryFindPost data this.WebLog.Id postId) with
|
||||||
| Some p -> let justPublished = p.PublishedOn = int64 0 && form.PublishNow
|
| Some p -> let justPublished = p.PublishedOn = int64 0 && form.PublishNow
|
||||||
let post = match postId with
|
let post = match postId with
|
||||||
| "new" -> { p with
|
| "new" -> { p with
|
||||||
@ -242,14 +243,14 @@ type PostModule(conn : IConnection, clock : IClock) as this =
|
|||||||
Revisions = { AsOf = now
|
Revisions = { AsOf = now
|
||||||
SourceType = form.Source
|
SourceType = form.Source
|
||||||
Text = form.Text } :: post.Revisions }
|
Text = form.Text } :: post.Revisions }
|
||||||
|> savePost conn
|
|> savePost data
|
||||||
let model = MyWebLogModel(this.Context, this.WebLog)
|
let model = MyWebLogModel(this.Context, this.WebLog)
|
||||||
{ UserMessage.Empty with
|
{ UserMessage.Empty with
|
||||||
Level = Level.Info
|
Level = Level.Info
|
||||||
Message = System.String.Format
|
Message = System.String.Format
|
||||||
(Resources.MsgPostEditSuccess,
|
(Resources.MsgPostEditSuccess,
|
||||||
(match postId with | "new" -> Resources.Added | _ -> Resources.Updated),
|
(match postId with "new" -> Resources.Added | _ -> Resources.Updated),
|
||||||
(match justPublished with | true -> Resources.AndPublished | _ -> "")) }
|
(match justPublished with true -> Resources.AndPublished | _ -> "")) }
|
||||||
|> model.AddMessage
|
|> model.AddMessage
|
||||||
this.Redirect (sprintf "/post/%s/edit" pId) model
|
this.Redirect (sprintf "/post/%s/edit" pId) model
|
||||||
| None -> this.NotFound ()
|
| _ -> this.NotFound ()
|
@ -1,7 +1,8 @@
|
|||||||
namespace MyWebLog
|
namespace MyWebLog
|
||||||
|
|
||||||
open MyWebLog.Data.User
|
open MyWebLog.Data
|
||||||
open MyWebLog.Entities
|
open MyWebLog.Entities
|
||||||
|
open MyWebLog.Logic.User
|
||||||
open Nancy
|
open Nancy
|
||||||
open Nancy.Authentication.Forms
|
open Nancy.Authentication.Forms
|
||||||
open Nancy.Cryptography
|
open Nancy.Cryptography
|
||||||
@ -12,7 +13,7 @@ open RethinkDb.Driver.Net
|
|||||||
open System.Text
|
open System.Text
|
||||||
|
|
||||||
/// Handle /user URLs
|
/// Handle /user URLs
|
||||||
type UserModule(conn : IConnection, cfg : AppConfig) as this =
|
type UserModule(data : IMyWebLogData, cfg : AppConfig) as this =
|
||||||
inherit NancyModule("/user")
|
inherit NancyModule("/user")
|
||||||
|
|
||||||
/// Hash the user's password
|
/// Hash the user's password
|
||||||
@ -37,7 +38,7 @@ type UserModule(conn : IConnection, cfg : AppConfig) as this =
|
|||||||
this.ValidateCsrfToken ()
|
this.ValidateCsrfToken ()
|
||||||
let form = this.Bind<LogOnForm> ()
|
let form = this.Bind<LogOnForm> ()
|
||||||
let model = MyWebLogModel(this.Context, this.WebLog)
|
let model = MyWebLogModel(this.Context, this.WebLog)
|
||||||
match tryUserLogOn conn form.Email (pbkdf2 form.Password) with
|
match tryUserLogOn data form.Email (pbkdf2 form.Password) with
|
||||||
| Some user -> this.Session.[Keys.User] <- user
|
| Some user -> this.Session.[Keys.User] <- user
|
||||||
{ UserMessage.Empty with Level = Level.Info
|
{ UserMessage.Empty with Level = Level.Info
|
||||||
Message = Resources.MsgLogOnSuccess }
|
Message = Resources.MsgLogOnSuccess }
|
||||||
@ -46,10 +47,10 @@ type UserModule(conn : IConnection, cfg : AppConfig) as this =
|
|||||||
// TODO: investigate if addMessage should update the session when it's called
|
// TODO: investigate if addMessage should update the session when it's called
|
||||||
upcast this.LoginAndRedirect (System.Guid.Parse user.Id,
|
upcast this.LoginAndRedirect (System.Guid.Parse user.Id,
|
||||||
fallbackRedirectUrl = defaultArg (Option.ofObj form.ReturnUrl) "/")
|
fallbackRedirectUrl = defaultArg (Option.ofObj form.ReturnUrl) "/")
|
||||||
| None -> { UserMessage.Empty with Level = Level.Error
|
| _ -> { UserMessage.Empty with Level = Level.Error
|
||||||
Message = Resources.ErrBadLogOnAttempt }
|
Message = Resources.ErrBadLogOnAttempt }
|
||||||
|> model.AddMessage
|
|> model.AddMessage
|
||||||
this.Redirect (sprintf "/user/logon?returnUrl=%s" form.ReturnUrl) model
|
this.Redirect (sprintf "/user/logon?returnUrl=%s" form.ReturnUrl) model
|
||||||
|
|
||||||
/// Log a user off
|
/// Log a user off
|
||||||
member this.LogOff () =
|
member this.LogOff () =
|
@ -1,7 +1,7 @@
|
|||||||
namespace MyWebLog
|
namespace MyWebLog
|
||||||
|
|
||||||
open MyWebLog.Data.WebLog
|
|
||||||
open MyWebLog.Entities
|
open MyWebLog.Entities
|
||||||
|
open MyWebLog.Logic.WebLog
|
||||||
open Nancy
|
open Nancy
|
||||||
open Nancy.Session.Persistable
|
open Nancy.Session.Persistable
|
||||||
open Newtonsoft.Json
|
open Newtonsoft.Json
|
7
src/MyWebLog.App/paket.references
Normal file
7
src/MyWebLog.App/paket.references
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
FSharp.Formatting
|
||||||
|
Nancy
|
||||||
|
Nancy.Authentication.Forms
|
||||||
|
Nancy.Session.RethinkDB
|
||||||
|
NodaTime
|
||||||
|
RethinkDb.Driver
|
||||||
|
Suave
|
@ -4,17 +4,17 @@ open System.Reflection
|
|||||||
open System.Runtime.CompilerServices
|
open System.Runtime.CompilerServices
|
||||||
open System.Runtime.InteropServices
|
open System.Runtime.InteropServices
|
||||||
|
|
||||||
[<assembly: AssemblyTitle("MyWebLog.Data")>]
|
[<assembly: AssemblyTitle("MyWebLog.Data.RethinkDB")>]
|
||||||
[<assembly: AssemblyDescription("Data access for myWebLog")>]
|
[<assembly: AssemblyDescription("RethinkDB data access for myWebLog")>]
|
||||||
[<assembly: AssemblyConfiguration("")>]
|
[<assembly: AssemblyConfiguration("")>]
|
||||||
[<assembly: AssemblyCompany("DJS Consulting")>]
|
[<assembly: AssemblyCompany("DJS Consulting")>]
|
||||||
[<assembly: AssemblyProduct("MyWebLog.Data")>]
|
[<assembly: AssemblyProduct("MyWebLog.Data.RethinkDB")>]
|
||||||
[<assembly: AssemblyCopyright("Copyright © 2016")>]
|
[<assembly: AssemblyCopyright("Copyright © 2016")>]
|
||||||
[<assembly: AssemblyTrademark("")>]
|
[<assembly: AssemblyTrademark("")>]
|
||||||
[<assembly: AssemblyCulture("")>]
|
[<assembly: AssemblyCulture("")>]
|
||||||
[<assembly: ComVisible(false)>]
|
[<assembly: ComVisible(false)>]
|
||||||
[<assembly: Guid("1fba0b84-b09e-4b16-b9b6-5730dea27192")>]
|
[<assembly: Guid("1fba0b84-b09e-4b16-b9b6-5730dea27192")>]
|
||||||
[<assembly: AssemblyVersion("0.9.1.0")>]
|
[<assembly: AssemblyVersion("0.9.2.0")>]
|
||||||
[<assembly: AssemblyFileVersion("1.0.0.0")>]
|
[<assembly: AssemblyFileVersion("1.0.0.0")>]
|
||||||
|
|
||||||
do
|
do
|
@ -1,8 +1,7 @@
|
|||||||
module MyWebLog.Data.Category
|
module MyWebLog.Data.RethinkDB.Category
|
||||||
|
|
||||||
open FSharp.Interop.Dynamic
|
open FSharp.Interop.Dynamic
|
||||||
open MyWebLog.Entities
|
open MyWebLog.Entities
|
||||||
open Rethink
|
|
||||||
open RethinkDb.Driver.Ast
|
open RethinkDb.Driver.Ast
|
||||||
open System.Dynamic
|
open System.Dynamic
|
||||||
|
|
||||||
@ -14,20 +13,6 @@ let private category (webLogId : string) (catId : string) =
|
|||||||
.Get(catId)
|
.Get(catId)
|
||||||
.Filter(fun c -> c.["WebLogId"].Eq(webLogId))
|
.Filter(fun c -> c.["WebLogId"].Eq(webLogId))
|
||||||
|
|
||||||
/// Sort categories by their name, with their children sorted below them, including an indent level
|
|
||||||
let sortCategories categories =
|
|
||||||
let rec getChildren (cat : Category) indent =
|
|
||||||
seq {
|
|
||||||
yield cat, indent
|
|
||||||
for child in categories |> List.filter (fun c -> c.ParentId = Some cat.Id) do
|
|
||||||
yield! getChildren child (indent + 1)
|
|
||||||
}
|
|
||||||
categories
|
|
||||||
|> List.filter (fun c -> c.ParentId.IsNone)
|
|
||||||
|> List.map (fun c -> getChildren c 0)
|
|
||||||
|> Seq.collect id
|
|
||||||
|> Seq.toList
|
|
||||||
|
|
||||||
/// Get all categories for a web log
|
/// Get all categories for a web log
|
||||||
let getAllCategories conn (webLogId : string) =
|
let getAllCategories conn (webLogId : string) =
|
||||||
r.Table(Table.Category)
|
r.Table(Table.Category)
|
||||||
@ -36,7 +21,6 @@ let getAllCategories conn (webLogId : string) =
|
|||||||
.RunListAsync<Category>(conn)
|
.RunListAsync<Category>(conn)
|
||||||
|> await
|
|> await
|
||||||
|> Seq.toList
|
|> Seq.toList
|
||||||
|> sortCategories
|
|
||||||
|
|
||||||
/// Get a specific category by its Id
|
/// Get a specific category by its Id
|
||||||
let tryFindCategory conn webLogId catId : Category option =
|
let tryFindCategory conn webLogId catId : Category option =
|
||||||
@ -45,52 +29,41 @@ let tryFindCategory conn webLogId catId : Category option =
|
|||||||
| null -> None
|
| null -> None
|
||||||
| cat -> Some <| unbox cat
|
| cat -> Some <| unbox cat
|
||||||
|
|
||||||
/// Save a category
|
/// Add a category
|
||||||
let saveCategory conn webLogId (cat : Category) =
|
let addCategory conn (cat : Category) =
|
||||||
match cat.Id with
|
r.Table(Table.Category)
|
||||||
| "new" -> let newCat = { cat with Id = string <| System.Guid.NewGuid()
|
.Insert(cat)
|
||||||
WebLogId = webLogId }
|
.RunResultAsync(conn) |> await |> ignore
|
||||||
r.Table(Table.Category)
|
|
||||||
.Insert(newCat)
|
|
||||||
.RunResultAsync(conn) |> await |> ignore
|
|
||||||
newCat.Id
|
|
||||||
| _ -> let upd8 = ExpandoObject()
|
|
||||||
upd8?Name <- cat.Name
|
|
||||||
upd8?Slug <- cat.Slug
|
|
||||||
upd8?Description <- cat.Description
|
|
||||||
upd8?ParentId <- cat.ParentId
|
|
||||||
(category webLogId cat.Id)
|
|
||||||
.Update(upd8)
|
|
||||||
.RunResultAsync(conn) |> await |> ignore
|
|
||||||
cat.Id
|
|
||||||
|
|
||||||
/// Remove a category from a given parent
|
/// Update a category
|
||||||
let removeCategoryFromParent conn webLogId parentId catId =
|
let updateCategory conn (cat : Category) =
|
||||||
match tryFindCategory conn webLogId parentId with
|
let upd8 = ExpandoObject()
|
||||||
| Some parent -> let upd8 = ExpandoObject()
|
upd8?Name <- cat.Name
|
||||||
upd8?Children <- parent.Children
|
upd8?Slug <- cat.Slug
|
||||||
|> List.filter (fun childId -> childId <> catId)
|
upd8?Description <- cat.Description
|
||||||
(category webLogId parentId)
|
upd8?ParentId <- cat.ParentId
|
||||||
.Update(upd8)
|
(category cat.WebLogId cat.Id)
|
||||||
.RunResultAsync(conn) |> await |> ignore
|
.Update(upd8)
|
||||||
| None -> ()
|
.RunResultAsync(conn) |> await |> ignore
|
||||||
|
|
||||||
/// Add a category to a given parent
|
/// Update a category's children
|
||||||
let addCategoryToParent conn webLogId parentId catId =
|
let updateChildren conn webLogId parentId (children : string list) =
|
||||||
match tryFindCategory conn webLogId parentId with
|
let upd8 = ExpandoObject()
|
||||||
| Some parent -> let upd8 = ExpandoObject()
|
upd8?Children <- children
|
||||||
upd8?Children <- catId :: parent.Children
|
(category webLogId parentId)
|
||||||
(category webLogId parentId)
|
.Update(upd8)
|
||||||
.Update(upd8)
|
.RunResultAsync(conn) |> await |> ignore
|
||||||
.RunResultAsync(conn) |> await |> ignore
|
|
||||||
| None -> ()
|
|
||||||
|
|
||||||
/// Delete a category
|
/// Delete a category
|
||||||
let deleteCategory conn cat =
|
let deleteCategory conn cat =
|
||||||
// Remove the category from its parent
|
// Remove the category from its parent
|
||||||
match cat.ParentId with
|
match cat.ParentId with
|
||||||
| Some parentId -> removeCategoryFromParent conn cat.WebLogId parentId cat.Id
|
| Some parentId -> match tryFindCategory conn cat.WebLogId parentId with
|
||||||
| None -> ()
|
| Some parent -> parent.Children
|
||||||
|
|> List.filter (fun childId -> childId <> cat.Id)
|
||||||
|
|> updateChildren conn cat.WebLogId parentId
|
||||||
|
| _ -> ()
|
||||||
|
| _ -> ()
|
||||||
// Move this category's children to its parent
|
// Move this category's children to its parent
|
||||||
let newParent = ExpandoObject()
|
let newParent = ExpandoObject()
|
||||||
newParent?ParentId <- cat.ParentId
|
newParent?ParentId <- cat.ParentId
|
@ -1,4 +1,4 @@
|
|||||||
namespace MyWebLog.Data
|
namespace MyWebLog.Data.RethinkDB
|
||||||
|
|
||||||
open RethinkDb.Driver
|
open RethinkDb.Driver
|
||||||
open RethinkDb.Driver.Net
|
open RethinkDb.Driver.Net
|
@ -1,4 +1,5 @@
|
|||||||
module MyWebLog.Data.Rethink
|
[<AutoOpen>]
|
||||||
|
module MyWebLog.Data.RethinkDB.Extensions
|
||||||
|
|
||||||
open RethinkDb.Driver.Ast
|
open RethinkDb.Driver.Ast
|
||||||
open RethinkDb.Driver.Net
|
open RethinkDb.Driver.Net
|
161
src/MyWebLog.Data.RethinkDB/MyWebLog.Data.RethinkDB.fsproj
Normal file
161
src/MyWebLog.Data.RethinkDB/MyWebLog.Data.RethinkDB.fsproj
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="12.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>d6c2be5e-883a-4f34-9905-b730543ca380</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<RootNamespace>MyWebLog.Data.RethinkDB</RootNamespace>
|
||||||
|
<AssemblyName>MyWebLog.Data.RethinkDB</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||||
|
<TargetFSharpCoreVersion>4.4.0.0</TargetFSharpCoreVersion>
|
||||||
|
<Name>MyWebLog.Data.RethinkDB</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.RethinkDB.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.RethinkDB.xml</DocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="mscorlib" />
|
||||||
|
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Numerics" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Extensions.fs" />
|
||||||
|
<Compile Include="Table.fs" />
|
||||||
|
<Compile Include="DataConfig.fs" />
|
||||||
|
<Compile Include="Category.fs" />
|
||||||
|
<Compile Include="Page.fs" />
|
||||||
|
<Compile Include="Post.fs" />
|
||||||
|
<Compile Include="User.fs" />
|
||||||
|
<Compile Include="WebLog.fs" />
|
||||||
|
<Compile Include="SetUp.fs" />
|
||||||
|
<Compile Include="RethinkMyWebLogData.fs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MyWebLog.Entities\MyWebLog.Entities.fsproj">
|
||||||
|
<Name>MyWebLog.Entities</Name>
|
||||||
|
<Project>{a87f3cf5-2189-442b-8acf-929f5153ac22}</Project>
|
||||||
|
<Private>True</Private>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<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)" Condition="Exists('$(FSharpTargetsPath)')" />
|
||||||
|
<!-- 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>
|
||||||
|
-->
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Common.Logging">
|
||||||
|
<HintPath>..\packages\Common.Logging\lib\net40\Common.Logging.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Common.Logging.Core">
|
||||||
|
<HintPath>..\packages\Common.Logging.Core\lib\net40\Common.Logging.Core.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Dynamitey">
|
||||||
|
<HintPath>..\packages\Dynamitey\lib\net40\Dynamitey.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="FSharp.Interop.Dynamic">
|
||||||
|
<HintPath>..\packages\FSharp.Interop.Dynamic\lib\portable-net45+sl50+win\FSharp.Interop.Dynamic.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v4.0'">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
<HintPath>..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
<HintPath>..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="RethinkDb.Driver">
|
||||||
|
<HintPath>..\packages\RethinkDb.Driver\lib\net45\RethinkDb.Driver.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
</Project>
|
70
src/MyWebLog.Data.RethinkDB/Page.fs
Normal file
70
src/MyWebLog.Data.RethinkDB/Page.fs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
module MyWebLog.Data.RethinkDB.Page
|
||||||
|
|
||||||
|
open FSharp.Interop.Dynamic
|
||||||
|
open MyWebLog.Entities
|
||||||
|
open RethinkDb.Driver.Ast
|
||||||
|
open System.Dynamic
|
||||||
|
|
||||||
|
let private r = RethinkDb.Driver.RethinkDB.R
|
||||||
|
|
||||||
|
/// Try to find a page by its Id, optionally including revisions
|
||||||
|
let tryFindPageById conn webLogId (pageId : string) includeRevs =
|
||||||
|
let pg = r.Table(Table.Page)
|
||||||
|
.Get(pageId)
|
||||||
|
match (match includeRevs with
|
||||||
|
| true -> pg.RunAtomAsync<Page>(conn)
|
||||||
|
| _ -> pg.Without("Revisions").RunAtomAsync<Page>(conn)
|
||||||
|
|> await |> box) with
|
||||||
|
| null -> None
|
||||||
|
| page -> let pg : Page = unbox page
|
||||||
|
match pg.WebLogId = webLogId with true -> Some pg | _ -> None
|
||||||
|
|
||||||
|
/// Find a page by its permalink
|
||||||
|
let tryFindPageByPermalink conn (webLogId : string) (permalink : string) =
|
||||||
|
r.Table(Table.Page)
|
||||||
|
.GetAll(r.Array(webLogId, permalink)).OptArg("index", "Permalink")
|
||||||
|
.Without("Revisions")
|
||||||
|
.RunCursorAsync<Page>(conn)
|
||||||
|
|> await
|
||||||
|
|> Seq.tryHead
|
||||||
|
|
||||||
|
/// Get a list of all pages (excludes page text and revisions)
|
||||||
|
let findAllPages conn (webLogId : string) =
|
||||||
|
r.Table(Table.Page)
|
||||||
|
.GetAll(webLogId).OptArg("index", "WebLogId")
|
||||||
|
.OrderBy("Title")
|
||||||
|
.Without("Text", "Revisions")
|
||||||
|
.RunListAsync<Page>(conn)
|
||||||
|
|> await
|
||||||
|
|> Seq.toList
|
||||||
|
|
||||||
|
/// Add a page
|
||||||
|
let addPage conn (page : Page) =
|
||||||
|
r.Table(Table.Page)
|
||||||
|
.Insert(page)
|
||||||
|
.RunResultAsync(conn) |> await |> ignore
|
||||||
|
|
||||||
|
/// Update a page
|
||||||
|
let updatePage conn (page : Page) =
|
||||||
|
match tryFindPageById conn page.WebLogId page.Id false with
|
||||||
|
| Some _ -> let upd8 = ExpandoObject()
|
||||||
|
upd8?Title <- page.Title
|
||||||
|
upd8?Permalink <- page.Permalink
|
||||||
|
upd8?PublishedOn <- page.PublishedOn
|
||||||
|
upd8?UpdatedOn <- page.UpdatedOn
|
||||||
|
upd8?Text <- page.Text
|
||||||
|
upd8?Revisions <- page.Revisions
|
||||||
|
r.Table(Table.Page)
|
||||||
|
.Get(page.Id)
|
||||||
|
.Update(upd8)
|
||||||
|
.RunResultAsync(conn) |> await |> ignore
|
||||||
|
| _ -> ()
|
||||||
|
|
||||||
|
/// Delete a page
|
||||||
|
let deletePage conn webLogId pageId =
|
||||||
|
match tryFindPageById conn webLogId pageId false with
|
||||||
|
| Some _ -> r.Table(Table.Page)
|
||||||
|
.Get(pageId)
|
||||||
|
.Delete()
|
||||||
|
.RunResultAsync(conn) |> await |> ignore
|
||||||
|
| _ -> ()
|
@ -1,8 +1,7 @@
|
|||||||
module MyWebLog.Data.Post
|
module MyWebLog.Data.RethinkDB.Post
|
||||||
|
|
||||||
open FSharp.Interop.Dynamic
|
open FSharp.Interop.Dynamic
|
||||||
open MyWebLog.Entities
|
open MyWebLog.Entities
|
||||||
open Rethink
|
|
||||||
open RethinkDb.Driver.Ast
|
open RethinkDb.Driver.Ast
|
||||||
open System.Dynamic
|
open System.Dynamic
|
||||||
|
|
||||||
@ -146,6 +145,22 @@ let findFeedPosts conn webLogId nbr : (Post * User option) list =
|
|||||||
| null -> None
|
| null -> None
|
||||||
| user -> Some <| unbox user)
|
| user -> Some <| unbox user)
|
||||||
|
|
||||||
|
/// Add a post
|
||||||
|
let addPost conn post =
|
||||||
|
r.Table(Table.Post)
|
||||||
|
.Insert(post)
|
||||||
|
.RunResultAsync(conn)
|
||||||
|
|> ignore
|
||||||
|
|
||||||
|
/// Update a post
|
||||||
|
let updatePost conn post =
|
||||||
|
r.Table(Table.Post)
|
||||||
|
.Get(post.Id)
|
||||||
|
.Replace( { post with Categories = []
|
||||||
|
Comments = [] } )
|
||||||
|
.RunResultAsync(conn)
|
||||||
|
|> ignore
|
||||||
|
|
||||||
/// Save a post
|
/// Save a post
|
||||||
let savePost conn post =
|
let savePost conn post =
|
||||||
match post.Id with
|
match post.Id with
|
47
src/MyWebLog.Data.RethinkDB/RethinkMyWebLogData.fs
Normal file
47
src/MyWebLog.Data.RethinkDB/RethinkMyWebLogData.fs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
namespace MyWebLog.Data.RethinkDB
|
||||||
|
|
||||||
|
open MyWebLog.Data
|
||||||
|
open RethinkDb.Driver.Net
|
||||||
|
|
||||||
|
/// RethinkDB implementation of myWebLog data persistence
|
||||||
|
type RethinkMyWebLogData(conn : IConnection, cfg : DataConfig) =
|
||||||
|
interface IMyWebLogData with
|
||||||
|
member this.SetUp = fun () -> SetUp.startUpCheck cfg
|
||||||
|
|
||||||
|
member this.AllCategories = Category.getAllCategories conn
|
||||||
|
member this.CategoryById = Category.tryFindCategory conn
|
||||||
|
member this.CategoryBySlug = Category.tryFindCategoryBySlug conn
|
||||||
|
member this.AddCategory = Category.addCategory conn
|
||||||
|
member this.UpdateCategory = Category.updateCategory conn
|
||||||
|
member this.UpdateChildren = Category.updateChildren conn
|
||||||
|
member this.DeleteCategory = Category.deleteCategory conn
|
||||||
|
|
||||||
|
member this.PageById = Page.tryFindPageById conn
|
||||||
|
member this.PageByPermalink = Page.tryFindPageByPermalink conn
|
||||||
|
member this.AllPages = Page.findAllPages conn
|
||||||
|
member this.AddPage = Page.addPage conn
|
||||||
|
member this.UpdatePage = Page.updatePage conn
|
||||||
|
member this.DeletePage = Page.deletePage conn
|
||||||
|
|
||||||
|
member this.PageOfPublishedPosts = Post.findPageOfPublishedPosts conn
|
||||||
|
member this.PageOfCategorizedPosts = Post.findPageOfCategorizedPosts conn
|
||||||
|
member this.PageOfTaggedPosts = Post.findPageOfTaggedPosts conn
|
||||||
|
member this.NewerPost = Post.tryFindNewerPost conn
|
||||||
|
member this.NewerCategorizedPost = Post.tryFindNewerCategorizedPost conn
|
||||||
|
member this.NewerTaggedPost = Post.tryFindNewerTaggedPost conn
|
||||||
|
member this.OlderPost = Post.tryFindOlderPost conn
|
||||||
|
member this.OlderCategorizedPost = Post.tryFindOlderCategorizedPost conn
|
||||||
|
member this.OlderTaggedPost = Post.tryFindOlderTaggedPost conn
|
||||||
|
member this.PageOfAllPosts = Post.findPageOfAllPosts conn
|
||||||
|
member this.PostById = Post.tryFindPost conn
|
||||||
|
member this.PostByPermalink = Post.tryFindPostByPermalink conn
|
||||||
|
member this.PostByPriorPermalink = Post.tryFindPostByPriorPermalink conn
|
||||||
|
member this.FeedPosts = Post.findFeedPosts conn
|
||||||
|
member this.AddPost = Post.addPost conn
|
||||||
|
member this.UpdatePost = Post.updatePost conn
|
||||||
|
|
||||||
|
member this.LogOn = User.tryUserLogOn conn
|
||||||
|
|
||||||
|
member this.WebLogByUrlBase = WebLog.tryFindWebLogByUrlBase conn
|
||||||
|
member this.DashboardCounts = WebLog.findDashboardCounts conn
|
||||||
|
|
@ -1,6 +1,5 @@
|
|||||||
module MyWebLog.Data.SetUp
|
module MyWebLog.Data.RethinkDB.SetUp
|
||||||
|
|
||||||
open Rethink
|
|
||||||
open RethinkDb.Driver.Ast
|
open RethinkDb.Driver.Ast
|
||||||
open System
|
open System
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
/// Constants for tables used in myWebLog
|
/// Constants for tables used in myWebLog
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module MyWebLog.Data.Table
|
module MyWebLog.Data.RethinkDB.Table
|
||||||
|
|
||||||
/// The Category table
|
/// The Category table
|
||||||
let Category = "Category"
|
let Category = "Category"
|
@ -1,7 +1,6 @@
|
|||||||
module MyWebLog.Data.User
|
module MyWebLog.Data.RethinkDB.User
|
||||||
|
|
||||||
open MyWebLog.Entities
|
open MyWebLog.Entities
|
||||||
open Rethink
|
|
||||||
|
|
||||||
let private r = RethinkDb.Driver.RethinkDB.R
|
let private r = RethinkDb.Driver.RethinkDB.R
|
||||||
|
|
@ -1,20 +1,10 @@
|
|||||||
module MyWebLog.Data.WebLog
|
module MyWebLog.Data.RethinkDB.WebLog
|
||||||
|
|
||||||
open MyWebLog.Entities
|
open MyWebLog.Entities
|
||||||
open Rethink
|
|
||||||
open RethinkDb.Driver.Ast
|
open RethinkDb.Driver.Ast
|
||||||
|
|
||||||
let private r = RethinkDb.Driver.RethinkDB.R
|
let private r = RethinkDb.Driver.RethinkDB.R
|
||||||
|
|
||||||
/// Counts of items displayed on the admin dashboard
|
|
||||||
type DashboardCounts =
|
|
||||||
{ /// The number of pages for the web log
|
|
||||||
Pages : int
|
|
||||||
/// The number of pages for the web log
|
|
||||||
Posts : int
|
|
||||||
/// The number of categories for the web log
|
|
||||||
Categories : int }
|
|
||||||
|
|
||||||
/// Detemine the web log by the URL base
|
/// Detemine the web log by the URL base
|
||||||
let tryFindWebLogByUrlBase conn (urlBase : string) =
|
let tryFindWebLogByUrlBase conn (urlBase : string) =
|
||||||
r.Table(Table.WebLog)
|
r.Table(Table.WebLog)
|
2
src/MyWebLog.Data.RethinkDB/paket.references
Normal file
2
src/MyWebLog.Data.RethinkDB/paket.references
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
FSharp.Interop.Dynamic
|
||||||
|
RethinkDb.Driver
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
open Newtonsoft.Json
|
open Newtonsoft.Json
|
||||||
|
|
||||||
// ---- Constants ----
|
// --- Constants ---
|
||||||
|
|
||||||
/// Constants to use for revision source language
|
/// Constants to use for revision source language
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
@ -38,7 +38,7 @@ module CommentStatus =
|
|||||||
[<Literal>]
|
[<Literal>]
|
||||||
let Spam = "Spam"
|
let Spam = "Spam"
|
||||||
|
|
||||||
// ---- Entities ----
|
// --- Entities ---
|
||||||
|
|
||||||
/// A revision of a post or page
|
/// A revision of a post or page
|
||||||
type Revision =
|
type Revision =
|
||||||
@ -288,3 +288,14 @@ with
|
|||||||
Revisions = []
|
Revisions = []
|
||||||
Categories = []
|
Categories = []
|
||||||
Comments = [] }
|
Comments = [] }
|
||||||
|
|
||||||
|
// --- UI Support ---
|
||||||
|
|
||||||
|
/// Counts of items displayed on the admin dashboard
|
||||||
|
type DashboardCounts =
|
||||||
|
{ /// The number of pages for the web log
|
||||||
|
Pages : int
|
||||||
|
/// The number of pages for the web log
|
||||||
|
Posts : int
|
||||||
|
/// The number of categories for the web log
|
||||||
|
Categories : int }
|
114
src/MyWebLog.Entities/IMyWebLogData.fs
Normal file
114
src/MyWebLog.Entities/IMyWebLogData.fs
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
namespace MyWebLog.Data
|
||||||
|
|
||||||
|
open MyWebLog.Entities
|
||||||
|
|
||||||
|
/// Interface required to provide data to myWebLog's logic layer
|
||||||
|
type IMyWebLogData =
|
||||||
|
/// Function to set up the data store
|
||||||
|
abstract SetUp : (unit -> unit)
|
||||||
|
|
||||||
|
// --- Category ---
|
||||||
|
|
||||||
|
/// Get all categories for a web log
|
||||||
|
abstract AllCategories : (string -> Category list)
|
||||||
|
|
||||||
|
/// Try to find a category by its Id and web log Id (web log, category Ids)
|
||||||
|
abstract CategoryById : (string -> string -> Category option)
|
||||||
|
|
||||||
|
/// Try to find a category by its slug (web log Id, slug)
|
||||||
|
abstract CategoryBySlug : (string -> string -> Category option)
|
||||||
|
|
||||||
|
/// Add a category
|
||||||
|
abstract AddCategory : (Category -> unit)
|
||||||
|
|
||||||
|
/// Update a category
|
||||||
|
abstract UpdateCategory : (Category -> unit)
|
||||||
|
|
||||||
|
/// Update a category's children
|
||||||
|
abstract UpdateChildren : (string -> string -> string list -> unit)
|
||||||
|
|
||||||
|
/// Delete a Category
|
||||||
|
abstract DeleteCategory : (Category -> unit)
|
||||||
|
|
||||||
|
// --- Page ---
|
||||||
|
|
||||||
|
/// Try to find a page by its Id and web log Id (web log, page Ids), choosing whether to include revisions
|
||||||
|
abstract PageById : (string -> string -> bool -> Page option)
|
||||||
|
|
||||||
|
/// Try to find a page by its permalink and web log Id (web log Id, permalink)
|
||||||
|
abstract PageByPermalink : (string -> string -> Page option)
|
||||||
|
|
||||||
|
/// Get all pages for a web log
|
||||||
|
abstract AllPages : (string -> Page list)
|
||||||
|
|
||||||
|
/// Add a page
|
||||||
|
abstract AddPage : (Page -> unit)
|
||||||
|
|
||||||
|
/// Update a page
|
||||||
|
abstract UpdatePage : (Page -> unit)
|
||||||
|
|
||||||
|
/// Delete a page by its Id and web log Id (web log, page Ids)
|
||||||
|
abstract DeletePage : (string -> string -> unit)
|
||||||
|
|
||||||
|
// --- Post ---
|
||||||
|
|
||||||
|
/// Find a page of published posts for the given web log (web log Id, page #, # per page)
|
||||||
|
abstract PageOfPublishedPosts : (string -> int -> int -> Post list)
|
||||||
|
|
||||||
|
/// Find a page of published posts within a given category (web log Id, cat Id, page #, # per page)
|
||||||
|
abstract PageOfCategorizedPosts : (string -> string -> int -> int -> Post list)
|
||||||
|
|
||||||
|
/// Find a page of published posts tagged with a given tag (web log Id, tag, page #, # per page)
|
||||||
|
abstract PageOfTaggedPosts : (string -> string -> int -> int -> Post list)
|
||||||
|
|
||||||
|
/// Try to find the next newer published post for the given post
|
||||||
|
abstract NewerPost : (Post -> Post option)
|
||||||
|
|
||||||
|
/// Try to find the next newer published post within a given category
|
||||||
|
abstract NewerCategorizedPost : (string -> Post -> Post option)
|
||||||
|
|
||||||
|
/// Try to find the next newer published post tagged with a given tag
|
||||||
|
abstract NewerTaggedPost : (string -> Post -> Post option)
|
||||||
|
|
||||||
|
/// Try to find the next older published post for the given post
|
||||||
|
abstract OlderPost : (Post -> Post option)
|
||||||
|
|
||||||
|
/// Try to find the next older published post within a given category
|
||||||
|
abstract OlderCategorizedPost : (string -> Post -> Post option)
|
||||||
|
|
||||||
|
/// Try to find the next older published post tagged with a given tag
|
||||||
|
abstract OlderTaggedPost : (string -> Post -> Post option)
|
||||||
|
|
||||||
|
/// Find a page of all posts for the given web log (web log Id, page #, # per page)
|
||||||
|
abstract PageOfAllPosts : (string -> int -> int -> Post list)
|
||||||
|
|
||||||
|
/// Try to find a post by its Id and web log Id (web log, post Ids)
|
||||||
|
abstract PostById : (string -> string -> Post option)
|
||||||
|
|
||||||
|
/// Try to find a post by its permalink (web log Id, permalink)
|
||||||
|
abstract PostByPermalink : (string -> string -> Post option)
|
||||||
|
|
||||||
|
/// Try to find a post by a prior permalink (web log Id, permalink)
|
||||||
|
abstract PostByPriorPermalink : (string -> string -> Post option)
|
||||||
|
|
||||||
|
/// Get posts for the RSS feed for the given web log and number of posts
|
||||||
|
abstract FeedPosts : (string -> int -> (Post * User option) list)
|
||||||
|
|
||||||
|
/// Add a post
|
||||||
|
abstract AddPost : (Post -> unit)
|
||||||
|
|
||||||
|
/// Update a post
|
||||||
|
abstract UpdatePost : (Post -> unit)
|
||||||
|
|
||||||
|
// --- User ---
|
||||||
|
|
||||||
|
/// Attempt to log on a user
|
||||||
|
abstract LogOn : (string -> string -> User option)
|
||||||
|
|
||||||
|
// --- WebLog ---
|
||||||
|
|
||||||
|
/// Get a web log by its URL base
|
||||||
|
abstract WebLogByUrlBase : (string -> WebLog option)
|
||||||
|
|
||||||
|
/// Get dashboard counts for a web log
|
||||||
|
abstract DashboardCounts : (string -> DashboardCounts)
|
91
src/MyWebLog.Entities/MyWebLog.Entities.fsproj
Normal file
91
src/MyWebLog.Entities/MyWebLog.Entities.fsproj
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="12.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>a87f3cf5-2189-442b-8acf-929f5153ac22</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<RootNamespace>MyWebLog.Entities</RootNamespace>
|
||||||
|
<AssemblyName>MyWebLog.Entities</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||||
|
<TargetFSharpCoreVersion>4.4.0.0</TargetFSharpCoreVersion>
|
||||||
|
<Name>MyWebLog.Entities</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.Entities.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.Entities.xml</DocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="mscorlib" />
|
||||||
|
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Numerics" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Entities.fs" />
|
||||||
|
<Compile Include="IMyWebLogData.fs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<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)" Condition="Exists('$(FSharpTargetsPath)')" />
|
||||||
|
<!-- 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>
|
||||||
|
-->
|
||||||
|
<Choose>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v4.0'">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
<HintPath>..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.2')">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
<HintPath>..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Paket>True</Paket>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
</Project>
|
1
src/MyWebLog.Entities/paket.references
Normal file
1
src/MyWebLog.Entities/paket.references
Normal file
@ -0,0 +1 @@
|
|||||||
|
Newtonsoft.Json
|
56
src/MyWebLog.Logic/Category.fs
Normal file
56
src/MyWebLog.Logic/Category.fs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
module MyWebLog.Logic.Category
|
||||||
|
|
||||||
|
open MyWebLog.Data
|
||||||
|
open MyWebLog.Entities
|
||||||
|
|
||||||
|
/// Sort categories by their name, with their children sorted below them, including an indent level
|
||||||
|
let sortCategories categories =
|
||||||
|
let rec getChildren (cat : Category) indent =
|
||||||
|
seq {
|
||||||
|
yield cat, indent
|
||||||
|
for child in categories |> List.filter (fun c -> c.ParentId = Some cat.Id) do
|
||||||
|
yield! getChildren child (indent + 1)
|
||||||
|
}
|
||||||
|
categories
|
||||||
|
|> List.filter (fun c -> c.ParentId.IsNone)
|
||||||
|
|> List.map (fun c -> getChildren c 0)
|
||||||
|
|> Seq.collect id
|
||||||
|
|> Seq.toList
|
||||||
|
|
||||||
|
/// Find all categories for a given web log
|
||||||
|
let findAllCategories (data : IMyWebLogData) webLogId =
|
||||||
|
data.AllCategories webLogId
|
||||||
|
|> sortCategories
|
||||||
|
|
||||||
|
/// Try to find a category for a given web log Id and category Id
|
||||||
|
let tryFindCategory (data : IMyWebLogData) webLogId catId = data.CategoryById webLogId catId
|
||||||
|
|
||||||
|
/// Try to find a category by its slug for a given web log
|
||||||
|
let tryFindCategoryBySlug (data : IMyWebLogData) webLogId slug = data.CategoryBySlug webLogId slug
|
||||||
|
|
||||||
|
/// Save a category
|
||||||
|
let saveCategory (data : IMyWebLogData) (cat : Category) =
|
||||||
|
match cat.Id with
|
||||||
|
| "new" -> let newCat = { cat with Id = string <| System.Guid.NewGuid() }
|
||||||
|
data.AddCategory newCat
|
||||||
|
newCat.Id
|
||||||
|
| _ -> data.UpdateCategory cat
|
||||||
|
cat.Id
|
||||||
|
|
||||||
|
/// Remove a category from its parent
|
||||||
|
let removeCategoryFromParent (data : IMyWebLogData) webLogId parentId catId =
|
||||||
|
match tryFindCategory data webLogId parentId with
|
||||||
|
| Some parent -> parent.Children
|
||||||
|
|> List.filter (fun childId -> childId <> catId)
|
||||||
|
|> data.UpdateChildren webLogId parentId
|
||||||
|
| None -> ()
|
||||||
|
|
||||||
|
/// Add a category to a given parent
|
||||||
|
let addCategoryToParent (data : IMyWebLogData) webLogId parentId catId =
|
||||||
|
match tryFindCategory data webLogId parentId with
|
||||||
|
| Some parent -> catId :: parent.Children
|
||||||
|
|> data.UpdateChildren webLogId parentId
|
||||||
|
| None -> ()
|
||||||
|
|
||||||
|
/// Delete a category
|
||||||
|
let deleteCategory (data : IMyWebLogData) cat = data.DeleteCategory cat
|
@ -1,18 +1,17 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="12.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')" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
<ProjectGuid>1fba0b84-b09e-4b16-b9b6-5730dea27192</ProjectGuid>
|
<ProjectGuid>29f6eda3-4f43-4bb3-9c63-ae238a9b7f12</ProjectGuid>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<RootNamespace>myWebLog.Data</RootNamespace>
|
<RootNamespace>MyWebLog.Logic</RootNamespace>
|
||||||
<AssemblyName>MyWebLog.Data</AssemblyName>
|
<AssemblyName>MyWebLog.Logic</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||||
<TargetFSharpCoreVersion>4.4.0.0</TargetFSharpCoreVersion>
|
<TargetFSharpCoreVersion>4.4.0.0</TargetFSharpCoreVersion>
|
||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
<Name>MyWebLog.Logic</Name>
|
||||||
<Name>myWebLog.Data</Name>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
@ -22,7 +21,7 @@
|
|||||||
<OutputPath>bin\Debug\</OutputPath>
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<WarningLevel>3</WarningLevel>
|
<WarningLevel>3</WarningLevel>
|
||||||
<DocumentationFile>bin\Debug\MyWebLog.Data.xml</DocumentationFile>
|
<DocumentationFile>bin\Debug\MyWebLog.Logic.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
@ -31,8 +30,31 @@
|
|||||||
<OutputPath>bin\Release\</OutputPath>
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<WarningLevel>3</WarningLevel>
|
<WarningLevel>3</WarningLevel>
|
||||||
<DocumentationFile>bin\Release\myWebLog.Data.XML</DocumentationFile>
|
<DocumentationFile>bin\Release\MyWebLog.Logic.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="mscorlib" />
|
||||||
|
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Numerics" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Category.fs" />
|
||||||
|
<Compile Include="Page.fs" />
|
||||||
|
<Compile Include="Post.fs" />
|
||||||
|
<Compile Include="User.fs" />
|
||||||
|
<Compile Include="WebLog.fs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MyWebLog.Entities\MyWebLog.Entities.fsproj">
|
||||||
|
<Name>MyWebLog.Entities</Name>
|
||||||
|
<Project>{a87f3cf5-2189-442b-8acf-929f5153ac22}</Project>
|
||||||
|
<Private>True</Private>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
|
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -48,56 +70,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Otherwise>
|
</Otherwise>
|
||||||
</Choose>
|
</Choose>
|
||||||
<Import Project="$(FSharpTargetsPath)" />
|
<Import Project="$(FSharpTargetsPath)" Condition="Exists('$(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="Category.fs" />
|
|
||||||
<Compile Include="Page.fs" />
|
|
||||||
<Compile Include="Post.fs" />
|
|
||||||
<Compile Include="User.fs" />
|
|
||||||
<Compile Include="WebLog.fs" />
|
|
||||||
<None Include="ConvertOld.fsx" />
|
|
||||||
<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="Dynamitey">
|
|
||||||
<HintPath>..\packages\Dynamitey.1.0.2.0\lib\net40\Dynamitey.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="FSharp.Interop.Dynamic">
|
|
||||||
<HintPath>..\packages\FSharp.Interop.Dynamic.3.0.0.0\lib\portable-net45+sl50+win\FSharp.Interop.Dynamic.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="mscorlib" />
|
|
||||||
<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.9\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.
|
<!-- 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.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
<Target Name="BeforeBuild">
|
<Target Name="BeforeBuild">
|
29
src/MyWebLog.Logic/Page.fs
Normal file
29
src/MyWebLog.Logic/Page.fs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/// Logic for manipulating <see cref="Page" /> entities
|
||||||
|
module MyWebLog.Logic.Page
|
||||||
|
|
||||||
|
open MyWebLog.Data
|
||||||
|
open MyWebLog.Entities
|
||||||
|
|
||||||
|
/// Find a page by its Id and web log Id
|
||||||
|
let tryFindPage (data : IMyWebLogData) webLogId pageId = data.PageById webLogId pageId true
|
||||||
|
|
||||||
|
/// Find a page by its Id and web log Id, without the revision list
|
||||||
|
let tryFindPageWithoutRevisions (data : IMyWebLogData) webLogId pageId = data.PageById webLogId pageId false
|
||||||
|
|
||||||
|
/// Find a page by its permalink
|
||||||
|
let tryFindPageByPermalink (data : IMyWebLogData) webLogId permalink = data.PageByPermalink webLogId permalink
|
||||||
|
|
||||||
|
/// Find a list of all pages (excludes text and revisions)
|
||||||
|
let findAllPages (data : IMyWebLogData) webLogId = data.AllPages webLogId
|
||||||
|
|
||||||
|
/// Save a page
|
||||||
|
let savePage (data : IMyWebLogData) (page : Page) =
|
||||||
|
match page.Id with
|
||||||
|
| "new" -> let newPg = { page with Id = string <| System.Guid.NewGuid() }
|
||||||
|
data.AddPage newPg
|
||||||
|
newPg.Id
|
||||||
|
| _ -> data.UpdatePage page
|
||||||
|
page.Id
|
||||||
|
|
||||||
|
/// Delete a page
|
||||||
|
let deletePage (data : IMyWebLogData) webLogId pageId = data.DeletePage webLogId pageId
|
60
src/MyWebLog.Logic/Post.fs
Normal file
60
src/MyWebLog.Logic/Post.fs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/// Logic for manipulating <see cref="Post" /> entities
|
||||||
|
module MyWebLog.Logic.Post
|
||||||
|
|
||||||
|
open MyWebLog.Data
|
||||||
|
open MyWebLog.Entities
|
||||||
|
|
||||||
|
/// Find a page of published posts
|
||||||
|
let findPageOfPublishedPosts (data : IMyWebLogData) webLogId pageNbr nbrPerPage =
|
||||||
|
data.PageOfPublishedPosts webLogId pageNbr nbrPerPage
|
||||||
|
|
||||||
|
/// Find a pages of published posts in a given category
|
||||||
|
let findPageOfCategorizedPosts (data : IMyWebLogData) webLogId catId pageNbr nbrPerPage =
|
||||||
|
data.PageOfCategorizedPosts webLogId catId pageNbr nbrPerPage
|
||||||
|
|
||||||
|
/// Find a page of published posts tagged with a given tag
|
||||||
|
let findPageOfTaggedPosts (data : IMyWebLogData) webLogId tag pageNbr nbrPerPage =
|
||||||
|
data.PageOfTaggedPosts webLogId tag pageNbr nbrPerPage
|
||||||
|
|
||||||
|
/// Find the next newer published post for the given post
|
||||||
|
let tryFindNewerPost (data : IMyWebLogData) post = data.NewerPost post
|
||||||
|
|
||||||
|
/// Find the next newer published post in a given category for the given post
|
||||||
|
let tryFindNewerCategorizedPost (data : IMyWebLogData) catId post = data.NewerCategorizedPost catId post
|
||||||
|
|
||||||
|
/// Find the next newer published post tagged with a given tag for the given post
|
||||||
|
let tryFindNewerTaggedPost (data : IMyWebLogData) tag post = data.NewerTaggedPost tag post
|
||||||
|
|
||||||
|
/// Find the next older published post for the given post
|
||||||
|
let tryFindOlderPost (data : IMyWebLogData) post = data.OlderPost post
|
||||||
|
|
||||||
|
/// Find the next older published post in a given category for the given post
|
||||||
|
let tryFindOlderCategorizedPost (data : IMyWebLogData) catId post = data.OlderCategorizedPost catId post
|
||||||
|
|
||||||
|
/// Find the next older published post tagged with a given tag for the given post
|
||||||
|
let tryFindOlderTaggedPost (data : IMyWebLogData) tag post = data.OlderTaggedPost tag post
|
||||||
|
|
||||||
|
/// Find a page of all posts for a web log
|
||||||
|
let findPageOfAllPosts (data : IMyWebLogData) webLogId pageNbr nbrPerPage =
|
||||||
|
data.PageOfAllPosts webLogId pageNbr nbrPerPage
|
||||||
|
|
||||||
|
/// Try to find a post by its Id
|
||||||
|
let tryFindPost (data : IMyWebLogData) webLogId postId = data.PostById webLogId postId
|
||||||
|
|
||||||
|
/// Try to find a post by its permalink
|
||||||
|
let tryFindPostByPermalink (data : IMyWebLogData) webLogId permalink = data.PostByPermalink webLogId permalink
|
||||||
|
|
||||||
|
/// Try to find a post by its prior permalink
|
||||||
|
let tryFindPostByPriorPermalink (data : IMyWebLogData) webLogId permalink = data.PostByPriorPermalink webLogId permalink
|
||||||
|
|
||||||
|
/// Find posts for the RSS feed
|
||||||
|
let findFeedPosts (data : IMyWebLogData) webLogId nbrOfPosts = data.FeedPosts webLogId nbrOfPosts
|
||||||
|
|
||||||
|
/// Save a post
|
||||||
|
let savePost (data : IMyWebLogData) post =
|
||||||
|
match post.Id with
|
||||||
|
| "new" -> let newPost = { post with Id = string <| System.Guid.NewGuid() }
|
||||||
|
data.AddPost newPost
|
||||||
|
newPost.Id
|
||||||
|
| _ -> data.UpdatePost post
|
||||||
|
post.Id
|
7
src/MyWebLog.Logic/User.fs
Normal file
7
src/MyWebLog.Logic/User.fs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/// Logic for manipulating <see cref="User" /> entities
|
||||||
|
module MyWebLog.Logic.User
|
||||||
|
|
||||||
|
open MyWebLog.Data
|
||||||
|
|
||||||
|
/// Try to log on a user
|
||||||
|
let tryUserLogOn (data : IMyWebLogData) email passwordHash = data.LogOn email passwordHash
|
11
src/MyWebLog.Logic/WebLog.fs
Normal file
11
src/MyWebLog.Logic/WebLog.fs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/// Logic for manipulating <see cref="WebLog" /> entities
|
||||||
|
module MyWebLog.Logic.WebLog
|
||||||
|
|
||||||
|
open MyWebLog.Data
|
||||||
|
open MyWebLog.Entities
|
||||||
|
|
||||||
|
/// Find a web log by its URL base
|
||||||
|
let tryFindWebLogByUrlBase (data : IMyWebLogData) urlBase = data.WebLogByUrlBase urlBase
|
||||||
|
|
||||||
|
/// Find the counts for the admin dashboard
|
||||||
|
let findDashboardCounts (data : IMyWebLogData) webLogId = data.DashboardCounts webLogId
|
4
src/MyWebLog.Tests/MyWebLog.Tests.fs
Normal file
4
src/MyWebLog.Tests/MyWebLog.Tests.fs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
namespace MyWebLog.Web
|
||||||
|
|
||||||
|
type Web() =
|
||||||
|
member this.X = "F#"
|
70
src/MyWebLog.Tests/MyWebLog.Tests.fsproj
Normal file
70
src/MyWebLog.Tests/MyWebLog.Tests.fsproj
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="12.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>07e60874-6cf5-4d53-aee0-f17ef28228dd</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<RootNamespace>MyWebLog.Tests</RootNamespace>
|
||||||
|
<AssemblyName>MyWebLog.Tests</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||||
|
<TargetFSharpCoreVersion>4.4.0.0</TargetFSharpCoreVersion>
|
||||||
|
<Name>MyWebLog.Tests</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.Tests.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.Tests.xml</DocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="mscorlib" />
|
||||||
|
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Numerics" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="MyWebLog.Tests.fs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<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)" Condition="Exists('$(FSharpTargetsPath)')" />
|
||||||
|
<!-- 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>
|
14
src/build.cmd
Normal file
14
src/build.cmd
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
@echo off
|
||||||
|
cls
|
||||||
|
|
||||||
|
.paket\paket.bootstrapper.exe
|
||||||
|
if errorlevel 1 (
|
||||||
|
exit /b %errorlevel%
|
||||||
|
)
|
||||||
|
|
||||||
|
.paket\paket.exe restore
|
||||||
|
if errorlevel 1 (
|
||||||
|
exit /b %errorlevel%
|
||||||
|
)
|
||||||
|
|
||||||
|
packages\FAKE\tools\FAKE.exe build.fsx %*
|
42
src/build.fsx
Normal file
42
src/build.fsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// include Fake libs
|
||||||
|
#r "./packages/FAKE/tools/FakeLib.dll"
|
||||||
|
|
||||||
|
open Fake
|
||||||
|
|
||||||
|
// Directories
|
||||||
|
let buildDir = "./build/"
|
||||||
|
let deployDir = "./deploy/"
|
||||||
|
|
||||||
|
|
||||||
|
// Filesets
|
||||||
|
let appReferences =
|
||||||
|
!! "/**/*.csproj"
|
||||||
|
++ "/**/*.fsproj"
|
||||||
|
|
||||||
|
// version info
|
||||||
|
let version = "0.1" // or retrieve from CI server
|
||||||
|
|
||||||
|
// Targets
|
||||||
|
Target "Clean" (fun _ ->
|
||||||
|
CleanDirs [buildDir; deployDir]
|
||||||
|
)
|
||||||
|
|
||||||
|
Target "Build" (fun _ ->
|
||||||
|
// compile all projects below src/app/
|
||||||
|
MSBuildDebug buildDir "Build" appReferences
|
||||||
|
|> Log "AppBuild-Output: "
|
||||||
|
)
|
||||||
|
|
||||||
|
Target "Deploy" (fun _ ->
|
||||||
|
!! (buildDir + "/**/*.*")
|
||||||
|
-- "*.zip"
|
||||||
|
|> Zip buildDir (deployDir + "ApplicationName." + version + ".zip")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Build order
|
||||||
|
"Clean"
|
||||||
|
==> "Build"
|
||||||
|
==> "Deploy"
|
||||||
|
|
||||||
|
// start build
|
||||||
|
RunTargetOrDefault "Build"
|
33
src/build.sh
Normal file
33
src/build.sh
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if test "$OS" = "Windows_NT"
|
||||||
|
then
|
||||||
|
# use .Net
|
||||||
|
|
||||||
|
.paket/paket.bootstrapper.exe
|
||||||
|
exit_code=$?
|
||||||
|
if [ $exit_code -ne 0 ]; then
|
||||||
|
exit $exit_code
|
||||||
|
fi
|
||||||
|
|
||||||
|
.paket/paket.exe restore
|
||||||
|
exit_code=$?
|
||||||
|
if [ $exit_code -ne 0 ]; then
|
||||||
|
exit $exit_code
|
||||||
|
fi
|
||||||
|
|
||||||
|
packages/FAKE/tools/FAKE.exe $@ --fsiargs build.fsx
|
||||||
|
else
|
||||||
|
# use mono
|
||||||
|
mono .paket/paket.bootstrapper.exe
|
||||||
|
exit_code=$?
|
||||||
|
if [ $exit_code -ne 0 ]; then
|
||||||
|
exit $exit_code
|
||||||
|
fi
|
||||||
|
|
||||||
|
mono .paket/paket.exe restore
|
||||||
|
exit_code=$?
|
||||||
|
if [ $exit_code -ne 0 ]; then
|
||||||
|
exit $exit_code
|
||||||
|
fi
|
||||||
|
mono packages/FAKE/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx
|
||||||
|
fi
|
@ -1,77 +0,0 @@
|
|||||||
module MyWebLog.Data.Page
|
|
||||||
|
|
||||||
open FSharp.Interop.Dynamic
|
|
||||||
open MyWebLog.Entities
|
|
||||||
open Rethink
|
|
||||||
open RethinkDb.Driver.Ast
|
|
||||||
open System.Dynamic
|
|
||||||
|
|
||||||
let private r = RethinkDb.Driver.RethinkDB.R
|
|
||||||
|
|
||||||
/// Shorthand to get the page by its Id, filtering on web log Id
|
|
||||||
let private page (webLogId : string) (pageId : string) =
|
|
||||||
r.Table(Table.Page)
|
|
||||||
.Get(pageId)
|
|
||||||
.Filter(ReqlFunction1(fun p -> upcast p.["WebLogId"].Eq(webLogId)))
|
|
||||||
|
|
||||||
/// Get a page by its Id
|
|
||||||
let tryFindPage conn webLogId pageId =
|
|
||||||
match r.Table(Table.Page)
|
|
||||||
.Get(pageId)
|
|
||||||
.RunAtomAsync<Page>(conn) |> await |> box with
|
|
||||||
| null -> None
|
|
||||||
| page -> let pg : Page = unbox page
|
|
||||||
match pg.WebLogId = webLogId with true -> Some pg | _ -> None
|
|
||||||
|
|
||||||
/// Get a page by its Id (excluding revisions)
|
|
||||||
let tryFindPageWithoutRevisions conn webLogId pageId : Page option =
|
|
||||||
match (page webLogId pageId)
|
|
||||||
.Without("Revisions")
|
|
||||||
.RunAtomAsync<Page>(conn) |> await |> box with
|
|
||||||
| null -> None
|
|
||||||
| page -> Some <| unbox page
|
|
||||||
|
|
||||||
/// Find a page by its permalink
|
|
||||||
let tryFindPageByPermalink conn (webLogId : string) (permalink : string) =
|
|
||||||
r.Table(Table.Page)
|
|
||||||
.GetAll(r.Array(webLogId, permalink)).OptArg("index", "Permalink")
|
|
||||||
.Without("Revisions")
|
|
||||||
.RunCursorAsync<Page>(conn)
|
|
||||||
|> await
|
|
||||||
|> Seq.tryHead
|
|
||||||
|
|
||||||
/// Get a list of all pages (excludes page text and revisions)
|
|
||||||
let findAllPages conn (webLogId : string) =
|
|
||||||
r.Table(Table.Page)
|
|
||||||
.GetAll(webLogId).OptArg("index", "WebLogId")
|
|
||||||
.OrderBy("Title")
|
|
||||||
.Without("Text", "Revisions")
|
|
||||||
.RunListAsync<Page>(conn)
|
|
||||||
|> await
|
|
||||||
|> Seq.toList
|
|
||||||
|
|
||||||
/// Save a page
|
|
||||||
let savePage conn (pg : Page) =
|
|
||||||
match pg.Id with
|
|
||||||
| "new" -> let newPage = { pg with Id = string <| System.Guid.NewGuid() }
|
|
||||||
r.Table(Table.Page)
|
|
||||||
.Insert(page)
|
|
||||||
.RunResultAsync(conn) |> await |> ignore
|
|
||||||
newPage.Id
|
|
||||||
| _ -> let upd8 = ExpandoObject()
|
|
||||||
upd8?Title <- pg.Title
|
|
||||||
upd8?Permalink <- pg.Permalink
|
|
||||||
upd8?PublishedOn <- pg.PublishedOn
|
|
||||||
upd8?UpdatedOn <- pg.UpdatedOn
|
|
||||||
upd8?Text <- pg.Text
|
|
||||||
upd8?Revisions <- pg.Revisions
|
|
||||||
(page pg.WebLogId pg.Id)
|
|
||||||
.Update(upd8)
|
|
||||||
.RunResultAsync(conn) |> await |> ignore
|
|
||||||
pg.Id
|
|
||||||
|
|
||||||
/// Delete a page
|
|
||||||
let deletePage conn webLogId pageId =
|
|
||||||
(page webLogId pageId)
|
|
||||||
.Delete()
|
|
||||||
.RunResultAsync(conn) |> await |> ignore
|
|
@ -1,10 +0,0 @@
|
|||||||
<?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="Dynamitey" version="1.0.2.0" targetFramework="net452" />
|
|
||||||
<package id="FSharp.Core" version="4.0.0.1" targetFramework="net452" />
|
|
||||||
<package id="FSharp.Interop.Dynamic" version="3.0.0.0" targetFramework="net452" />
|
|
||||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
|
|
||||||
<package id="RethinkDb.Driver" version="2.3.9" targetFramework="net452" />
|
|
||||||
</packages>
|
|
@ -1,186 +0,0 @@
|
|||||||
<?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="AppConfig.fs" />
|
|
||||||
<Compile Include="ViewModels.fs" />
|
|
||||||
<Compile Include="ModuleExtensions.fs" />
|
|
||||||
<Compile Include="AdminModule.fs" />
|
|
||||||
<Compile Include="CategoryModule.fs" />
|
|
||||||
<Compile Include="PageModule.fs" />
|
|
||||||
<Compile Include="PostModule.fs" />
|
|
||||||
<Compile Include="UserModule.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="CSharpFormat">
|
|
||||||
<HintPath>..\packages\FSharp.Formatting.2.14.4\lib\net40\CSharpFormat.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Dynamitey">
|
|
||||||
<HintPath>..\packages\Dynamitey.1.0.2.0\lib\net40\Dynamitey.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="FSharp.CodeFormat">
|
|
||||||
<HintPath>..\packages\FSharp.Formatting.2.14.4\lib\net40\FSharp.CodeFormat.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="FSharp.Compiler.Service">
|
|
||||||
<HintPath>..\packages\FSharp.Compiler.Service.2.0.0.6\lib\net45\FSharp.Compiler.Service.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="FSharp.Formatting.Common">
|
|
||||||
<HintPath>..\packages\FSharp.Formatting.2.14.4\lib\net40\FSharp.Formatting.Common.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="FSharp.Interop.Dynamic">
|
|
||||||
<HintPath>..\packages\FSharp.Interop.Dynamic.3.0.0.0\lib\portable-net45+sl50+win\FSharp.Interop.Dynamic.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="FSharp.Literate">
|
|
||||||
<HintPath>..\packages\FSharp.Formatting.2.14.4\lib\net40\FSharp.Literate.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="FSharp.Markdown">
|
|
||||||
<HintPath>..\packages\FSharp.Formatting.2.14.4\lib\net40\FSharp.Markdown.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="FSharp.MetadataFormat">
|
|
||||||
<HintPath>..\packages\FSharp.Formatting.2.14.4\lib\net40\FSharp.MetadataFormat.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="FSharpVSPowerTools.Core">
|
|
||||||
<HintPath>..\packages\FSharpVSPowerTools.Core.2.3.0\lib\net45\FSharpVSPowerTools.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.9.0\lib\net452\Nancy.Session.Persistable.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Nancy.Session.RethinkDb">
|
|
||||||
<HintPath>..\packages\Nancy.Session.RethinkDB.0.9.0\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="NodaTime">
|
|
||||||
<HintPath>..\packages\NodaTime.1.3.2\lib\net35-Client\NodaTime.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="RazorEngine">
|
|
||||||
<HintPath>..\packages\FSharp.Formatting.2.14.4\lib\net40\RazorEngine.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="RethinkDb.Driver">
|
|
||||||
<HintPath>..\packages\RethinkDb.Driver.2.3.9\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.ComponentModel.DataAnnotations" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
<Reference Include="System.Numerics" />
|
|
||||||
<Reference Include="System.ServiceModel" />
|
|
||||||
<Reference Include="System.Web.Razor">
|
|
||||||
<HintPath>..\packages\FSharp.Formatting.2.14.4\lib\net40\System.Web.Razor.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
</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>
|
|
@ -1,19 +0,0 @@
|
|||||||
<?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="Dynamitey" version="1.0.2.0" targetFramework="net452" />
|
|
||||||
<package id="FSharp.Compiler.Service" version="2.0.0.6" targetFramework="net452" />
|
|
||||||
<package id="FSharp.Core" version="4.0.0.1" targetFramework="net452" />
|
|
||||||
<package id="FSharp.Formatting" version="2.14.4" targetFramework="net452" />
|
|
||||||
<package id="FSharp.Interop.Dynamic" version="3.0.0.0" targetFramework="net452" />
|
|
||||||
<package id="FSharpVSPowerTools.Core" version="2.3.0" 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.9.0" targetFramework="net452" />
|
|
||||||
<package id="Nancy.Session.RethinkDB" version="0.9.0" targetFramework="net452" />
|
|
||||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
|
|
||||||
<package id="NodaTime" version="1.3.2" targetFramework="net452" />
|
|
||||||
<package id="RethinkDb.Driver" version="2.3.9" targetFramework="net452" />
|
|
||||||
<package id="Suave" version="1.1.3" targetFramework="net452" />
|
|
||||||
</packages>
|
|
@ -1,39 +1,14 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 14
|
# Visual Studio 2013
|
||||||
VisualStudioVersion = 14.0.25420.1
|
VisualStudioVersion = 12.0.31101.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "myWebLog", "myWebLog\myWebLog.csproj", "{B9F6DB52-65A1-4C2A-8C97-739E08A1D4FB}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{DF15419B-90C6-4F45-8EC1-7A63C5D3565C}"
|
||||||
EndProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "myWebLog.Web", "myWebLog.Web\myWebLog.Web.fsproj", "{E6EE110A-27A6-4A19-B0CB-D24F48F71B53}"
|
paket.dependencies = paket.dependencies
|
||||||
EndProject
|
EndProjectSection
|
||||||
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
|
EndProject
|
||||||
Global
|
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
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
@ -15,7 +15,20 @@
|
|||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
</assemblyBinding>
|
</assemblyBinding>
|
||||||
</runtime>
|
</runtime>
|
||||||
|
<system.data>
|
||||||
|
<DbProviderFactories>
|
||||||
|
<add name="SqlClient Data Provider"
|
||||||
|
invariant="System.Data.SqlClient"
|
||||||
|
description=".NET Framework Data Provider for SQL Server"
|
||||||
|
type="System.Data.SqlClient.SqlClientFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||||
|
</DbProviderFactories>
|
||||||
|
</system.data>
|
||||||
|
<connectionStrings>
|
||||||
|
<clear />
|
||||||
|
<add name="SessionStore"
|
||||||
|
providerName="System.Data.SqlClient"
|
||||||
|
connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\danie\Documents\Sandbox\myWebLog\src\myWebLog\session.mdf;Integrated Security=True;Connect Timeout=30" />
|
||||||
|
</connectionStrings>
|
||||||
</configuration>
|
</configuration>
|
||||||
<!-- publicKeyToken="32ab4ba45e0a69a1"
|
<!-- publicKeyToken="32ab4ba45e0a69a1"
|
||||||
culture="neutral"
|
culture="neutral"
|
||||||
|
@ -56,20 +56,27 @@
|
|||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\myWebLog.Data\myWebLog.Data.fsproj">
|
<ProjectReference Include="..\MyWebLog.App\MyWebLog.App.fsproj">
|
||||||
<Project>{1fba0b84-b09e-4b16-b9b6-5730dea27192}</Project>
|
<Project>{9cea3a8b-e8aa-44e6-9f5f-2095ceed54eb}</Project>
|
||||||
<Name>myWebLog.Data</Name>
|
<Name>MyWebLog.App</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\myWebLog.Resources\myWebLog.Resources.csproj">
|
<ProjectReference Include="..\MyWebLog.Data.RethinkDB\MyWebLog.Data.RethinkDB.fsproj">
|
||||||
|
<Project>{d6c2be5e-883a-4f34-9905-b730543ca380}</Project>
|
||||||
|
<Name>myWebLog.Web</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\MyWebLog.Entities\MyWebLog.Entities.fsproj">
|
||||||
|
<Project>{a87f3cf5-2189-442b-8acf-929f5153ac22}</Project>
|
||||||
|
<Name>MyWebLog.Entities</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\MyWebLog.Logic\MyWebLog.Logic.fsproj">
|
||||||
|
<Project>{29f6eda3-4f43-4bb3-9c63-ae238a9b7f12}</Project>
|
||||||
|
<Name>MyWebLog.Entities</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\MyWebLog.Resources\MyWebLog.Resources.csproj">
|
||||||
<Project>{a12ea8da-88bc-4447-90cb-a0e2dcc37523}</Project>
|
<Project>{a12ea8da-88bc-4447-90cb-a0e2dcc37523}</Project>
|
||||||
<Name>myWebLog.Resources</Name>
|
<Name>myWebLog.Resources</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\myWebLog.Web\myWebLog.Web.fsproj">
|
|
||||||
<Project>{e6ee110a-27a6-4a19-b0cb-d24f48f71b53}</Project>
|
|
||||||
<Name>myWebLog.Web</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="content\scripts\tinymce-init.js" />
|
<Content Include="content\scripts\tinymce-init.js" />
|
||||||
<Content Include="content\styles\admin.css" />
|
<Content Include="content\styles\admin.css" />
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<article>
|
<article>
|
||||||
<h1>
|
<h1>
|
||||||
<a href="/@Current.Post.Permalink"
|
<a href="/@Current.Post.Permalink"
|
||||||
title="@Translate.PermanentLinkTo "@Current.Post.Title@quot;">@Current.Post.Title</a>
|
title="@Translate.PermanentLinkTo "@Current.Post.Title"">@Current.Post.Title</a>
|
||||||
</h1>
|
</h1>
|
||||||
<p>
|
<p>
|
||||||
<i class="fa fa-calendar" title="@Translate.Date"></i> @Current.PublishedDate
|
<i class="fa fa-calendar" title="@Translate.Date"></i> @Current.PublishedDate
|
||||||
|
13
src/paket.dependencies
Normal file
13
src/paket.dependencies
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
framework: net40, net45, net452
|
||||||
|
source https://www.nuget.org/api/v2
|
||||||
|
nuget Common.Logging 3.3.0
|
||||||
|
nuget FAKE
|
||||||
|
nuget FSharp.Interop.Dynamic
|
||||||
|
nuget FSharp.Formatting
|
||||||
|
nuget Nancy
|
||||||
|
nuget Nancy.Authentication.Forms
|
||||||
|
nuget Nancy.Session.RethinkDb
|
||||||
|
nuget Newtonsoft.Json
|
||||||
|
nuget NodaTime
|
||||||
|
nuget RethinkDb.Driver
|
||||||
|
nuget Suave
|
34
src/paket.lock
Normal file
34
src/paket.lock
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
FRAMEWORK: NET40, NET45, NET452
|
||||||
|
NUGET
|
||||||
|
remote: https://www.nuget.org/api/v2
|
||||||
|
Common.Logging (3.3)
|
||||||
|
Common.Logging.Core (>= 3.3)
|
||||||
|
Common.Logging.Core (3.3.1)
|
||||||
|
Dynamitey (1.0.2)
|
||||||
|
FAKE (4.36)
|
||||||
|
FSharp.Compiler.Service (2.0.0.6)
|
||||||
|
FSharp.Core (4.0.0.1)
|
||||||
|
FSharp.Formatting (2.14.4)
|
||||||
|
FSharp.Compiler.Service (2.0.0.6)
|
||||||
|
FSharpVSPowerTools.Core (>= 2.3 < 2.4)
|
||||||
|
FSharp.Interop.Dynamic (3.0)
|
||||||
|
Dynamitey (>= 1.0.2)
|
||||||
|
FSharp.Core (>= 3.1.2.1)
|
||||||
|
FSharpVSPowerTools.Core (2.3)
|
||||||
|
FSharp.Compiler.Service (>= 2.0.0.3)
|
||||||
|
Nancy (1.4.3)
|
||||||
|
Nancy.Authentication.Forms (1.4.1)
|
||||||
|
Nancy (>= 1.4.1)
|
||||||
|
Nancy.Session.Persistable (0.9)
|
||||||
|
Nancy (>= 1.4.3)
|
||||||
|
Newtonsoft.Json (>= 9.0.1)
|
||||||
|
Nancy.Session.RethinkDB (0.9)
|
||||||
|
Nancy.Session.Persistable (>= 0.9)
|
||||||
|
RethinkDb.Driver (>= 2.3.9)
|
||||||
|
Newtonsoft.Json (9.0.1)
|
||||||
|
NodaTime (1.3.2)
|
||||||
|
RethinkDb.Driver (2.3.10)
|
||||||
|
Common.Logging (>= 3.3) - framework: net45, net452
|
||||||
|
Newtonsoft.Json (>= 9.0.1) - framework: net45, net452
|
||||||
|
Suave (1.1.3)
|
||||||
|
FSharp.Core (>= 3.1.2.5)
|
Loading…
Reference in New Issue
Block a user