mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-09-29 17:34:27 -04:00
* Restore the Ruby 4.0.6 upgrade PR #4831 committed a stale Gemfile.lock over the newer one, taking .ruby-version back to 3.2.3 and rolling back active_median, dalli, parallel, rbs and selenium-webdriver. Dockerfile and .devcontainer/Dockerfile still build on Ruby 4, so the Gemfile's version check fails against the image. Restores both files to what they were before that merge. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Upgrade Font Awesome from 5.15.1 to 6.7.2 Font names have moved on twice since this was pinned: the codebase still carried Font Awesome 4 names that render as an empty box, and FA6 icons such as fa-ellipsis-vertical were unavailable. The 6.x gem no longer ships _font-awesome-sprockets.scss, but its @font-face rules still call fa-font-path(), so application.scss defines that against Sprockets' font-path helper. Its fonts live under assets/fonts/font-awesome, which is already in the precompile list. Icon names: - The bare "fa" prefix is not a style in 6. Every "fa fa-<name>" becomes "fas fa-<name>" (38 call sites, all solid; the one brands icon already used fab). - fa-sun-o was a Font Awesome 4 name and had been rendering as a box; now fa-sun. - fa-pencil was likewise broken under 5, where it was fa-pencil-alt. It exists again in 6, so the existing name now works. - activity_icon asked for 'fa-truck-pickup' through a helper that already adds the prefix, so it emitted "fa-fa-truck-pickup". Verified that the solid, regular and brands fonts all resolve through the asset pipeline. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * couple more places to upgrade font awesome --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
86 lines
3.3 KiB
React
86 lines
3.3 KiB
React
import React from 'react';
|
|
|
|
import {formatDate} from '../dates';
|
|
import PlantedDate from './PlantedDate';
|
|
import PlantingChip from './PlantingChip';
|
|
|
|
// One annual planting as a row of two aligned columns: the crop, which is also
|
|
// the planting's menu (and when it was planted), and how it is getting on
|
|
// (badges, then a progress bar or a note when there is nothing to predict from).
|
|
// `handlers` is what the menu's items open (see selectPlantingAction).
|
|
export default function PlantingRow({planting, defaultIconUrl, highlighted, highlightKind = 'added', onUpdated, handlers}) {
|
|
const {badges} = planting;
|
|
|
|
return (
|
|
<div className={`planting-row${highlighted ? ` planting-just-${highlightKind}` : ''}`}>
|
|
<div className="planting-row-crop">
|
|
<div className="planting-row-chip">
|
|
<PlantingChip planting={planting} defaultIconUrl={defaultIconUrl} highlighted={highlighted && highlightKind === 'added'} handlers={handlers} />
|
|
{highlighted && highlightKind === 'harvested' && (
|
|
<span className="harvest-recorded-tag"><i className="fas fa-check" aria-hidden="true" /> Harvest recorded</span>
|
|
)}
|
|
</div>
|
|
<PlantedDate planting={planting} onUpdated={onUpdated} />
|
|
</div>
|
|
<div className="planting-row-status">
|
|
{badges.length > 0 && (
|
|
<div className="planting-badges">
|
|
{badges.map((badge) => (
|
|
<span key={badge.kind} className={`badge text-bg-info badge-${badge.kind.replace('_', '-')}`} title={badge.title}>
|
|
{badge.label}
|
|
</span>
|
|
))}
|
|
</div>
|
|
)}
|
|
{planting.progress_note ? (
|
|
<small className="planting-row-note">{planting.progress_note}</small>
|
|
) : (
|
|
<Progress percentage={planting.percentage_grown} state={planting.progress_state} finishLabel={planting.finish_predicted_label} harvests={planting.harvests} />
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// The bar, with a tick at the date of each harvest, on the bar's own scale.
|
|
// The ticks are for the eye; the hidden sentence is for everything else.
|
|
function Progress({percentage, state, finishLabel, harvests = []}) {
|
|
if (percentage === null || percentage === undefined) return null;
|
|
|
|
const last = harvests[harvests.length - 1];
|
|
|
|
return (
|
|
<div className="planting-progress">
|
|
<div className="planting-progress-track">
|
|
<div className="progress">
|
|
<div
|
|
className={`progress-bar progress-bar--${state}`}
|
|
role="progressbar"
|
|
aria-valuemin="0"
|
|
aria-valuemax="100"
|
|
aria-valuenow={percentage}
|
|
style={{width: `${percentage}%`}}
|
|
/>
|
|
</div>
|
|
{harvests.map((harvest, index) => (
|
|
<span
|
|
key={`${harvest.date}-${index}`}
|
|
className="harvest-tick"
|
|
style={{left: `${harvest.percent}%`}}
|
|
title={`Harvested ${formatDate(harvest.date)}`}
|
|
/>
|
|
))}
|
|
</div>
|
|
{last && (
|
|
<span className="visually-hidden">
|
|
{harvests.length} {harvests.length === 1 ? 'harvest' : 'harvests'}, the latest on {formatDate(last.date)}
|
|
</span>
|
|
)}
|
|
<div className="planting-progress-labels">
|
|
<span>{Math.round(percentage)}%</span>
|
|
{finishLabel && <span>{finishLabel}</span>}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|