Issues with Crop Planning Module

I mentioned this on last weeks dev call and most noticeably there is a styling problem but it is not a simple css fix.

My setup: Docker install of FarmOS: 3.4.6 on laptop running Ubuntu 24.04.3 LTS

Starting with a brand new plan for a bed 1 in plot 1 with only one plant asset added

Issues with left column

  • has white background despite dark theme selected

  • x-overflow is 1 line above so obscures asset name

  • on inspection this is a hard coded padding-bottom : 15px in the div with a class of sg-table-body

  • if the divider is moved to show full name it looks OK as the scroll bar is not shown

  • items in list appear only in the order they were added, not alphabetical, sortable or draggable.

strange actions on rhs

  • click on year => rhs expands to end Dec, but only from Feb in this example. Also unable to return to previous spanned layout without page reload
  • click on a month => rhs expands to just that month, for example “April”, no return to previous view possible.
  • Now Click in year => only shows from Apr to Dec, only page refresh enables showing of earlier months
  • It appears that the bars on rhs don’t consistently line up with the plantings on lhs

some suggessstions

  • I have not discovered where the white background comes from, ideally it should pick up the gin theme light/dark settings.
  • Row height seems to be fixed at 34px from close to the end of the file farmOS-timeline.js. Those values are the same as from the file in the git repo https://github.com/mstenta/farmOS-timeline/blob/main/src/instance.js but could the values be in keeping with the layout density setting from the gin theme.
  • I have not ascertained where the padding-bottom: 15px , mentioned above, comes from!
  • The plant assets added to the plan could be displayed in the table structure used to show the different assets , logs, purchases etc. Could this table be shown sorted alphabetically by plant_type (crop/variety) or by location or another field and then that order used to display the gantt timelines. Also the tabular layout would enabling the bulk actions at the bottom.
1 Like

1 Like

Thanks for documenting these issues @waterleat! I’ve run into some of them too, and haven’t had time to dig in and debug. I’ll leave some info/ideas in case anyone else wants to try…

Disclaimer: The farmOS Crop Plan module is still in “alpha” - but does not have dedicated funding, so any volunteer help is welcome!

First, these are the main “components” involved:

  • svelte-gantt - This is the client-side Javascript library that we depend on. It handles almost all of the gantt visualization rendering. It provides a lot of options, and ultimately determines what capabilities we have. This means we also inherit bugs from this library, so some of the issues we’re encountering may require opening upstream bug reports.
  • farmOS-timeline.js - This is a client-side JS library that we built as a wrapper around svelte-gantt (similar to how we built farmOS-map.js as a wrapper around OpenLayers). It is managed in a separate repository from farmOS itself, in case anyone wants to use it in third-party/client-side apps (also similar to farmOS-map.js). It is very simple, and basically serves these purposes:
    1. Provides standardized functions for creating and managing instances of svelte-gantt objects in a global window.farmOS.timeline variable. This is ultimately what runs new SvelteGantt() with preset options.
    2. Provides a standard addTask() method for adding “tasks” (aka colored timeline bars) to the gantt (while also handling things like updating the timeline range, “past” highlighting, etc).
    3. Provides a build process (via GitHub Actions) that runs npm run build to create versioned releases of farmOS-timeline.js that we can then pull into farmOS itself here: farmOS/composer.libraries.json at cf7885d2f53f361319bda6ae2fde02dd4f2a2ab9 · farmOS/farmOS · GitHub (farmOS does not have any Javascript build tooling itself, and only downloads the pre-built JS files it needs). This makes the Javascript available for modules within farmOS to use.
  • farm_timeline module - This is an “experimental” module that is included in farmOS core (as of v3.3.0), which provides the connection between farmOS-timeline.js and Drupal/PHP. This serves a couple of purposes:
    1. This is the core module that other modules (both farmOS core modules and community add-on modules) can depend on if they want to use the timeline features. The Crop Planning and Grazing Planning modules both list it as a dependency in their [module].info.yml (eg: farm_crop_plan/farm_crop_plan.info.yml at 2878201463a377aa190df44024acf8ade6eab2cb · mstenta/farm_crop_plan · GitHub)
    2. It provides a Drupal RenderElement type called farm_timeline, so that timelines can be added to Drupal render arrays that are used to build HTML. This also adds timeline-specific CSS and JS to any page that includes a farm_timeline render element (see below).
    3. It adds the following CSS on top of the default svelte-gantt styles: farmOS/modules/core/timeline/css/farm_timeline.css at 4.x · farmOS/farmOS · GitHub
    4. It provides a Drupal Javascript behavior that is responsible for attaching a farmOS-timeline instance to a specific HTML DOM element, and logic for adding tasks to the timeline (using the addTask() method described above), and creating popups: farmOS/modules/core/timeline/js/farm_timeline.js at 4.x · farmOS/farmOS · GitHub
  • farmOS Crop Plan module - This adds the concept of a crop plan, and leverages all of the above to insert a timeline gantt render element at the top of /plan/[id] pages that renders plant assets and their logs as colored bars on the timeline.

