This commit is contained in:
Paul Schneider 2026-02-14 16:54:27 +00:00
commit 45514010f2
3505 changed files with 154 additions and 523 deletions

View file

@ -0,0 +1,88 @@
@model BlogPostCreateViewModel
@{
ViewData["Title"] = "Blog post edition";
}
@section header {
<link href="~/css/main/dropzone.css" rel="stylesheet">
<script src="~/js/dropzone.js"></script>
@{ await Html.RenderPartialAsync("_FSScriptsPartial"); }
}
<h2>Blog post</h2>
<label><input type="checkbox" id="vcbtn" />Editer le code source Markdown</label>
<div asp-validation-summary="All" class="text-danger"></div>
<img class="blogphoto" alt="" src="@Model.Photo" title="Photo associée au post">
<h2 title="Titre du post" class="blogtitle" id="titleview" >@Model.Title</h2>
<div title="Contenu du post" id="contentview">@Model.Content</div>
<hr>
<form asp-controller="Blogspot" asp-action="Create">
<div class="form-horizontal">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group mdcoding">
<label asp-for="Title" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Title" class="form-control" data-from="titleview"/>
<span asp-validation-for="Title" class="text-danger" >
</span>
</div>
</div>
<div class="form-group">
<label asp-for="Photo" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Photo" class="form-control" />
<span asp-validation-for="Photo" class="text-danger" >
</span>
</div>
</div>
<div class="form-group mdcoding">
<label asp-for="Content" class="col-md-2 control-label" ></label>
<div class="col-md-10">
<textarea asp-for="Content" class="form-control" id="Content" data-from="contentview">
</textarea>
<span asp-validation-for="Content" class="text-danger" >
</span>
</div>
</div>
<div class="form-group">
<label asp-for="ACL" class="col-md-2 control-label"></label>
<div class="col-md-10">
@await Component.InvokeAsync("CirclesControl", Model)
</div>
</div>
<div class="form-group">
<label asp-for="Publish" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Publish" class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button class="btn btn-primary" >Save</button>
</div>
</div>
</div>
</form>
@await Component.InvokeAsync("Directory","")
<div >
@{ await Html.RenderPartialAsync("_PostFilesPartial"); }
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>

View file

@ -0,0 +1,58 @@
@model BlogPost
@{
ViewData["Title"] = "Delete";
}
@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
<h3>AreYourSureYouWantToDeleteThis</h3>
<div>
<h4>Blog</h4>
<hr />
<dl class="dl-horizontal">
<dt>
Author
</dt>
<dd>
@Model.Author
</dd>
<dt>
@Html.DisplayNameFor(model => model.Content)
</dt>
<dd>
@Html.DisplayFor(model => model.Content)
</dd>
<dt>
@Html.DisplayNameFor(model => model.DateModified)
</dt>
<dd>
@Html.DisplayFor(model => model.DateModified)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Photo)
</dt>
<dd>
@Html.DisplayFor(model => model.Photo)
</dd>
<dt>
@Html.DisplayNameFor(model => model.DateCreated)
</dt>
<dd>
@Html.DisplayFor(model => model.DateCreated)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Title)
</dt>
<dd>
@Html.DisplayFor(model => model.Title)
</dd>
</dl>
<form asp-action="Delete">
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-primary" /> |
<a asp-action="Index">Back to List</a>
</div>
</form>
</div>

View file

