Client Data Manipulation & Verticall Scrolling
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using Abp.AutoMapper;
using Health.Products;
namespace Health.Web.Areas.Products.Models
{
[AutoMap(typeof(GroupDiscount))]
public class GroupDiscountViewModel
{
[Required]
[Display(Name = "Kod")]
[AdditionalMetadata("minLength", "1")]
[AdditionalMetadata("maxLength", "3")]
[UIHint("StdTextBox")]
public string Id { get; set; }
[Required]
[Display(Name = "Çalışma Şekli")]
[UIHint("LookUpsByKey")]
public GroupDiscountWorkingTypeEnum WorkingType { get; set; }
[Required]
[Display(Name = "Grup İsmi", Prompt = "2 ile 50 karakter uzunluğunda olmalı.")]
[AdditionalMetadata("minLength", "2")]
[AdditionalMetadata("maxLength", "50")]
[UIHint("StdTextBox")]
public string Name { get; set; }
[Display(Name = "Acente")]
[UIHint("AgentCode")]
public string AgentCode { get; set; }
public List<Dictionary<string, object>> ExceptionsGridData { get; set; }
}
}
@using Health.Products
@using Health.Web.Web.Framework
@using Newtonsoft.Json
@model Health.Web.Areas.Products.Models.GroupDiscountViewModel
@{
var areaName = ViewContext.RouteData.DataTokens["area"];
var controllerName = ViewContext.RouteData.Values["controller"].ToString();
var actionName = ViewContext.RouteData.Values["action"].ToString();
var actionUrl = Url.Action(actionName, @controllerName, new { area = (string)@areaName });
var exceptionsGridServerData = MvcHtmlString.Create(JsonConvert.SerializeObject(Model.ExceptionsGridData));
}
<style>
/* vertical scroll css updates */
#ajaxModalContent .table-scrollable {
margin-top: 0 !important;
border: 0 !important;
}
#ajaxModalContent .dataTables_scroll {
margin-bottom: 0 !important;
}
#ajaxModalContent .dataTables_scrollHead {
border-bottom: 0 !important;
}
#ajaxModalContent .dataTables_scrollHeadInner {
width: 100% !important;
}
#ajaxModalContent .dataTables_scrollBody {
max-width: 643px !important;/* tucks the scrollbar inside the div */
overflow-x: hidden !important;/* hide horizontal scroller */
}
#ajaxModalContent table.dataTable {
width: 100% !important;
margin-top: 0 !important;
}
#datatableExceptions {
border-bottom: 0 !important;
}
</style>
@Html.AntiForgeryToken()
<div class="modal-body">
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Id, new { @class = "control-label col-md-3" })
<div class="col-md-9">
@if (actionName == "Update")
{
<label class="control-label">@Html.DisplayTextFor(model => model.Id)</label>
}
else
{
@Html.EditorFor(model => model.Id)
@Html.ValidationMessageFor(model => model.Id, "", new { @class = "text-danger" })
}
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Name, new { @class = "control-label col-md-3" })
<div class="col-md-9">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.WorkingType, new { @class = "control-label col-md-3" })
<div class="col-md-9">
@Html.EditorFor(model => model.WorkingType, new { lookUpKey = "DiscountWorkingType" })
@Html.ValidationMessageFor(model => model.WorkingType, "", new {@class = "text-danger"})
</div>
</div>
<div id="exceptionDetails" style="display: none">
<div class="form-group">
@Html.LabelFor(model => model.AgentCode, new { @class = "control-label col-md-3" })
<div class="col-md-7" style="padding-right: 0">
@Html.EditorFor(model => model.AgentCode)
@Html.ValidationMessageFor(model => model.AgentCode, "", new { @class = "text-danger" })
</div>
<div class="col-md-2 text-right" style="padding-left: 0">
<button class="btn btn-right" type="button" id="add-agency"><i class="fa fa-plus"></i> İstisna Ekle</button>
</div>
</div>
<div class="form-group">
<div class="col-md-3">
</div>
<div class="col-md-9">
<div class="table-container">
<table class="table table-striped table-bordered table-hover" id="datatableExceptions">
<thead>
<tr role="row" class="heading">
<th class="text-center"></th>
<th>@Html.DisplayNameFor(model => model.AgentCode)</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<div class="text-right">
<button class="btn red" type="button" id="delete-agency"><i class="fa fa-trash-o"></i> Seçilenleri Sil</button>
</div>
</div>
</div>
</div>
</div>
</div>
@Html.Script(
@<script>
var __RequestVerificationToken = function () { return $('input[name="__RequestVerificationToken"]').val(); }
var exceptionsGrid = new Datatable();
var exceptionsGridLocalData;
$(document).ready(function () {
/* Show "Acente" selection only for "Direkt Ugula" working type. */
if ("@Model.WorkingType" === "ApplyDirect") {
$("#exceptionDetails").show();
}
/* build the grid structure */
exceptionsGrid = $("#datatableExceptions").DataTable({
language: { url: "/Scripts/DataTables/Turkish.json" },
processing: false,
searching: false,
info: false,
paging: false,
ordering: false,
autoWidth: false,
scrollY: "308px",
scrollCollapse: true,
createdRow: function(row, data, dataIndex) {
$(row).attr('id', 'rowItem-' + data.id);
},
columns: [
{
data: "id",
width: "10%",
createdCell: function (td, cellData, rowData, row, col) {
$(td).css('text-align', 'center');
},
render: function (data, type, full, meta) {
return '<label class="mt-checkbox mt-checkbox-single mt-checkbox-outline">' +
'<input type="checkbox" class="checkboxes" value="' + $('<div/>').text(data).html() + '"\/>' +
'<span></span>' +
'</label>';
}
}, {
data: 'name',
width: "90%"
}, {
data: "codes",
visible: false
}
],
initComplete: function(settings, json) {
/* dynamically add rows to grid */
var dtApi = this.api();
dtApi.clear();
dtApi.rows.add(JSON.parse('@exceptionsGridServerData')).draw();
},
drawCallback: function(settings) {
//var api = this.api();
/* mark the rows that need to be deleted */
exceptionsGrid.$('input[type="checkbox"]').change(function () {
var itemId = this.value;
var row = exceptionsGrid.row("#rowItem-" + itemId).node();
if (this.checked) { $(row).addClass("to-be-deleted"); }
else { $(row).removeClass("to-be-deleted"); }
});
/* update the hidden element value that keeps the datatable data as JSON string */
/* used for updating */
exceptionsGridLocalData = getGridDataInJson(exceptionsGrid);
/* fixes the checkbox column width mismatch betw. body & header when scroller is activated */
if ($("#datatableExceptions").height() >= parseInt(settings.oScroll.sY.replace("px", ""))) {
var headerFirstColOuterWidth = $("#datatableExceptions_wrapper .dataTables_scrollHeadInner th:first-of-type").outerWidth();
var bodyFirstColOuterWidth = $("#datatableExceptions tr td:first-of-type").outerWidth();
var widthDifference = headerFirstColOuterWidth - bodyFirstColOuterWidth;
var bodyFirstColWidth = $("#datatableExceptions tr td:first-of-type").width();
bodyFirstColWidth += widthDifference;
$("#datatableExceptions tr td:first-of-type").css("min-width", bodyFirstColWidth + "px");
}
}
});
$("#WorkingType").on("select2:select", function() {
var workingTypeId = parseInt($(this).val());
var $divObj = $("#exceptionDetails");
if (workingTypeId !== 0) {
toggleDiv("hide", "fast", $divObj);
} else {
toggleDiv("show", "fast", $divObj);
}
});
$("#add-agency").on("click", function() {
var selectedObj = getSelectedItem("#AgentCode");
if (isObjValid(selectedObj.value)) {
var exists = false;
var rowObj = {};
rowObj.id = selectedObj.value;
rowObj.name = selectedObj.text; //removeCodesFromAgencyName(selectedObj.text);
rowObj.codes = getCodesFromAgencyName(selectedObj.text);
exceptionsGrid.rows().every(function (rowIdx, tableLoop, rowLoop) {
var data = this.data(); // ... do something with this.data(), or this.node(), etc..
if (stringsMatch(data.codes, rowObj.codes)) {
exists = true;
}
});
if (!exists) {
exceptionsGrid.row.add(rowObj).draw(); /* add row to table */
} else {
toastr.error("Aynı acente daha önce eklenmiş!", 'İşlem Başarısız');
}
}
});
$("#delete-agency").click(function (e) {
e.preventDefault();
exceptionsGrid.rows(".to-be-deleted").remove().draw();
return false;
});
$("#ajaxModalContent form").on("submit", function(e) {
e.preventDefault();
var workingTypeSelection = getSelectedItem("#WorkingType");
var data = {
"__RequestVerificationToken": __RequestVerificationToken,
"name": $("#Name").val(),
"workingType": workingTypeSelection.value,
"exceptionsGridData": exceptionsGridLocalData
};
var xhrParams = {
requestMethod: "POST",
url: "@actionUrl",
dataType: "json",
data: data,
formToValidateObj: $("#ajaxModalContent form"),
blockElem: "#ajaxModalContent",
iconOnly: false,
message: "Kaydediliyor...",
unblockOnComplete: true
};
var xhrPromise = jqAjax(xhrParams);
xhrPromise.done(function (xhr) {
if (xhr.success) {
$("#ajaxModal").modal("hide");
ajaxPopUpSucceed(xhr);
}
});
});
});
function removeCodesFromAgencyName(str) {
return str.substr(str.indexOf(' ') + 1);
}
function getCodesFromAgencyName(str) {
return str.split(' ')[0];
}
</script>
)
public ActionResult Create()
{
var groupDiscountViewModel = new GroupDiscountViewModel()
{
Id = "",
Name = "",
WorkingType = GroupDiscountWorkingTypeEnum.ApplyDirect,
AgentCode = "",
ExceptionsGridData = new List<Dictionary<string, object>>()
};
return View(groupDiscountViewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
[HandleException]
public async Task<ActionResult> Create(GroupDiscountViewModel groupDiscountViewModel)
{
if (ModelState.IsValid)
{
groupDiscountViewModel.Id = groupDiscountViewModel.Id.ToUpper();
bool groupDiscountUnique = _productManager.GetAllGroupDiscounts()
.SingleOrDefault(e => e.Id == groupDiscountViewModel.Id) == null;
if (groupDiscountUnique)
{
await _productManager.InsertGroupDiscountAsync(Mapper.Map(groupDiscountViewModel, (GroupDiscount)null));
return Json($"<b>{groupDiscountViewModel.Id}</b> kodlu grup indirimi başarıyla eklendi.");
}
throw new UserFriendlyException($"<b>{groupDiscountViewModel.Id}</b> kodlu grup indirimi daha önce girilmiş.");
}
throw new UserFriendlyException(MyHelpers.GetModelStateErrorMessage(ModelState));
}
[Route("~/Products/GroupDiscount/Update/{id?}")]
public async Task<ActionResult> Update(string id = null)
{
if (id != null)
{
try
{
var groupDiscount = await _productManager.GetGroupDiscountFirstOrDefault(id);
var groupDiscountViewModel = Mapper.Map<GroupDiscount, GroupDiscountViewModel>(groupDiscount);
var exceptionsList = groupDiscount.Exceptions.ToList();
var exceptionsGridData = new List<Dictionary<string, object>>();
foreach (var exception in exceptionsList)
{
var acente = await _customerManager.GetAcenteByMustKodAsync(exception.AgentCode);
var exceptionsGridRow = new Dictionary<string, object>();
exceptionsGridRow.Add("id", "exists-" + exception.Id);
exceptionsGridRow.Add("name", acente.Isim);
exceptionsGridRow.Add("codes", exception.BranchCode + "-" + exception.SourceCode + "-" + exception.AgentCode);
exceptionsGridData.Add(exceptionsGridRow);
}
groupDiscountViewModel.ExceptionsGridData = exceptionsGridData;
return View("Update", groupDiscountViewModel);
}
catch (Exception e)
{
return RedirectToAction("Create");
}
}
return RedirectToAction("Create");
}
[Route("~/Products/GroupDiscount/Update/{id?}")]
[HttpPost]
[ValidateAntiForgeryToken]
[HandleException]
public async Task<ActionResult> Update(GroupDiscountViewModel groupDiscountViewModel)
{
var groupDiscount = await _productManager.GetGroupDiscountFirstOrDefault(groupDiscountViewModel.Id);
/* update GroupDiscount table */
Mapper.Map(groupDiscountViewModel, groupDiscount);
await _productManager.UpdateGroupDiscountAsync(groupDiscount);
/* first delete all from the exceptions table */
await _productManager.DeleteGroupDiscountExceptionAsync(groupDiscount.Id);
/* update GroupDiscountException table */
if (groupDiscount.WorkingType.ToString("G") == "ApplyDirect"
&& groupDiscountViewModel.ExceptionsGridData != null)
{
/* insert everything */
foreach (var exceptionDict in groupDiscountViewModel.ExceptionsGridData)
{
var groupDiscountException = new GroupDiscountException();
//var id = ((string[])exceptionDict["id"])[0];
//var name = ((string[])exceptionDict["name"])[0];
var codes = ((string[])exceptionDict["codes"])[0].Split('-');
groupDiscountException.BranchCode = Convert.ToInt32(codes[0]);
groupDiscountException.SourceCode = Convert.ToInt32(codes[1]);
groupDiscountException.AgentCode = codes[2];
groupDiscountException.GroupDiscountId = groupDiscount.Id;
await _productManager.InsertGroupDiscountExceptionAsync(groupDiscountException);
}
}
return Json($"<b>{groupDiscount.Id}</b> kodlu kayıt güncellendi.");
}