It may seem like a lot of separate pieces (it is!) but this allows us to build timelines in many different contexts, both inside and outside of farmOS core (via separation of concerns).

Also, for cross-reference, here is the thread where all of this started: farmOS Crop Plan module v3 alpha release

I will cross-link to this thread from there as well…

Now for some quick thoughts on specific issues that you outlined, @waterleat:

It’s promising to see that most of the timeline appears to adapt to dark mode - is it just the left column that doesn’t?

We might be able to fix this ourselves in the farm_timeline module. I would assume that the Gin theme provides some sort of indicator that dark mode is in use, which we can presumably use in our own CSS to alter the svelte-gantt colors.

I would also be curious if there are any open issues/requests for the svelte-gantt library to support dark mode itself. I couldn’t find any in GitHub · Where software is built

I was frustrated by this issue myself when I was developing the first pass at these pieces, and it seemed to be an upstream issue that I couldn’t figure out. I ended up trying to solve it with some CSS in farm_timeline.css (in farmOS core), but it was hard because it depended a lot of what assets (and how many) were included. So this needs more investigation…

This must be coming from the svelte-gantt library. We aren’t adding this in any of the farmOS modules/libraries (as far as I can tell).

This is also default behavior from the svelte-gantt library - although we can probably play with the default width in our CSS. The challenge is that asset name lengths are unpredictable, and I’m not sure if there’s any way we can measure them and update the width via CSS/JS… or if we would want to, because the wider we get the more it eats into the timeline.

This is something we can decide how to handle ourselves in the farmOS Crop Plan module.

However, if I remember correctly, they are currently sorted by where they appear on the timeline, so that the top rows “happen first” and the bottom rows “happen last”, thus providing you with a sensible “cascade” visualization from top to bottom, left to right, showing how your season will roll out visually.

If we sorted alphabetically, the timeline bars would end up randomly all over the place. It may still be useful for finding plantings in a big list, but if we add this then we should make it a secondary option that you have to click to change IMO.

These are all behaviors (and maybe bugs) of the svelte-gantt library, as far as I can tell.

For what it’s worth, we decided to use svelte-gantt because it seemed to be the only JS library that met our needs and was actively maintained.

That said, it hasn’t been updated in 10 months, and this question from 2 weeks ago is unanswered:

This project looks really promising and i have a perfect use case for it. Question is: Is it maintained and alive?

We intentionally designated the farm_timeline module as experimental in farmOS core because of the uncertainty around this upstream dependency.

It would be a shame if we had to drop it due to bugs and lack of maintenance.

The other idea I considered when we were researching options was to write our own SVG-based timeline rendering logic directly in PHP, without any JS library dependencies. That would give us the most flexibility, but at the expense of a) maintenance, and b) client-side JS interactivity (which could also be added/maintained by us).

I just did a quick search and found this: GitHub - frappe/gantt: Open Source Javascript Gantt

Not sure if we saw that one previously… it seems like it is more widely used and maintained. :thinking:

Just to say: the other benefit of separating all the pieces like this is we can potentially swap out the upstream dependency inside the farmOS-timeline.js library to use something different.

The “separation of concerns” in our current implementation isn’t perfect… we would still need to make changes in farmOS and farmOS Crop Plan / farmOS Grazing Plan, since those have some baked in assumptions that svelte-gantt is being used… but maybe it’s worth considering.

Hi All. Long-time lurker, first-time poster (I think).

Please redirect me if I’m not following the complete context, but…

You may also have the option to “clip” asset names with text-overflow: ellipsis; and add something like a tooltip to show full name on hover. Or, force the asset name to wrap to the next line with white-space: wrap; so that the height of the element increases without causing the horizontal / left-to-right scrollbar to appear.

It’s a workaround, but to my memory, those are the most easily-reachable alternatives.

Hoping 2026 allows some time for me to contribute, but I’ll settle to reading for the moment.

Happy Holidays, Louis

1 Like

I have a working solution to the alphabetical ordering.

in file /www/web/modules/farm_crop_plan/src/Controller/CropPlanTimeline.php