@ -0,0 +1,105 @@
@model BlogPost
@{
ViewData["Title"]=Model.Title;
}
@section scripts {
<script src="~/js/comment.js" asp-append-version="true"></script>
<script>
$.psc.blogcomment.prototype.options.lang = '@System.Globalization.CultureInfo.CurrentUICulture.Name';
$.psc.blogcomment.prototype.options.apictrlr = '/api/blogcomments';
$.psc.blogcomment.prototype.options.authorId = '@User.GetUserId()';
$.psc.blogcomment.prototype.options.authorName = '@User.GetUserName()';
$(document).ready(function() {
$('#cmtBtn').click(function() {
$.ajax({
async: true,
cache: false,
type: 'POST',
method: 'POST',
contentType: "application/json",
data: JSON.stringify({
Content: $('#Comment').val(),
ReceiverId: @Model.Id
}),
error: function(xhr,data) {
if (xhr.status=400)
{
if (xhr.responseJSON)
{
$('#commentValidation').html(
xhr.responseJSON.Content);
} else {
$('#commentValidation').html(
"Une erreur est survenue : "+xhr.status+"<br/>"+
"<code><pre>"+xhr.responseText+"</pre></code>"
)
}
}
},
success: function (data) {
var comment = $('#Comment').val();
$('#Comment').val('');
$('#commentValidation').empty();
var nnode = '<div data-type="blogcomment" data-id="'+data.id+'" data-allow-edit="True" data-allow-moderate="@ViewData["moderatoFlag"]" data-date="'+data.dateCreated+'" data-username="@User.GetUserName()">'+comment+'</div>';
$('#comments').append($(nnode).blogcomment())
},
url:'/api/blogcomments'
});
});
})
</script>
<style>
.avatar, .commentmeta, .blogcomment p , .subcomments {
display: inline-block;
}
.blogcomment {
display: inline-block;
margin:.3em;
}
</style>
}
<div class="post">
<div class="float-left">
<img class="photo" src="@Model.Photo" >
</div>
<h1 ismarkdown>@Model.Title</h1>
@Html.DisplayFor(m=>m.Author)
<asciidoc>@Html.DisplayFor(m=>m.Content)</asciidoc>
</div>
<div id="comments">
@if (Model.Comments!=null) {
foreach (var comment in Model.Comments.Where(c=>c.ParentId==null)) {
@await Component.InvokeAsync("Comment", new { id = comment.Id })
}
}
</div>
@if (User.GetUserId()!=null) {
<div class="form-horizontal">
<div class="input-group" >
<input name="Comment" id="Comment" class="form-control" placeholder="..."/>
<span class="input-group-btn">
<span id="commentValidation"></span>
<input type="button" value="Comment" class="btn btn-secondary"
data-receiverId="@Model.Id" id="cmtBtn"
/>
</span>
</div>
<span asp-validation-for="Content" class="text-danger" ></span>
</div>
}
else {
<p><i>Vous devez être identifié pour commenter.</i> </p>
}
@if ((await AuthorizationService.AuthorizeAsync(User, Model, new EditPermission())).Succeeded) {
<a asp-action="Edit" asp-route-id="@Model.Id" class="btn btn-link">Edit</a>
}
<a asp-action="Index" class="btn btn-link">Back to List</a>

View file

@ -0,0 +1,120 @@
@model BlogPostEditViewModel
@{
ViewData["Title"] = "Blog post edition";
}
@section header {
<link href="~/css/main/dropzone.css" rel="stylesheet">
<style>
.box__dragndrop,
.box__uploading,
.box__success,
.box__error {
display: none;
}
.box.has-advanced-upload {
background-color: white;
outline: 2px dashed black;
outline-offset: -10px;
}
.box.has-advanced-upload .box__dragndrop {
display: inline;
}
.box.is-dragover {
background-color: grey;
}
.ql-snow.ql-toolbar {
border: outset grey 2px;
}
</style>
<script src="~/js/dropzone.js"></script>
@{ await Html.RenderPartialAsync("_FSScriptsPartial"); }
}
<h2 >Blog post</h2>
<label><input type="checkbox" id="vcbtn" />Editer le code source Markdown</label>
<div asp-validation-summary="All" class="text-danger"></div>
<div id="Titletoolbar" class="hidden ql-snow ql-toolbar">
<button class="ql-format-button ql-italic"></button>
<button class="ql-format-button ql-underline"></button>
<button class="ql-format-button ql-strike"></button>
</div>
<img class="blogphoto" alt="" src="@Model.Photo" title="Photo associée au post">
<h2 title="Titre du post" class="blogtitle" id="titleview" >@Model.Title</h2>
<div title="Contenu du post" id="contentview"><asciidoc>@Model.Content</asciidoc></div>
<hr>
<form asp-action="Edit">
<div class="form-horizontal">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
@Html.HiddenFor(m=>m.Id)
<div class="form-group mdcoding">
<label asp-for="Title" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Title" class="form-control" data-from="titleview"/>
<span asp-validation-for="Title" class="text-danger" >
</span>
</div>
</div>
<div class="form-group">
<label asp-for="Photo" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Photo" class="form-control" />
<span asp-validation-for="Photo" class="text-danger" >
</span>
</div>
</div>
<div class="form-group mdcoding">
<label asp-for="Content" class="col-md-2 control-label" ></label>
<div class="col-md-10">
<textarea asp-for="Content" class="form-control" id="Content" data-from="contentview">
</textarea>
<span asp-validation-for="Content" class="text-danger" >
</span>
</div>
</div>
<div class="form-group">
<label asp-for="ACL" class="col-md-2 control-label"></label>
<div class="col-md-10">
@await Component.InvokeAsync("CirclesControl", Model)
</div>
</div>
<div class="form-group">
<label asp-for="Publish" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input type="checkbox" asp-for="Publish" class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</div>
</div>
</form>
@await Component.InvokeAsync("Directory","")
<div >
@{ await Html.RenderPartialAsync("_PostFilesPartial"); }
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>

View file

