files tree made better.

This commit is contained in:
Paul Schneider 2019-01-01 16:28:47 +00:00
commit ccc91bbf19
1630 changed files with 18209 additions and 41860 deletions

View file

@ -0,0 +1,58 @@
@model BlogPost
@{
ViewData["Title"] = "Create";
}
<h2>Create</h2>
<form asp-action="Create" role="form" method="POST">
<div class="form-horizontal">
<h4>Blog</h4>
<hr />
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Title" class="form-control" />
<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">
<label asp-for="Content" class="col-md-2 control-label"></label>
<div class="col-md-10">
<textarea asp-for="Content" class="form-control" >
</textarea>
<span asp-validation-for="Content" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="Visible" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Visible" class="form-control"/>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
</form>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

View file

@ -0,0 +1,70 @@
@model BlogPost
@{
ViewData["Title"] = "Delete";
}
@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>Blog</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@SR["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.Rate)
</dt>
<dd>
@Html.DisplayFor(model => model.Rate)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Title)
</dt>
<dd>
@Html.DisplayFor(model => model.Title)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Visible)
</dt>
<dd>
@Html.DisplayFor(model => model.Visible)
</dd>
</dl>
<form asp-action="Delete">
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-default" /> |
<a asp-action="Index">Back to List</a>
</div>
</form>
</div>

View file

@ -0,0 +1,119 @@
@model BlogPost
@{
ViewData["Title"]=Model.Title;
}
@section header {
<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 = '@ViewData["apicmtctlr"]';
$.psc.blogcomment.prototype.options.authorId = '@User.GetUserId()';
$.psc.blogcomment.prototype.options.authorName = '@User.GetUserName()';
$(document).ready(function() {
$('#cmtBtn').click(function() {
var receiverid = $(this).data('receiverid');
var comment = $('#Comment').val();
var data = {
Id:0,
Content: comment,
PostId: receiverid,
AuthorId: '@User.GetUserId()',
Visible:true
};
$.ajax({
async: true,
cache: false,
type: 'POST',
method: 'POST',
contentType: "application/json",
data: JSON.stringify(data),
error: function(xhr,data) {
if (xhr.status=400)
{
$('span.field-validation-valid[data-valmsg-for="Content"]').html(
xhr.responseJSON.Content);
} else {
$('span.field-validation-valid[data-valmsg-for="Content"]').html(
"Une erreur est survenue : "+xhr.status+"<br/>"+
"<code><pre>"+xhr.responseText+"</pre></code>"
)
}
},
success: function (data) {
var comment = $('#Comment').val();
$('#Comment').val('');
$('span.field-validation-valid[data-valmsg-for="Content"]').empty();
var htmlcmt = htmlize(comment);
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()">'+htmlcmt+'</div>';
$('#comments').append($(nnode).blogcomment())
},
url:'@ViewData["apicmtctlr"]'
});
});
})
</script>
<style>
.avatar, .commentmeta, .blogcomment p , .subcomments {
display: inline-block;
}
.blogcomment {
display: inline-block;
margin:.3em;
}
</style>
}
<div class="container">
<h1 class="blogtitle" ismarkdown>@Model.Title</h1>
<img class="blogphoto" alt="" src="@Model.Photo" >
<div class="blogpost">
<div markdown="@Model.Content" class="blog"></div>
<hr/>
<div class="meta">
@Html.DisplayFor(model => model.Author)
@Html.DisplayNameFor(model => model.DateModified) :
@Html.DisplayFor(model => model.DateModified)
@Html.DisplayNameFor(model => model.DateCreated) :
@Html.DisplayFor(model => model.DateCreated)
@Component.Invoke("Tagger",Model)
</div>
<div id="comments">
@if (Model.Comments!=null) {
foreach (var comment in Model.Comments.Where(c=>c.ParentId==null)) {
@Html.DisplayFor(model=>comment,"Comment","Comment")
}
}
</div>
@if (User.GetUserId()!=null) {
<div class="form-horizontal">
<div class="input-group" >
<input id="Comment" class="form-control" placeholder="@SR["DoCommentPlaceHolder"]"/>
<span class="input-group-btn">
<input type="button" value="@SR["DoComment"]" 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>
}
</div>
@if (await AuthorizationService.AuthorizeAsync(User, Model, new EditRequirement())) {
<a asp-action="Edit" asp-route-id="@Model.Id" class="btn btn-link">@SR["Edit"]</a>
}
<a asp-action="Index" class="btn btn-link">@SR["Back to List"]</a>
</div>

