mirror of https://github.com/abpframework/abp.git
17 changed files with 491 additions and 108 deletions
@ -0,0 +1,85 @@ |
|||||
|
@page |
||||
|
|
||||
|
@using Microsoft.AspNetCore.Mvc.Localization |
||||
|
@using Volo.Abp.AspNetCore.Mvc.UI.Layout |
||||
|
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Comments |
||||
|
@using Volo.CmsKit.Admin.Web.Menus |
||||
|
@using Volo.CmsKit.Localization |
||||
|
|
||||
|
@inject IPageLayout PageLayout |
||||
|
@inject IHtmlLocalizer<CmsKitResource> L |
||||
|
|
||||
|
@model IndexModel |
||||
|
|
||||
|
@{ |
||||
|
PageLayout.Content.Title = L["Comments"].Value; |
||||
|
PageLayout.Content.BreadCrumb.Add(L["Menu:CMS"].Value); |
||||
|
PageLayout.Content.MenuItemName = CmsKitAdminMenus.Comments.CommentsMenu; |
||||
|
} |
||||
|
|
||||
|
@section styles { |
||||
|
<abp-style-bundle> |
||||
|
<abp-style src="/Pages/CmsKit/Comments/index.css" /> |
||||
|
</abp-style-bundle> |
||||
|
} |
||||
|
|
||||
|
@section scripts { |
||||
|
<abp-script-bundle> |
||||
|
<abp-script src="/client-proxies/cms-kit-common-proxy.js" /> |
||||
|
<abp-script src="/client-proxies/cms-kit-admin-proxy.js" /> |
||||
|
<abp-script src="/Pages/CmsKit/Comments/index.js" /> |
||||
|
</abp-script-bundle> |
||||
|
} |
||||
|
|
||||
|
<abp-alert id="commentsAlert" alert-type="Warning" style="display: none;"> |
||||
|
</abp-alert> |
||||
|
|
||||
|
<abp-card class="mb-4"> |
||||
|
<abp-card-body> |
||||
|
<div id="CmsKitCommentsWrapper"> |
||||
|
<form id="CmsKitCommentsFilterForm" method="post"> |
||||
|
<abp-row class="align-items-end"> |
||||
|
<abp-column size-lg="_4" size-md="_12"> |
||||
|
<abp-row> |
||||
|
<abp-column size-lg="_6" size-md="_6"> |
||||
|
<abp-input asp-for="@Model.CreationStartDate" class="singledatepicker" label="@L["StartDate"].Value" type="text" /> |
||||
|
</abp-column> |
||||
|
<abp-column size-lg="_6" size-md="_6"> |
||||
|
<abp-input asp-for="@Model.CreationEndDate" class="singledatepicker" label="@L["EndDate"].Value" type="text" /> |
||||
|
</abp-column> |
||||
|
</abp-row> |
||||
|
</abp-column> |
||||
|
|
||||
|
<abp-column size-lg="_2" size-md="_6"> |
||||
|
<abp-input asp-for="@Model.Author" label="@L["Username"].Value" type="text" /> |
||||
|
</abp-column> |
||||
|
|
||||
|
<abp-column size-lg="_2" size-md="_6"> |
||||
|
<abp-input asp-for="@Model.EntityType" label="@L["EntityType"].Value" type="text" /> |
||||
|
</abp-column> |
||||
|
|
||||
|
<abp-column size-lg="_2" size-md="_6"> |
||||
|
<select asp-for="@Model.IsApproved" label="@L["IsApproved"].Value"> |
||||
|
<option value="">@L["All"].Value</option> |
||||
|
<option value="true">@L["Approved"].Value</option> |
||||
|
<option value="false">@L["Rejected"].Value</option> |
||||
|
<option value="null">@L["Pending"].Value</option> |
||||
|
</select> |
||||
|
</abp-column> |
||||
|
|
||||
|
<abp-column size-lg="_2" size-md="_6"> |
||||
|
<abp-button class="w-100 mb-3" button-type="Primary" type="submit"> |
||||
|
<i class="fa fa-search" aria-hidden="true"></i> |
||||
|
</abp-button> |
||||
|
</abp-column> |
||||
|
</abp-row> |
||||
|
</form> |
||||
|
</div> |
||||
|
</abp-card-body> |
||||
|
</abp-card> |
||||
|
|
||||
|
<abp-card> |
||||
|
<abp-card-body> |
||||
|
<abp-table id="CommentsTable" class="nowrap"></abp-table> |
||||
|
</abp-card-body> |
||||
|
</abp-card> |
||||
@ -0,0 +1,18 @@ |
|||||
|
using System; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.RazorPages; |
||||
|
|
||||
|
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Comments.Waiting; |
||||
|
|
||||
|
public class IndexModel : CmsKitAdminPageModel |
||||
|
{ |
||||
|
public string EntityType { get; set; } |
||||
|
|
||||
|
public string Author { get; set; } |
||||
|
|
||||
|
public DateTime? CreationStartDate { get; set; } |
||||
|
|
||||
|
public DateTime? CreationEndDate { get; set; } |
||||
|
public string IsApproved { get; set; } |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,230 @@ |
|||||
|
$(function () { |
||||
|
var l = abp.localization.getResource("CmsKit"); |
||||
|
|
||||
|
var commentsService = volo.cmsKit.admin.comments.commentAdmin; |
||||
|
|
||||
|
var detailsModal = new abp.ModalManager(abp.appPath + "CmsKit/Comments/DetailsModal"); |
||||
|
|
||||
|
moment()._locale.preparse = (string) => string; |
||||
|
moment()._locale.postformat = (string) => string; |
||||
|
|
||||
|
var getFormattedDate = function ($datePicker) { |
||||
|
if (!$datePicker.val()) { |
||||
|
return null; |
||||
|
} |
||||
|
var momentDate = moment($datePicker.val(), $datePicker.data('daterangepicker').locale.format); |
||||
|
return momentDate.isValid() ? momentDate.toISOString() : null; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
var defaultStartDate = moment().add(-7, 'days'); |
||||
|
$("#CreationStartDate").val(defaultStartDate.format('L')); |
||||
|
|
||||
|
$('.singledatepicker').daterangepicker({ |
||||
|
"singleDatePicker": true, |
||||
|
"showDropdowns": true, |
||||
|
"autoUpdateInput": false, |
||||
|
"autoApply": true, |
||||
|
"opens": "center", |
||||
|
"drops": "auto" |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
|
||||
|
$('.singledatepicker').attr('autocomplete', 'off'); |
||||
|
|
||||
|
$('.singledatepicker').on('apply.daterangepicker', function (ev, picker) { |
||||
|
$(this).val(picker.startDate.format('l')); |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
var filterForm = $('#CmsKitCommentsFilterForm'); |
||||
|
|
||||
|
var getFilter = function () { |
||||
|
var filterObj = filterForm.serializeFormToObject(); |
||||
|
|
||||
|
filterObj.creationStartDate = getFormattedDate($('#CreationStartDate')); |
||||
|
filterObj.creationEndDate = getFormattedDate($('#CreationEndDate')); |
||||
|
|
||||
|
return filterObj; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
var _dataTable = $('#CommentsTable').DataTable(abp.libs.datatables.normalizeConfiguration({ |
||||
|
processing: true, |
||||
|
serverSide: true, |
||||
|
paging: true, |
||||
|
scrollX: true, |
||||
|
searching: false, |
||||
|
scrollCollapse: true, |
||||
|
ajax: abp.libs.datatables.createAjax(commentsService.getList, getFilter), |
||||
|
columnDefs: [ |
||||
|
{ |
||||
|
width: "10%", |
||||
|
title: l("Actions"), |
||||
|
targets: 0, |
||||
|
orderable: false, |
||||
|
rowAction: { |
||||
|
items: [ |
||||
|
{ |
||||
|
text: l('Details'), |
||||
|
action: function (data) { |
||||
|
location.href = 'Comments/' + data.record.id; |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
text: l('Delete'), |
||||
|
visible: abp.auth.isGranted('CmsKit.Comments.Delete'), |
||||
|
confirmMessage: function (data) { |
||||
|
return l("CommentDeletionConfirmationMessage") |
||||
|
}, |
||||
|
action: function (data) { |
||||
|
commentsService |
||||
|
.delete(data.record.id) |
||||
|
.then(function () { |
||||
|
_dataTable.ajax.reloadEx(); |
||||
|
abp.notify.success(l('DeletedSuccessfully')); |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
text: function (data) { |
||||
|
return data.isApproved ? l('Revoke Approval') : l('Approve'); |
||||
|
}, |
||||
|
action: function (data) { |
||||
|
var newApprovalStatus = !data.record?.isApproved; |
||||
|
|
||||
|
commentsService |
||||
|
.updateApprovalStatus(data.record.id, { IsApproved: newApprovalStatus }) |
||||
|
.then(function () { |
||||
|
_dataTable.ajax.reloadEx(); |
||||
|
var message = newApprovalStatus ? l('ApprovedSuccessfully') : l('ApprovalRevokedSuccessfully'); |
||||
|
abp.notify.success(message); |
||||
|
}) |
||||
|
.catch(function (error) { |
||||
|
console.log("error", error) |
||||
|
abp.notify.error(error.message); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
width: "10%", |
||||
|
title: l("Username"), |
||||
|
orderable: false, |
||||
|
data: "author.userName", |
||||
|
render: function (data) { |
||||
|
if (data !== null) { |
||||
|
return GetFilterableDatatableContent('#Author', $.fn.dataTable.render.text().display(data)); //prevent against possible XSS
|
||||
|
} |
||||
|
return ""; |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
width: "15%", |
||||
|
title: l("EntityType"), |
||||
|
orderable: false, |
||||
|
data: "entityType", |
||||
|
render: function (data) { |
||||
|
if (data !== null) { |
||||
|
return GetFilterableDatatableContent('#EntityType', $.fn.dataTable.render.text().display(data)); |
||||
|
} |
||||
|
return ""; |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
title: l("URL"), |
||||
|
data: "url", |
||||
|
render: function (data, type, row) { |
||||
|
if (data !== null) { |
||||
|
return '<a href="' + data + '#comment-' + row.id + '" target="_blank"><i class="fa fa-location-arrow"></i></a>'; |
||||
|
} |
||||
|
return ""; |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
title: l("Text"), |
||||
|
data: "text", |
||||
|
orderable: false, |
||||
|
render: function (data) { |
||||
|
data = $.fn.dataTable.render.text().display(data || ""); |
||||
|
|
||||
|
var maxChars = 64; |
||||
|
|
||||
|
if (data.length > maxChars) { |
||||
|
return ( |
||||
|
'<span data-toggle="tooltip" title="' + |
||||
|
data + |
||||
|
'">' + |
||||
|
data.substring(0, maxChars) + |
||||
|
"..." + |
||||
|
"</span>" |
||||
|
); |
||||
|
} else { |
||||
|
return data; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
width: "15%", |
||||
|
title: l("CreationTime"), |
||||
|
data: "creationTime", |
||||
|
orderable: true, |
||||
|
dataFormat: "datetime" |
||||
|
}, |
||||
|
{ |
||||
|
width: "5%", |
||||
|
title: l("Status"), |
||||
|
orderable: false, |
||||
|
|
||||
|
data: "isApproved", |
||||
|
render: function (data, type, row) { |
||||
|
var icons = '' |
||||
|
|
||||
|
if (data === null) { |
||||
|
icons = '<i class="fa-solid fa-hourglass-start"></i>'; |
||||
|
} else if (typeof data === "boolean") { |
||||
|
if (data) { |
||||
|
icons = '<i class="fa-solid fa-check" style="color: #63E6BE;"></i>'; |
||||
|
} else { |
||||
|
icons = '<i class="fa-solid fa-x" style="color: #e0102f;"></i>'; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return icons; |
||||
|
} |
||||
|
} |
||||
|
] |
||||
|
})); |
||||
|
|
||||
|
function GetFilterableDatatableContent(filterSelector, data) { |
||||
|
return '<span class="datatableCell" data-field="' + filterSelector + '" data-val="' + data + '">' + data + '</span>'; |
||||
|
} |
||||
|
|
||||
|
$(document).on('click', '.datatableCell', function () { |
||||
|
var inputSelector = $(this).attr('data-field'); |
||||
|
var value = $(this).attr('data-val'); |
||||
|
|
||||
|
$(inputSelector).val(value); |
||||
|
|
||||
|
_dataTable.ajax.reloadEx(); |
||||
|
}); |
||||
|
|
||||
|
filterForm.submit(function (e) { |
||||
|
e.preventDefault(); |
||||
|
_dataTable.ajax.reloadEx(); |
||||
|
}); |
||||
|
// Get and display pending comment count
|
||||
|
commentsService.getPendingCommentCount().then(function (count) { |
||||
|
console.log(count) |
||||
|
if (count > 0) { |
||||
|
var alertMessage = 'You have pending comments: ' + count; |
||||
|
var alertElement = '<abp-alert alert-type="Warning">' + alertMessage + '</abp-alert>'; |
||||
|
console.log(count) |
||||
|
$('#commentsAlert').html(alertElement); |
||||
|
$('#commentsAlert').show() |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
Loading…
Reference in new issue