@ -0,0 +1,91 @@
@model IEnumerable<IBlogPost>
@{
ViewData["Title"] = "Blogs, l'index";
}
@section header {
<style>
.collapsed {
height: 1em;
}
.sametitlegrip {
text-decoration: underline;
cursor: pointer;
}
.sametitle {
overflow: hidden;
transition: height 1s;
}
td {
transition: height 1s;
}
div.row {
border-bottom: dashed black 1px;
}
</style>
}
@section scripts {
<script>
$(document).ready(function () {
$(".sametitle").addClass("collapsed")
.on("mouseover",function(){
$(this).removeClass("collapsed")
}).on("mouseout",function(){
$(this).addClass("collapsed")
});
}
)
</script>
}
<h2>@ViewData["Title"]</h2>
<p class="text-success">@ViewData["StatusMessage"]</p>
@if (User.IsSignedIn()) {
<p>
<a asp-action="Create">Create a new article</a>
</p>
}
<div class="blog-index">
@{
int maxTextLen = 75;
foreach (var post in Model) {
<div class="post card">
<a asp-action="Details" asp-route-id="@post.Id" class="bloglink" >
<div class="float-left"><img class="photo card-photo" src="@post.Photo" ></div>
<h3 class="index-post-title">@post.Title</h3>
</a>
<div>
<a asp-action="Details" asp-route-id="@post.Id">
<asciidoc summary="@maxTextLen">@post.Content</asciidoc></a>
<span style="font-size:x-small;">@Html.DisplayFor(m => post.Author)</span>
<span style="font-size:xx-small;">
posté le @post.DateCreated.ToString("dddd d MMM yyyy à H:mm")
@if ((post.DateModified - post.DateCreated).Minutes > 0){ 
@:- Modifié le @post.DateModified.ToString("dddd d MMM yyyy à H:mm")
})
</span>
</div>
<div class="actiongroup">
@if ((await AuthorizationService.AuthorizeAsync(User, post, new ReadPermission())).Succeeded)
{
<a asp-action="Details" asp-route-id="@post.Id" class="btn btn-light">Details</a>
}
else
{
<a asp-action="Details" asp-route-id="@post.Id" class="btn btn-light">Details</a>
}
@if ((await AuthorizationService.AuthorizeAsync(User, post, new EditPermission())).Succeeded)
{
<a asp-action="Edit" asp-route-id="@post.Id" class="btn btn-primary">Edit</a>
<a asp-action="Delete" asp-route-id="@post.Id" class="btn btn-danger">Delete</a>
}
</div>
</div>
}
}
</div>
@if(Model.Count()==0){<p>Néant</p>}

View file

@ -0,0 +1,46 @@
@model IEnumerable<BlogPost>
<h2 markdown="@ViewData["Title"]"></h2>
<p class="text-success">@ViewData["StatusMessage"]</p>
<p>
<a asp-action="Create" asp-route-title="@ViewData["Title"]">Poster au même titre</a>
</p>
<table class="table">
@foreach (var item in Model) {
<tr>
<td><a asp-action="Details" asp-route-id="@item.Id" class="bloglink">
<img src="@item.Photo" class="blogphoto"></a>
</td>
<td>
<asciidoc>@((item.Content?.Length > 256) ? item.Content.Substring(0, 256) + " ..." : item.Content)</asciidoc>
<span style="font-size:x-small;">(@item.Author.UserName </span>,
<span style="font-size:xx-small;">
posté le @item.DateCreated.ToString("dddd d MMM yyyy à H:mm")
@if ((item.DateModified - item.DateCreated).Minutes > 0){ 
@:- Modifié le @item.DateModified.ToString("dddd d MMM yyyy à H:mm")
})
</span>
</td>
<td>
<ul class="actiongroup">
@if ((await AuthorizationService.AuthorizeAsync(User, item, new ReadPermission())).Succeeded) {
<li>
<a asp-action="Details" asp-route-id="@item.Id" class="btn btn-light">Details</a>
</li>
}
@if ((await AuthorizationService.AuthorizeAsync(User, item, new EditPermission())).Succeeded) {
<li><a asp-action="Edit" asp-route-id="@item.Id" class="btn btn-primary">Edit</a>
</li>
<li><a asp-action="Delete" asp-route-id="@item.Id" class="btn btn-danger">Delete</a>
</li>
}
</ul>
</td>
</tr>
}
</table>

View file

@ -0,0 +1,76 @@
@model IEnumerable<BlogPost>
@{
ViewData["Title"] = "User posts";
}
<h2>Index</h2>
<p class="text-success">@ViewData["StatusMessage"]</p>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<tr>
<th>
Author
</th>
<th>
@Html.DisplayNameFor(model => model.Content)
</th>
<th>
@Html.DisplayNameFor(model => model.DateModified)
</th>
<th>
@Html.DisplayNameFor(model => model.Photo)
</th>
<th>
@Html.DisplayNameFor(model => model.UserModified)
</th>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@item.Author?.UserName
</td>
<td>
<div md-content="@item.Content"/>
</td>
<td>
<table>
<tr>
<td>
@Html.DisplayFor(modelItem => item.DateModified)
</td>
<td>
@Html.DisplayFor(modelItem => item.Photo)
</td>
<td>
@Html.DisplayFor(modelItem => item.UserModified)
</td>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
</tr>
</table>
</td>
<td>
<ul class="actiongroup">
<li>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a>
</li><li>
<a asp-action="Details" asp-route-id="@item.Id">Details</a>
</li><li>
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</li>
</ul>
</td>
</tr>
}
</table>