Skip to content

Commit

Permalink
Improvements - Admin panel - Product pictures - allow set information…
Browse files Browse the repository at this point in the history
… about alt and title attribute for the picture to every language
  • Loading branch information
KrzysztofPajak committed Aug 13, 2021
1 parent 98910bb commit 8747955
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Grand.Domain;
using Grand.Domain.Common;
using Grand.Domain.Media;
using System;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Grand.Business.Storage.Interfaces
Expand Down Expand Up @@ -155,6 +157,13 @@ public partial interface IPictureService
/// <returns>Picture</returns>
Task<Picture> UpdatePicture(Picture picture);

/// <summary>
/// Updates the picture field
/// </summary>
/// <param name="picture">Picture</param>
Task UpdatField<T>(Picture picture,
Expression<Func<Picture, T>> expression, T value);

/// <summary>
/// Updates a SEO filename of a picture
/// </summary>
Expand Down
23 changes: 22 additions & 1 deletion src/Business/Grand.Business.Storage/Services/PictureService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using Grand.Business.Common.Extensions;
using Grand.SharedKernel.Extensions;
using Grand.Domain.Common;
using System.Linq.Expressions;

namespace Grand.Business.Storage.Services
{
Expand Down Expand Up @@ -484,7 +485,8 @@ public virtual async Task<Picture> GetPictureById(string pictureId)
SeoFilename = p.SeoFilename,
TitleAttribute = p.TitleAttribute,
Reference = p.Reference,
ObjectId = p.ObjectId
ObjectId = p.ObjectId,
Locales = p.Locales
});
return await Task.FromResult(query.FirstOrDefault());
});
Expand Down Expand Up @@ -690,6 +692,25 @@ public virtual async Task<Picture> UpdatePicture(Picture picture)
return picture;
}

/// <summary>
/// Updates the picture
/// </summary>
/// <param name="picture">Picture</param>
/// <returns>Picture</returns>
public virtual async Task UpdatField<T>(Picture picture, Expression<Func<Picture, T>> expression, T value)
{
if (picture == null)
throw new ArgumentNullException(nameof(picture));

await _pictureRepository.UpdateField<T>(picture.Id, expression, value);

//event notification
await _mediator.EntityUpdated(picture);

//clare cache
await _cacheBase.RemoveByPrefix(string.Format(CacheKey.PICTURE_BY_ID, picture.Id));

}
/// <summary>
/// Save picture on file system
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

@using Microsoft.AspNetCore.Mvc.Razor;

