Assets need to be optionally organized in hierarchies. Whether this lineage for livestock or plants, or establish an area structure, there should exist a way to handle these assets.
Some modules that could support us to do this:
- https://www.drupal.org/project/entity_hierarchy
- https://www.drupal.org/project/entity_reference_hierarchy
- https://www.drupal.org/project/entity_reference_tree
- https://www.drupal.org/project/hierarchy_manager
Comments
Comment #2
m.stentaCurrent status: I have created a
parententity reference field on all asset types in the 2.x branch, which includes Plant, Animal, Sensor, Equipment, Group, and Compost.In my
areas2xbranch, I'm working on adding additional asset types including: Land, Structure, and Water (which will be migrated from the area taxonomy terms, see #2363393: Make "Area" into a type of Farm Asset). These asset types will also have the sameparentfield.Adding #3151233: [META] farmOS 2.x Data Model as a parent issue.
Comment #3
m.stentaThis has a few aspects to it.
One is the data model itself: the entities and the fields that relate them. We pretty much have that done, with the
parentfield.The other aspect is UI/UX...
For most asset types (eg: Plants and Animals) we don't need much more than that. We just want to be able to see that "this animal is the parent of that animal" which is easy to do with the Asset Entity View Display, and with Views (as we are currently doing in 1.x).
I think the bigger task here is replicating (and improving upon) the features that we currently have in 1.x, where areas are taxonomy terms. Taxonomy terms already have hierarchy, and Drupal provides some basic tools to manage that like the "Relations" field in the term edit form (for selecting parent and weight), and the click-and-drag hierarchy editor (eg: /admin/structure/taxonomy/farm_areas, which we link to from /farm/areas to allow changing the hierarchy).
The "click and drag interface for changing hierarchy" (for "location" assets specifically) is therefore a minimum requirement for this issue.
But within that, we need to consider how to make that interface more scalable generally. We have some future use-cases that will have 10s of thousands of location assets.
So perhaps we need to think about making our own UI for organizing hierarchies - which limits the depth of the hierarchy that is included in the form. So rather than organizing ALL location assets in the same form, you would only be working with sub-sets at any given time.
The other missing piece here is "weight". Taxonomy hierarchy has two fields: parent (for defining the parent entity) and weight (to define how the term is sorted among other children at the same level). We have a
parentfield in 2.x - but we don't have aweightfield.And honestly, I wonder: do we need
weight? I don't think we really do. Organizing alphabetically 100% of the time seems perfectly reasonable for every use-case I've encountered thusfar, and I would be OK with making that an official decision, to keep this simpler. In fact, I often find myself using the core taxonomy "Reset to alphabetical" button in 1.x.Comment #4
m.stentaThinking more broadly about this... even if we DO have use-cases where custom ordering is required, I'm not sure that the weight should be stored on the asset itself. It might make more sense for it to be saved separately. Consider the case where one asset has multiple parents. With a single "weight" value, you can't control the order of that asset among the children of both parents separately - which sort of breaks the whole concept of ordering altogether.
This is an existing limitation in Drupal core as well. Terms can technically have multiple parents, but only a single weight. I've run into issue with this in previous projects, and there seem to be some long-standing core issues still open because of it (eg: #969194: Drag’n’drop only partially disabled when term has multiple parents).
So my thought is: let's forget about "weight" for now (because I don't think we have a clear need for it). And if we need it in the future, it should be managed separately from the asset entities themselves, which should ONLY reference the parent. "Weight" within hierarchy is really a separate feature from the data model itself, IMO.
Comment #5
m.stentaIt's reminding me of the Nodequeue module I used in D6/D7. ;-)
The comparison there is: nodequeues (intentionally ordered lists of nodes) are a separate concept from the nodes themselves. And one node can be in multiple queues with different weights.
Comment #6
m.stentaAdding this module to consider as well: https://www.drupal.org/project/hierarchy_manager
It sounds like it is primarily focused on creating the draggable list feature, which is one of our primary needs. It works with the core Entity Reference field type.
Combined with https://www.drupal.org/project/entity_reference_tree (which provides a form widget), these two modules may cover our UI/UX needs.
My only hesitation is that they use a JS library that depends on jQuery (https://www.jstree.com/). That isn't a deal-breaker, but in general reducing dependencies on jQuery is a good thing moving forward (Jamie is actively working on removing Bootstrap and jQuery entirely from Field Kit).
But that said, maybe they would provide a good short-term solution with little effort. It might be worth putting heads together with Jamie about potential Vue.js-based approaches (perhaps more custom) - because in the medium term we are hoping to merge more of those UI efforts/components with Field Kit work.
The other two module (https://www.drupal.org/project/entity_hierarchy and https://www.drupal.org/project/entity_reference_hierarchy) also look interesting. I'm hesitant about the first one (
entity_hierarchy) because it is providing its own field type, rather than using core entity reference, and I'm not sure we need/want that added layer on the data model level. And I'm not sure I understand what the second one (entity_reference_hierarchy) does. :-)Comment #7
m.stentaSpecifically, this new field type is extending the core entity reference and adding a "weight" field, which we don't really want/need: https://git.drupalcode.org/project/entity_hierarchy/-/blob/8.x-2.x/src/P...
And... it sounds like it only supports a single parent (probably for the same reasons described above regarding the "weight" and ordering conundrum under multiple parents).
-https://www.drupal.org/project/entity_hierarchy
Comment #8
m.stentaAdding some conversation with @jgaehring here regarding "weight" for posterity/context:
Comment #9
pcambraSide questions first:
Entity hierarchy (https://www.drupal.org/project/entity_hierarchy) creates a nested set (there's a weight field as you mention) and there are smart operations on the entity retrieving data for views https://git.drupalcode.org/project/entity_hierarchy/-/tree/8.x-2.x/src/P... while https://www.drupal.org/project/entity_reference_hierarchy seems to save the information in the parent for the whole tree and has a depth extra field.
I did look into https://www.drupal.org/project/hierarchy_manager but it has a mention that only supports menus and taxonomies.
Just for reference, the "new" nodequeue is https://www.drupal.org/project/entityqueue.
Now the relevant part:
It seems that rather than having a complex field type that builds on top of an entity reference to facilitate us a hierarchy, we would like to keep the parent as it is and maybe have a widget and a hierarchical formatter for the parent field?
A few thoughts:
- How would we want to manage the hierarchies? Drag and drop is out of the question since we don't want weighted entities.
- Does the editor need to access the parent to see the children? what about grandchildren? Seems that we need at least "special pages" where these hierarchies are represented
- Could we solve these "tree" representation issues with computed fields?
- Maybe we could have some progressive decoupled block here and use a javascript library incorporating https://www.lullabot.com/articles/widget-registry-how-serve-reusable-int..., I'm sure @jgaehring could help a lot with this.
Comment #10
m.stentaThis sounds right to me.
And maybe a second question is: do we want to be able to manage the hierarchy in BOTH the individual asset context AND in broader contexts?
The former would be the responsibility of the widget, in my mind. So when you are editing an individual asset, and you want to modify where it lives in the hierarchy, you do so via the widget. This maps to the current "Relations" field in 1.x, provided by Drupal core taxonomy module (and woefully insufficient for managing large hierarchical lists).
The latter would be a standalone UI, akin to the "list terms" form provided by Drupal core taxonomy module for drag-and-drop management of the full hierarchy.
I do think we want both - to be able to manage hierarchy from the standpoint of an individual asset AND from the standpoint of the hierarchy as a whole (and/or from subsets of that hierarchy).
Interesting idea - can you elaborate what you mean/envision? Perhaps this is how we handle the latter feature (managing sets/subsets of the hierarchy as a whole)?
I can imagine a page at
location/hierarchy(or something) which is a FULL hierarchy manager of all "location" assets, perhaps with options for filtering down to certain asset types (Land / Structure / Water) and other conditions.This brings up an important distinction we should make: we really only want these "advanced" hierarchy management features for "location" assets. We do not need/want them for animal/plant/etc lineage management (I don't think). The difference, in practice, is that locations will have a relatively shallow hierarchy. Whereas the "lineage" hierarchy of living assets giving birth to children has a potentially unlimited depth (animal 1 begets animal 2 begets animal 3... and onward). Further, animal hierarchy won't change. Location hierarchy will. Location hierarchy represents the land owner/manager's mental model of the land - whereas lineage hierarchy represents ACTUAL parental lineage.
Those differences don't necessarily mean we need different fields - I think the simple shared
parententity reference field is still sufficient. It only changes how we need to treat different asset types in the UI.How we draw that distinction is an open question. We could simply say "Land, Structure, and Water" asset types will appear in the hierarchy management features - others will not. But there may be contrib modules that want to add additional asset types to that set. Another option is using a field on the assets themselves (or on the asset types perhaps) as the filter. In my
areas2xbranch, I am adding alocationboolean field to all assets (defaulting to TRUE on Land, Structure, and Water assets, FALSE on others) - so this could be used as the filter, perhaps.Good point about "drag and drop" and "weighted entities" being practically incompatible. I overlooked that. I suppose being able to drag horizontally (to set hierarchy) but not vertically (to set order) might be possible... but it would be tricky. Vertical dragging is a prereq for horizontal dragging - and that would create an implication in the user's mind that ordering is possible. If the order then changed to alphabetical after saving (while still maintaining the hierarchy), that might be confusing/frustrating - even if we make it clear that order will not be preserved. Still - it is an option. (I could also imagine some JS logic that automatically keeps the order alphabetical during drag-and-drop, while still allowing hierarchy change.... in theory... but the usability of that may end up be horrible in practice).
This is a very good question also, as it relates to access control. We'll need to remember to consider this in any custom code we build for managing these hierarchies.
Comment #11
m.stentaOh I forgot to finish this thought...
Beyond
location/hierarchy, which has the FULL hierarchy, perhaps we can also havelocation/hierarchy/%parentwhich limits the management form to only include children of the specified parent - so you are only editing a subset of the hierarchy.For small farms, with a small number of areas, they may only ever use
location/hierarchy. But for larger operations, or country-wide area management use-cases with 10s of thousands of areas, maybe they only edit the sub-sets.And in those very large use-cases, we may even need to disable/restrict the root
location/hierarchypath, or riskmemory_limiterrors.Comment #12
m.stentaThis has got me thinking... maybe we should just focus on this
location/hierarchy/%parentidea as a first step. Having the ability to manage hierarchy from individual assets (via widget/formatter) might not be necessary if we have an easy to uselocation/hierarchy/%parentform.The
parentreference field widget is really just for selecting the parent - it doesn't necessarily need to have much more than that - so maybe https://www.drupal.org/project/entity_browser is all we need across all asset types. And maybe we do customize the formatter - but just to include a link to thelocation/hierarchy/%parentpage.Perhaps
location/hierarchy/%parentis all we need for "minimum viable product" on this?Comment #13
m.stentaOne simple idea here might be: only allow managing 2 or 3 levels deep. And to go deeper you must click on one of the nested items to load its children in
location/hierarchy/%parent.So
location/hierarchywould show levels 1, 2, and 3, and let you arrange all of their relative hierarchies. But in order to arrange levels 4, 5, 6, ... you would click on one of the parents in level 3. Does that make sense? Essentially "drilling down" to manage sub-hierarchies - but never working with more than 3 layers deep at a time?Comment #14
pcambraI'm starting to think that we will be better off breaking this into 2 different tasks for now:
1) Asset widget: It doesn't seem a simple autocomplete will do, and Entity Browser is an excellent, albeit complex, module, it is pluggable and we could have different plugins per "asset type", we could implement something like https://www.drupal.org/project/content_browser but for location assets of that type. We could make it more complex for "location" assets while keeping a simple widget for the rest.
Hot question: Can the hierarchy be mixed?, if I have a lake in my property, I might want the water asset being in the hierarchy of a larger land asset.
2) Asset formatter, I plan out 2 separate options, we show a simplified formatter (configurable?), such as show parent / children that displays the immediate siblings. we then add a link there that opens either of these two (we could even implement both down the line):
- An offcanvas that show some hierarchical representation: https://dri.es/how-to-use-drupal-8-off-canvas-dialog-in-your-modules
- A decoupled block leveraging a js library (even vue) https://www.lullabot.com/articles/widget-registry-how-serve-reusable-int...
I would leave "dragging" out of the MVP until we really know what we want.
Comment #15
m.stentaYes absolutely. The hierarchy will include assets of any type, potentially. Especially if we filter based on the
locationboolean field. Paul has talked about cases where he would like to make Plants into locations themselves - eg: with an Orchard (long-term crop spanning years/decades), rather than having two separate Land and Plant assets. In that scenario, the Orchard asset (a Plant asset type) would have thelocationboolean set to TRUE, and would therefore be included in the hierarchy editor.Comment #16
m.stentaI agree it makes sense to spin off sub-issues and prioritize them separately.
I think the "dragging" piece is arguably the most important - because it is what current users depend on 99% of the time for managing their hierarchy. So maybe we just need to dig into that a bit more and think about how it should work.
And in the larger use-cases, it may be even more critical. I'm not sure I can imagine using the individual asset widget to manage 10,000 areas.
Comment #17
m.stentaQuick update: @jgaehring has some ideas for making the drag and drop work as a Vue.js component. And @pcambra is going to explore using Entity Browser for the widget (perhaps with a custom plugin).
So perhaps this will be a good opportunity to explore adding a Vue.js component to farmOS. We can add a
location/hierarchy/%parentpage that builds the markup, and load the Vue.js component in client side.Comment #18
m.stentaOh just remembered: one thing we will need to prevent is circular relationships (eg: Asset A is parent of Asset B is parent of Asset A). This logic will need to be somewhere in farmOS. Perhaps we make a new
farm_hierarchymodule (and move the currentparentfield storage over there), which can add this constraint somehow. This should probably be split off to a separate issue.Comment #19
pcambraThis is music to my ears, we can add a widget with vue with the technique mentioned above and leverage a widget library that can be used elsewhere.
I don't necessarily think a different module is required, we could add a circle hierarchy validator on the ER fields for #18, I don't think we're the only ones with the problem.
Comment #20
m.stentaCreated a child issue: #3179016: Prevent circular asset parent relationships
Comment #21
m.stentaSplit off some more standalone issues:
They are just stubs right now... might want to copy the relevant bits of this discussion into them (as well as some of the things we said in Matrix chat).
Comment #22
m.stentaComment #23
m.stenta#3179023: Location hierarchy drag-and-drop editor will be merged soon...
I think we can close this. The important pieces of this discussion have been figured out/implemented.