Hinsura
1/29/2018 - 6:43 AM

DataTable - v1

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.");
}