@model ProductModel.ProductPictureModel
@{
Layout = Grand.Web.Admin.Extensions.Constants.Layout_AdminPopup;
Expand All @@ -11,6 +12,27 @@
asp-route-btnId="@Context.Request.Query["btnId"]"
asp-route-formId="@Context.Request.Query["formId"]">


<!-- #region languages template -->
@{ Func<int, HelperResult> template = @<div class="form-body">
<div class="form-group">
<admin-label asp-for="@Model.Locales[item].AltAttribute" class="col-sm-3 control-label" />
<div class="col-md-9 col-sm-9">
<admin-input asp-for="@Model.Locales[item].AltAttribute" />
<span asp-validation-for="@Model.Locales[item].AltAttribute"></span>
</div>
</div>
<div class="form-group">
<admin-label asp-for="@Model.Locales[item].TitleAttribute" class="col-sm-3 control-label" />
<div class="col-md-9 col-sm-9">
<admin-input asp-for="@Model.Locales[item].TitleAttribute" />
<span asp-validation-for="@Model.Locales[item].TitleAttribute"></span>
</div>
</div>
<input asp-for="@Model.Locales[item].LanguageId" type="hidden" />
</div>;
}

<div asp-validation-summary="All"></div>
<input asp-for="ProductId" type="hidden" />
<input asp-for="Id" type="hidden" />
Expand All @@ -28,20 +50,24 @@
<a href="@Model.PictureUrl" target="_blank"><img src="@Model.PictureUrl" width="150" /></a>
</div>
</div>
<div class="form-group">
<admin-label asp-for="OverrideAltAttribute" />
<div class="col-md-9 col-sm-9">
<admin-input asp-for="OverrideAltAttribute" />
<span asp-validation-for="OverrideAltAttribute"></span>
</div>
</div>
<div class="form-group">
<admin-label asp-for="OverrideTitleAttribute" />
<div class="col-md-9 col-sm-9">
<admin-input asp-for="OverrideTitleAttribute" />
<span asp-validation-for="OverrideTitleAttribute"></span>
<localized-editor localized-template=template name="productpicturevalue-localized" language-ids=@Model.Locales.Select(c=>c.LanguageId).ToList()>
<div class="form-body">
<div class="form-group">
<admin-label asp-for="AltAttribute" class="col-sm-3 control-label" />
<div class="col-md-9 col-sm-9">
<admin-input asp-for="AltAttribute" />
<span asp-validation-for="AltAttribute"></span>
</div>
</div>
<div class="form-group">
<admin-label asp-for="TitleAttribute" class="col-sm-3 control-label" />
<div class="col-md-9 col-sm-9">
<admin-input asp-for="TitleAttribute" />
<span asp-validation-for="TitleAttribute"></span>
</div>
</div>
</div>
</div>
</localized-editor>
<div class="form-group">
<admin-label asp-for="DisplayOrder" />
<div class="col-md-9 col-sm-9">
Expand All @@ -52,7 +78,7 @@
<div class="form-actions">
<div class="row">
<div class="offset-md-3 offset-sm-3 col-md-9 col-sm-9">
<button class="k-button" type="submit" name="save"><i class="fa fa-check"></i> &nbsp;@Loc["Admin.Common.Save"] </button>
<button class="k-button" type="submit" name="save"><i class="fa fa-check"></i>@Loc["Admin.Common.Save"] </button>
</div>
</div>
</div>
Expand Down
9 changes: 8 additions & 1 deletion src/Web/Grand.Web.Admin/Controllers/ProductController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1335,7 +1335,14 @@ public async Task<IActionResult> ProductPicturePopup(string productId, string id
if (pp == null)
return Content("Product picture not exist");

var model = await _productViewModelService.PrepareProductPictureModel(product, pp);
var (model, picture) = await _productViewModelService.PrepareProductPictureModel(product, pp);
//locales
await AddLocales(_languageService, model.Locales, (locale, languageId) =>
{
locale.AltAttribute = picture?.GetTranslation(x => x.AltAttribute, languageId, false);
locale.TitleAttribute = picture?.GetTranslation(x => x.TitleAttribute, languageId, false);
});

return View(model);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public interface IProductViewModelService

//Pictures
Task<IList<ProductModel.ProductPictureModel>> PrepareProductPicturesModel(Product product);
Task<ProductModel.ProductPictureModel> PrepareProductPictureModel(Product product, ProductPicture productPicture);
Task<(ProductModel.ProductPictureModel model, Picture Picture)> PrepareProductPictureModel(Product product, ProductPicture productPicture);
Task InsertProductPicture(Product product, Picture picture, int displayOrder, string overrideAltAttribute, string overrideTitleAttribute);
Task UpdateProductPicture(ProductModel.ProductPictureModel model);
Task DeleteProductPicture(ProductModel.ProductPictureModel model);
Expand Down
26 changes: 22 additions & 4 deletions src/Web/Grand.Web.Admin/Models/Catalog/ProductModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -485,8 +485,13 @@ public AddProductSpecificationAttributeModel()
public IList<SelectListItem> AvailableOptions { get; set; }
}

public partial class ProductPictureModel : BaseEntityModel
public partial class ProductPictureModel : BaseEntityModel, ILocalizedModel<ProductPictureModel.ProductPictureLocalizedModel>
{
public ProductPictureModel()
{
Locales = new List<ProductPictureLocalizedModel>();
}

public string ProductId { get; set; }

[UIHint("MultiPicture")]
Expand All @@ -500,12 +505,25 @@ public partial class ProductPictureModel : BaseEntityModel
public int DisplayOrder { get; set; }

[GrandResourceDisplayName("Admin.Catalog.Products.Pictures.Fields.OverrideAltAttribute")]

public string OverrideAltAttribute { get; set; }
public string AltAttribute { get; set; }

[GrandResourceDisplayName("Admin.Catalog.Products.Pictures.Fields.OverrideTitleAttribute")]
public string TitleAttribute { get; set; }

public IList<ProductPictureLocalizedModel> Locales { get; set; }

public partial class ProductPictureLocalizedModel : ILocalizedModelLocal
{
public string LanguageId { get; set; }

[GrandResourceDisplayName("Admin.Catalog.Products.Pictures.Fields.OverrideAltAttribute")]
public string AltAttribute { get; set; }

[GrandResourceDisplayName("Admin.Catalog.Products.Pictures.Fields.OverrideTitleAttribute")]
public string TitleAttribute { get; set; }

}

public string OverrideTitleAttribute { get; set; }
}

public partial class ProductCategoryModel : BaseEntityModel
Expand Down
28 changes: 13 additions & 15 deletions src/Web/Grand.Web.Admin/Services/ProductViewModelService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2903,29 +2903,29 @@ public virtual async Task<IList<ProductModel.ProductPictureModel>> PrepareProduc
ProductId = product.Id,
PictureId = x.PictureId,
PictureUrl = picture != null ? await _pictureService.GetPictureUrl(picture) : null,
OverrideAltAttribute = picture?.AltAttribute,
OverrideTitleAttribute = picture?.TitleAttribute,
AltAttribute = picture?.AltAttribute,
TitleAttribute = picture?.TitleAttribute,
DisplayOrder = x.DisplayOrder
};
items.Add(m);
}
return items;
}