in the public function byPlantType(PlanInterface $plan) starts about line 100. Find the first foreach line

`foreach ($`crop_plantings_by_type` as $plant_type_id => $crop_plantings) {`

and replace with

    // Start of sorting aphabetically by the plant_type taxonomy term name
    $plant_type_tids = array_keys($crop_plantings_by_type);

    // Load all the taxonomy terms in one efficient query
    $terms = Term::loadMultiple($plant_type_tids);

    // Build a mapping of TID => term name (lowercase for case-insensitive sorting)
    $tid_to_name = [];
    foreach ($terms as $tid => $term) {
      $tid_to_name[$tid] = strtolower($term->label()); // or $term->getName()
    }

    // Sort the TIDs by the term name
    $sorted_tids = array_keys($crop_plantings_by_type);
    uasort($sorted_tids, function ($tid_a, $tid_b) use ($tid_to_name) {
      return $tid_to_name[$tid_a] <=> $tid_to_name[$tid_b];
    });

    // Build the sorted array
    $sorted_plan_records = [];
    foreach ($sorted_tids as $tid) {
      $sorted_plan_records[$tid] = $crop_plantings_by_type[$tid];
    }

    // Now $sorted_plan_records is sorted by plant_type name alphabetically

    foreach ($sorted_plan_records as $plant_type_id => $crop_plantings) {

this fixes my desire to see all of my broad beans together

Please fell free to comment and improve

PS. the way the css is produced is beyond my current skill level

1 Like

Forgot to mention this patch needs

use Drupal\taxonomy\Entity\Term;

now I will try to order the display by location

1 Like

It’s a workaround, but to my memory, those are the most easily-reachable alternatives.

Thanks for the suggestions @louis! Definitely worth looking into these ideas! Let me know if you need help setting up a local instance to test with. :slight_smile:

@waterleat I can’t help but notice that your “Plant types” are:

  • Broad Bean / Spring Sown / …
  • Broad Bean: 5) Main crop
  • Broad Bean: All Year Round

Why don’t you just have a single plant type called “Broad Bean”, instead? That would group all of your plants together.

The intention of the “Plant type” taxonomy is to list species/varieties of plants. It is not intended to include other qualifiers like “main crop” / “spring sown” / “all year round”. It seems like you could use “Season” terms for some of those instead.

For example: the “Feb26 b01-p01 Broad Beans…” planting could have a Plant Type of “Broad Beans” and a Season of “2025 Spring”.

Yes I agree that the plant_type names are inconsistent. I had assumed that it was holding data like succession plantings for autumn or spring sowings.

The term plant_type and the synonym crop/variety are confusing. I understand that this has evolved over time and different farms have completely different requirements.

I notice that the seed asset which is tied to the plant’s variety_name is not incorporated in the planting_record which leads to more confusion in my head. The wife says that is easily done, but then she is a Luddite when it comes to computers.

@mstenta I remember you saying that you have to know what data you want to record for your own farm, but finding how that fits into the farmos system is the key. I have taken this study to try to understand how the Drupal system works with all those .yml files and multiple modules. Still WIP!

1 Like

Yea, it was originally just called “Crop/variety”, and we changed the “machine name” to plant_type in v2, but kept the “Crop/variety” as the label for it. The intention is for this to be equivalent to the animal_type (“Species/breed”) term reference field on Animal assets.

I’m not sure I understand 100% what you mean, but FWIW: the seed asset was added later as a way to track seed inventory. So the idea is, you can create Seed assets for each “Crop/variety” (plant_type) that you have, use purchase logs to increment their inventory, and seeding logs to decrement them. The seeding log should only reference the seed asset in the inventory_asset field of the quantity, though, while the seeding log itself would reference a plant asset in its asset field. Thus, you can represent that one or more plant assets were “created” from a single seed asset (eg: you may plant your seeds in multiple places, or over multiple years). So the seed asset is managed separately from the plant asset. The log then basically represents something like “15 seeds were taken from the Cherry Tomato seed asset, and planted into Bed 1 (in the location reference), to create the 2025 Cherry Tomato plant asset”.

Recording that kind of log is a manual process right now. The Planting quick form does not have any knowledge of seed assets or inventory adjustments (yet), but that would be a great next step for it IMO. Then you could use the Planting quick form to select a Seed asset, decrement its inventory, and create a Plant asset and Seeding log (and optionally a Transplanting and Harvest log) all in one step.

Yes, and worth emphasizing: you don’t need to track seed inventory to use farmOS. But the data model is there if you want to. We still need to add more UI forms/helpers for those kinds of things, which will help to make it more obvious how it is meant to work.