diff --git a/CHANGELOG.md b/CHANGELOG.md index c0602cebd6..ea843bcc56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### New features + +- [#2351: Build the basic plugin details page](https://github.com/alphagov/govuk-prototype-kit/pull/2351) + ### Fixes - [#2357: Simplify and improve acceptance tests](https://github.com/alphagov/govuk-prototype-kit/pull/2357) diff --git a/cypress/e2e/plugins/plugin-utils.js b/cypress/e2e/plugins/plugin-utils.js index 8a8416ab16..45c90b2604 100644 --- a/cypress/e2e/plugins/plugin-utils.js +++ b/cypress/e2e/plugins/plugin-utils.js @@ -42,22 +42,21 @@ function provePluginTemplatesUninstalled (plugin) { } function initiatePluginAction (action, plugin, pluginName, options = {}) { - if (action === 'install') { - cy.visit(managePluginsPagePath) - } else { - cy.visit(manageInstalledPluginsPagePath) - } + cy.visit(managePluginsPagePath) if (pluginName) { cy.get(`[data-plugin-package-name="${plugin}"]`) .scrollIntoView() - .find('h4') + .find('a') .contains(pluginName) } cy.get(`[data-plugin-package-name="${plugin}"]`) .scrollIntoView() - .find('button') + .find('a') + .click() + + cy.get('button') .contains(capitalize(action)) .click() @@ -73,7 +72,7 @@ function provePluginInstalled (plugin, pluginName) { if (pluginName) { cy.get(`[data-plugin-package-name="${plugin}"]`) .scrollIntoView() - .find('h4') + .find('a') .contains(pluginName) } @@ -91,7 +90,7 @@ function provePluginUninstalled (plugin, pluginName) { if (pluginName) { cy.get(`[data-plugin-package-name="${plugin}"]`) .scrollIntoView() - .find('h4') + .find('a') .contains(pluginName) } @@ -108,7 +107,10 @@ function provePluginUpdated (plugin, pluginName) { provePluginInstalled(plugin, pluginName) cy.get(`[data-plugin-package-name="${plugin}"]`) .scrollIntoView() - .find('button') + .find('a') + .click() + + cy.get('button') .contains(capitalize('update')).should('not.exist') } @@ -117,10 +119,13 @@ function provePluginInstalledOldVersion (plugin, pluginName) { if (pluginName) { cy.get(`[data-plugin-package-name="${plugin}"]`) .scrollIntoView() - .find('h4') + .find('a') .contains(pluginName) } + cy.get(`[data-plugin-package-name="${plugin}"] strong.govuk-tag`) + .contains('Update available') + cy.get('#installed-plugins-link').click() cy.get(`[data-plugin-package-name="${plugin}"]`) diff --git a/lib/assets/sass/manage-prototype.scss b/lib/assets/sass/manage-prototype.scss index 977587e8a3..979d48a9fd 100644 --- a/lib/assets/sass/manage-prototype.scss +++ b/lib/assets/sass/manage-prototype.scss @@ -440,6 +440,15 @@ body .govuk-prototype-kit-manage-prototype-govuk-tag { padding-left: 0 !important; } +.govuk-prototype-kit-manage-prototype-plugin-heading { + margin-bottom: 0; +} + +.govuk-prototype-kit-manage-prototype-plugin-sub-heading { + color: #505a5f; + margin-bottom: 15px; +} + .govuk-prototype-kit-manage-prototype-plugin-list-plugin-list { border-top: 1px solid #b1b4b6; margin-bottom: 2em; @@ -574,3 +583,10 @@ body .govuk-prototype-kit-manage-prototype-govuk-tag { } } } + +.govuk-prototype-kit-manage-prototype-plugin-details-links { + padding-top: 20px; + margin-bottom: 20px; + border-top: 2px solid #b1b4b6; + border-bottom: 2px solid #b1b4b6; +} diff --git a/lib/manage-prototype-handlers.js b/lib/manage-prototype-handlers.js index 8c5b50c3be..258d16da2f 100644 --- a/lib/manage-prototype-handlers.js +++ b/lib/manage-prototype-handlers.js @@ -411,13 +411,14 @@ function buildPluginData (pluginData) { packageName, latestVersion, installedLocally, - installLink: `${contextPath}/plugins/install?package=${encodeURIComponent(packageName)}`, + installLink: installedVersion ? undefined : `${contextPath}/plugins/install?package=${encodeURIComponent(packageName)}`, installCommand: `npm install ${packageName}`, updateLink: installed && !installedLocally && latestVersion !== installedVersion ? `${contextPath}/plugins/update?package=${encodeURIComponent(packageName)}` : undefined, updateCommand: latestVersion && `npm install ${packageName}@${latestVersion}`, uninstallLink: installed && !required ? `${contextPath}/plugins/uninstall?package=${encodeURIComponent(packageName)}${installedLocally ? `&version=${encodeURIComponent(localVersion)}` : ''}` : undefined, uninstallCommand: `npm uninstall ${packageName}`, - installedVersion + installedVersion, + inThisPlugin: getInThisPluginDetails(pluginConfig) } } @@ -436,7 +437,7 @@ async function prepareForPluginPage (isInstalledPage, search) { status: isInstalledPage ? 'installed' : 'search', plugins: plugins.map(buildPluginData), found: plugins.length, - updates: installedPlugins.filter(plugin => plugin.installedVersion !== plugin.latestVersion).length + updates: installedPlugins.filter(plugin => !plugin.installedLocally && plugin.installedVersion !== plugin.latestVersion).length } } @@ -567,6 +568,24 @@ async function getPluginForRequest (req) { return chosenPlugin } +function getInThisPluginDetails (pluginConfig) { + const { nunjucksMacros = [], templates = [] } = pluginConfig || {} + const list = [] + if (nunjucksMacros?.length) { + list.push({ + title: 'Components', + items: nunjucksMacros.map(({ macroName }) => macroName) + }) + } + if (templates?.length) { + list.push({ + title: 'Templates', + items: templates.map(({ name }) => name) + }) + } + return list +} + function modeIsComplete (mode, { installedVersion, latestVersion, version, installedLocally }) { switch (mode) { case 'update': @@ -726,6 +745,19 @@ async function postPluginsModeHandler (req, res) { res.json({ status }) } +async function getPluginDetailsHandler (req, res) { + const packageName = req.query.package + const plugin = await lookupPackageInfo(packageName) + const { name, scope, installedVersion, latestVersion, ...pluginData } = buildPluginData(plugin) + const viewData = { + ...pluginData, + installedVersion, + latestVersion, + plugin: { name, scope, version: installedVersion || latestVersion } + } + res.render(getManagementView('plugin-details.njk'), viewData) +} + module.exports = { contextPath, setKitRestarted, @@ -749,5 +781,6 @@ module.exports = { getPluginsModeHandler, postPluginsStatusHandler, postPluginsModeMiddleware, - postPluginsModeHandler + postPluginsModeHandler, + getPluginDetailsHandler } diff --git a/lib/manage-prototype-handlers.test.js b/lib/manage-prototype-handlers.test.js index b2b3b010b6..764b9e332e 100644 --- a/lib/manage-prototype-handlers.test.js +++ b/lib/manage-prototype-handlers.test.js @@ -412,7 +412,8 @@ describe('manage-prototype-handlers', () => { name: pluginDisplayName.name, packageName, uninstallCommand: `npm uninstall ${packageName}`, - updateCommand: `npm install ${packageName}@${latestVersion}` + updateCommand: `npm install ${packageName}@${latestVersion}`, + inThisPlugin: [] } beforeEach(() => { diff --git a/lib/manage-prototype-routes.js b/lib/manage-prototype-routes.js index 42c824c03e..e3147d1880 100644 --- a/lib/manage-prototype-routes.js +++ b/lib/manage-prototype-routes.js @@ -24,7 +24,8 @@ const { postPluginsModeHandler, postPluginsStatusHandler, pluginCacheMiddleware, - postPluginsHandler + postPluginsHandler, + getPluginDetailsHandler } = require('./manage-prototype-handlers') const { packageDir, projectDir } = require('./utils/paths') const { govukFrontendPaths } = require('./govukFrontendPaths') @@ -79,6 +80,8 @@ router.post('/plugins/:mode', postPluginsModeMiddleware) router.post('/plugins/:mode', csrfProtection, postPluginsModeHandler) +router.get('/plugin-details', getPluginDetailsHandler) + // Find GOV.UK Frontend (via internal package, project fallback) router.use('/dependencies/govuk-frontend', express.static( govukFrontendPaths([packageDir, projectDir]).baseDir) diff --git a/lib/nunjucks/views/manage-prototype/plugin-details.njk b/lib/nunjucks/views/manage-prototype/plugin-details.njk new file mode 100644 index 0000000000..ce5c4ec475 --- /dev/null +++ b/lib/nunjucks/views/manage-prototype/plugin-details.njk @@ -0,0 +1,90 @@ +{% extends "views/manage-prototype/layout.njk" %} +{% from "govuk/components/button/macro.njk" import govukButton %} + +{% block beforeContent %} + {{ super() }} + Back to plugins +{% endblock %} + +{% block content %} +
+ {% include "views/manage-prototype/plugin-header.njk" %} + +
+
+ {% if newerLink %} +

