Get parent object of Vaadin `TreeGrid` node - vaadin8

My TreeGid component shows the relation between images and Products. The relation between image and product objects is n:m (see below for a simplified example, product 60148971 is linked to at least two images).
When a user selects a product (see example) it is important to know its parent node. We need this information from the UI model because the product can have more than one parent. As far as I understand, this is not possible in Vaadin 8.1+. Can anyone confirm this?
My current solution is to use simple Link objects as node, this object contains a reference to the image and the product. For usage, see code snippet (extremely simplified, just to get the idea).
#Override // from HierarchicalDataProvider
public Stream<HasTitle> fetchChildren(final HierarchicalQuery hq) {
HasTitle item = hq.getParent();
...
} else if (item instanceof Product) {
final Product p = (Product)item;
return p.getImages().stream()
.map(img -> new Link(p, img));
...
}
However, I consider this a hack. So if there is a more efficient way to do this, please let me know!
(using Vaadin 8.2.alpha2)

Related

Laravel resource return array element check against different model

The subject of this question was a bit hard to formulate.
So i'll try to describe as detailed as possible my problem/question.
1 have 2 models.
Category
Product
On my product edit page i render a tree (jstree) with categories, for each category the product belongsTo the node of the tree needs to be checked.
My current approach is in the categoryResource i check if the category id belongs to the product, but this (of course) returns in a lot of queries as per category a query is fired to determine if the category belongs to the product.
public function toArray($request)
{
// got a product id?
if (request('product_id')) {
$categories = Product::findOrFail(request('product_id'))->categories->pluck('id');
}
return [
'checked' => !is_null($categories) && $categories->contains($this->id)
];
}
Other solution would be to load product categories in the controller and loop rebuild the 'resource' but this just doesn't feel right and also i need to be build recursive stuff (for child categegories) which Resource model can already handle.
Anyone got a more proper and solid solution?
If more information is required i'm happy to oblige :)

Yii2 authentication based on record level

