.NET Core / Nancy 2 migration in progress
Only 55 build errors to go! :/ What remains is things that do not exist in .NET Core yet, or API changes (specifically with Nancy and NodaTime).
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
open MyWebLog.Data
|
||||
open MyWebLog.Entities
|
||||
open MyWebLog.Logic.WebLog
|
||||
open MyWebLog.Resources
|
||||
open Nancy
|
||||
open RethinkDb.Driver.Net
|
||||
|
||||
@@ -11,11 +12,11 @@ type AdminModule(data : IMyWebLogData) as this =
|
||||
inherit NancyModule("/admin")
|
||||
|
||||
do
|
||||
this.Get.["/"] <- fun _ -> this.Dashboard ()
|
||||
this.Get("/", fun _ -> this.Dashboard ())
|
||||
|
||||
/// Admin dashboard
|
||||
member this.Dashboard () =
|
||||
member this.Dashboard () : obj =
|
||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||
let model = DashboardModel(this.Context, this.WebLog, findDashboardCounts data this.WebLog.Id)
|
||||
model.PageTitle <- Resources.Dashboard
|
||||
model.PageTitle <- Strings.get "Dashboard"
|
||||
upcast this.View.["admin/dashboard", model]
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
module MyWebLog.App
|
||||
|
||||
open Microsoft.AspNetCore.Builder
|
||||
open Microsoft.AspNetCore.Hosting
|
||||
open Microsoft.Extensions.Configuration
|
||||
open MyWebLog
|
||||
open MyWebLog.Data
|
||||
open MyWebLog.Data.RethinkDB
|
||||
open MyWebLog.Entities
|
||||
open MyWebLog.Logic.WebLog
|
||||
open MyWebLog.Resources
|
||||
open Nancy
|
||||
open Nancy.Authentication.Forms
|
||||
open Nancy.Bootstrapper
|
||||
@@ -19,16 +23,14 @@ open Nancy.TinyIoc
|
||||
open Nancy.ViewEngines.SuperSimpleViewEngine
|
||||
open NodaTime
|
||||
open RethinkDb.Driver.Net
|
||||
open Suave
|
||||
open Suave.Owin
|
||||
open System
|
||||
open System.Configuration
|
||||
open System.IO
|
||||
open System.Reflection
|
||||
open System.Text.RegularExpressions
|
||||
|
||||
/// Establish the configuration for this instance
|
||||
let cfg = try AppConfig.FromJson (System.IO.File.ReadAllText "config.json")
|
||||
with ex -> raise <| ApplicationException(Resources.ErrBadAppConfig, ex)
|
||||
with ex -> raise <| Exception (Strings.get "ErrBadAppConfig", ex)
|
||||
|
||||
let data : IMyWebLogData = upcast RethinkMyWebLogData(cfg.DataConfig.Conn, cfg.DataConfig)
|
||||
|
||||
@@ -40,9 +42,7 @@ type TranslateTokenViewEngineMatcher() =
|
||||
static let regex = Regex("@Translate\.(?<TranslationKey>[a-zA-Z0-9-_]+);?", RegexOptions.Compiled)
|
||||
interface ISuperSimpleViewEngineMatcher with
|
||||
member this.Invoke (content, model, host) =
|
||||
let translate (m : Match) =
|
||||
let key = m.Groups.["TranslationKey"].Value
|
||||
match MyWebLog.Resources.ResourceManager.GetString key with null -> key | xlat -> xlat
|
||||
let translate (m : Match) = Strings.get m.Groups.["TranslationKey"].Value
|
||||
regex.Replace(content, translate)
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ type MyWebLogBootstrapper() =
|
||||
|
||||
|
||||
let version =
|
||||
let v = Reflection.Assembly.GetExecutingAssembly().GetName().Version
|
||||
let v = typeof<AppConfig>.GetType().GetTypeInfo().Assembly.GetName().Version
|
||||
match v.Build with
|
||||
| 0 -> match v.Minor with 0 -> string v.Major | _ -> sprintf "%d.%d" v.Major v.Minor
|
||||
| _ -> sprintf "%d.%d.%d" v.Major v.Minor v.Build
|
||||
@@ -135,13 +135,22 @@ type RequestEnvironment() =
|
||||
match tryFindWebLogByUrlBase data ctx.Request.Url.HostName with
|
||||
| Some webLog -> ctx.Items.[Keys.WebLog] <- webLog
|
||||
| None -> // TODO: redirect to domain set up page
|
||||
ApplicationException (sprintf "%s %s" ctx.Request.Url.HostName Resources.ErrNotConfigured)
|
||||
Exception (sprintf "%s %s" ctx.Request.Url.HostName (Strings.get "ErrNotConfigured"))
|
||||
|> raise
|
||||
ctx.Items.[Keys.Version] <- version
|
||||
null
|
||||
pipelines.BeforeRequest.AddItemToStartOfPipeline establishEnv
|
||||
|
||||
|
||||
let app = OwinApp.ofMidFunc "/" (NancyMiddleware.UseNancy (NancyOptions()))
|
||||
type Startup() =
|
||||
member this.Configure (app : IApplicationBuilder) =
|
||||
app.UseOwin(fun x -> x.UseNancy() |> ignore) |> ignore
|
||||
|
||||
let Run () = startWebServer defaultConfig app // webPart
|
||||
|
||||
let Run () =
|
||||
WebHostBuilder()
|
||||
.UseContentRoot(System.IO.Directory.GetCurrentDirectory())
|
||||
.UseKestrel()
|
||||
.UseStartup<Startup>()
|
||||
.Build()
|
||||
.Run()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
open MyWebLog.Data
|
||||
open MyWebLog.Logic.Category
|
||||
open MyWebLog.Entities
|
||||
open MyWebLog.Resources
|
||||
open Nancy
|
||||
open Nancy.ModelBinding
|
||||
open Nancy.Security
|
||||
@@ -13,13 +14,13 @@ type CategoryModule(data : IMyWebLogData) as this =
|
||||
inherit NancyModule()
|
||||
|
||||
do
|
||||
this.Get .["/categories" ] <- fun _ -> this.CategoryList ()
|
||||
this.Get .["/category/{id}/edit" ] <- fun parms -> this.EditCategory (downcast parms)
|
||||
this.Post .["/category/{id}/edit" ] <- fun parms -> this.SaveCategory (downcast parms)
|
||||
this.Delete.["/category/{id}/delete"] <- fun parms -> this.DeleteCategory (downcast parms)
|
||||
this.Get ("/categories", fun _ -> this.CategoryList ())
|
||||
this.Get ("/category/{id}/edit", fun parms -> this.EditCategory (downcast parms))
|
||||
this.Post ("/category/{id}/edit", fun parms -> this.SaveCategory (downcast parms))
|
||||
this.Delete("/category/{id}/delete", fun parms -> this.DeleteCategory (downcast parms))
|
||||
|
||||
/// Display a list of categories
|
||||
member this.CategoryList () =
|
||||
member this.CategoryList () : obj =
|
||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||
let model = CategoryListModel(this.Context, this.WebLog,
|
||||
(findAllCategories data this.WebLog.Id
|
||||
@@ -67,8 +68,8 @@ type CategoryModule(data : IMyWebLogData) as this =
|
||||
{ UserMessage.Empty with
|
||||
Level = Level.Info
|
||||
Message = System.String.Format
|
||||
(Resources.MsgCategoryEditSuccess,
|
||||
(match catId with "new" -> Resources.Added | _ -> Resources.Updated)) }
|
||||
(Strings.get "MsgCategoryEditSuccess",
|
||||
Strings.get (match catId with "new" -> "Added" | _ -> "Updated")) }
|
||||
|> model.AddMessage
|
||||
this.Redirect (sprintf "/category/%s/edit" newCatId) model
|
||||
| _ -> this.NotFound ()
|
||||
@@ -82,7 +83,7 @@ type CategoryModule(data : IMyWebLogData) as this =
|
||||
| Some cat -> deleteCategory data cat
|
||||
let model = MyWebLogModel(this.Context, this.WebLog)
|
||||
{ UserMessage.Empty with Level = Level.Info
|
||||
Message = System.String.Format(Resources.MsgCategoryDeleted, cat.Name) }
|
||||
Message = System.String.Format(Strings.get "MsgCategoryDeleted", cat.Name) }
|
||||
|> model.AddMessage
|
||||
this.Redirect "/categories" model
|
||||
| _ -> this.NotFound ()
|
||||
|
||||
@@ -1,302 +0,0 @@
|
||||
<?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>
|
||||
21
src/MyWebLog.App/MyWebLog.App.xproj
Normal file
21
src/MyWebLog.App/MyWebLog.App.xproj
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>9cea3a8b-e8aa-44e6-9f5f-2095ceed54eb</ProjectGuid>
|
||||
<RootNamespace>Nancy.Session.Persistable</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
@@ -4,6 +4,7 @@ open FSharp.Markdown
|
||||
open MyWebLog.Data
|
||||
open MyWebLog.Entities
|
||||
open MyWebLog.Logic.Page
|
||||
open MyWebLog.Resources
|
||||
open Nancy
|
||||
open Nancy.ModelBinding
|
||||
open Nancy.Security
|
||||
@@ -15,10 +16,10 @@ type PageModule(data : IMyWebLogData, clock : IClock) as this =
|
||||
inherit NancyModule()
|
||||
|
||||
do
|
||||
this.Get .["/pages" ] <- fun _ -> this.PageList ()
|
||||
this.Get .["/page/{id}/edit" ] <- fun parms -> this.EditPage (downcast parms)
|
||||
this.Post .["/page/{id}/edit" ] <- fun parms -> this.SavePage (downcast parms)
|
||||
this.Delete.["/page/{id}/delete"] <- fun parms -> this.DeletePage (downcast parms)
|
||||
this.Get ("/pages", fun _ -> this.PageList ())
|
||||
this.Get ("/page/{id}/edit", fun parms -> this.EditPage (downcast parms))
|
||||
this.Post ("/page/{id}/edit", fun parms -> this.SavePage (downcast parms))
|
||||
this.Delete("/page/{id}/delete", fun parms -> this.DeletePage (downcast parms))
|
||||
|
||||
/// List all pages
|
||||
member this.PageList () =
|
||||
@@ -32,18 +33,17 @@ type PageModule(data : IMyWebLogData, clock : IClock) as this =
|
||||
member this.EditPage (parameters : DynamicDictionary) =
|
||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||
let pageId = parameters.["id"].ToString ()
|
||||
match (match pageId with
|
||||
| "new" -> Some Page.Empty
|
||||
| _ -> tryFindPage data this.WebLog.Id pageId) with
|
||||
| Some page -> let rev = match page.Revisions
|
||||
|> List.sortByDescending (fun r -> r.AsOf)
|
||||
|> List.tryHead with
|
||||
| Some r -> r
|
||||
| _ -> Revision.Empty
|
||||
let model = EditPageModel(this.Context, this.WebLog, page, rev)
|
||||
model.PageTitle <- match pageId with "new" -> Resources.AddNewPage | _ -> Resources.EditPage
|
||||
upcast this.View.["admin/page/edit", model]
|
||||
| _ -> this.NotFound ()
|
||||
match pageId with "new" -> Some Page.Empty | _ -> tryFindPage data this.WebLog.Id pageId
|
||||
|> function
|
||||
| Some page -> let rev = match page.Revisions
|
||||
|> List.sortByDescending (fun r -> r.AsOf)
|
||||
|> List.tryHead with
|
||||
| Some r -> r
|
||||
| _ -> Revision.Empty
|
||||
let model = EditPageModel(this.Context, this.WebLog, page, rev)
|
||||
model.PageTitle <- Strings.get <| match pageId with "new" -> "AddNewPage" | _ -> "EditPage"
|
||||
upcast this.View.["admin/page/edit", model]
|
||||
| _ -> this.NotFound ()
|
||||
|
||||
/// Save a page
|
||||
member this.SavePage (parameters : DynamicDictionary) =
|
||||
@@ -70,8 +70,8 @@ type PageModule(data : IMyWebLogData, clock : IClock) as this =
|
||||
{ UserMessage.Empty with
|
||||
Level = Level.Info
|
||||
Message = System.String.Format
|
||||
(Resources.MsgPageEditSuccess,
|
||||
(match pageId with "new" -> Resources.Added | _ -> Resources.Updated)) }
|
||||
(Strings.get "MsgPageEditSuccess",
|
||||
Strings.get (match pageId with "new" -> "Added" | _ -> "Updated")) }
|
||||
|> model.AddMessage
|
||||
this.Redirect (sprintf "/page/%s/edit" pId) model
|
||||
| _ -> this.NotFound ()
|
||||
@@ -85,7 +85,7 @@ type PageModule(data : IMyWebLogData, clock : IClock) as this =
|
||||
| Some page -> deletePage data page.WebLogId page.Id
|
||||
let model = MyWebLogModel(this.Context, this.WebLog)
|
||||
{ UserMessage.Empty with Level = Level.Info
|
||||
Message = Resources.MsgPageDeleted }
|
||||
Message = Strings.get "MsgPageDeleted" }
|
||||
|> model.AddMessage
|
||||
this.Redirect "/pages" model
|
||||
| _ -> this.NotFound ()
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
namespace MyWebLog
|
||||
|
||||
open FSharp.Markdown
|
||||
open MyWebLog.Data
|
||||
open MyWebLog.Entities
|
||||
open MyWebLog.Logic.Category
|
||||
open MyWebLog.Logic.Page
|
||||
open MyWebLog.Logic.Post
|
||||
open MyWebLog.Resources
|
||||
open Nancy
|
||||
open Nancy.ModelBinding
|
||||
open Nancy.Security
|
||||
@@ -58,18 +58,18 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
||||
upcast this.Response.FromStream(stream, sprintf "application/%s+xml" format)
|
||||
|
||||
do
|
||||
this.Get .["/" ] <- fun _ -> this.HomePage ()
|
||||
this.Get .["/{permalink*}" ] <- fun parms -> this.CatchAll (downcast parms)
|
||||
this.Get .["/posts/page/{page:int}" ] <- fun parms -> this.PublishedPostsPage (getPage <| downcast parms)
|
||||
this.Get .["/category/{slug}" ] <- fun parms -> this.CategorizedPosts (downcast parms)
|
||||
this.Get .["/category/{slug}/page/{page:int}"] <- fun parms -> this.CategorizedPosts (downcast parms)
|
||||
this.Get .["/tag/{tag}" ] <- fun parms -> this.TaggedPosts (downcast parms)
|
||||
this.Get .["/tag/{tag}/page/{page:int}" ] <- fun parms -> this.TaggedPosts (downcast parms)
|
||||
this.Get .["/feed" ] <- fun _ -> this.Feed ()
|
||||
this.Get .["/posts/list" ] <- fun _ -> this.PostList 1
|
||||
this.Get .["/posts/list/page/{page:int}" ] <- fun parms -> this.PostList (getPage <| downcast parms)
|
||||
this.Get .["/post/{postId}/edit" ] <- fun parms -> this.EditPost (downcast parms)
|
||||
this.Post.["/post/{postId}/edit" ] <- fun parms -> this.SavePost (downcast parms)
|
||||
this.Get ("/", fun _ -> this.HomePage ())
|
||||
this.Get ("/{permalink*}", fun parms -> this.CatchAll (downcast parms))
|
||||
this.Get ("/posts/page/{page:int}", fun parms -> this.PublishedPostsPage (getPage <| downcast parms))
|
||||
this.Get ("/category/{slug}", fun parms -> this.CategorizedPosts (downcast parms))
|
||||
this.Get ("/category/{slug}/page/{page:int}", fun parms -> this.CategorizedPosts (downcast parms))
|
||||
this.Get ("/tag/{tag}", fun parms -> this.TaggedPosts (downcast parms))
|
||||
this.Get ("/tag/{tag}/page/{page:int}", fun parms -> this.TaggedPosts (downcast parms))
|
||||
this.Get ("/feed", fun _ -> this.Feed ())
|
||||
this.Get ("/posts/list", fun _ -> this.PostList 1)
|
||||
this.Get ("/posts/list/page/{page:int}", fun parms -> this.PostList (getPage <| downcast parms))
|
||||
this.Get ("/post/{postId}/edit", fun parms -> this.EditPost (downcast parms))
|
||||
this.Post("/post/{postId}/edit", fun parms -> this.SavePost (downcast parms))
|
||||
|
||||
// ---- Display posts to users ----
|
||||
|
||||
@@ -87,7 +87,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
||||
| true -> false
|
||||
| _ -> Option.isSome <| tryFindOlderPost data (List.head model.Posts).Post
|
||||
model.UrlPrefix <- "/posts"
|
||||
model.PageTitle <- match pageNbr with 1 -> "" | _ -> sprintf "%s%i" Resources.PageHash pageNbr
|
||||
model.PageTitle <- match pageNbr with 1 -> "" | _ -> sprintf "%s%i" (Strings.get "PageHash") pageNbr
|
||||
this.ThemedView "index" model
|
||||
|
||||
/// Display either the newest posts or the configured home page
|
||||
@@ -187,7 +187,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
||||
model.HasNewer <- pageNbr > 1
|
||||
model.HasOlder <- List.length model.Posts > 24
|
||||
model.UrlPrefix <- "/posts/list"
|
||||
model.PageTitle <- Resources.Posts
|
||||
model.PageTitle <- Strings.get "Posts"
|
||||
upcast this.View.["admin/post/list", model]
|
||||
|
||||
/// Edit a post
|
||||
@@ -206,7 +206,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
||||
sprintf "%s%s"
|
||||
(String.replicate (snd cat) " ")
|
||||
(fst cat).Name)
|
||||
model.PageTitle <- match post.Id with "new" -> Resources.AddNewPost | _ -> Resources.EditPost
|
||||
model.PageTitle <- Strings.get <| match post.Id with "new" -> "AddNewPost" | _ -> "EditPost"
|
||||
upcast this.View.["admin/post/edit"]
|
||||
| _ -> this.NotFound ()
|
||||
|
||||
@@ -248,9 +248,9 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
||||
{ UserMessage.Empty with
|
||||
Level = Level.Info
|
||||
Message = System.String.Format
|
||||
(Resources.MsgPostEditSuccess,
|
||||
(match postId with "new" -> Resources.Added | _ -> Resources.Updated),
|
||||
(match justPublished with true -> Resources.AndPublished | _ -> "")) }
|
||||
(Strings.get "MsgPostEditSuccess",
|
||||
Strings.get (match postId with "new" -> "Added" | _ -> "Updated"),
|
||||
(match justPublished with true -> Strings.get "AndPublished" | _ -> "")) }
|
||||
|> model.AddMessage
|
||||
this.Redirect (sprintf "/post/%s/edit" pId) model
|
||||
| _ -> this.NotFound ()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
open MyWebLog.Data
|
||||
open MyWebLog.Entities
|
||||
open MyWebLog.Logic.User
|
||||
open MyWebLog.Resources
|
||||
open Nancy
|
||||
open Nancy.Authentication.Forms
|
||||
open Nancy.Cryptography
|
||||
@@ -22,9 +23,9 @@ type UserModule(data : IMyWebLogData, cfg : AppConfig) as this =
|
||||
|> Seq.fold (fun acc byt -> sprintf "%s%s" acc (byt.ToString "x2")) ""
|
||||
|
||||
do
|
||||
this.Get .["/logon" ] <- fun _ -> this.ShowLogOn ()
|
||||
this.Post.["/logon" ] <- fun parms -> this.DoLogOn (downcast parms)
|
||||
this.Get .["/logoff"] <- fun _ -> this.LogOff ()
|
||||
this.Get ("/logon", fun _ -> this.ShowLogOn ())
|
||||
this.Post("/logon", fun parms -> this.DoLogOn (downcast parms))
|
||||
this.Get ("/logoff", fun _ -> this.LogOff ())
|
||||
|
||||
/// Show the log on page
|
||||
member this.ShowLogOn () =
|
||||
@@ -41,14 +42,14 @@ type UserModule(data : IMyWebLogData, cfg : AppConfig) as this =
|
||||
match tryUserLogOn data form.Email (pbkdf2 form.Password) with
|
||||
| Some user -> this.Session.[Keys.User] <- user
|
||||
{ UserMessage.Empty with Level = Level.Info
|
||||
Message = Resources.MsgLogOnSuccess }
|
||||
Message = Strings.get "MsgLogOnSuccess" }
|
||||
|> model.AddMessage
|
||||
this.Redirect "" model |> ignore // Save the messages in the session before the Nancy redirect
|
||||
// TODO: investigate if addMessage should update the session when it's called
|
||||
upcast this.LoginAndRedirect (System.Guid.Parse user.Id,
|
||||
fallbackRedirectUrl = defaultArg (Option.ofObj form.ReturnUrl) "/")
|
||||
| _ -> { UserMessage.Empty with Level = Level.Error
|
||||
Message = Resources.ErrBadLogOnAttempt }
|
||||
Message = Strings.get "ErrBadLogOnAttempt" }
|
||||
|> model.AddMessage
|
||||
this.Redirect (sprintf "/user/logon?returnUrl=%s" form.ReturnUrl) model
|
||||
|
||||
@@ -59,7 +60,7 @@ type UserModule(data : IMyWebLogData, cfg : AppConfig) as this =
|
||||
this.Session.DeleteAll ()
|
||||
let model = MyWebLogModel(this.Context, this.WebLog)
|
||||
{ UserMessage.Empty with Level = Level.Info
|
||||
Message = Resources.MsgLogOffSuccess }
|
||||
Message = Strings.get "MsgLogOffSuccess" }
|
||||
|> model.AddMessage
|
||||
this.Redirect "" model |> ignore
|
||||
upcast this.LogoutAndRedirect "/"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
open MyWebLog.Entities
|
||||
open MyWebLog.Logic.WebLog
|
||||
open MyWebLog.Resources
|
||||
open Nancy
|
||||
open Nancy.Session.Persistable
|
||||
open Newtonsoft.Json
|
||||
@@ -41,15 +42,15 @@ with
|
||||
member this.ToDisplay =
|
||||
let classAndLabel =
|
||||
dict [
|
||||
Level.Error, ("danger", Resources.Error)
|
||||
Level.Warning, ("warning", Resources.Warning)
|
||||
Level.Error, ("danger", Strings.get "Error")
|
||||
Level.Warning, ("warning", Strings.get "Warning")
|
||||
Level.Info, ("info", "")
|
||||
]
|
||||
seq {
|
||||
yield "<div class=\"alert alert-dismissable alert-"
|
||||
yield fst classAndLabel.[this.Level]
|
||||
yield "\" role=\"alert\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\""
|
||||
yield Resources.Close
|
||||
yield Strings.get "Close"
|
||||
yield "\">×</button><strong>"
|
||||
match snd classAndLabel.[this.Level] with
|
||||
| "" -> ()
|
||||
@@ -136,12 +137,12 @@ type MyWebLogModel(ctx : NancyContext, webLog : WebLog) =
|
||||
member this.FooterLogo =
|
||||
seq {
|
||||
yield "<img src=\"/default/footer-logo.png\" alt=\"myWebLog\" title=\""
|
||||
yield sprintf "%s %s • " Resources.PoweredBy this.Generator
|
||||
yield Resources.LoadedIn
|
||||
yield sprintf "%s %s • " (Strings.get "PoweredBy") this.Generator
|
||||
yield Strings.get "LoadedIn"
|
||||
yield " "
|
||||
yield TimeSpan(System.DateTime.Now.Ticks - this.RequestStart).TotalSeconds.ToString "f3"
|
||||
yield " "
|
||||
yield Resources.Seconds.ToLower ()
|
||||
yield (Strings.get "Seconds").ToLower ()
|
||||
yield "\" />"
|
||||
}
|
||||
|> Seq.reduce (+)
|
||||
@@ -337,7 +338,7 @@ type PostForDisplay(webLog : WebLog, post : Post) =
|
||||
| 0 -> ""
|
||||
| 1 | 2 | 3 | 4 | 5 -> this.Post.Tags |> pipedTags
|
||||
| count -> sprintf "%s %s" (this.Post.Tags |> List.take 3 |> pipedTags)
|
||||
(System.String.Format(Resources.andXMore, count - 3))
|
||||
(System.String.Format(Strings.get "andXMore", count - 3))
|
||||
|
||||
|
||||
/// Model for all page-of-posts pages
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
FSharp.Formatting
|
||||
Nancy
|
||||
Nancy.Authentication.Forms
|
||||
Nancy.Session.RethinkDB
|
||||
NodaTime
|
||||
RethinkDb.Driver
|
||||
Suave
|
||||
48
src/MyWebLog.App/project.json
Normal file
48
src/MyWebLog.App/project.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"buildOptions": {
|
||||
"compilerName": "fsc",
|
||||
"compile": {
|
||||
"includeFiles": [
|
||||
"AssemblyInfo.fs",
|
||||
"Keys.fs",
|
||||
"AppConfig.fs",
|
||||
"ViewModels.fs",
|
||||
"ModuleExtensions.fs",
|
||||
"AdminModule.fs",
|
||||
"CategoryModule.fs",
|
||||
"PageModule.fs",
|
||||
"PostModule.fs",
|
||||
"UserModule.fs",
|
||||
"App.fs"
|
||||
]
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Hosting": "1.0.0",
|
||||
"Microsoft.AspNetCore.Owin": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"MyWebLog.Data.RethinkDB": "0.9.2",
|
||||
"MyWebLog.Entities": "0.9.2",
|
||||
"MyWebLog.Logic": "0.9.2",
|
||||
"MyWebLog.Resources": "0.9.2",
|
||||
"Nancy": "2.0.0-barneyrubble",
|
||||
"Nancy.Authentication.Forms": "2.0.0-barneyrubble",
|
||||
"Nancy.Session.Persistable": "0.9.1-pre",
|
||||
"Nancy.Session.RethinkDB": "0.9.1-pre",
|
||||
"NodaTime": "2.0.0-alpha20160729"
|
||||
},
|
||||
"frameworks": {
|
||||
"netstandard1.6": {
|
||||
"imports": "dnxcore50",
|
||||
"dependencies": {
|
||||
"Microsoft.FSharp.Core.netcore": "1.0.0-alpha-160629",
|
||||
"NETStandard.Library": "1.6.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tools": {
|
||||
"dotnet-compile-fsc": "1.0.0-preview2-*"
|
||||
},
|
||||
"version": "0.9.2"
|
||||
}
|
||||
Reference in New Issue
Block a user