View file

@ -0,0 +1,244 @@
@model BlogPost
@{
ViewData["Title"] = SR["Blog post edition"];
}
@section header{
<link href="~/css/main/quill.snow.css" rel="stylesheet">
<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>
<script src="~/js/quill.js"></script>
<script src="~/js/to-markdown.js"></script>
<script>
$(document).ready(function() {
$(".mdcoding").addClass('hidden');
var onchange = function(){
var nv = $(this).val();
var tid = $(this).data('from');
$('#'+tid).html(htmlize(nv));
};
$("#Content").change(onchange);
$("#Title").change(onchange);
$('#vcbtn').change(function(){
var vc = $(this).prop('checked');
if (vc) {
$("#contentview").addClass('hidden');
$("#titleview").addClass('hidden');
$(".mdcoding").removeClass('hidden');
} else {
$("#contentview").removeClass('hidden');
$("#titleview").removeClass('hidden');
$(".mdcoding").addClass('hidden');
}
});
var initQuill = function() {
var editortitre = new Quill('#titleview', {
modules: { toolbar: '#Titletoolbar' },
theme: 'snow'
});
var editorcontenu = new Quill('#contentview', {
modules: { toolbar: '#contentbar' },
theme: 'snow'
});
editortitre.on('selection-change', function(range) {
if (range) {
$('#contentbar').addClass('hidden');
$('#Titletoolbar').removeClass('hidden');
}
});
editortitre.on('text-change',function(delta,source){
if (source=='user')
{
updateMD('Title',$('#ql-editor-1').html())
}
});
editorcontenu.on('selection-change', function(range) {
if (range) {
$('#contentbar').removeClass('hidden');
$('#Titletoolbar').addClass('hidden');
}
});
editorcontenu.on('text-change',function(delta,source){
if (source=='user')
{
updateMD('Content',$('#ql-editor-2').html())
}
});
};
initQuill();
Dropzone.options.postfiles= {
maxFilesize: 20, // MB TODO: let sell it.
autoProcessQueue: true,
accept: function(file, done) {
if (file.name == "justinbieber.jpg") {
done("Naha, you don't.")
}
else { done() }
},
success: function (file, response, ev) {
console.log('response:');
console.log(response);
for(i=0;i<response.length;i++) {
var file = response[i];
console.log('response item:');
console.log(file);
$('<p><a href="/files/@User.GetUserName()/'+file.FileName+'">'+file.FileName+'</a></p>').appendTo('#ql-editor-2');
updateMD('Content',$('#contentview').html())
}
},
url: "/api/fs"
};
});
</script>
@Html.Partial("_ValidationScriptsPartial")
}
<h2 > @SR["Blog post edition"] </h2>
<label><input type="checkbox" id="vcbtn" />Editer le code source Markdown</label>
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div>
<div id="Titletoolbar" class="hidden ql-snow ql-toolbar">
<button class="ql-format-button ql-bold"></button>
<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" ismarkdown>@Model.Title</h2>
<div id="contentbar" class="hidden ql-snow ql-toolbar">
<span class="ql-format-group">
<button class="ql-format-button ql-bold"></button>
<button class="ql-format-button ql-italic"></button>
<button class="ql-format-button ql-underline"></button>
<button class="ql-format-button ql-strike"></button>
<environment names="Development">
<button class="ql-format-button ql-link"></button>
<button class="ql-format-button ql-image"></button>
<button class="ql-format-button ql-video"></button>
<button class="ql-format-button ql-file"></button>
</environment>
</span>
<span class="ql-format-group">
<span title="List" class="ql-format-button ql-list"></span>
<span class="ql-format-separator"></span>
<span title="Bullet" class="ql-format-button ql-bullet"></span>
<span class="ql-format-separator"></span>
<select title="Text Alignment" class="ql-align">
<option value="left" label="Left" selected=""></option>
<option value="center" label="Center"></option>
<option value="right" label="Right"></option>
<option value="justify" label="Justify"></option>
</select>
</span>
</div>
<div title="Contenu du post" id="contentview" markdown="@Model.Content"></div>
<hr>
<form asp-action="@ViewData["PostTarget"]">
<div class="form-horizontal">
<hr />
<p class="text-success">@ViewData["StatusMessage"]</p>
<div asp-validation-summary="ValidationSummary.ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<input type="hidden" asp-for="AuthorId" />
<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="Visible" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Visible" class="form-control"/>
</div>
</div>
<div class="form-group">
<label asp-for="ACL" class="col-md-2 control-label"></label>
<div class="col-md-10">
@Component.Invoke("CirclesControl",Model)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</form>
<div>
</div>
@await Component.InvokeAsync("Directory","")
<div >
<form id="postfiles" class="dropzone" method="post" enctype="multipart/form-data">
<div class="fallback">
<input name="File[]" type="file" id="filesinput"/>
</div>
<input type="hidden" name="postId" value="@Model.Id" />
@Html.AntiForgeryToken()
</form>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>

