Skip to content

Commit

Permalink
feat: add version overview customization - refs #264531
Browse files Browse the repository at this point in the history
  • Loading branch information
dana-cfc4 committed Mar 14, 2024
1 parent 656cfa7 commit 7a63c94
Show file tree
Hide file tree
Showing 6 changed files with 354 additions and 1 deletion.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@

## Features

Demo GIF
Volto-cotrolpanel presents an overview of all frontend and backend packages used and their versions

![Volto Control Panel](https://raw.githubusercontent.com/eea/volto-controlpanel/version-overview/docs/volto-controlpanel.gif)

## Getting started

Expand Down
Binary file added docs/volto-controlpanel.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/**
* Version Overview component.
* @module components/manage/Controlpanels/VersionOverview
*/

import React from 'react';
import { FormattedMessage } from 'react-intl';
import { Grid, Label, Header } from 'semantic-ui-react';
import { formatDate } from '@plone/volto/helpers/Utils/Date';
import packageJson from '@plone/volto/../package.json';

import config from '@plone/volto/registry';

const VersionOverview = ({
cmf_version,
debug_mode,
pil_version,
plone_version,
plone_restapi_version,
python_version,
zope_version,
eggs = {},
frontend = {},
backend = {},
}) => {
const { addonsInfo } = config.settings;
const locale = config.settings.dateLocale || 'en-gb';
const frontendVersion = frontend.version || config.settings.frontendVersion;
const backendVersion = backend.version || config.settings.backendVersion;
const voltoVersion = packageJson.version;

return (
<Grid columns={2} stackable>
<Grid.Row>
<Grid.Column>
{frontend.date && (
<Label className="highlight" ribbon>
Updated:{' '}
{formatDate({
date: frontend.date,
format: {
dateStyle: 'medium',
timeStyle: 'short',
},
locale: locale,
})}{' '}
</Label>
)}
<Header as="h3">
<span>Frontend {frontendVersion ? frontendVersion : ''}</span>
</Header>
{frontendVersion && (
<a
href={[
config.settings.changelogUrlPrefix,
config.settings.frontendName,
config.settings.changelogUrlSuffix,
].join('/')}
target="_blank"
rel="noreferrer"
>
History: {frontend.old_version}{frontendVersion}
</a>
)}
<ul style={{ fontSize: '16px', fontFamily: 'Monospace' }}>
{voltoVersion && <li>Volto {voltoVersion}</li>}
{addonsInfo.map((addon) => (
<li key={addon.name}>{`${addon.name} ${addon.version || ''}`}</li>
))}
</ul>
</Grid.Column>
<Grid.Column>
{backend.date && (
<Label className="high" ribbon="right">
Updated:{' '}
{formatDate({
date: backend.date,
format: {
dateStyle: 'medium',
timeStyle: 'short',
},
locale: locale,
})}
</Label>
)}
<Header as="h3" textAlign="right">
Backend {backendVersion ? backendVersion : ''}
</Header>
<a
className="ui right aligned container"
href={[
config.settings.changelogUrlPrefix,
config.settings.backendName,
config.settings.changelogUrlSuffix,
].join('/')}
target="_blank"
rel="noreferrer"
>
History: {backend.old_version}{backendVersion}
</a>
<ul
style={{
fontSize: '16px',
fontFamily: 'Monospace',
}}
>
<li>Plone {plone_version}</li>
<li>plone.restapi {plone_restapi_version}</li>
<li>CMF {cmf_version}</li>
<li>Zope {zope_version}</li>
<li>Python {python_version}</li>
<li>PIL {pil_version}</li>
{Object.keys(eggs).map((k) => (
<li>
{k} {eggs[k]}
</li>
))}
</ul>
</Grid.Column>
</Grid.Row>
<Grid.Row columns={1}>
<Grid.Column>
{debug_mode !== 'No' && (
<p>
<FormattedMessage
id="Warning Regarding debug mode"
defaultMessage="You are running in 'debug mode'. This mode is intended for sites that are under development. This allows many configuration changes to be immediately visible, but will make your site run more slowly. To turn off debug mode, stop the server, set 'debug-mode=off' in your buildout.cfg, re-run bin/buildout and then restart the server process."
/>
</p>
)}
</Grid.Column>
</Grid.Row>
</Grid>
);
};

export default VersionOverview;
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import React from 'react';
import { render } from '@testing-library/react';
import VersionOverview from './VersionOverview';
import config from '@plone/volto/registry';
import '@testing-library/jest-dom/extend-expect';

jest.mock('@plone/volto/helpers/Utils/Date', () => ({
formatDate: jest.fn(() => 'formatted date'),
}));

config.settings.addonsInfo = [
{ name: 'addon1', version: '1.0.0' },
{ name: 'addon2', version: '2.0.0' },
{ test: 'test' },
];

describe('VersionOverview', () => {
it('renders correctly', () => {
const frontend = {
version: '1.0.0',
old_version: '0.9.0',
date: new Date(),
};
const backend = {
version: '1.0.0',
old_version: '0.9.0',
date: new Date(),
};
const eggs = { egg1: '1.0.0', egg2: '2.0.0' };

const { queryAllByText } = render(
<VersionOverview
cmf_version="1.0.0"
debug_mode="No"
pil_version="1.0.0"
plone_version="1.0.0"
plone_restapi_version="1.0.0"
python_version="1.0.0"
zope_version="1.0.0"
eggs={eggs}
frontend={frontend}
backend={backend}
/>,
);

expect(queryAllByText(/Frontend 1.0.0/)).not.toBeNull();
expect(queryAllByText(/Backend 1.0.0/)).not.toBeNull();

expect(queryAllByText(/Plone 1.0.0/)).not.toBeNull();
expect(queryAllByText(/plone.restapi 1.0.0/)).not.toBeNull();
expect(queryAllByText(/CMF 1.0.0/)).not.toBeNull();
expect(queryAllByText(/Zope 1.0.0/)).not.toBeNull();
expect(queryAllByText(/Python 1.0.0/)).not.toBeNull();
expect(queryAllByText(/PIL 1.0.0/)).not.toBeNull();
expect(queryAllByText(/egg1 1.0.0/)).not.toBeNull();
expect(queryAllByText(/egg2 2.0.0/)).not.toBeNull();
});

it('renders correctly', () => {
config.settings.frontendVersion = '1.0.0';
config.settings.BackendVersion = '1.0.0';

const { queryAllByText } = render(
<VersionOverview
cmf_version="1.0.0"
debug_mode="Yes"
pil_version="1.0.0"
plone_version="1.0.0"
plone_restapi_version="1.0.0"
python_version="1.0.0"
zope_version="1.0.0"
/>,
);

expect(queryAllByText(/Frontend 1.0.0/)).not.toBeNull();
expect(queryAllByText(/Backend 1.0.0/)).not.toBeNull();

expect(queryAllByText(/Plone 1.0.0/)).not.toBeNull();
expect(queryAllByText(/plone.restapi 1.0.0/)).not.toBeNull();
expect(queryAllByText(/CMF 1.0.0/)).not.toBeNull();
expect(queryAllByText(/Zope 1.0.0/)).not.toBeNull();
expect(queryAllByText(/Python 1.0.0/)).not.toBeNull();
expect(queryAllByText(/PIL 1.0.0/)).not.toBeNull();
expect(queryAllByText(/egg1 1.0.0/)).not.toBeNull();
expect(queryAllByText(/egg2 2.0.0/)).not.toBeNull();
});

it('renders correctly', () => {
config.settings.frontendVersion = undefined;
config.settings.BackendVersion = undefined;

const { queryAllByText } = render(
<VersionOverview
cmf_version="1.0.0"
debug_mode="Yes"
pil_version="1.0.0"
plone_version="1.0.0"
plone_restapi_version="1.0.0"
python_version="1.0.0"
zope_version="1.0.0"
/>,
);

expect(queryAllByText(/Frontend 1.0.0/)).not.toBeNull();
expect(queryAllByText(/Backend 1.0.0/)).not.toBeNull();

expect(queryAllByText(/Plone 1.0.0/)).not.toBeNull();
expect(queryAllByText(/plone.restapi 1.0.0/)).not.toBeNull();
expect(queryAllByText(/CMF 1.0.0/)).not.toBeNull();
expect(queryAllByText(/Zope 1.0.0/)).not.toBeNull();
expect(queryAllByText(/Python 1.0.0/)).not.toBeNull();
expect(queryAllByText(/PIL 1.0.0/)).not.toBeNull();
expect(queryAllByText(/egg1 1.0.0/)).not.toBeNull();
expect(queryAllByText(/egg2 2.0.0/)).not.toBeNull();
});
});
49 changes: 49 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,53 @@
import packageJson from '../../../../package.json';
import { updateSystemInfo } from '@eeacms/volto-controlpanel/system';

const applyConfig = (config) => {
if (process.env.NODE_ENV !== 'production') {
// Enable description block for cypress
config.blocks.blocksConfig.description.restricted = false;
}

// Disable non-GDPR compliant blocks
config.blocks.blocksConfig.video.restricted = true;
config.blocks.blocksConfig.maps.restricted = true;
config.blocks.blocksConfig.html.restricted = true;

// Changelogs
config.settings.changelogUrlPrefix =
config.settings.changelogPrefix || __SERVER__
? process.env?.RAZZLE_CHANGELOG_PREFIX
: window.env?.RAZZLE_CHANGELOG_PREFIX || 'https://github.com/eea';

config.settings.changelogUrlSuffix =
config.settings.changelogSuffix || __SERVER__
? process.env?.RAZZLE_CHANGELOG_SUFFIX
: window.env?.RAZZLE_CHANGELOG_SUFFIX || 'releases';

config.settings.frontendVersion =
config.settings.frontendVersion || __SERVER__
? process.env?.RAZZLE_FRONTEND_VERSION
: window.env?.RAZZLE_FRONTEND_VERSION || packageJson.version;

config.settings.frontendName =
config.settings.frontendName || __SERVER__
? process.env?.RAZZLE_FRONTEND_NAME
: window.env?.RAZZLE_FRONTEND_NAME || packageJson.name;

config.settings.backendVersion =
config.settings.backendVersion || __SERVER__
? process.env?.RAZZLE_BACKEND_VERSION
: window.env?.RAZZLE_BACKEND_VERSION || '';

config.settings.backendName =
config.settings.backendName || __SERVER__
? process.env?.RAZZLE_BACKEND_NAME
: window.env?.RAZZLE_BACKEND_NAME || 'plone-backend';

// Persist FRONTEND_VERSION on backend registry
if (__SERVER__) {
updateSystemInfo(config);
}

return config;
};

Expand Down
49 changes: 49 additions & 0 deletions src/system.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* eslint no-console: ["error", { allow: ["warn", "log"] }] */
export const updateSystemInfo = (config) => {
let fetch = require('node-fetch');
const internalApi =
config.settings.internalApiPath || config.settings.devProxyToApiPath;
const version = config.settings.frontendVersion;

// Nothing to do
if (!version || !internalApi) {
return config;
}

// Backend @system update via PATCH is allowed only via internal API
if (
!(
internalApi.startsWith('http://localhost') ||
internalApi.startsWith('http://backend')
)
) {
return config;
}

// Persist FRONTEND_VERSION on backend registry
const url = `${internalApi}/@system`;
fetch(url, {
method: 'PATCH',
body: JSON.stringify({
'eea.kitkat.interfaces.IEEAVersionsFrontend.version': version,
}),
headers: {
Accept: 'application/json',
},
})
.then((response) => response.text())
.then((text) => {
if (text) {
console.log(`Updating FRONTEND_VERSION on backend registry: ${text}`);
} else {
console.log(
`FRONTEND_VERSION already up-to-date on backend registry: ${version}`,
);
}
})
.catch((err) =>
console.warn(`Could NOT update FRONTEND_VERSION on backend: ${err}`),
);

return config;
};

0 comments on commit 7a63c94

Please sign in to comment.