From 4fd89f78b9cecbb37ed83790ac6dc9b148fee8f3 Mon Sep 17 00:00:00 2001 From: Jurriaan Roelofs Date: Tue, 27 Jan 2026 13:40:36 +0100 Subject: [PATCH 1/2] docs: add Plotly.js installation instructions to README The status report references the README for installation details, but the documentation was missing. Add CLI commands for: - Asset Packagist repository configuration - oomphinc/composer-installers-extender setup - Plotly.js installation Closes #21 --- README.md | 20 ++++++++++++++++++++ rl.install | 4 ++-- src/Controller/ReportsController.php | 9 +++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2f3903f..9bd5d37 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,26 @@ composer require drupal/rl drush en rl ``` +### Plotly.js Library (Required for Charts) + +The RL module uses Plotly.js for experiment charts. Install it via Composer using +[Asset Packagist](https://asset-packagist.org): + +```bash +# Add Asset Packagist repository (if not already configured) +composer config repositories.asset-packagist composer https://asset-packagist.org + +# Install the Composer plugin for npm assets (if not already installed) +composer require oomphinc/composer-installers-extender +composer config extra.installer-types --json '["npm-asset"]' +composer config extra.installer-paths.web/libraries/\{\$name\} --json '["type:npm-asset"]' + +# Install Plotly.js +composer require npm-asset/plotly.js-dist-min:^2.35 +``` + +This installs the library to `web/libraries/plotly.js-dist-min/`. + ### Post-Installation: Verify rl.php Access The RL module includes a `.htaccess` file that allows direct access to diff --git a/rl.install b/rl.install index bec40b4..fc9e93b 100644 --- a/rl.install +++ b/rl.install @@ -435,8 +435,8 @@ function rl_requirements($phase) { if ($phase == 'runtime') { // Check if Plotly.js library is installed. - $plotly_path = DRUPAL_ROOT . '/libraries/plotly.js-dist-min/plotly.min.js'; - if (!file_exists($plotly_path)) { + $library_finder = \Drupal::service('library.libraries_directory_file_finder'); + if (!$library_finder->find('plotly.js-dist-min/plotly.min.js')) { $requirements['rl_plotly_library'] = [ 'title' => t('RL: Plotly.js library'), 'severity' => REQUIREMENT_ERROR, diff --git a/src/Controller/ReportsController.php b/src/Controller/ReportsController.php index 1977d2a..7e845f0 100644 --- a/src/Controller/ReportsController.php +++ b/src/Controller/ReportsController.php @@ -243,6 +243,15 @@ public function experimentDetailTitle($experiment_id) { * A render array. */ public function experimentDetail($experiment_id) { + // Check if Plotly.js library is installed. + $library_finder = \Drupal::service('library.libraries_directory_file_finder'); + if (!$library_finder->find('plotly.js-dist-min/plotly.min.js')) { + $status_url = Url::fromRoute('system.status')->toString(); + $this->messenger()->addWarning($this->t('Charts require the Plotly.js library. See Status report for installation instructions.', [ + '@url' => $status_url, + ])); + } + // Get experiment totals from storage. $experiment_totals = $this->experimentStorage->getExperimentTotals($experiment_id); From 4b7b59287294087f393d0389a57cbeffd045a3bb Mon Sep 17 00:00:00 2001 From: Jurriaan Roelofs Date: Tue, 27 Jan 2026 21:47:03 +0100 Subject: [PATCH 2/2] fix: use dependency injection for library finder in ReportsController Replace \Drupal::service() call with injected LibrariesDirectoryFileFinder to follow Drupal coding standards. --- src/Controller/ReportsController.php | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Controller/ReportsController.php b/src/Controller/ReportsController.php index 7e845f0..ad7cb84 100644 --- a/src/Controller/ReportsController.php +++ b/src/Controller/ReportsController.php @@ -3,6 +3,7 @@ namespace Drupal\rl\Controller; use Drupal\Component\Utility\Html; +use Drupal\Core\Asset\LibrariesDirectoryFileFinder; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Datetime\DateFormatterInterface; use Drupal\Core\Link; @@ -70,6 +71,13 @@ class ReportsController extends ControllerBase { */ protected RequestStack $requestStack; + /** + * The libraries directory file finder. + * + * @var \Drupal\Core\Asset\LibrariesDirectoryFileFinder + */ + protected LibrariesDirectoryFileFinder $libraryFinder; + /** * Constructs a ReportsController object. * @@ -87,8 +95,10 @@ class ReportsController extends ControllerBase { * The snapshot storage. * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack * The request stack. + * @param \Drupal\Core\Asset\LibrariesDirectoryFileFinder $library_finder + * The libraries directory file finder. */ - public function __construct(ExperimentDataStorageInterface $experiment_storage, DateFormatterInterface $date_formatter, ExperimentDecoratorManager $decorator_manager, RendererInterface $renderer, ArmDataValidator $arm_data_validator, SnapshotStorageInterface $snapshot_storage, RequestStack $request_stack) { + public function __construct(ExperimentDataStorageInterface $experiment_storage, DateFormatterInterface $date_formatter, ExperimentDecoratorManager $decorator_manager, RendererInterface $renderer, ArmDataValidator $arm_data_validator, SnapshotStorageInterface $snapshot_storage, RequestStack $request_stack, LibrariesDirectoryFileFinder $library_finder) { $this->experimentStorage = $experiment_storage; $this->dateFormatter = $date_formatter; $this->decoratorManager = $decorator_manager; @@ -96,6 +106,7 @@ public function __construct(ExperimentDataStorageInterface $experiment_storage, $this->armDataValidator = $arm_data_validator; $this->snapshotStorage = $snapshot_storage; $this->requestStack = $request_stack; + $this->libraryFinder = $library_finder; } /** @@ -114,7 +125,8 @@ public static function create(ContainerInterface $container): static { $container->get('renderer'), $container->get('rl.arm_data_validator'), $container->get('rl.snapshot_storage'), - $container->get('request_stack') + $container->get('request_stack'), + $container->get('library.libraries_directory_file_finder') ); } @@ -244,8 +256,7 @@ public function experimentDetailTitle($experiment_id) { */ public function experimentDetail($experiment_id) { // Check if Plotly.js library is installed. - $library_finder = \Drupal::service('library.libraries_directory_file_finder'); - if (!$library_finder->find('plotly.js-dist-min/plotly.min.js')) { + if (!$this->libraryFinder->find('plotly.js-dist-min/plotly.min.js')) { $status_url = Url::fromRoute('system.status')->toString(); $this->messenger()->addWarning($this->t('Charts require the Plotly.js library. See Status report for installation instructions.', [ '@url' => $status_url,