Within yii2 I need some RBAC access control also on record level. As a yii2 beginner I'm searching for the best point to enter the logic but struggle through the documents.
Example:
A table Children mentions a child, besides lots of other children.
A child usually has two parents in table Parents.
Besides other access control with yii2-admin/user these two parents can view and manipulate the record of their own child/ren but not others.
the logged in user is a parent.
Example table Children:
|id|name|age|
|1|Max|10|
|2|Moritz|11|
|3|Lena|8|
...
Example table Parents:
|id|relation|name|
|1|mother|Anna|
|2|father|Paul|
|3|mother|Lisa|
...
Example table Xref (Relation to Children and Parents):
|child_id|parent_id|
|1|1|
|1|2|
|2|3|
|3|1|
|3|2|
...
I think the activeRecord class Children would be the the right place for a behaviour like that, right?
Does someone have an example code to point me to the right direction for an efficient code,
where Paul and Anna could modify the record for 'Max' but not for 'Moritz'?
I hardly ever use relational DBs with Yii2 but I will illustrate what I meant as best as possible:
I'm going to illustrate the Parent Class as the child will be roughly similar (appart from the relationship direction):
class ParentModel extends ActiveRecord
{
/**
* #return string the name of the table associated with this ActiveRecord class.
*/
public static function tableName()
{
return 'Parents';
}
public function getChildren()
{
// ParentModel has_many ChildModel via Xref.child_id -> id
return $this->hasMany(ChildModel::className(), ['id' => 'child_id'])
->viaTable('Xref', ['parent_id' => 'id']);
}
}
With this you can get all children by using (for example):
$user = ParentModel::findOne($userID);
$children = $user->children;
You can then use all RBAC functionalities to make sure you users can't access an edit form action/view. Or use RBAC rules to make sure only the appropriate content is being handled.
Or you could write your own checks to make sure (for example) that the children being handled really belong to the Parent accessing the controller action. (by say... comparing the user's children to the ones being handled, though depending on your structure this could be handled by RBAC Rules)
But regardless of the actions, that logic should remain on the controller layer. On some very rare occasions you might have to put access right logic in your models but the models should have that logic separated and not related to the RBAC system. I've personally had this issue with graph traversal logic which is on an ActiveQuery level. But that's another issue in it's own right.

How to show all products in nopCommerce?

I would like to show all products without creating any new category and mapping to it.
Can any one help me?
Thanks in advance.
It's true; in order for a product to be displayed in nopCommerce, it must be assigned to a category. Your best bet is to create a top-level umbrella category, like "All Products", and add all of your products to that umbrella category.
As far as I know their must be a category associated with product.
You can create a plugin, map a route to it (for example map to 'allproducts' route), and create your own Controllers, Actions and Views within the plugin. Then insert in the main menu a link to the route by mean of
#Html.RouteLink(routeName, null) //or similar overloads
The plugin creation part is too huge to be described here. http://www.nopcommerce.com/documentation.aspx is a good start.
PS:/ Regarding routing, each plugin can implement a route registrar by implementing the "IRouteProvider" interface.
:)
You can do that by modifying the code. I have done it before. It is actually quite simple.
Modify the Category action of the Catalogue controller to receive a nullable CategoryId:
public ActionResult Category(int? categoryId, CatalogPagingFilteringModel command){
modify the action to not break because of this nullable paramters.
The most important part to modify is where you build the list of category Ids to filter:
var categoryIds = new List<int>();
if (category != null)
{
categoryIds.Add(category.Id);
}
if (_catalogSettings.ShowProductsFromSubcategories)
{
//include subcategories
categoryIds.AddRange(GetChildCategoryIds(category.Id));
}
The mothod _productService.SearchProducts will receive an empty list of category Ids and will not filter any products.

Should you join entities and merge them into a POCO?

There are times where I have to display the relationship between two entities. Question is, should you retrieve the data all in one query (with a join statement)?
For example, I have the entity User and Picture. A picture is created by one user. If I wanted to display list of picture names, and who uploaded the certain picture.
Two approaches:
1) Using Entity Framework relationship, where Pictures is an entity, and it has a User property (the user that created it). The User is an entity too.
foreach(var picture : context.Pictures.all){
picture.name
picture.user.name
}
2) Combining Picture & User into one POCO object and return that to the controller.
Controller:
foreach(var pictureUser : dal.GetPictureUsers){
pictureUser.PictureName
pictureUser.UserName
}
GetPictureUsers()
{
PictureUser pictureUserPoc = new PictureUsersql.Include("Picture").include("User").Select(sa=> new PictureUser {
PictureName = sa.PictureName,
UserName = sa.UserName});
}
The latter one was suggested in order to increase performance. Personally I would have written it in the former way since you do not couple what you want in the View logic (having Picture and User relationship printed) in the data access layer.
I hope I have stated the question clearly.
Thanks!
#foreach (var profile in Model)
{
#Html.DisplayFor(model=>profile.PictureName);
#Html.DisplayFor(model=>profile.User.Name);
}
The Model represents the Pictures; if you strongly type the view then you can use it.

ASP.NET MVC 3 areas and DDD aggregate roots

I'm building a site and am considering using areas to cover a similar scenario to the one I'm about to describe.
I currently have a site with 4 sections, lets call these Create, Manage, Section 3 and Section 4
Create and Manage are actions on the domain object that I'm working with. The domain object has a number of collections of sub objects that relate to it. These need to be created and managed as well.
I am using Products as an example so as not to give anything away but it doesn't quite fit the same domain - so please don't say "Why don't you have a Products section"
My current implementation has a ManageController which has Actions like Categories, Category, ProductsForCategory
I'm thinking I need areas, however, some URLs will need to be scoped so I want
/Manage/Category/8/Products
/Manage/Category/8/Product/1
Is this possible using Areas? Do I need to set up new routing rules?
Would my CategoryController have 2 parameters on the action e.g.
public ActionResult Product(int categoryId, int productId)
{
//get category
var cat = GetCategory(categoryId);
//get product
var product = cat.Products.SingleOrDefault(x=>x.Id == productId);
if(product == null)
return RedirectToAction("Index","Manage");
return View(product);
}
Then I would have a routing rule that passed in the category id?
Is my thinking on this correct?
This is possible with Areas.. although it's my understanding that areas are mainly recommended for structuring your code into a meaningful folder structure to deal with large-ish MVC apps, whereas it looks like you want to use it for achieving nested routes?
To map your nested route to /Manage/Category/8/Product/1 you could create your "Manage" area, and then add a route like so:
context.MapRoute(null,
"Manage/{controller}/{categoryId}/{action}/{id}",
new
{
action = "Product",
id = "1",
categoryId = "2"
});
You then create an action method to accept those params:
public ActionResult Product(string categoryId, string id)
However, your question talks about aggregate DDD roots, so I suspect I've only answered part of the question?

Resources