View file

@ -0,0 +1,50 @@
@model IEnumerable<IGrouping<string,BlogPost>>
@{
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">@SR["Create a new article"]</a>
</p>
}
<div class="container">
@await Component.InvokeAsync("BlogIndex",User.GetUserId()??"_anonymous_",0,25);
</div>

View file

@ -0,0 +1,61 @@
@model IEnumerable<BlogPost>
<h2 markdown="@ViewData["Title"]"></h2>
<p class="text-success">@ViewData["StatusMessage"]</p>
@if (User.IsSignedIn()) {
<label>
<input type="checkbox" id="cbv" checked/>Invisibles, posts privés</label>
<script>
$("#cbv").change(function() {
if (this.checked) {
$("tr.hiddenpost").removeClass("hidden");
} else {
$("tr.hiddenpost").addClass("hidden");
}
});
</script>
}
<p>
<a asp-action="Create" asp-route-title="@ViewData["Title"]">@SR["Poster au même titre"]</a>
</p>
<table class="table">
@foreach (var item in Model) {
var trclass = (item.Visible)?"visiblepost":"hiddenpost";
<tr class="@trclass">
<td><a asp-action="Details" asp-route-id="@item.Id" class="bloglink">
<img src="@item.Photo" class="blogphoto"></a>
</td>
<td>
<markdown>@((item.Content?.Length > 256) ? item.Content.Substring(0, 256) + " ..." : item.Content)</markdown>
<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 ViewRequirement())) {
<li>
<a asp-action="Details" asp-route-id="@item.Id" class="btn btn-lg">Details</a>
</li>
}
@if (await AuthorizationService.AuthorizeAsync(User, item, new EditRequirement())) {
<li><a asp-action="Edit" asp-route-id="@item.Id" class="btn btn-default">@SR["Edit"]</a>
</li>
<li><a asp-action="Delete" asp-route-id="@item.Id" class="btn btn-danger">@SR["Delete"]</a>
</li>
}
</ul>
</td>
</tr>
}
</table>

View file

@ -0,0 +1,88 @@
@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>
@SR["Author"]
</th>
<th>
@Html.DisplayNameFor(model => model.Content)
</th>
<th>
@Html.DisplayNameFor(model => model.Modified)
</th>
<th>
@Html.DisplayNameFor(model => model.Photo)
</th>
<th>
@Html.DisplayNameFor(model => model.Posted)
</th>
<th>
@Html.DisplayNameFor(model => model.Rate)
</th>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Visible)
</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.Modified)
</td>
<td>
@Html.DisplayFor(modelItem => item.Photo)
</td>
<td>
@Html.DisplayFor(modelItem => item.Posted)
</td>
<td>
@Html.DisplayFor(modelItem => item.Rate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Visible)
</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>