faszoooom
This commit is contained in:
parent
8da9c65328
commit
1749555ed5
|
|
@ -0,0 +1,16 @@
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models;
|
||||||
|
|
||||||
|
namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Components
|
||||||
|
{
|
||||||
|
[ViewComponent(Name = "FileUploadGridComponent")]
|
||||||
|
public class FileUploadGridComponent : ViewComponent
|
||||||
|
{
|
||||||
|
public async Task<IViewComponentResult> InvokeAsync(TestGridModel model)
|
||||||
|
{
|
||||||
|
// Here you can fetch data for this grid if needed
|
||||||
|
// For demo, just pass the model
|
||||||
|
return View(model.ViewComponentName +".cshtml", model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
// ViewComponent Class
|
||||||
|
using DocumentFormat.OpenXml.Wordprocessing;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models;
|
||||||
|
using Nop.Services.Plugins;
|
||||||
|
using Org.BouncyCastle.Asn1.Ocsp;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Components
|
||||||
|
{
|
||||||
|
[ViewComponent(Name = "TestChildGrid")]
|
||||||
|
public class TestChildGridViewComponent : ViewComponent
|
||||||
|
{
|
||||||
|
public IViewComponentResult Invoke(TestGridModel model)
|
||||||
|
{
|
||||||
|
return View(model.ViewComponentLocation, model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -86,7 +86,8 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
||||||
public async Task<IActionResult> OrderList(OrderSearchModel searchModel)
|
public async Task<IActionResult> OrderList(OrderSearchModel searchModel)
|
||||||
{
|
{
|
||||||
//prepare model
|
//prepare model
|
||||||
var orderListModel = await GetOrderListModelByFilter(searchModel);
|
//var orderListModel = await GetOrderListModelByFilter(searchModel);
|
||||||
|
var orderListModel = new OrderListModel();
|
||||||
|
|
||||||
var valami = Json(orderListModel);
|
var valami = Json(orderListModel);
|
||||||
Console.WriteLine(valami);
|
Console.WriteLine(valami);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,12 @@
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace DevExtreme.NETCore.Demos.Controllers
|
||||||
|
{
|
||||||
|
public class FileManagerController : Controller
|
||||||
|
{
|
||||||
|
public IActionResult BindingToFileSystem()
|
||||||
|
{
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
using DevExtreme.AspNet.Mvc.FileManagement;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace DevExtreme.NETCore.Demos.Controllers
|
||||||
|
{
|
||||||
|
public class FileManagerScriptsApiController : Controller
|
||||||
|
{
|
||||||
|
IWebHostEnvironment _webHostEnvironment;
|
||||||
|
|
||||||
|
public FileManagerScriptsApiController(IWebHostEnvironment webHostEnvironment)
|
||||||
|
{
|
||||||
|
_webHostEnvironment = webHostEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
[HttpPost]
|
||||||
|
[Route("api/file-manager-file-system", Name = "FileManagementFileSystemApi")]
|
||||||
|
public object FileSystem(FileSystemCommand command, string arguments, int orderId)
|
||||||
|
{
|
||||||
|
var valami = new List<int>();
|
||||||
|
|
||||||
|
var config = new FileSystemConfiguration
|
||||||
|
{
|
||||||
|
Request = Request,
|
||||||
|
FileSystemProvider = new PhysicalFileSystemProvider(_webHostEnvironment.ContentRootPath + $"/wwwroot/uploads/orders/{orderId}"),
|
||||||
|
//uncomment the code below to enable file/folder management
|
||||||
|
//AllowCopy = true,
|
||||||
|
//AllowCreate = true,
|
||||||
|
//AllowMove = true,
|
||||||
|
//AllowDelete = true,
|
||||||
|
//AllowRename = true,
|
||||||
|
//AllowUpload = true,
|
||||||
|
//AllowDownload = true,
|
||||||
|
AllowedFileExtensions = new[] { ".pdf", ".jpg", ".jpeg" }
|
||||||
|
};
|
||||||
|
var processor = new FileSystemCommandProcessor(config);
|
||||||
|
var result = processor.Execute(command, arguments);
|
||||||
|
return result.GetClientCommandResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -42,6 +42,19 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
||||||
var testGridModel2 = new TestGridModel();
|
var testGridModel2 = new TestGridModel();
|
||||||
testGridModel2.GridName = "Orders";
|
testGridModel2.GridName = "Orders";
|
||||||
testGridModel2.ViewComponentName = "ShippingDocumentGridComponent";
|
testGridModel2.ViewComponentName = "ShippingDocumentGridComponent";
|
||||||
|
testGridModel2.ChildGrids = new List<TestGridModel>();
|
||||||
|
var childGrid1 = new TestGridModel
|
||||||
|
{
|
||||||
|
GridName = "TestGrid",
|
||||||
|
ViewComponentName = "TestGridComponent",
|
||||||
|
ParentGridId = testGridModel2.Id,
|
||||||
|
ChildGrids = new List<TestGridModel>()
|
||||||
|
};
|
||||||
|
testGridModel2.Configuration = new GridConfiguration();
|
||||||
|
testGridModel2.Configuration.ShowChildGridsAsTabs = true;
|
||||||
|
testGridModel2.ChildGrids.Add(childGrid1);
|
||||||
|
|
||||||
|
|
||||||
testPageModel.Grids.Add(testGridModel2);
|
testPageModel.Grids.Add(testGridModel2);
|
||||||
|
|
||||||
var testGridModel = new TestGridModel();
|
var testGridModel = new TestGridModel();
|
||||||
|
|
@ -58,6 +71,22 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
||||||
return View("~/Plugins/Misc.FruitBankPlugin/Areas/Admin/Views/Order/Test.cshtml", testPageModel);
|
return View("~/Plugins/Misc.FruitBankPlugin/Areas/Admin/Views/Order/Test.cshtml", testPageModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> LoadChildGrid([FromBody] LoadChildGridRequest request)
|
||||||
|
{
|
||||||
|
// request.contextId is the actual row ID (data.Id from DevExtreme)
|
||||||
|
// request.childModel is the full TestGridModel object
|
||||||
|
|
||||||
|
// Add the context ID to the model's DataContext
|
||||||
|
if (request.ChildModel.DataContext == null)
|
||||||
|
request.ChildModel.DataContext = new Dictionary<string, int>();
|
||||||
|
|
||||||
|
request.ChildModel.DataContext["contextId"] = request.ContextId;
|
||||||
|
|
||||||
|
// Invoke the view component with the full model
|
||||||
|
return ViewComponent(request.ChildModel.ViewComponentLocation, new { model = request.ChildModel });
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<IActionResult> GetShippings()
|
public async Task<IActionResult> GetShippings()
|
||||||
{
|
{
|
||||||
|
|
@ -135,6 +164,17 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
||||||
return Json(model);
|
return Json(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Request model for deserialization
|
||||||
|
public class LoadChildGridRequest
|
||||||
|
{
|
||||||
|
public int ContextId { get; set; } // The actual row ID from data.Id
|
||||||
|
public TestGridModel ChildModel { get; set; } // The full child grid model
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[RequestSizeLimit(10485760)] // 10MB
|
[RequestSizeLimit(10485760)] // 10MB
|
||||||
[RequestFormLimits(MultipartBodyLengthLimit = 10485760)]
|
[RequestFormLimits(MultipartBodyLengthLimit = 10485760)]
|
||||||
|
|
@ -254,7 +294,8 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
||||||
Console.WriteLine(extractedPartnerData.TaxId);
|
Console.WriteLine(extractedPartnerData.TaxId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extractedPartnerData.Country != null) {
|
if (extractedPartnerData.Country != null)
|
||||||
|
{
|
||||||
|
|
||||||
Console.WriteLine(extractedPartnerData.Country);
|
Console.WriteLine(extractedPartnerData.Country);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
using Nop.Web.Framework.Models;
|
||||||
|
|
||||||
|
namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models.Catalog;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a product list model
|
||||||
|
/// </summary>
|
||||||
|
public partial record ProductListModel : BasePagedListModel<ProductModel>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -1,18 +1,185 @@
|
||||||
//using Nop.Web.Framework.Models;
|
namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models
|
||||||
//using Nop.Web.Framework.Mvc.ModelBinding;
|
|
||||||
//using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a grid with potential child grids
|
||||||
|
/// </summary>
|
||||||
public class TestGridModel
|
public class TestGridModel
|
||||||
{
|
{
|
||||||
public Guid Id = Guid.NewGuid();
|
public TestGridModel()
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid();
|
||||||
|
ChildGrids = new List<TestGridModel>();
|
||||||
|
Configuration = new GridConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identity
|
||||||
|
public Guid Id { get; set; }
|
||||||
public string GridName { get; set; }
|
public string GridName { get; set; }
|
||||||
//public string GridControllerName { get; set; }
|
|
||||||
//public string GridEndpointName { get; set; }
|
// View Component Information
|
||||||
public string ViewComponentName { get; set; }
|
public string ViewComponentName { get; set; }
|
||||||
public string ViewComponentLocation { get; set; }
|
public string ViewComponentLocation { get; set; }
|
||||||
|
|
||||||
public int? ParentRowId { get; set; }
|
// Hierarchy
|
||||||
|
public Guid? ParentGridId { get; set; }
|
||||||
|
public int Level { get; set; } // 0 = top level, 1 = first nested, etc.
|
||||||
|
public List<TestGridModel> ChildGrids { get; set; }
|
||||||
|
|
||||||
|
// Grid Behavior Configuration
|
||||||
|
public GridConfiguration Configuration { get; set; }
|
||||||
|
|
||||||
|
// Data Context (optional - for passing entity IDs or filter params)
|
||||||
|
public Dictionary<string, int> DataContext { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Configuration for grid rendering and behavior
|
||||||
|
/// </summary>
|
||||||
|
public class GridConfiguration
|
||||||
|
{
|
||||||
|
// Display Settings
|
||||||
|
public bool ShowChildGridsAsTabs { get; set; } = true;
|
||||||
|
public bool ShowChildGridsAsAccordion { get; set; } = false;
|
||||||
|
public bool ShowChildGridsInline { get; set; } = false;
|
||||||
|
|
||||||
|
// Rendering Options
|
||||||
|
public string ChildGridContainerCssClass { get; set; } = "nested-grid-container";
|
||||||
|
public bool LazyLoadChildren { get; set; } = false;
|
||||||
|
public bool CollapseByDefault { get; set; } = false;
|
||||||
|
|
||||||
|
// Data Loading
|
||||||
|
public string ChildDataEndpoint { get; set; }
|
||||||
|
public bool RequiresParentRowSelection { get; set; } = false;
|
||||||
|
|
||||||
|
// Metadata
|
||||||
|
public string Description { get; set; }
|
||||||
|
public int DisplayOrder { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Builder class for easier model construction
|
||||||
|
/// </summary>
|
||||||
|
public class TestPageModelBuilder
|
||||||
|
{
|
||||||
|
private readonly TestPageModel _model;
|
||||||
|
private readonly Dictionary<Guid, TestGridModel> _gridLookup;
|
||||||
|
|
||||||
|
public TestPageModelBuilder()
|
||||||
|
{
|
||||||
|
_model = new TestPageModel();
|
||||||
|
_gridLookup = new Dictionary<Guid, TestGridModel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestPageModelBuilder AddRootGrid(TestGridModel grid)
|
||||||
|
{
|
||||||
|
grid.Level = 0;
|
||||||
|
grid.ParentGridId = null;
|
||||||
|
_model.Grids.Add(grid);
|
||||||
|
_gridLookup[grid.Id] = grid;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestPageModelBuilder AddChildGrid(Guid parentId, TestGridModel childGrid)
|
||||||
|
{
|
||||||
|
if (_gridLookup.TryGetValue(parentId, out var parentGrid))
|
||||||
|
{
|
||||||
|
childGrid.Level = parentGrid.Level + 1;
|
||||||
|
childGrid.ParentGridId = parentId;
|
||||||
|
parentGrid.ChildGrids.Add(childGrid);
|
||||||
|
_gridLookup[childGrid.Id] = childGrid;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestPageModel Build()
|
||||||
|
{
|
||||||
|
return _model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Example usage helper
|
||||||
|
/// </summary>
|
||||||
|
public static class TestPageModelExample
|
||||||
|
{
|
||||||
|
public static TestPageModel CreateSampleModel()
|
||||||
|
{
|
||||||
|
var builder = new TestPageModelBuilder();
|
||||||
|
|
||||||
|
// Level 0 - Root Grids
|
||||||
|
var customersGrid = new TestGridModel
|
||||||
|
{
|
||||||
|
GridName = "Customers",
|
||||||
|
ViewComponentName = "CustomerGrid",
|
||||||
|
Configuration = new GridConfiguration
|
||||||
|
{
|
||||||
|
RequiresParentRowSelection = false,
|
||||||
|
Description = "Main customer list"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var ordersRootGrid = new TestGridModel
|
||||||
|
{
|
||||||
|
GridName = "All Orders",
|
||||||
|
ViewComponentName = "OrderGrid"
|
||||||
|
};
|
||||||
|
|
||||||
|
builder.AddRootGrid(customersGrid);
|
||||||
|
builder.AddRootGrid(ordersRootGrid);
|
||||||
|
|
||||||
|
// Level 1 - Child of Customers
|
||||||
|
var customerOrdersGrid = new TestGridModel
|
||||||
|
{
|
||||||
|
GridName = "Customer Orders",
|
||||||
|
ViewComponentName = "CustomerOrderGrid",
|
||||||
|
Configuration = new GridConfiguration
|
||||||
|
{
|
||||||
|
RequiresParentRowSelection = true,
|
||||||
|
ShowChildGridsAsTabs = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var customerAddressesGrid = new TestGridModel
|
||||||
|
{
|
||||||
|
GridName = "Addresses",
|
||||||
|
ViewComponentName = "CustomerAddressGrid"
|
||||||
|
};
|
||||||
|
|
||||||
|
builder.AddChildGrid(customersGrid.Id, customerOrdersGrid);
|
||||||
|
builder.AddChildGrid(customersGrid.Id, customerAddressesGrid);
|
||||||
|
|
||||||
|
// Level 2 - Child of Customer Orders
|
||||||
|
var orderItemsGrid = new TestGridModel
|
||||||
|
{
|
||||||
|
GridName = "Order Items",
|
||||||
|
ViewComponentName = "OrderItemGrid",
|
||||||
|
Configuration = new GridConfiguration
|
||||||
|
{
|
||||||
|
RequiresParentRowSelection = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var orderShipmentsGrid = new TestGridModel
|
||||||
|
{
|
||||||
|
GridName = "Shipments",
|
||||||
|
ViewComponentName = "OrderShipmentGrid"
|
||||||
|
};
|
||||||
|
|
||||||
|
builder.AddChildGrid(customerOrdersGrid.Id, orderItemsGrid);
|
||||||
|
builder.AddChildGrid(customerOrdersGrid.Id, orderShipmentsGrid);
|
||||||
|
|
||||||
|
// Level 3 - Child of Order Items
|
||||||
|
var itemAttributesGrid = new TestGridModel
|
||||||
|
{
|
||||||
|
GridName = "Item Attributes",
|
||||||
|
ViewComponentName = "ItemAttributeGrid"
|
||||||
|
};
|
||||||
|
|
||||||
|
builder.AddChildGrid(orderItemsGrid.Id, itemAttributesGrid);
|
||||||
|
|
||||||
|
return builder.Build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6,6 +6,11 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models
|
||||||
{
|
{
|
||||||
public class TestPageModel
|
public class TestPageModel
|
||||||
{
|
{
|
||||||
|
public TestPageModel()
|
||||||
|
{
|
||||||
|
Grids = new List<TestGridModel>();
|
||||||
|
}
|
||||||
|
|
||||||
public List<TestGridModel> Grids { get; set; }
|
public List<TestGridModel> Grids { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
@model Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models.TestGridModel
|
||||||
|
@using DevExtreme.AspNet.Mvc
|
||||||
|
|
||||||
|
@{
|
||||||
|
if (Model.DataContext["contextId"] != null)
|
||||||
|
{
|
||||||
|
var contextId = Model.DataContext["contextId"];
|
||||||
|
<text>
|
||||||
|
<h4>contextId</h4>
|
||||||
|
</text>
|
||||||
|
})
|
||||||
|
// var gridId = $"dataGrid_{Guid.NewGuid():N}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
|
||||||
|
@Model.DataContext["contextId"], @Model.GridName, @Model.ViewComponentName
|
||||||
|
@* <form method="post" enctype="multipart/form-data" asp-controller="ManagementPage" asp-action="UploadFile">
|
||||||
|
@(Html.DevExtreme().FileUploader()
|
||||||
|
.ID("shippingDocumentUploader-" + contextId)
|
||||||
|
.Name("files")
|
||||||
|
.Multiple(true)
|
||||||
|
.Accept("application/pdf")
|
||||||
|
.UploadMode(FileUploadMode.UseForm)
|
||||||
|
)
|
||||||
|
<input type="hidden" name="ShippingDocumentId" value="@contextId" />
|
||||||
|
<% if (data.PartnerId) { %>
|
||||||
|
<input type="hidden" name="PartnerId" value="hello" />
|
||||||
|
<% } %>
|
||||||
|
@(Html.DevExtreme().Button()
|
||||||
|
.Text("Upload Files")
|
||||||
|
.Type(ButtonType.Success)
|
||||||
|
.UseSubmitBehavior(true)
|
||||||
|
)
|
||||||
|
</form>
|
||||||
|
<div class="content" id="selected-files">
|
||||||
|
<div>
|
||||||
|
<h4>Selected Files</h4>
|
||||||
|
</div>
|
||||||
|
</div> *@
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
@* @(Html.DevExtreme().FileManager()
|
||||||
|
.ID("fileManager_"+ contextId)
|
||||||
|
.FileSystemProvider(provider => provider.Remote()
|
||||||
|
.Url(Url.RouteUrl("FileManagementFileSystemApi"))
|
||||||
|
.BeforeAjaxSend(@<text>
|
||||||
|
function(e) {
|
||||||
|
e.ajaxSettings.data.orderId = data.Id;
|
||||||
|
}
|
||||||
|
</text>))
|
||||||
|
.Permissions(permissions => {
|
||||||
|
permissions.Download(true);
|
||||||
|
permissions.Upload(true);
|
||||||
|
})
|
||||||
|
.AllowedFileExtensions(new[] { ".pdf", ".jpg", ".jpeg" })
|
||||||
|
) *@
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function fileUploader_valueChanged(e) {
|
||||||
|
var files = e.value;
|
||||||
|
if(files.length > 0) {
|
||||||
|
$("#selected-files .selected-item").remove();
|
||||||
|
|
||||||
|
$.each(files, function(i, file) {
|
||||||
|
var $selectedItem = $("<div />").addClass("selected-item");
|
||||||
|
$selectedItem.append(
|
||||||
|
$("<span />").html("Name: " + file.name + "<br/>"),
|
||||||
|
$("<span />").html("Size " + file.size + " bytes" + "<br/>"),
|
||||||
|
$("<span />").html("Type " + file.type + "<br/>"),
|
||||||
|
$("<span />").html("Last Modified Date: " + file.lastModifiedDate)
|
||||||
|
);
|
||||||
|
$selectedItem.appendTo($("#selected-files"));
|
||||||
|
});
|
||||||
|
$("#selected-files").show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$("#selected-files").hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGridInstance() {
|
||||||
|
return $("#shippingDocumentUploader").dxFileUploader("instance");
|
||||||
|
}
|
||||||
|
|
||||||
|
function fileUploader_fileUploaded(e) {
|
||||||
|
const fileUploaderId = e.component.element().attr('id');
|
||||||
|
|
||||||
|
// 2. Extract the number from the ID
|
||||||
|
const match = fileUploaderId.match(/\d+$/);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const uniqueId = match[0];
|
||||||
|
const gridId = `shippingDocumentGridContainer-${uniqueId}`;
|
||||||
|
|
||||||
|
// 3. Get the DevExtreme grid instance and refresh it
|
||||||
|
const grid = $(`#${gridId}`).dxDataGrid('instance');
|
||||||
|
|
||||||
|
if (grid) {
|
||||||
|
grid.dxDataGrid("getDataSource").reload();
|
||||||
|
// Optional: Show a success notification
|
||||||
|
DevExpress.ui.notify("Documents updated successfully!", "success", 2000);
|
||||||
|
} else {
|
||||||
|
console.error(`DevExtreme grid with ID "${gridId}" not found.`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error("Could not find a unique ID number from the file uploader.");
|
||||||
|
}
|
||||||
|
// shippingDocumentGridContainer
|
||||||
|
//$("#shippingDocumentGridContainer" + e.component.ID).dxDataGrid("getDataSource").reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
@ -344,7 +344,7 @@
|
||||||
{
|
{
|
||||||
Title = "Needs Measurement",
|
Title = "Needs Measurement",
|
||||||
Width = "100",
|
Width = "100",
|
||||||
Render = new RenderCustom("renderColumnNeedsMeasurement"),
|
Render = new RenderCustom("renderColumnIsMeasurable"),
|
||||||
ClassName = NopColumnClassDefaults.CenterAll
|
ClassName = NopColumnClassDefaults.CenterAll
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -441,7 +441,7 @@
|
||||||
return `${textRenderer(row.CustomerFullName)} <br /><a href="${link}">${data}</a > `;
|
return `${textRenderer(row.CustomerFullName)} <br /><a href="${link}">${data}</a > `;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderColumnNeedsMeasurement(data, type, row, meta) {
|
function renderColumnIsMeasurable(data, type, row, meta) {
|
||||||
if(data === true) {
|
if(data === true) {
|
||||||
return '<span class="badge badge-warning">Yes</span>';
|
return '<span class="badge badge-warning">Yes</span>';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,6 @@
|
||||||
@model Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models.TestGridModel
|
@model Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models.TestGridModel
|
||||||
@using DevExtreme.AspNet.Mvc
|
@using DevExtreme.AspNet.Mvc
|
||||||
|
|
||||||
@{
|
|
||||||
var contextId = Model;
|
|
||||||
// var gridId = $"dataGrid_{Guid.NewGuid():N}";
|
|
||||||
}
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@(
|
@(
|
||||||
Html.DevExtreme().DataGrid()
|
Html.DevExtreme().DataGrid()
|
||||||
|
|
@ -27,7 +22,6 @@
|
||||||
editing.AllowDeleting(true);
|
editing.AllowDeleting(true);
|
||||||
})
|
})
|
||||||
.Columns(c => {
|
.Columns(c => {
|
||||||
|
|
||||||
c.Add().DataField("Id").AllowEditing(false);
|
c.Add().DataField("Id").AllowEditing(false);
|
||||||
c.Add().DataField("Partner.Name").AllowEditing(false);
|
c.Add().DataField("Partner.Name").AllowEditing(false);
|
||||||
c.Add()
|
c.Add()
|
||||||
|
|
@ -37,7 +31,6 @@
|
||||||
c.Add().DataField("PartnerId");
|
c.Add().DataField("PartnerId");
|
||||||
c.Add().DataField("DocumentIdNumber");
|
c.Add().DataField("DocumentIdNumber");
|
||||||
c.Add().DataField("IsAllMeasured");
|
c.Add().DataField("IsAllMeasured");
|
||||||
|
|
||||||
c.Add()
|
c.Add()
|
||||||
.Caption("Completed")
|
.Caption("Completed")
|
||||||
.DataType(GridColumnDataType.Boolean)
|
.DataType(GridColumnDataType.Boolean)
|
||||||
|
|
@ -60,244 +53,143 @@
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.MasterDetail(md => {
|
.MasterDetail(md => md.Enabled(true).Template(new TemplateName("masterDetailTemplate")))
|
||||||
md.Enabled(true);
|
|
||||||
md.Template(@<text>
|
|
||||||
<div class="master-detail-caption"><%- data.ShippingDate %> <%- data.LicencePlate %>'s shippingdocuments:</div>
|
|
||||||
<div id="fileuploader">
|
|
||||||
<div class="widget-container">
|
|
||||||
|
|
||||||
<section id="tabs" class="project-tab">
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-12">
|
|
||||||
<nav>
|
|
||||||
<div class="nav nav-tabs nav-fill" id="nav-tab" role="tablist">
|
|
||||||
<a class="nav-item nav-link active" id="nav-home-tab" data-toggle="tab" href="#nav-home" role="tab" aria-controls="nav-home" aria-selected="true">Partner info</a>
|
|
||||||
<a class="nav-item nav-link" id="nav-profile-tab" data-toggle="tab" href="#nav-profile" role="tab" aria-controls="nav-profile" aria-selected="false">Products</a>
|
|
||||||
<a class="nav-item nav-link" id="nav-contact-tab" data-toggle="tab" href="#nav-contact" role="tab" aria-controls="nav-contact" aria-selected="false">Files</a>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<div class="tab-content" id="nav-tabContent">
|
|
||||||
<div class="tab-pane fade show active" id="nav-home" role="tabpanel" aria-labelledby="nav-home-tab">
|
|
||||||
<table class="table" cellspacing="0">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Project Name</th>
|
|
||||||
<th>Employer</th>
|
|
||||||
<th>Awards</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td><a href="#">Work 1</a></td>
|
|
||||||
<td>Doe</td>
|
|
||||||
<td>john@example.com</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><a href="#">Work 2</a></td>
|
|
||||||
<td>Moe</td>
|
|
||||||
<td>mary@example.com</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><a href="#">Work 3</a></td>
|
|
||||||
<td>Dooley</td>
|
|
||||||
<td>july@example.com</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="tab-pane fade" id="nav-profile" role="tabpanel" aria-labelledby="nav-profile-tab">
|
|
||||||
<table class="table" cellspacing="0">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Project Name</th>
|
|
||||||
<th>Employer</th>
|
|
||||||
<th>Time</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td><a href="#">Work 1</a></td>
|
|
||||||
<td>Doe</td>
|
|
||||||
<td>john@example.com</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><a href="#">Work 2</a></td>
|
|
||||||
<td>Moe</td>
|
|
||||||
<td>mary@example.com</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><a href="#">Work 3</a></td>
|
|
||||||
<td>Dooley</td>
|
|
||||||
<td>july@example.com</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="tab-pane fade" id="nav-contact" role="tabpanel" aria-labelledby="nav-contact-tab">
|
|
||||||
<form method="post" enctype="multipart/form-data" asp-controller="ManagementPage" asp-action="UploadFile">
|
|
||||||
@(Html.DevExtreme().FileUploader()
|
|
||||||
.ID(new JS("'shippingDocumentUploader-' + data.Id"))
|
|
||||||
.Name("files")
|
|
||||||
.Multiple(true)
|
|
||||||
.Accept("application/pdf")
|
|
||||||
.UploadMode(FileUploadMode.UseForm)
|
|
||||||
)
|
|
||||||
|
|
||||||
<input type="hidden" name="ShippingDocumentId" value="<%- data.Id %>" />
|
|
||||||
<% if (data.PartnerId) { %>
|
|
||||||
<input type="hidden" name="PartnerId" value="<%- data.PartnerId %>" />
|
|
||||||
<% } %>
|
|
||||||
|
|
||||||
@(Html.DevExtreme().Button()
|
|
||||||
.Text("Upload Files")
|
|
||||||
.Type(ButtonType.Success)
|
|
||||||
.UseSubmitBehavior(true)
|
|
||||||
)
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div class="content" id="selected-files">
|
|
||||||
<div>
|
|
||||||
<h4>Selected Files</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@* <div id="@(new JS("'shippingDocumentGridContainer-' + data.ID"))"></div>
|
|
||||||
@(Html.DevExtreme().DataGrid<FruitBank.Common.Entities.ShippingDocument>()
|
|
||||||
.ColumnAutoWidth(true)
|
|
||||||
.ShowBorders(true)
|
|
||||||
.ID(new JS("'shippingDocumentGridContainer-' + data.Id"))
|
|
||||||
.Columns(columns => {
|
|
||||||
columns.AddFor(m => m.Id).AllowEditing(false);
|
|
||||||
|
|
||||||
columns.AddFor(m => m.Country);
|
|
||||||
|
|
||||||
columns.AddFor(m => m.Created);
|
|
||||||
|
|
||||||
columns.AddFor(m => m.PartnerId);
|
|
||||||
|
|
||||||
columns.Add()
|
|
||||||
.Caption("Completed")
|
|
||||||
.DataType(GridColumnDataType.Boolean)
|
|
||||||
.CalculateCellValue("calculateCellValue");
|
|
||||||
})
|
|
||||||
.DataSource(ds => ds.Mvc()
|
|
||||||
.Controller("Shipping")
|
|
||||||
.LoadAction("GetShippingDocumentsByShippingId")
|
|
||||||
.LoadParams(new { shippingId = new JS("data.Id") })
|
|
||||||
.Key("Id")
|
|
||||||
)
|
|
||||||
) *@
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</text>);
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@using (Html.DevExtreme().NamedTemplate("masterDetailTemplate"))
|
||||||
|
{
|
||||||
|
<div class="master-detail-caption">
|
||||||
|
<%- data.ShippingDate %> <%- data.LicencePlate %>'s shipping documents:
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (Model.ChildGrids != null && Model.ChildGrids.Any())
|
||||||
|
{
|
||||||
|
<div class="@Model.Configuration.ChildGridContainerCssClass mt-3" data-parent-id="<%- data.Id %>">
|
||||||
|
@if (Model.Configuration.ShowChildGridsAsTabs)
|
||||||
|
{
|
||||||
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
|
@for (int i = 0; i < Model.ChildGrids.Count; i++)
|
||||||
|
{
|
||||||
|
var child = Model.ChildGrids[i];
|
||||||
|
var isActive = i == 0 ? "active" : "";
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link @isActive"
|
||||||
|
data-toggle="tab"
|
||||||
|
data-child-index="@i"
|
||||||
|
href="#content-@child.Id-<%- data.Id %>"
|
||||||
|
onclick="reloadChildGrid(this, '<%- data.Id %>', @i)">
|
||||||
|
@child.GridName
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="tab-content mt-2">
|
||||||
|
@for (int i = 0; i < Model.ChildGrids.Count; i++)
|
||||||
|
{
|
||||||
|
var child = Model.ChildGrids[i];
|
||||||
|
var isActive = i == 0 ? "show active" : "";
|
||||||
|
|
||||||
|
<div class="tab-pane fade @isActive"
|
||||||
|
id="content-@child.Id-<%- data.Id %>"
|
||||||
|
data-child-index="@i">
|
||||||
|
@* Initial load - will be replaced by AJAX on first tab click *@
|
||||||
|
<div class="text-center p-3">
|
||||||
|
<span class="spinner-border spinner-border-sm" role="status"></span>
|
||||||
|
Loading...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// Store the parent grid model as JSON
|
||||||
|
var parentGridModel = @Html.Raw(Json.Serialize(Model));
|
||||||
|
|
||||||
|
// Global function to reload child grids
|
||||||
|
function reloadChildGrid(tabElement, contextId, childIndex) {
|
||||||
|
const $tab = $(tabElement);
|
||||||
|
const $contentPane = $($tab.attr('href'));
|
||||||
|
|
||||||
|
// Check if already loaded
|
||||||
|
if ($contentPane.data('loaded')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show loading state
|
||||||
|
$contentPane.html('<div class="text-center p-3"><span class="spinner-border spinner-border-sm"></span> Loading...</div>');
|
||||||
|
|
||||||
|
// Get the child model from the parent model
|
||||||
|
var childModel = parentGridModel.ChildGrids[childIndex];
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '@Url.Action("LoadChildGrid", "ManagementPage")',
|
||||||
|
type: 'POST',
|
||||||
|
contentType: 'application/json',
|
||||||
|
data: JSON.stringify({
|
||||||
|
contextId: contextId,
|
||||||
|
childModel: childModel
|
||||||
|
}),
|
||||||
|
success: function (data) {
|
||||||
|
$contentPane.html(data);
|
||||||
|
$contentPane.data('loaded', true);
|
||||||
|
},
|
||||||
|
error: function (xhr, status, error) {
|
||||||
|
$contentPane.html('<div class="alert alert-danger">Error loading grid: ' + error + '</div>');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load first tab automatically when master detail opens
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#orderDataGridContainer').on('contentReady', function() {
|
||||||
|
// This will trigger when master detail rows are expanded
|
||||||
|
$('.nav-tabs .nav-link.active').each(function() {
|
||||||
|
const contextId = $(this).closest('[data-parent-id]').attr('data-parent-id');
|
||||||
|
const childIndex = $(this).data('child-index');
|
||||||
|
if (contextId && childIndex !== undefined) {
|
||||||
|
reloadChildGrid(this, contextId, childIndex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function calculateCellValue(rowData) {
|
function calculateCellValue(rowData) {
|
||||||
return rowData.Status === "Completed";
|
return rowData.Status === "Completed";
|
||||||
}
|
}
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
function calculateItemsCount(rowData) {
|
function calculateItemsCount(rowData) {
|
||||||
return rowData.ShippingItems.length;
|
return rowData.ShippingItems ? rowData.ShippingItems.length : 0;
|
||||||
}
|
}
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function onDeleteBtnClick() {
|
function onDeleteBtnClick() {
|
||||||
let dataGrid = $("#gridContainer").dxDataGrid("instance");
|
let dataGrid = $("#orderDataGridContainer").dxDataGrid("instance");
|
||||||
$.when.apply($, dataGrid.getSelectedRowsData().map(function(data) {
|
$.when.apply($, dataGrid.getSelectedRowsData().map(function(data) {
|
||||||
return dataGrid.getDataSource().store().remove(data.ID);
|
return dataGrid.getDataSource().store().remove(data.Id);
|
||||||
})).done(function() {
|
})).done(function() {
|
||||||
dataGrid.refresh();
|
dataGrid.refresh();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateFilterExpression(filterValue, selectedFilterOperation, target) {
|
|
||||||
if(target === "search" && typeof(filterValue) === "string") {
|
|
||||||
return [this.dataField, "contains", filterValue]
|
|
||||||
}
|
|
||||||
return function(data) {
|
|
||||||
return (data.AssignedEmployee || []).indexOf(filterValue) !== -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSelectionChanged(data) {
|
function onSelectionChanged(data) {
|
||||||
let dataGrid = $("#gridContainer").dxDataGrid("instance");
|
let dataGrid = $("#orderDataGridContainer").dxDataGrid("instance");
|
||||||
dataGrid.option("toolbar.items[1].options.disabled", !data.selectedRowsData.length);
|
dataGrid.option("toolbar.items[1].options.disabled", !data.selectedRowsData.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRowExpanded(e) {
|
function onRowExpanded(e) {
|
||||||
e.component.dxDataGrid("getDataSource").reload();
|
// Trigger loading of first tab when row expands
|
||||||
|
const $firstTab = $(e.element).find('.master-detail-caption').next().find('.nav-link.active').first();
|
||||||
|
if ($firstTab.length) {
|
||||||
|
const contextId = e.key; // This is the actual row's Id (data.Id)
|
||||||
|
const childIndex = $firstTab.data('child-index');
|
||||||
|
if (contextId && childIndex !== undefined) {
|
||||||
|
setTimeout(() => reloadChildGrid($firstTab[0], contextId, childIndex), 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
function fileUploader_valueChanged(e) {
|
|
||||||
var files = e.value;
|
|
||||||
if(files.length > 0) {
|
|
||||||
$("#selected-files .selected-item").remove();
|
|
||||||
|
|
||||||
$.each(files, function(i, file) {
|
|
||||||
var $selectedItem = $("<div />").addClass("selected-item");
|
|
||||||
$selectedItem.append(
|
|
||||||
$("<span />").html("Name: " + file.name + "<br/>"),
|
|
||||||
$("<span />").html("Size " + file.size + " bytes" + "<br/>"),
|
|
||||||
$("<span />").html("Type " + file.type + "<br/>"),
|
|
||||||
$("<span />").html("Last Modified Date: " + file.lastModifiedDate)
|
|
||||||
);
|
|
||||||
$selectedItem.appendTo($("#selected-files"));
|
|
||||||
});
|
|
||||||
$("#selected-files").show();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
$("#selected-files").hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getGridInstance() {
|
|
||||||
return $("#shippingDocumentUploader").dxFileUploader("instance");
|
|
||||||
}
|
|
||||||
|
|
||||||
function fileUploader_fileUploaded(e) {
|
|
||||||
const fileUploaderId = e.component.element().attr('id');
|
|
||||||
|
|
||||||
// 2. Extract the number from the ID
|
|
||||||
const match = fileUploaderId.match(/\d+$/);
|
|
||||||
|
|
||||||
if (match) {
|
|
||||||
const uniqueId = match[0];
|
|
||||||
const gridId = `shippingDocumentGridContainer-${uniqueId}`;
|
|
||||||
|
|
||||||
// 3. Get the DevExtreme grid instance and refresh it
|
|
||||||
const grid = $(`#${gridId}`).dxDataGrid('instance');
|
|
||||||
|
|
||||||
if (grid) {
|
|
||||||
grid.dxDataGrid("getDataSource").reload();
|
|
||||||
// Optional: Show a success notification
|
|
||||||
DevExpress.ui.notify("Documents updated successfully!", "success", 2000);
|
|
||||||
} else {
|
|
||||||
console.error(`DevExtreme grid with ID "${gridId}" not found.`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.error("Could not find a unique ID number from the file uploader.");
|
|
||||||
}
|
|
||||||
// shippingDocumentGridContainer
|
|
||||||
//$("#shippingDocumentGridContainer" + e.component.ID).dxDataGrid("getDataSource").reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
@model Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models.TestGridModel
|
||||||
|
@using System.Text.Json
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header bg-info text-white">
|
||||||
|
<h4>Test Child Grid View Component</h4>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<h5>Grid Information:</h5>
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<tr>
|
||||||
|
<td><strong>Grid ID:</strong></td>
|
||||||
|
<td>@Model.Id</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Grid Name:</strong></td>
|
||||||
|
<td>@Model.GridName</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>View Component Name:</strong></td>
|
||||||
|
<td>@Model.ViewComponentName</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Level:</strong></td>
|
||||||
|
<td>@Model.Level</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Parent Grid ID:</strong></td>
|
||||||
|
<td>@(Model.ParentGridId?.ToString() ?? "None")</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
@if (Model.DataContext != null && Model.DataContext.Any())
|
||||||
|
{
|
||||||
|
<h5 class="mt-3">Data Context:</h5>
|
||||||
|
<table class="table table-bordered table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Key</th>
|
||||||
|
<th>Value</th>
|
||||||
|
<th>Type</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach (var kvp in Model.DataContext)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td><strong>@kvp.Key</strong></td>
|
||||||
|
<td>@kvp.Value</td>
|
||||||
|
<td><em>@kvp.Value?.GetType().Name</em></td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
@if (Model.DataContext.ContainsKey("contextId"))
|
||||||
|
{
|
||||||
|
<div class="alert alert-success mt-3">
|
||||||
|
<strong>Context ID Found:</strong> @Model.DataContext["contextId"]
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="alert alert-warning mt-3">
|
||||||
|
<strong>Warning:</strong> No contextId found in DataContext
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="alert alert-warning mt-3">
|
||||||
|
<strong>No Data Context available</strong>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (Model.Configuration != null)
|
||||||
|
{
|
||||||
|
<h5 class="mt-3">Configuration:</h5>
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<tr>
|
||||||
|
<td><strong>Show Child Grids As Tabs:</strong></td>
|
||||||
|
<td>@Model.Configuration.ShowChildGridsAsTabs</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Requires Parent Row Selection:</strong></td>
|
||||||
|
<td>@Model.Configuration.RequiresParentRowSelection</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Description:</strong></td>
|
||||||
|
<td>@(Model.Configuration.Description ?? "N/A")</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (Model.ChildGrids != null && Model.ChildGrids.Any())
|
||||||
|
{
|
||||||
|
<div class="alert alert-info mt-3">
|
||||||
|
<strong>Child Grids:</strong> This grid has @Model.ChildGrids.Count child grid(s)
|
||||||
|
<ul class="mb-0 mt-2">
|
||||||
|
@foreach (var child in Model.ChildGrids)
|
||||||
|
{
|
||||||
|
<li>@child.GridName (Level @child.Level)</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="alert alert-secondary mt-3">
|
||||||
|
<strong>No child grids</strong>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<h5 class="mt-3">Full Model JSON:</h5>
|
||||||
|
<pre class="bg-light p-3" style="max-height: 300px; overflow-y: auto;">@JsonSerializer.Serialize(Model, new JsonSerializerOptions { WriteIndented = true })</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,466 @@
|
||||||
|
@model ProductSearchModel
|
||||||
|
|
||||||
|
@using Nop.Core.Domain.Catalog;
|
||||||
|
|
||||||
|
@{
|
||||||
|
//page title
|
||||||
|
ViewBag.PageTitle = T("Admin.Catalog.Products").Text;
|
||||||
|
//active menu item (system name)
|
||||||
|
NopHtml.SetActiveMenuItemSystemName("Products");
|
||||||
|
}
|
||||||
|
|
||||||
|
@{
|
||||||
|
const string hideSearchBlockAttributeName = "ProductListPage.HideSearchBlock";
|
||||||
|
var hideSearchBlock = await genericAttributeService.GetAttributeAsync<bool>(await workContext.GetCurrentCustomerAsync(), hideSearchBlockAttributeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (Model.LicenseCheckModel.BlockPages != true)
|
||||||
|
{
|
||||||
|
<form asp-controller="Product" asp-action="List" method="post">
|
||||||
|
<div class="content-header clearfix">
|
||||||
|
<h1 class="float-left">
|
||||||
|
Fruitbank @T("Admin.Catalog.Products")
|
||||||
|
</h1>
|
||||||
|
<div class="float-right">
|
||||||
|
<a asp-action="Create" class="btn btn-primary">
|
||||||
|
<i class="fas fa-square-plus"></i>
|
||||||
|
@T("Admin.Common.AddNew")
|
||||||
|
</a>
|
||||||
|
<a asp-action="BulkEdit" class="btn btn-info">
|
||||||
|
<i class="fas fa-pen"></i>
|
||||||
|
@T("Admin.Catalog.Products.BulkEdit")
|
||||||
|
</a>
|
||||||
|
<button asp-action="DownloadCatalogPDF" type="submit" name="download-catalog-pdf" class="btn bg-purple">
|
||||||
|
<i class="far fa-file-pdf"></i>
|
||||||
|
@T("Admin.Catalog.Products.List.DownloadPDF")
|
||||||
|
</button>
|
||||||
|
<div class="btn-group">
|
||||||
|
<button type="button" class="btn btn-success">
|
||||||
|
<i class="fas fa-download"></i>
|
||||||
|
@T("Admin.Common.Export")
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
|
||||||
|
<span class="caret"></span>
|
||||||
|
<span class="sr-only"> </span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu" role="menu">
|
||||||
|
<li class="dropdown-item">
|
||||||
|
|
||||||
|
<button asp-action="ExportToXml" type="submit" name="exportxml-all">
|
||||||
|
<i class="far fa-file-code"></i>
|
||||||
|
@T("Admin.Common.ExportToXml.All")
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown-item">
|
||||||
|
|
||||||
|
<button type="button" id="exportxml-selected">
|
||||||
|
<i class="far fa-file-code"></i>
|
||||||
|
@T("Admin.Common.ExportToXml.Selected")
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown-divider"></li>
|
||||||
|
<li class="dropdown-item">
|
||||||
|
<button asp-action="ExportToExcel" type="submit" name="exportexcel-all">
|
||||||
|
<i class="far fa-file-excel"></i>
|
||||||
|
@T("Admin.Common.ExportToExcel.All")
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown-item">
|
||||||
|
<button type="button" id="exportexcel-selected">
|
||||||
|
<i class="far fa-file-excel"></i>
|
||||||
|
@T("Admin.Common.ExportToExcel.Selected")
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@if (!Model.IsLoggedInAsVendor || Model.AllowVendorsToImportProducts)
|
||||||
|
{
|
||||||
|
//a vendor cannot import products
|
||||||
|
<button type="button" name="importexcel" class="btn bg-olive" data-toggle="modal" data-target="#importexcel-window">
|
||||||
|
<i class="fas fa-upload"></i>
|
||||||
|
@T("Admin.Common.Import")
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
<button type="button" id="delete-selected" class="btn btn-danger">
|
||||||
|
<i class="far fa-trash-can"></i>
|
||||||
|
@T("Admin.Common.Delete.Selected")
|
||||||
|
</button>
|
||||||
|
<nop-action-confirmation asp-button-id="delete-selected" />
|
||||||
|
@await Component.InvokeAsync(typeof(AdminWidgetViewComponent), new { widgetZone = AdminWidgetZones.ProductListButtons, additionalData = Model })
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<section class="content">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="form-horizontal">
|
||||||
|
<div class="cards-group">
|
||||||
|
<div class="card card-default card-search">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row search-row @(!hideSearchBlock ? "opened" : "")" data-hideAttribute="@hideSearchBlockAttributeName">
|
||||||
|
<div class="search-text">@T("Admin.Common.Search")</div>
|
||||||
|
<div class="icon-search"><i class="fas fa-magnifying-glass" aria-hidden="true"></i></div>
|
||||||
|
<div class="icon-collapse"><i class="far fa-angle-@(!hideSearchBlock ? "up" : "down")" aria-hidden="true"></i></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="search-body @(hideSearchBlock ? "closed" : "")">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-5">
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<nop-label asp-for="SearchProductName" />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<nop-editor asp-for="SearchProductName" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row" @(Model.AvailableCategories.SelectionIsNotPossible() ? Html.Raw("style=\"display:none\"") : null)>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<nop-label asp-for="SearchCategoryId" />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<nop-select asp-for="SearchCategoryId" asp-items="Model.AvailableCategories" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row" @(Model.AvailableCategories.SelectionIsNotPossible() ? Html.Raw("style=\"display:none\"") : null)>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<nop-label asp-for="SearchIncludeSubCategories" />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<nop-editor asp-for="SearchIncludeSubCategories" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row" @(Model.AvailableManufacturers.SelectionIsNotPossible() ? Html.Raw("style=\"display:none\"") : null)>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<nop-label asp-for="SearchManufacturerId" />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<nop-select asp-for="SearchManufacturerId" asp-items="Model.AvailableManufacturers" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row" @(Model.AvailableVendors.SelectionIsNotPossible() || Model.IsLoggedInAsVendor ? Html.Raw("style='display: none;'") : null)>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<nop-label asp-for="SearchVendorId" />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<nop-select asp-for="SearchVendorId" asp-items="Model.AvailableVendors" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-7">
|
||||||
|
<div class="form-group row" @(Model.HideStoresList ? Html.Raw("style=\"display:none\"") : null)>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<nop-label asp-for="SearchStoreId" />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<nop-select asp-for="SearchStoreId" asp-items="Model.AvailableStores" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row" @(Model.AvailableWarehouses.SelectionIsNotPossible() ? Html.Raw("style=\"display:none\"") : null)>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<nop-label asp-for="SearchWarehouseId" />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<nop-select asp-for="SearchWarehouseId" asp-items="Model.AvailableWarehouses" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<nop-label asp-for="SearchProductTypeId" />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<nop-select asp-for="SearchProductTypeId" asp-items="Model.AvailableProductTypes" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<nop-label asp-for="SearchPublishedId" />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<nop-select asp-for="SearchPublishedId" asp-items="Model.AvailablePublishedOptions" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<nop-label asp-for="GoDirectlyToSku" />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="input-group input-group-short">
|
||||||
|
<nop-editor asp-for="GoDirectlyToSku" />
|
||||||
|
<span class="input-group-append">
|
||||||
|
<button type="submit" id="go-to-product-by-sku" name="go-to-product-by-sku" class="btn btn-info btn-flat">
|
||||||
|
@T("Admin.Common.Go")
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="text-center col-12">
|
||||||
|
<button type="button" id="search-products" class="btn btn-primary btn-search">
|
||||||
|
<i class="fas fa-magnifying-glass"></i>
|
||||||
|
@T("Admin.Common.Search")
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-default">
|
||||||
|
<div class="card-body">
|
||||||
|
<nop-doc-reference asp-string-resource="@T("Admin.Documentation.Reference.Products", Docs.Products + Utm.OnAdmin)" />
|
||||||
|
|
||||||
|
@await Html.PartialAsync("Table", new DataTablesModel
|
||||||
|
{
|
||||||
|
Name = "products-grid",
|
||||||
|
UrlRead = new DataUrl("ProductList", "CustomProduct", null),
|
||||||
|
SearchButtonId = "search-products",
|
||||||
|
Length = Model.PageSize,
|
||||||
|
LengthMenu = Model.AvailablePageSizes,
|
||||||
|
Filters = new List<FilterParameter>
|
||||||
|
{
|
||||||
|
new FilterParameter(nameof(Model.SearchProductName)),
|
||||||
|
new FilterParameter(nameof(Model.SearchCategoryId)),
|
||||||
|
new FilterParameter(nameof(Model.SearchIncludeSubCategories), typeof(bool)),
|
||||||
|
new FilterParameter(nameof(Model.SearchManufacturerId)),
|
||||||
|
new FilterParameter(nameof(Model.SearchStoreId)),
|
||||||
|
new FilterParameter(nameof(Model.SearchWarehouseId)),
|
||||||
|
new FilterParameter(nameof(Model.SearchVendorId)),
|
||||||
|
new FilterParameter(nameof(Model.SearchProductTypeId)),
|
||||||
|
new FilterParameter(nameof(Model.SearchPublishedId))
|
||||||
|
},
|
||||||
|
ColumnCollection = new List<ColumnProperty>
|
||||||
|
{
|
||||||
|
new ColumnProperty(nameof(ProductModel.Id))
|
||||||
|
{
|
||||||
|
IsMasterCheckBox = true,
|
||||||
|
Render = new RenderCheckBox("checkbox_products"),
|
||||||
|
ClassName = NopColumnClassDefaults.CenterAll,
|
||||||
|
Width = "50"
|
||||||
|
},
|
||||||
|
new ColumnProperty(nameof(ProductModel.PictureThumbnailUrl))
|
||||||
|
{
|
||||||
|
Title = T("Admin.Catalog.Products.Fields.PictureThumbnailUrl").Text,
|
||||||
|
Width = "100",
|
||||||
|
Render = new RenderPicture(width: 100)
|
||||||
|
},
|
||||||
|
new ColumnProperty(nameof(ProductModel.Name))
|
||||||
|
{
|
||||||
|
Title = T("Admin.Catalog.Products.Fields.Name").Text
|
||||||
|
},
|
||||||
|
new ColumnProperty(nameof(ProductModel.Sku))
|
||||||
|
{
|
||||||
|
Title = T("Admin.Catalog.Products.Fields.Sku").Text,
|
||||||
|
Width = "100"
|
||||||
|
},
|
||||||
|
new ColumnProperty(nameof(ProductModel.FormattedPrice))
|
||||||
|
{
|
||||||
|
Title = T("Admin.Catalog.Products.Fields.Price").Text
|
||||||
|
},
|
||||||
|
new ColumnProperty(nameof(ProductModel.StockQuantityStr))
|
||||||
|
{
|
||||||
|
Title = T("Admin.Catalog.Products.Fields.StockQuantity").Text
|
||||||
|
},
|
||||||
|
new ColumnProperty(nameof(ProductModel.Published))
|
||||||
|
{
|
||||||
|
Title = T("Admin.Catalog.Products.Fields.Published").Text,
|
||||||
|
Width = "80",
|
||||||
|
ClassName = NopColumnClassDefaults.CenterAll,
|
||||||
|
Render = new RenderBoolean()
|
||||||
|
},
|
||||||
|
new ColumnProperty(nameof(ProductModel.Id))
|
||||||
|
{
|
||||||
|
Title = T("Admin.Common.Edit").Text,
|
||||||
|
Width = "80",
|
||||||
|
ClassName = NopColumnClassDefaults.Button,
|
||||||
|
Render = new RenderButtonEdit(new DataUrl("~/Admin/Product/Edit"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
$(function() {
|
||||||
|
$('#delete-selected-action-confirmation-submit-button').bind('click', function () {
|
||||||
|
var postData = {
|
||||||
|
selectedIds: selectedIds
|
||||||
|
};
|
||||||
|
addAntiForgeryToken(postData);
|
||||||
|
$.ajax({
|
||||||
|
cache: false,
|
||||||
|
type: "POST",
|
||||||
|
url: "@(Url.Action("DeleteSelected", "Product"))",
|
||||||
|
data: postData,
|
||||||
|
error: function (jqXHR, textStatus, errorThrown) {
|
||||||
|
showAlert('deleteSelectedFailed', errorThrown);
|
||||||
|
},
|
||||||
|
complete: function (jqXHR, textStatus) {
|
||||||
|
if (jqXHR.status === 204)
|
||||||
|
{
|
||||||
|
showAlert('nothingSelectedAlert', '@T("Admin.Common.Alert.NothingSelected")');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateTable('#products-grid');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('#delete-selected-action-confirmation').modal('toggle');
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<nop-alert asp-alert-id="deleteSelectedFailed" />
|
||||||
|
<nop-alert asp-alert-id="nothingSelectedAlert" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
$("#@Html.IdFor(model => model.GoDirectlyToSku)").keydown(function (event) {
|
||||||
|
if (event.keyCode === 13) {
|
||||||
|
$("#go-to-product-by-sku").trigger("click");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</form>
|
||||||
|
}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
var displayModal = @((Model.LicenseCheckModel?.DisplayWarning == true || Model.LicenseCheckModel?.BlockPages == true).ToString().ToLower());
|
||||||
|
if (displayModal) {
|
||||||
|
$('#license-window').modal({
|
||||||
|
backdrop: 'static',
|
||||||
|
keyboard: false
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#license-window').on('shown.bs.modal', function (event) {
|
||||||
|
var modalCloseEl = $(this).find('button.close');
|
||||||
|
var closeTextEl = $('span', modalCloseEl);
|
||||||
|
|
||||||
|
var startFrom = 5;
|
||||||
|
closeTextEl.text(startFrom);
|
||||||
|
|
||||||
|
const timer = setInterval(function() {
|
||||||
|
if (startFrom-- > 0)
|
||||||
|
closeTextEl.text(startFrom);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
closeTextEl.html('×');
|
||||||
|
modalCloseEl.on('click', function() {
|
||||||
|
$('#license-window').modal('hide')
|
||||||
|
});
|
||||||
|
clearInterval(timer);
|
||||||
|
}, startFrom*1000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<div id="license-window" class="modal fade" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
@Html.Raw(Model.LicenseCheckModel?.WarningText)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@*import products form*@
|
||||||
|
<div id="importexcel-window" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="importexcel-window-title">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title" id="importexcel-window-title">@T("Admin.Common.ImportFromExcel")</h4>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
|
</div>
|
||||||
|
<form asp-controller="Product" asp-action="ImportExcel" method="post" enctype="multipart/form-data">
|
||||||
|
<div class="form-horizontal">
|
||||||
|
<div class="modal-body">
|
||||||
|
<ul class="common-list">
|
||||||
|
<li>
|
||||||
|
<em>@T("Admin.Catalog.Products.List.ImportFromExcelTip")</em>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<em>@T("Admin.Common.ImportFromExcel.ManyRecordsWarning")</em>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="col-md-2">
|
||||||
|
<div class="label-wrapper">
|
||||||
|
<label class="col-form-label">
|
||||||
|
@T("Admin.Common.ExcelFile")
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-10">
|
||||||
|
<input type="file" id="importexcelfile" name="importexcelfile" class="form-control" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
@T("Admin.Common.ImportFromExcel")
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@*export selected (XML). We don't use GET approach because it's limited to 2K-4K chars and won't work for large number of entities*@
|
||||||
|
<form asp-controller="Product" asp-action="ExportXmlSelected" method="post" id="export-xml-selected-form">
|
||||||
|
<input type="hidden" id="selectedIds" name="selectedIds" value="" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
$('#exportxml-selected').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var ids = selectedIds.join(",");
|
||||||
|
if (!ids) {
|
||||||
|
$('#exportXmlSelected-info').text("@T("Admin.Products.NoProducts")");
|
||||||
|
$("#exportXmlSelected").trigger("click");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('#export-xml-selected-form #selectedIds').val(ids);
|
||||||
|
$('#export-xml-selected-form').submit();
|
||||||
|
updateTable('#products-grid');
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<nop-alert asp-alert-id="exportXmlSelected" />
|
||||||
|
|
||||||
|
@*export selected (Excel). We don't use GET approach because it's limited to 2K-4K chars and won't work for large number of entities*@
|
||||||
|
<form asp-controller="Product" asp-action="ExportExcelSelected" method="post" id="export-excel-selected-form">
|
||||||
|
<input type="hidden" id="selectedIds" name="selectedIds" value="" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
$('#exportexcel-selected').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var ids = selectedIds.join(",");
|
||||||
|
if (!ids) {
|
||||||
|
$('#exportExcelSelected-info').text("@T("Admin.Products.NoProducts")");
|
||||||
|
$("#exportExcelSelected").trigger("click");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('#export-excel-selected-form #selectedIds').val(ids);
|
||||||
|
$('#export-excel-selected-form').submit();
|
||||||
|
updateTable('#products-grid');
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<nop-alert asp-alert-id="exportExcelSelected" />
|
||||||
|
|
@ -68,7 +68,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin
|
||||||
};
|
};
|
||||||
await _settingService.SaveSettingAsync(settings);
|
await _settingService.SaveSettingAsync(settings);
|
||||||
await _localizationService.AddOrUpdateLocaleResourceAsync("Plugins.Misc.FruitBankPlugin.Menu.ShipmentsList", "Shipment", "EN");
|
await _localizationService.AddOrUpdateLocaleResourceAsync("Plugins.Misc.FruitBankPlugin.Menu.ShipmentsList", "Shipment", "EN");
|
||||||
await _localizationService.AddOrUpdateLocaleResourceAsync("Plugins.Misc.FruitBankPlugin.Menu.ShipmentsList", "Shipment", "HU");
|
await _localizationService.AddOrUpdateLocaleResourceAsync("Plugins.Misc.FruitBankPlugin.Menu.ShipmentsList", "Szállítmányok", "HU");
|
||||||
await base.InstallAsync();
|
await base.InstallAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,9 +78,9 @@ public class PluginNopStartup : INopStartup
|
||||||
services.AddScoped<IOrderMeasurementService, OrderMeasurementService>();
|
services.AddScoped<IOrderMeasurementService, OrderMeasurementService>();
|
||||||
services.AddScoped<PendingMeasurementCheckoutFilter>();
|
services.AddScoped<PendingMeasurementCheckoutFilter>();
|
||||||
|
|
||||||
//services.AddScoped<OrderListModel, OrderListModelExtended>();
|
services.AddScoped<IOrderListModelExtended<OrderModelExtended>, OrderListModelExtended>();
|
||||||
//services.AddScoped<OrderModel, OrderModelExtended>();
|
services.AddScoped<OrderModel, OrderModelExtended>();
|
||||||
//services.AddScoped<OrderSearchModel, OrderSearchModelExtended>();
|
services.AddScoped<OrderSearchModel, OrderSearchModelExtended>();
|
||||||
|
|
||||||
services.AddScoped<IOrderModelFactory, CustomOrderModelFactory>();
|
services.AddScoped<IOrderModelFactory, CustomOrderModelFactory>();
|
||||||
services.AddScoped<IGenericAttributeService, GenericAttributeService>();
|
services.AddScoped<IGenericAttributeService, GenericAttributeService>();
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,16 @@ public class RouteProvider : IRouteProvider
|
||||||
name: "Plugin.FruitBank.Admin.ManagementPage.GetPartners",
|
name: "Plugin.FruitBank.Admin.ManagementPage.GetPartners",
|
||||||
pattern: "Admin/ManagementPage/GetPartners",
|
pattern: "Admin/ManagementPage/GetPartners",
|
||||||
defaults: new { controller = "ManagementPage", action = "GetPartners", area = AreaNames.ADMIN });
|
defaults: new { controller = "ManagementPage", action = "GetPartners", area = AreaNames.ADMIN });
|
||||||
|
|
||||||
|
endpointRouteBuilder.MapControllerRoute(
|
||||||
|
name: "Plugin.FruitBank.Admin.Products.List",
|
||||||
|
pattern: "Admin/Product/List",
|
||||||
|
defaults: new { controller = "CustomProduct", action = "List", area = AreaNames.ADMIN });
|
||||||
|
|
||||||
|
endpointRouteBuilder.MapControllerRoute(
|
||||||
|
name: "Plugin.FruitBank.Admin.Products.ProductList",
|
||||||
|
pattern: "Admin/Product/ProductList",
|
||||||
|
defaults: new { controller = "CustomProduct", action = "ProductList", area = AreaNames.ADMIN });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,11 @@
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="Areas\Admin\Views\Product\List.cshtml">
|
||||||
|
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||||
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="Areas\Admin\Views\_ViewStart.cshtml">
|
<Content Include="Areas\Admin\Views\_ViewStart.cshtml">
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
|
|
@ -149,6 +154,12 @@
|
||||||
<None Update="Areas\Admin\Components\_DocumentsGridPartial.cshtml">
|
<None Update="Areas\Admin\Components\_DocumentsGridPartial.cshtml">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Update="Areas\Admin\Views\Order\FileUploadGridComponent.cshtml">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Areas\Admin\Views\Order\TestGridComponent.cshtml">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
<None Update="Areas\Admin\Views\Order\ShippingDocumentGridComponent.cshtml">
|
<None Update="Areas\Admin\Views\Order\ShippingDocumentGridComponent.cshtml">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue