Try your search with a different keyword or use * as a wildcard.
@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">
@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>
@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", "Product", 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').on('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>
</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>
@*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" />
<nop-alert asp-alert-id="exportXmlSelected" />
<nop-alert asp-alert-id="deleteSelectedFailed" />
<nop-alert asp-alert-id="nothingSelectedAlert" />
<nop-action-confirmation asp-button-id="delete-selected" />