Page / Post edit pages work
Category in work
This commit is contained in:
		
							parent
							
								
									0d54fc2ec3
								
							
						
					
					
						commit
						458b8308ae
					
				| @ -53,22 +53,26 @@ type PageModule (data : IMyWebLogData, clock : IClock) as this = | ||||
|     let pageId = parameters.["id"].ToString () | ||||
|     let form   = this.Bind<EditPageForm> () | ||||
|     let now    = clock.GetCurrentInstant().ToUnixTimeTicks () | ||||
|     match pageId with "new" -> Some Page.Empty | _ -> tryFindPage data this.WebLog.Id pageId | ||||
|     match pageId with "new" -> Some Page.Empty | _ -> tryFindPage data this.WebLog.Id pageId  | ||||
|     |> function | ||||
|     | Some p -> | ||||
|         let page = match pageId with "new" -> { p with WebLogId = this.WebLog.Id } | _ -> p | ||||
|         let pId = { p with | ||||
|                       Title       = form.Title | ||||
|                       Permalink   = form.Permalink | ||||
|                       PublishedOn = match pageId with "new" -> now | _ -> page.PublishedOn | ||||
|                       UpdatedOn   = now | ||||
|                       Text        = match form.Source with | ||||
|                                     | RevisionSource.Markdown -> (* Markdown.TransformHtml *) form.Text | ||||
|                                     | _ -> form.Text | ||||
|                       Revisions   = { AsOf       = now | ||||
|                                       SourceType = form.Source | ||||
|                                       Text       = form.Text } :: page.Revisions } | ||||
|                   |> savePage data | ||||
|         let pId = | ||||
|           { p with | ||||
|               Title          = form.Title | ||||
|               Permalink      = form.Permalink | ||||
|               PublishedOn    = match pageId with "new" -> now | _ -> page.PublishedOn | ||||
|               UpdatedOn      = now | ||||
|               ShowInPageList = form.ShowInPageList | ||||
|               Text           = match form.Source with | ||||
|                                | RevisionSource.Markdown -> (* Markdown.TransformHtml *) form.Text | ||||
|                                | _ -> form.Text | ||||
|               Revisions      = { AsOf       = now | ||||
|                                  SourceType = form.Source | ||||
|                                  Text       = form.Text | ||||
|                                  } :: page.Revisions | ||||
|             } | ||||
|           |> savePage data | ||||
|         let model = MyWebLogModel (this.Context, this.WebLog) | ||||
|         { UserMessage.Empty with | ||||
|             Level   = Level.Info | ||||
|  | ||||
| @ -269,7 +269,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this = | ||||
|     match postId with "new" -> Some Post.Empty | _ -> tryFindPost data this.WebLog.Id postId | ||||
|     |> function | ||||
|     | Some p -> | ||||
|         let justPublished = p.PublishedOn = int64 0 && form.PublishNow | ||||
|         let justPublished = p.PublishedOn = 0L && form.PublishNow | ||||
|         let post = match postId with | ||||
|                    | "new" -> { p with | ||||
|                                   WebLogId = this.WebLog.Id | ||||
| @ -281,7 +281,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this = | ||||
|               Status      = match form.PublishNow with true -> PostStatus.Published | _ -> PostStatus.Draft | ||||
|               Title       = form.Title | ||||
|               Permalink   = form.Permalink | ||||
|               PublishedOn = match justPublished with true -> now | _ -> int64 0 | ||||
|               PublishedOn = match justPublished with true -> now | _ -> post.PublishedOn | ||||
|               UpdatedOn   = now | ||||
|               Text        = match form.Source with | ||||
|                             | RevisionSource.Markdown -> (* Markdown.TransformHtml *) form.Text | ||||
| @ -289,6 +289,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this = | ||||
|               CategoryIds = Array.toList form.Categories | ||||
|               Tags        = form.Tags.Split ',' | ||||
|                             |> Seq.map (fun t -> t.Trim().ToLowerInvariant ()) | ||||
|                             |> Seq.sort | ||||
|                             |> Seq.toList | ||||
|               Revisions   = { AsOf       = now | ||||
|                               SourceType = form.Source | ||||
|  | ||||
| @ -220,6 +220,8 @@ type CategoryEditModel (ctx, webLog, category) = | ||||
|   inherit MyWebLogModel (ctx, webLog) | ||||
|   /// The form with the category information | ||||
|   member val Form = CategoryForm (category) with get, set | ||||
|   /// The category being edited | ||||
|   member val Category = category | ||||
|   /// The categories | ||||
|   member val Categories : IndentedCategory list = [] with get, set | ||||
| 
 | ||||
| @ -336,9 +338,15 @@ type PostForDisplay (webLog : WebLog, post : Post) = | ||||
|   /// The time zone for the web log to which this post belongs | ||||
|   member this.TimeZone = webLog.TimeZone | ||||
|   /// The date the post was published | ||||
|   member this.PublishedDate = FormatDateTime.longDate this.TimeZone this.Post.PublishedOn | ||||
|   member this.PublishedDate = | ||||
|     match this.Post.Status with | ||||
|     | PostStatus.Published -> FormatDateTime.longDate this.TimeZone this.Post.PublishedOn | ||||
|     | _ -> FormatDateTime.longDate this.TimeZone this.Post.UpdatedOn | ||||
|   /// The time the post was published | ||||
|   member this.PublishedTime = FormatDateTime.time this.TimeZone this.Post.PublishedOn | ||||
|   member this.PublishedTime = | ||||
|     match this.Post.Status with | ||||
|     | PostStatus.Published -> FormatDateTime.time this.TimeZone this.Post.PublishedOn | ||||
|     | _ -> FormatDateTime.time this.TimeZone this.Post.UpdatedOn | ||||
|   /// Tags | ||||
|   member this.Tags = | ||||
|     match List.length this.Post.Tags with | ||||
| @ -389,14 +397,17 @@ type EditPostForm () = | ||||
|   /// The selected category Ids for the post | ||||
|   member val Categories : string[] = [||] with get, set | ||||
|   /// Whether the post should be published | ||||
|   member val PublishNow = true with get, set | ||||
|   member val PublishNow = false with get, set | ||||
| 
 | ||||
|   /// Fill the form with applicable values from a post | ||||
|   member this.ForPost (post : Post) = | ||||
|     this.Title      <- post.Title | ||||
|     this.Permalink  <- post.Permalink | ||||
|     this.Tags       <- List.reduce (fun acc x -> sprintf "%s, %s" acc x) post.Tags | ||||
|     this.Tags       <- match List.isEmpty post.Tags with | ||||
|                        | true -> "" | ||||
|                        | _ -> List.reduce (fun acc x -> sprintf "%s, %s" acc x) post.Tags | ||||
|     this.Categories <- List.toArray post.CategoryIds | ||||
|     this.PublishNow <- post.Status = PostStatus.Published || "new" = post.Id | ||||
|     this | ||||
| 
 | ||||
|   /// Fill the form with applicable values from a revision | ||||
| @ -412,7 +423,7 @@ type DisplayCategory = { | ||||
|   Name : string | ||||
|   Description : string | ||||
|   IsChecked : bool | ||||
|   }  | ||||
|   } | ||||
| with | ||||
|   /// Create a display category | ||||
|   static member Create (cat : Category, indent) isChecked = | ||||
| @ -442,6 +453,8 @@ type EditPostModel (ctx, webLog, post, revision) = | ||||
|   member this.PublishedDate = this.DisplayLongDate this.Post.PublishedOn | ||||
|   /// The published time | ||||
|   member this.PublishedTime = this.DisplayTime this.Post.PublishedOn | ||||
|   /// The "checked" attribute for the Publish Now box | ||||
|   member this.PublishNowCheckedAttr = match this.Form.PublishNow with true -> "checked=\"checked\"" | _ -> ""  | ||||
| 
 | ||||
| 
 | ||||
| // ---- User models ---- | ||||
|  | ||||
| @ -5,12 +5,6 @@ open RethinkDb.Driver.Ast | ||||
| 
 | ||||
| let private r = RethinkDb.Driver.RethinkDB.R | ||||
| 
 | ||||
| /// Shorthand to get a category by Id and filter by web log Id | ||||
| let private category (webLogId : string) (catId : string) = | ||||
|   r.Table(Table.Category) | ||||
|     .Get(catId) | ||||
|     .Filter(ReqlFunction1 (fun c -> upcast c.["WebLogId"].Eq webLogId)) | ||||
| 
 | ||||
| /// Get all categories for a web log | ||||
| let getAllCategories conn (webLogId : string) = | ||||
|   async { | ||||
| @ -24,10 +18,16 @@ let getAllCategories conn (webLogId : string) = | ||||
| /// Get a specific category by its Id | ||||
| let tryFindCategory conn webLogId catId : Category option = | ||||
|   async { | ||||
|     let! catt = (category webLogId catId).RunResultAsync<Category> conn | ||||
|     return catt | ||||
|     |> box | ||||
|     |> function null -> None | cat -> Some <| unbox cat | ||||
|     let! c = | ||||
|       r.Table(Table.Category) | ||||
|         .Get(catId) | ||||
|         .RunResultAsync<Category> conn | ||||
|     return  | ||||
|       match box c with | ||||
|       | null -> None | ||||
|       | catt -> | ||||
|           let cat : Category = unbox catt | ||||
|           match cat.WebLogId = webLogId with true -> Some cat | _ -> None | ||||
|     } | ||||
|   |> Async.RunSynchronously | ||||
| 
 | ||||
| @ -48,53 +48,63 @@ type CategoryUpdateRecord = | ||||
|   } | ||||
| /// Update a category | ||||
| let updateCategory conn (cat : Category) = | ||||
|   async { | ||||
|     do! (category cat.WebLogId cat.Id) | ||||
|           .Update({ CategoryUpdateRecord.Name = cat.Name | ||||
|   match tryFindCategory conn cat.WebLogId cat.Id with | ||||
|   | Some _ -> | ||||
|       async { | ||||
|           do! r.Table(Table.Category) | ||||
|                 .Get(cat.Id) | ||||
|                 .Update( | ||||
|                   { CategoryUpdateRecord.Name = cat.Name | ||||
|                     Slug        = cat.Slug | ||||
|                     Description = cat.Description | ||||
|                     ParentId    = cat.ParentId | ||||
|                     }) | ||||
|           .RunResultAsync conn | ||||
|     } | ||||
|   |> Async.RunSynchronously | ||||
|                 .RunResultAsync conn | ||||
|         } | ||||
|       |> Async.RunSynchronously | ||||
|   | _ -> () | ||||
| 
 | ||||
| type CategoryChildrenUpdateRecord = | ||||
|   { Children : string list } | ||||
| /// Update a category's children | ||||
| let updateChildren conn webLogId parentId (children : string list) = | ||||
|   async { | ||||
|     do! (category webLogId parentId) | ||||
|           .Update({ CategoryChildrenUpdateRecord.Children = children }) | ||||
|           .RunResultAsync conn | ||||
|     } | ||||
|   |> Async.RunSynchronously | ||||
|   match tryFindCategory conn webLogId parentId with | ||||
|   | Some _ -> | ||||
|       async { | ||||
|         do! r.Table(Table.Category) | ||||
|               .Get(parentId) | ||||
|               .Update(dict [ "Children", children ]) | ||||
|               .RunResultAsync conn | ||||
|         } | ||||
|       |> Async.RunSynchronously | ||||
|   | _ -> () | ||||
| 
 | ||||
| type CategoryParentUpdateRecord = | ||||
|   { ParentId : string option } | ||||
| type PostCategoriesUpdateRecord = | ||||
|   { CategoryIds : string list } | ||||
| /// Delete a category | ||||
| let deleteCategory conn (cat : Category) = | ||||
|   async { | ||||
|     // Remove the category from its parent | ||||
|     match cat.ParentId with | ||||
|     | Some parentId -> match tryFindCategory conn cat.WebLogId parentId with | ||||
|                        | Some parent -> parent.Children | ||||
|                                         |> List.filter (fun childId -> childId <> cat.Id) | ||||
|                                         |> updateChildren conn cat.WebLogId parentId | ||||
|                        | _ -> () | ||||
|     | Some parentId -> | ||||
|         match tryFindCategory conn cat.WebLogId parentId with | ||||
|         | Some parent -> parent.Children | ||||
|                          |> List.filter (fun childId -> childId <> cat.Id) | ||||
|                          |> updateChildren conn cat.WebLogId parentId | ||||
|         | _ -> () | ||||
|     | _ -> () | ||||
|     // Move this category's children to its parent | ||||
|     let newParent = { CategoryParentUpdateRecord.ParentId = cat.ParentId } | ||||
|     cat.Children | ||||
|     |> List.map  (fun childId -> | ||||
|         async { | ||||
|           do! (category cat.WebLogId childId) | ||||
|                 .Update(newParent) | ||||
|                 .RunResultAsync conn | ||||
|           }) | ||||
|     |> List.iter Async.RunSynchronously | ||||
|         match tryFindCategory conn cat.WebLogId childId with | ||||
|         | Some _ -> | ||||
|             async { | ||||
|               do! r.Table(Table.Category) | ||||
|                     .Get(childId) | ||||
|                     .Update(dict [ "ParentId", cat.ParentId ]) | ||||
|                     .RunResultAsync conn | ||||
|               } | ||||
|             |> Some | ||||
|         | _ -> None) | ||||
|     |> List.filter Option.isSome | ||||
|     |> List.map    Option.get | ||||
|     |> List.iter   Async.RunSynchronously | ||||
|     // Remove the category from posts where it is assigned | ||||
|     let! posts = | ||||
|       r.Table(Table.Post) | ||||
| @ -105,13 +115,9 @@ let deleteCategory conn (cat : Category) = | ||||
|     posts | ||||
|     |> List.map (fun post -> | ||||
|         async { | ||||
|           let newCats =  | ||||
|             { PostCategoriesUpdateRecord.CategoryIds = post.CategoryIds | ||||
|                                                        |> List.filter (fun c -> c <> cat.Id) | ||||
|             } | ||||
|           do! r.Table(Table.Post) | ||||
|                 .Get(post.Id) | ||||
|                 .Update(newCats) | ||||
|                 .Update(dict [ "CategoryIds", post.CategoryIds |> List.filter (fun c -> c <> cat.Id) ]) | ||||
|                 .RunResultAsync conn | ||||
|           }) | ||||
|     |> List.iter Async.RunSynchronously | ||||
|  | ||||
| @ -62,6 +62,7 @@ type PageUpdateRecord = | ||||
|     Permalink : string | ||||
|     PublishedOn : int64 | ||||
|     UpdatedOn : int64 | ||||
|     ShowInPageList : bool | ||||
|     Text : string | ||||
|     Revisions : Revision list } | ||||
| /// Update a page | ||||
| @ -75,6 +76,7 @@ let updatePage conn (page : Page) = | ||||
|                         Permalink = page.Permalink | ||||
|                         PublishedOn = page.PublishedOn | ||||
|                         UpdatedOn = page.UpdatedOn | ||||
|                         ShowInPageList = page.ShowInPageList | ||||
|                         Text = page.Text | ||||
|                         Revisions = page.Revisions }) | ||||
|               .RunResultAsync conn | ||||
|  | ||||
| @ -85,10 +85,12 @@ let tryFindOlderTaggedPost conn (tag : string) post = | ||||
| let findPageOfAllPosts conn (webLogId : string) pageNbr nbrPerPage = | ||||
|   // FIXME: sort unpublished posts by their last updated date | ||||
|   async { | ||||
|   //  .orderBy(r.desc(r.branch(r.row("Status").eq("Published"), r.row("PublishedOn"), r.row("UpdatedOn")))) | ||||
|     return! | ||||
|       r.Table(Table.Post) | ||||
|         .GetAll(webLogId).OptArg("index", "WebLogId") | ||||
|         .OrderBy(r.Desc "PublishedOn") | ||||
|         .OrderBy(r.Desc (ReqlFunction1 (fun p -> | ||||
|             upcast r.Branch (p.["Status"].Eq("Published"), p.["PublishedOn"], p.["UpdatedOn"])))) | ||||
|         .Slice((pageNbr - 1) * nbrPerPage, pageNbr * nbrPerPage) | ||||
|         .RunResultAsync<Post list> conn | ||||
|     } | ||||
|  | ||||
| @ -8,6 +8,9 @@ | ||||
|   "AndPublished": " and Published", | ||||
|   "andXMore": "and {0} more...", | ||||
|   "at": "at", | ||||
|   "BackToCategoryList": "Back to Category List", | ||||
|   "BackToPageList": "Back to Page List", | ||||
|   "BackToPostList": "Back to Post List", | ||||
|   "Categories": "Categories", | ||||
|   "Category": "Category", | ||||
|   "CategoryDeleteWarning": "Are you sure you wish to delete the category", | ||||
| @ -36,7 +39,7 @@ | ||||
|   "MsgLogOffSuccess": "Log off successful | Have a nice day!", | ||||
|   "MsgLogOnSuccess": "Log on successful | Welcome to myWebLog!", | ||||
|   "MsgPageDeleted": "Deleted page successfully", | ||||
|   "MsgPageEditSuccess": "{0} edited successfully", | ||||
|   "MsgPageEditSuccess": "{0} page successfully", | ||||
|   "MsgPostEditSuccess": "{0}{1} post successfully", | ||||
|   "Name": "Name", | ||||
|   "NewerPosts": "Newer Posts", | ||||
|  | ||||
| @ -5,6 +5,9 @@ | ||||
|     @AntiForgeryToken | ||||
|     <div class="row"> | ||||
|       <div class="col-xs-12"> | ||||
|         <a href="/categories" class="btn btn-default"> | ||||
|           <i class="fa fa-list-ul"></i> @Translate.BackToCategoryList | ||||
|         </a> | ||||
|         <div class="form-group"> | ||||
|           <label class="control-label" for="Name">@Translate.Name</label> | ||||
|           <input type="text" class="form-control" id="Name" name="Name" value="@Model.Form.Name" /> | ||||
|  | ||||
| @ -5,6 +5,9 @@ | ||||
|     @AntiForgeryToken | ||||
|     <div class="row"> | ||||
|       <div class="col-sm-9"> | ||||
|         <a href="/pages" class="btn btn-default"> | ||||
|           <i class="fa fa-list-ul"></i> @Translate.BackToPageList | ||||
|         </a> | ||||
|         <div class="form-group"> | ||||
|           <label class="control-label" for="Title">@Translate.Title</label> | ||||
|           <input type="text" name="Title" id="Title" class="form-control" value="@Model.Form.Title" /> | ||||
| @ -12,10 +15,11 @@ | ||||
|         <div class="form-group"> | ||||
|           <label class="control-label" for="Permalink">@Translate.Permalink</label> | ||||
|           <input type="text" name="Permalink" id="Permalink" class="form-control" value="@Model.Form.Permalink" /> | ||||
|           <p class="form-hint"><em>@Translate.startingWith</em> http://@Model.WebLog.UrlBase/ </p> | ||||
|           <p class="form-hint"><em>@Translate.startingWith</em> //@Model.WebLog.UrlBase/</p> | ||||
|         </div> | ||||
|         <!-- // TODO: Markdown / HTML choice --> | ||||
|        <div class="form-group"> | ||||
|         <input type="hidden" name="Source" value="html" /> | ||||
|         <div class="form-group"> | ||||
|           <textarea name="Text" id="Text" rows="15" class="form-control">@Model.Form.Text</textarea> | ||||
|         </div> | ||||
|       </div> | ||||
| @ -34,7 +38,7 @@ | ||||
|               </div> | ||||
|             @EndIf | ||||
|             <div class="form-group"> | ||||
|               <input type="checkbox" name="ShowInPageList" id="ShowInPageList" @Model.PageListChecked /> | ||||
|               <input type="checkbox" name="ShowInPageList" id="ShowInPageList" value="true" @Model.PageListChecked /> | ||||
|                 <label for="ShowInPageList">@Translate.ShowInPageList</label> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
| @ -5,6 +5,9 @@ | ||||
|     @AntiForgeryToken | ||||
|     <div class="row"> | ||||
|       <div class="col-sm-9"> | ||||
|         <a href="/posts/list" class="btn btn-default"> | ||||
|           <i class="fa fa-list-ul"></i> @Translate.BackToPostList | ||||
|         </a> | ||||
|         <div class="form-group"> | ||||
|           <label class="control-label" for="Title">@Translate.Title</label> | ||||
|           <input type="text" name="Title" id="Title" class="form-control" value="@Model.Form.Title" /> | ||||
| @ -12,10 +15,10 @@ | ||||
|         <div class="form-group"> | ||||
|           <label class="control-label" for="Permalink">@Translate.Permalink</label> | ||||
|           <input type="text" name="Permalink" id="Permalink" class="form-control" value="@Model.Form.Permalink" /> | ||||
|           <!-- // FIXME: hard-coded "http" --> | ||||
|           <p class="form-hint"><em>@Translate.startingWith</em> http://@Model.WebLog.UrlBase/ </p> | ||||
|           <p class="form-hint"><em>@Translate.startingWith</em> //@Model.WebLog.UrlBase/ </p> | ||||
|         </div> | ||||
|         <!-- // TODO: Markdown / HTML choice --> | ||||
|         <input type="hidden" name="Source" value="html" /> | ||||
|         <div class="form-group"> | ||||
|           <textarea name="Text" id="Text" rows="15">@Model.Form.Text</textarea> | ||||
|         </div> | ||||
| @ -49,7 +52,7 @@ | ||||
|           <div class="panel-body" style="max-height:350px;overflow:scroll;"> | ||||
|             @Each.Categories | ||||
|               @Current.Indent | ||||
|               <input type="checkbox" id="Category-@Current.Id" name="Category" value="@Current.Id" @Current.CheckedAttr /> | ||||
|               <input type="checkbox" id="Category-@Current.Id" name="Categories" value="@Current.Id" @Current.CheckedAttr /> | ||||
|                 | ||||
|               <label for="Category-@Current.Id" title="@Current.Description">@Current.Name</label> | ||||
|               <br/> | ||||
| @ -62,7 +65,7 @@ | ||||
|           @EndIf | ||||
|           @IfNot.IsPublished | ||||
|             <div> | ||||
|               <input type="checkbox" name="PublishNow" id="PublishNow" value="true" checked="checked" /> | ||||
|               <input type="checkbox" name="PublishNow" id="PublishNow" value="true" @Model.PublishNowCheckedAttr /> | ||||
|                 <label for="PublishNow">@Translate.PublishThisPost</label> | ||||
|             </div> | ||||
|           @EndIf | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user