Latest version: {{ newerVersion }}

+ {% endif %} + {% if installedLinkAsDifferentLink %} +

Installed version: {{ installedLinkAsDifferentVersion }}

+ {% endif %} + +
+
+ {% if installLink %} + {{ govukButton({ + html: 'Install ' + plugin.name + '', + attributes: { id: "install-" + packageName, formaction: installLink } + }) }} + {% endif %} + {% if updateLink %} + {{ govukButton({ + html: 'Update ' + plugin.name + '', + attributes: { id: "update-" + packageName, formaction: updateLink } + }) }} + {% endif %} + {% if uninstallLink %} + {{ govukButton({ + html: 'Uninstall ' + plugin.name + '', + classes: "govuk-button--secondary", + attributes: { id: "uninstall-" + packageName, formaction: uninstallLink } + }) }} + {% endif %} +
+
+ + {% if plugin.releaseDateTime or preparedPluginLinks.releaseNotes or preparedPluginLinks.versionHistory %} + + {% endif %} +

Report

+ {% if debugInfo %} +
+                   {{ debugInfo }}
+                  
+ {% endif %} +
+ +
+

About this plugin

+ +

{{ description | default('No description has been provided.') }}

+ + {% if preparedPluginLinks.documentation %} +

How to use this plugin

+ {% endif %} + + {% if inThisPlugin.length %} +

