Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move information to the sidebar, enforce max width #447

Merged
merged 4 commits into from
Nov 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 7 additions & 23 deletions src/components/LineChart.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,8 @@ import PropTypes from 'prop-types';
import {Line} from 'react-chartjs-2';
import moment from 'moment';

const calculateHeight = (total) => {
if (total > 100000) return 275;
if (total > 50000) return 250;
if (total > 25000) return 225;
if (total > 10000) return 200;
if (total > 5000) return 175;
return 150;
};

const calculateMinMax = (data) => {
const maxValue = Math.max(...data);
// calculate a dynamic value to center the graph
const scaleDifference = Math.pow(10, maxValue.toString().length-1);
return {
min: 0,
max: parseInt((maxValue/scaleDifference)+1)*scaleDifference // plus 1 to add more space in the top
};
const calculateMax = (data) => {
return 1.2 * Math.max(...data);
};

const chartData = (labels, data) => {
Expand All @@ -39,7 +24,6 @@ const chartData = (labels, data) => {
};

const options = (data) => {
const {min, max} = calculateMinMax(data);
return {
responsive: true,
maintainAspectRatio: false,
Expand All @@ -61,9 +45,10 @@ const options = (data) => {
}
}],
yAxes: [{
display: false,
ticks: {
min,
max,
min: 0,
max: calculateMax(data),
fontSize: 9,
}
}]
Expand All @@ -77,13 +62,13 @@ const styles = {
}
};

function LineChart({installations, total}) {
function LineChart({installations}) {
if (!installations) {
return null;
}
const labels = [];
const data = [];
const height = calculateHeight(total);
const height = 80;
const length = installations.length;
installations.slice(length > 12 ? length - 12 : 0, length).forEach((installation) => {
labels.push(moment.utc(installation.timestamp).format('MMM'));
Expand All @@ -101,7 +86,6 @@ function LineChart({installations, total}) {
}

LineChart.propTypes = {
total: PropTypes.number.isRequired,
installations: PropTypes.arrayOf(PropTypes.shape({
timestamp: PropTypes.number,
total: PropTypes.number
Expand Down
2 changes: 1 addition & 1 deletion src/components/PluginLastReleased.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function PluginLastReleased({plugin}) {
const time = getTime(plugin);
return (
<div>
{'Last released: '}
{'Released: '}
<TimeAgo date={time} formatter={formatter}/>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/PluginReadableInstalls.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ function PluginReadableInstalls({currentInstalls}) {
if (!currentInstalls) {
return <>No usage data available</>;
}
return <>{currentInstalls}</>;
return <>{new Intl.NumberFormat('en-US').format(currentInstalls)}</>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've never used this util. If you specify the format does it only do it for us style numbers? Is possible to let the browser pick the locale?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we omit the locale name, the browser locale will be used. But when formatting dates we are also using US locale and almost all the texts are in English, so I thought this is more consistent.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yea totally a good plan. I was just curious how it worked.

I think I started separating dates into its own components for that reason, so we could eventually fix it. I just didn't go far enough

}

PluginReadableInstalls.propTypes = {
Expand Down
57 changes: 41 additions & 16 deletions src/styles/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,21 @@ body a:active {color:#c00}
.NoLabels > .Categories label > span {margin-left:0 !important; color:#0275d8; cursor:pointer}

h1.title {
margin-top: 1rem;
margin-right: 2rem;
}

body #grid-box .NoLabels {padding: 2rem 0; background:#e5f8ff}
body #grid-box .NoLabels .Cols3 {font-size:.85rem}
body #grid-box .NoLabels .Cols3 {font-size:.875rem}
body #grid-box .NoLabels .Cols3 label > span {margin-left:.5rem}
body #grid-box .NoLabels .Entry-box {display:block; padding: 0.25rem 0;
line-height: 1rem; font-size:.85rem}
body #grid-box .NoLabels .Entry-box {
display: block;
padding: 0.25rem 0;
line-height: 1rem;
font-size:.875rem
}
body #grid-box .NoLabels .Entry-box a {cursor:pointer}
body #grid-box .NoLabels legend {font-size:1.1rem; }

.update-link {margin:4rem 0;}
.update-link h6 {margin-bottom:.25rem}

#cb-item-finder-grid-box > .grid > .no-results {padding:.5rem; color:rgba(0,0,0,.667); display:block;}
.not-found-box {text-align:center;}
.not-found {margin:6rem 0; padding:1.5rem 0 1.5rem 8rem; position:relative; display:inline-block; text-align:left;}
Expand Down Expand Up @@ -222,19 +223,27 @@ transform: scale(-1, 1);
.maintainers > .maintainer {display:block;}

.container-fluid.padded {padding:3rem 4rem}
#pluginPage #grid-box {font-size:.85rem;}
#pluginPage #grid-box .gutter {background:#eee; padding:2rem }
#pluginPage #grid-box {font-size:.875rem;}
#pluginPage #grid-box .gutter {padding:2rem }
#pluginPage #grid-box .gutter > .btn { display:block; text-align:left; padding:.5rem 1rem .75rem 3.5rem; position:relative; margin-bottom:1rem}
#pluginPage #grid-box .gutter > .btn i {font-size:2.25rem; position:absolute; left:.75rem; top:.5rem}
#pluginPage #grid-box .gutter > .btn > span {font-size:1.1rem; line-height:1.3rem; font-weight:500}
#pluginPage #grid-box .gutter > .btn > .v {display:block; font-weight:200; font-size:.75rem; white-space:normal}
#pluginPage #grid-box .gutter .lbl {display:inline-block; margin-right:.5rem}
##pluginPage #grid-box .gutter .label-link a{display:block; line-height: 1.5rem; padding: 4px 0;}
#pluginPage #grid-box .gutter .chart {margin:1rem 0 2rem}
#pluginPage #grid-box .gutter .chart {margin:1rem 0 0}

.gutter .sidebarSection {
margin-top: 1rem;
padding-top:.5rem;
border-top: 1px #AAA solid;
}

#pluginPage #grid-box {
margin-left: 15px;
margin-right: 15px;
}

#pluginPage #grid-box .download {margin:2rem 0 2rem -.5rem;}
#pluginPage #grid-box .alert > .alert-icon {
background-repeat: no-repeat;
Expand All @@ -249,6 +258,11 @@ transform: scale(-1, 1);
opacity: .54;
}

#grid-box .pluginContainer {
max-width: 72rem;
margin: auto;
}

.alert-warning .alert-icon .main-path {
fill: #856404
}
Expand All @@ -274,8 +288,18 @@ transform: scale(-1, 1);
}
.row.flex {display:flex}

div.title-details .sub {display:block; font-weight:normal; font-size:.85rem; color:#999; margin-top:.25rem}
div.title-details .version {display:block; font-weight:normal; font-size:.85rem; color:#999; margin-top:.25rem}
.title-wrapper {
display:flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
margin-top: 1rem;
}

.plugin-id {
opacity: .7;
margin-bottom: .5rem;
}

.markdown-body .anchor {display:none}
.markdown-body h1 {font-size:2rem; margin:4rem 0 1rem;}
Expand Down Expand Up @@ -315,7 +339,7 @@ body .item-finder.Tiles a.item,
.Tile {
display: block;
border: .1rem solid #ccc;
font-size: .85rem;
font-size: .875rem;
height: 16.5rem;
width:13rem;
box-sizing: border-box;
Expand Down Expand Up @@ -553,11 +577,11 @@ body .item-finder.Table .Entry-box:nth-child(odd) > .Entry > div.Excerpt{box-sha
*/
body .item-finder.Table a.Entry > div,
.tbody > .Row > .Tile > div {display:table-cell; max-height:3.3rem; height:auto; padding:.25rem; border-bottom:1px solid #eee}
body .item-finder.Table a.Entry > div.Score {margin:0; font-size:.85rem; position:static}
body .item-finder.Table a.Entry > div.Score {margin:0; font-size:.875rem; position:static}
body .item-finder.Table a.Entry > div.Wiki {display:none}
body .item-finder.Table a.Entry > div.Title,
.tbody > .Row > .Tile > div.Title{width:20%}
body .item-finder.Table a.Entry > div.Title > h4 {font-size:.85rem; color:#369; font-weight:bold;}
body .item-finder.Table a.Entry > div.Title > h4 {font-size:.875rem; color:#369; font-weight:bold;}
body .item-finder.Table a.Entry > div.Icon,
.tbody > .Row > .Tile > div.Icon {display:none}
body .item-finder.Table a.Entry > div.Authors > div,
Expand Down Expand Up @@ -620,7 +644,7 @@ nav .nav-item.active {box-shadow:inset #D33833 0 -2px}

color:#999;
padding:1px 2px;
font-size:.85rem;
font-size:.875rem;
display:block;
width:auto;
position:relative;
Expand Down Expand Up @@ -884,6 +908,7 @@ a.card:hover {

/* From atlassian batch.css - https://wiki.jenkins.io/s/f68dfafb2b4588f7b31742327b4469ae-CDN/en_GB/6441/82994790ee2f720a5ec8daf4850ac5b7b34d2194/be65c4ed0984ca532b26983f5fc1813e/_/download/contextbatch/css/_super/batch.css?atlassian.aui.raphael.disabled=true */
.confluenceTable{border-collapse:collapse}.confluenceTh,.confluenceTd{border:1px solid #c1c7d0;padding:7px 10px;vertical-align:top;text-align:left;min-width:8px}.confluenceTable ol,.confluenceTable ul{margin-left:0;padding-left:22px}.confluenceTable,.table-wrap{margin:10px 0 0 0;overflow-x:auto}.confluenceTable:first-child,.table-wrap:first-child{margin-top:0}table.confluenceTable th.confluenceTh,table.confluenceTable th.confluenceTh>p,table.confluenceTable td.confluenceTd.highlight,table.confluenceTable td.confluenceTd.highlight>p,table.confluenceTable th.confluenceTh.highlight-grey,table.confluenceTable th.confluenceTh.highlight-grey>p,table.confluenceTable td.confluenceTd.highlight-grey,table.confluenceTable td.confluenceTd.highlight-grey>p{background-color:#f4f5f7}table.confluenceTable th.confluenceTh.info,table.confluenceTable th.confluenceTh.info>p,table.confluenceTable td.confluenceTd.highlight.info,table.confluenceTable td.confluenceTd.highlight.info>p,table.confluenceTable th.confluenceTh.highlight-blue,table.confluenceTable th.confluenceTh.highlight-blue>p,table.confluenceTable td.confluenceTd.highlight-blue,table.confluenceTable td.confluenceTd.highlight-blue>p{background-color:#deebff}table.confluenceTable th.confluenceTh.success,table.confluenceTable th.confluenceTh.success>p,table.confluenceTable td.confluenceTd.highlight.success,table.confluenceTable td.confluenceTd.highlight.success>p,table.confluenceTable th.confluenceTh.highlight-green,table.confluenceTable th.confluenceTh.highlight-green>p,table.confluenceTable td.confluenceTd.highlight-green,table.confluenceTable td.confluenceTd.highlight-green>p{background-color:#e3fcef}table.confluenceTable th.confluenceTh.warning,table.confluenceTable th.confluenceTh.warning>p,table.confluenceTable td.confluenceTd.highlight.warning,table.confluenceTable td.confluenceTd.highlight.warning>p,table.confluenceTable th.confluenceTh.highlight-red,table.confluenceTable th.confluenceTh.highlight-red>p,table.confluenceTable td.confluenceTd.highlight-red,table.confluenceTable td.confluenceTd.highlight-red>p{background-color:#ffebe5}table.confluenceTable th.confluenceTh.note,table.confluenceTable th.confluenceTh.note>p,table.confluenceTable td.confluenceTd.highlight.note,table.confluenceTable td.confluenceTd.highlight.note>p,table.confluenceTable th.confluenceTh.highlight-yellow,table.confluenceTable th.confluenceTh.highlight-yellow>p,table.confluenceTable td.confluenceTd.highlight-yellow,table.confluenceTable td.confluenceTd.highlight-yellow>p{background-color:#fffae5}table.confluenceTable th.confluenceTh,table.confluenceTable th.confluenceTh>p{font-weight:bold}table.confluenceTable th.confluenceTh.nohighlight,table.confluenceTable th.confluenceTh.nohighlight>p{font-weight:normal;background-color:transparent}table.confluenceTable td.confluenceTd img,table.confluenceTable td.confluenceTd .confluence-embedded-file-wrapper img,table.confluenceTable th.confluenceTh .confluence-embedded-file-wrapper img{max-width:none}table.confluenceTable td.numberingColumn{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}

#grid-box .content {
word-break: break-word;
}
Expand Down
104 changes: 49 additions & 55 deletions src/templates/plugin.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,17 @@ function PluginPage({data: {jenkinsPlugin: plugin, reverseDependencies: reverseD
<Layout id="pluginPage" reportProblemRelativeSourcePath={pluginPage} reportProblemUrl={`/${plugin.name}`} reportProblemTitle={plugin.title}>
<SEO title={cleanTitle(plugin.title)} description={plugin.excerpt} pathname={`/${plugin.id}`}/>

<div className="row flex">
<div className="row flex pluginContainer">
<div className="col-md-9 main">
<h1 className="title">
{cleanTitle(plugin.title)}
</h1>
<div className="title-wrapper">
<h1 className="title">
{cleanTitle(plugin.title)}
</h1>
<div className="plugin-id">
{'ID: '}
{plugin.name}
</div>
</div>
<PluginActiveWarnings securityWarnings={plugin.securityWarnings} />
<PluginGovernanceStatus plugin={plugin} />
<ul className="nav nav-tabs">
Expand All @@ -65,35 +71,6 @@ function PluginPage({data: {jenkinsPlugin: plugin, reverseDependencies: reverseD
</ul>
<div className="padded">
{state.selectedTab === 'documentation' && (<>
<div className="title-details">
<span className="version">
{'Version: '}
{plugin.version}
</span>
<span className="sub">
{'Minimum Jenkins requirement: '}
{plugin.requiredCore}
</span>
<span className="sub">
{'ID: '}
{plugin.name}
</span>
</div>
<div className="row flex">
<div className="col-md-4">
{plugin.stats && <div>
{'Installs: '}
<PluginReadableInstalls currentInstalls={plugin.stats.currentInstalls} />
</div>}
{plugin.scm && plugin.scm.link && <div><a href={plugin.scm.link}>GitHub →</a></div>}
<PluginLastReleased plugin={plugin} />
</div>
<div className="col-md-4 maintainers">
<h5>Maintainers</h5>
<PluginMaintainers maintainers={plugin.maintainers} />
</div>
</div>

{plugin.wiki.content && <div className="content" dangerouslySetInnerHTML={{__html: plugin.wiki.content}} />}
</>)}
{state.selectedTab === 'releases' && <PluginReleases pluginId={plugin.id} />}
Expand All @@ -108,23 +85,39 @@ function PluginPage({data: {jenkinsPlugin: plugin, reverseDependencies: reverseD
<span>Archives</span>
<span className="v">Get past versions</span>
</a>
<div className="chart">
<LineChart
total={plugin.stats.currentInstalls}
installations={plugin.stats.installations}
/>
<h5>{`Version: ${plugin.version}`}</h5>
<PluginLastReleased plugin={plugin} />
<div>
{'Requires Jenkins '}
{plugin.requiredCore}
</div>
<div className="sidebarSection">
{plugin.stats && <h5>
{'Installs: '}
<PluginReadableInstalls currentInstalls={plugin.stats.currentInstalls} />
</h5>}
<div className="chart">
<LineChart
installations={plugin.stats.installations}
/>
</div>
</div>
<div className="sidebarSection">
<h5>Links</h5>
{plugin.scm && plugin.scm.link && <div className="label-link"><a href={plugin.scm.link}>GitHub</a></div>}
<div className="label-link"><a href={`https://javadoc.jenkins.io/plugin/${plugin.name}`}>Javadoc</a></div>
</div>
<div className="sidebarSection">
<h5>Labels</h5>
<PluginLabels labels={plugin.labels} />
</div>
<div className="sidebarSection">
<h5>Maintainers</h5>
<PluginMaintainers maintainers={plugin.maintainers} />
</div>

<h5>Links</h5>
{plugin.scm && plugin.scm.link && <div className="label-link"><a href={plugin.scm.link}>GitHub</a></div>}
<div className="label-link"><a href={`https://javadoc.jenkins.io/plugin/${plugin.name}`}>Javadoc</a></div>

<h5>Labels</h5>
<PluginLabels labels={plugin.labels} />
<br/>
{shouldShowWikiUrl(plugin.wiki) &&
<div className="update-link">
<h5>Help us to improve this page!</h5>
<div className="sidebarSection">
<h5>Help us improve this page!</h5>
{'This content is served from the '}
<a href={plugin.wiki.url} target="_wiki">Jenkins Wiki</a>
{' the '}
Expand All @@ -135,17 +128,18 @@ function PluginPage({data: {jenkinsPlugin: plugin, reverseDependencies: reverseD
</div>
}
{shouldShowGitHubUrl(plugin.wiki) &&
<div className="update-link">
<h5>Help us to improve this page!</h5>
<div className="sidebarSection">
<h5>Help us improve this page!</h5>
{'To propose a change submit a pull request to '}
<a href={plugin.wiki.url} rel="noopener noreferrer" target="_blank">the plugin page</a>
{' on GitHub. Read more about GitHub support on the plugin site in the '}
<a href="https://jenkins.io/doc/developer/publishing/documentation/" rel="noopener noreferrer" target="_blank">Jenkins developer documentation</a>
{'.'}
{' on GitHub.'}
</div>
}
{plugin.securityWarnings &&
<div className="sidebarSection">
<PluginInactiveWarnings securityWarnings={plugin.securityWarnings} />
</div>
}

<PluginInactiveWarnings securityWarnings={plugin.securityWarnings} />
</div>
</div>
</Layout>
Expand Down