public virtual async Task<ProductModel.ProductPictureModel> PrepareProductPictureModel(Product product, ProductPicture productPicture)
public virtual async Task<(ProductModel.ProductPictureModel model, Picture Picture)> PrepareProductPictureModel(Product product, ProductPicture productPicture)
{
var picture = await _pictureService.GetPictureById(productPicture.PictureId);
var model = new ProductModel.ProductPictureModel {
Id = productPicture.Id,
ProductId = product.Id,
PictureId = productPicture.PictureId,
PictureUrl = picture != null ? await _pictureService.GetPictureUrl(picture) : null,
OverrideAltAttribute = picture?.AltAttribute,
OverrideTitleAttribute = picture?.TitleAttribute,
DisplayOrder = productPicture.DisplayOrder
AltAttribute = picture?.AltAttribute,
TitleAttribute = picture?.TitleAttribute,
DisplayOrder = productPicture.DisplayOrder,
};

return model;
return (model, picture);
}

public virtual async Task InsertProductPicture(Product product, Picture picture, int displayOrder, string overrideAltAttribute, string overrideTitleAttribute)
Expand Down Expand Up @@ -2957,10 +2957,10 @@ public virtual async Task UpdateProductPicture(ProductModel.ProductPictureModel
var productPicture = product.ProductPictures.Where(x => x.Id == model.Id).FirstOrDefault();
if (productPicture == null)
throw new ArgumentException("No product picture found with the specified id");

//a vendor should have access only to his products
if (_workContext.CurrentVendor != null)
{

if (product != null && product.VendorId != _workContext.CurrentVendor.Id)
{
throw new ArgumentException("This is not your product");
Expand All @@ -2972,15 +2972,13 @@ public virtual async Task UpdateProductPicture(ProductModel.ProductPictureModel
throw new ArgumentException("No picture found with the specified id");

productPicture.DisplayOrder = model.DisplayOrder;

await _productService.UpdateProductPicture(productPicture, product.Id);

await _pictureService.UpdatePicture(picture.Id,
await _pictureService.LoadPictureBinary(picture),
picture.MimeType,
picture.SeoFilename,
model.OverrideAltAttribute,
model.OverrideTitleAttribute);
//Update picture fields
await _pictureService.UpdatField(picture, x => x.AltAttribute, model.AltAttribute);
await _pictureService.UpdatField(picture, x => x.TitleAttribute, model.TitleAttribute);
await _pictureService.UpdatField(picture, x => x.Locales, model.Locales.ToTranslationProperty());

}
public virtual async Task DeleteProductPicture(ProductModel.ProductPictureModel model)
{
Expand Down

0 comments on commit 8747955

Please sign in to comment.