Included in this plugin

+ {% for section in inThisPlugin %} +

{{ section.title }}

+
    + {% for item in section.items %} +
  • {{ item }}
  • + {% endfor %} +
+ {% endfor %} + {% endif %} +
+
+
+{% endblock %} diff --git a/lib/nunjucks/views/manage-prototype/plugin-header.njk b/lib/nunjucks/views/manage-prototype/plugin-header.njk new file mode 100644 index 0000000000..89466e5701 --- /dev/null +++ b/lib/nunjucks/views/manage-prototype/plugin-header.njk @@ -0,0 +1,9 @@ +
+
+

{{ plugin.name }}

+

v{{ plugin.version }}

+ {% if plugin.scope %} +

By {{ plugin.scope }}

+ {% endif %} +
+
diff --git a/lib/nunjucks/views/manage-prototype/plugins.njk b/lib/nunjucks/views/manage-prototype/plugins.njk index 1cb2129512..f8cc8e1ade 100644 --- a/lib/nunjucks/views/manage-prototype/plugins.njk +++ b/lib/nunjucks/views/manage-prototype/plugins.njk @@ -5,46 +5,47 @@ {% from "govuk/components/tag/macro.njk" import govukTag %} {% block content %} -
-
-
-

Plugins

-

- Plugins provide you with new components, styles and other features -

-
+
+
+

Plugins

+

+ Plugins provide you with new components, styles and other features +

+
-
-
- {% if isSearchPage %} - - - {% else %} - - - {% endif %} - {% if updatesMessage %} - {{ govukTag({ - text: updatesMessage - }) }} - {% endif %} -
+
+
+ {% if isSearchPage %} + + + {% else %} + + + {% endif %} + {% if updatesMessage %} + {{ govukTag({ + text: updatesMessage + }) }} + {% endif %} +
-
- {% if isSearchPage %} +
+ {% if isSearchPage %}
{{ govukLabel({ @@ -78,31 +79,39 @@ {{ foundMessage }}
- {% endif %} + {% endif %} -
    - {% for plugin in plugins %} -
  • +
      + {% for plugin in plugins %} +
    • -
      -

      - {{ plugin.name }} -

      - {% if plugin.scope %} -
      - By {{ plugin.scope }} -
      - {% endif %} - {% if plugin.installedVersion %} -
      - v{{ plugin.installedVersion }} -
      - {% endif %} -
      -
      - {% if isSearchPage and plugin.installedVersion %} +
      + + {{ plugin.name }} + + {% if plugin.scope %} +
      + By {{ plugin.scope }} +
      + {% endif %} + {% if plugin.installedVersion %} +
      + version {{ plugin.installedVersion }} +
      + {% endif %} +
      +
      +
      + {% if plugin.updateLink %} +

      + {{ govukTag({ + text: "Update available" + }) }} +

      + {% elseif isSearchPage and plugin.installedVersion %}

      {{ govukTag({ text: "Installed", @@ -110,46 +119,16 @@ }) }}

      {% endif %} - {% if plugin.description %} -
      - {{ plugin.description }} -
      - {% endif %} -
      -
      - {% if not plugin.installedVersion %} - {{ govukButton({ - html: 'Install ' + plugin.name + '', - attributes: { id: "install-" + plugin.packageName, formaction: plugin.installLink } - }) }} - {% endif %} - {% if isInstalledPage %} - {% if plugin.updateLink %} - {{ govukButton({ - html: 'Update ' + plugin.name + '', - attributes: { id: "update-" + plugin.packageName, formaction: plugin.updateLink } - }) }} - {% endif %} - {% if plugin.uninstallLink %} - {{ govukButton({ - html: 'Uninstall ' + plugin.name + '', - classes: "govuk-button--secondary", - attributes: { id: "uninstall-" + plugin.packageName, formaction: plugin.uninstallLink } - }) }} - {% endif %} - {% endif %} - {% if plugin.helpLink %} - Help - {{ plugin.name }} - {% endif %} -
      -
      -
    • - {% endfor %} -
    -
+ {% if plugin.description %} +
+ {{ plugin.description }} +
+ {% endif %} +
+ + {% endfor %} +
- +
{% endblock %}