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

Bug fixes and Plugin Versions content #231

Merged
merged 14 commits into from
Aug 6, 2021
19 changes: 16 additions & 3 deletions src/components/Plugin/Plugin.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ export class Plugin extends Component {
async componentDidMount() {
let { pluginData } = this.state;

if (!pluginData) {
if (!pluginData)
pluginData = await this.fetchPluginData();
}
else
this.fetchPluginVersions(pluginData.name)

this.setState({ pluginData, loading: false });
if (this.isLoggedIn()) {
Expand All @@ -67,7 +68,7 @@ export class Plugin extends Component {
if (this.isLoggedIn()) {
return this.isFavorite() ? this.unfavPlugin() : this.favPlugin();
}
return Promise.resolve();
return this.showNotifications(new Error('You need to be logged in!'))
zrthxn marked this conversation as resolved.
Show resolved Hide resolved
}

favPlugin = async () => {
Expand Down Expand Up @@ -132,6 +133,18 @@ export class Plugin extends Component {
}
}

async fetchPluginVersions(name) {
try {
const versions = await this.client.getPlugins({ limit: 10e6, name });
return this.setState((prevState) =>
({ pluginData: { ...prevState.pluginData, versions: versions.data } })
);
} catch (e) {
this.showNotifications(new HttpApiCallError(e));
return e
}
}

async fetchIsPluginStarred({ name }) {
try {
const response = await this.client.getPluginStars({ plugin_name: name });
Expand Down
271 changes: 151 additions & 120 deletions src/components/Plugin/components/PluginBody/PluginBody.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Required for setting README html

import React, { useState, useEffect, useCallback } from 'react';
import { Link } from 'react-router-dom';
import {
Grid,
GridItem,
Expand All @@ -13,6 +12,7 @@ import {
Popover,
ClipboardCopy,
Button,
ExpandableSection,
} from '@patternfly/react-core';
import { DownloadIcon, UserAltIcon } from '@patternfly/react-icons';
import PropTypes from 'prop-types';
Expand All @@ -22,7 +22,6 @@ import { sanitize } from 'dompurify';
import './PluginBody.css';
import ErrorNotification from '../../../Notification';
import HttpApiCallError from '../../../../errors/HttpApiCallError';
// eslint-disable-next-line import/named
import { GithubAPIRepoError, GithubAPIProfileError, GithubAPIReadmeError } from '../../../../errors/GithubError';

const PluginBody = ({ pluginData }) => {
Expand Down Expand Up @@ -81,7 +80,38 @@ const PluginBody = ({ pluginData }) => {
fetchRepo();
}, [fetchReadme, fetchRepoData, pluginData.public_repo, showNotifications]);

const versionString = (v) => `Version ${v}${v === pluginData.version ? ' (This)' : ''}`;
const InstallButton = () => {
if (pluginData.version)
return <>
<p><b>Version { pluginData.version }</b></p>
<ClipboardCopy isReadOnly>
{ `${process.env.REACT_APP_STORE_URL}plugins/${pluginData.id}/` }
zrthxn marked this conversation as resolved.
Show resolved Hide resolved
</ClipboardCopy>
</>


if (pluginData.versions)
return <>
<p><b>Version { pluginData.versions[0].version }</b></p>
<ClipboardCopy isReadOnly>
{ `${process.env.REACT_APP_STORE_URL}plugins/${pluginData.versions[0].id}/` }
</ClipboardCopy>
<br />
<ExpandableSection toggleText="More Versions">
zrthxn marked this conversation as resolved.
Show resolved Hide resolved
{
pluginData.versions.slice(1).map((version) =>(
<div key={version.version}>
<a href={`/p/${version.id}`}>
Version {version.version}
</a>
</div>
))
}
</ExpandableSection>
</>

return <p>Loading</p>
}

return (
<>
Expand All @@ -101,132 +131,130 @@ const PluginBody = ({ pluginData }) => {

<article>
<Card id="plugin-body">
<Tabs activeKey={activeTab} onSelect={handleTabClick}>
<Tab eventKey={1} title={<TabTitleText>Overview</TabTitleText>}>
<Grid hasGutter>
<GridItem md={8} sm={12}>
<Grid hasGutter>
<GridItem md={8} sm={12}>
<Tabs activeKey={activeTab} onSelect={handleTabClick}>
<Tab eventKey={1} title={<TabTitleText>Overview</TabTitleText>}>
<div style={{ color: 'gray', margin: '1em 0' }}>README</div>
{ readme ? <div dangerouslySetInnerHTML={{ __html: readme }} /> : null }
</GridItem>
<GridItem md={4} sm={12}>
<div className="plugin-body-side-col">
<div className="plugin-body-detail-section">
<h4>Install</h4>
<p>Click to install this plugin to your ChRIS Server.</p>
<br />
<Popover
position="bottom"
headerContent={<b>Install to your ChRIS server</b>}
bodyContent={() => (
<div>
<p>
Copy and Paste the URL below into your ChRIS Admin Dashboard
to install this plugin.
</p>
<br />
<ClipboardCopy isReadOnly>
</Tab>

<Tab eventKey={2} title={<TabTitleText>Parameters</TabTitleText>}>
<Grid hasGutter className="plugin-body-main">
<GridItem sm={12}>Parameters content</GridItem>
</Grid>
</Tab>

{
pluginData.versions &&
<Tab eventKey={3} title={<TabTitleText>Versions</TabTitleText>}>
<Grid hasGutter className="plugin-body-main">
<GridItem sm={12}>
{
pluginData.versions ? (
<>
<h2>Versions of this plugin</h2>
{
pluginData.url ? pluginData.url
: `${process.env.REACT_APP_STORE_URL}plugins/${pluginData.id}/`
pluginData.versions.map((version) => (
<div key={version}>
<a href={`/p/${version.id}`}>
Version { version.version }
</a>
</div>
))
}
</ClipboardCopy>
</div>
)}
>
<Button isBlock style={{ fontSize: '1.125em' }}>
<DownloadIcon />
{' '}
Install to ChRIS
</Button>
</Popover>
</div>
<div className="plugin-body-detail-section">
<h4>Repository</h4>
<a href={pluginData.public_repo}>
{pluginData.public_repo}
</a>
</div>
<div className="plugin-body-detail-section">
<h4>Contributors</h4>
{
pluginData.authors.map((author) => (
<a key={author} href={`#${author}`}>
<p>
<UserAltIcon />
{' '}
{author}
</p>
</a>
))
}

<br />
<a className="pf-m-link" href={`${pluginData.public_repo}/graphs/contributors`}>
View all contributors
</a>
</div>
<div className="plugin-body-detail-section">
<h4>Plugin ID</h4>
{pluginData.id}
</div>
<div className="plugin-body-detail-section">
<h4>License</h4>
{ repoData ? repoData.license.name : pluginData.license }
</div>
<div className="plugin-body-detail-section">
<h4>Content Type</h4>
{pluginData.type}
</div>
<div className="plugin-body-detail-section">
<h4>Date added</h4>
{(new Date(pluginData.creation_date)).toDateString()}
</div>
</div>
</GridItem>
</Grid>
</Tab>

<Tab eventKey={2} title={<TabTitleText>Parameters</TabTitleText>}>
<Grid hasGutter className="plugin-body-main">
<GridItem sm={12}>Parameters content</GridItem>
</Grid>
</Tab>

<Tab eventKey={3} title={<TabTitleText>Versions</TabTitleText>}>
<Grid hasGutter className="plugin-body-main">
<GridItem sm={12}>
{
pluginData.versions !== undefined ? (
<>
<h2>Versions of this plugin</h2>
{
Object.keys(pluginData.versions).length > 1
? Object.keys(pluginData.versions).map((version) => (
<div key={version}>
<Link
href={`/plugin/${pluginData.name}/${version}`}
to={`/plugin/${pluginData.name}/${version}`}
>
{versionString(version)}
</Link>
</div>
)) : (
</>
) : (
<div>
{versionString(Object.keys(pluginData.versions).toString())}
<p>This is the only version of this plugin.</p>
</div>
)
}
</>
) : (
}
</GridItem>
</Grid>
</Tab>
}
</Tabs>
</GridItem>

<GridItem md={4} sm={12}>
<div className="plugin-body-side-col">
<div className="plugin-body-detail-section">
<h4>Install</h4>
<p>Click to install this plugin to your ChRIS Server.</p>
<br />
<Popover
position="bottom"
maxWidth="30rem"
headerContent={<b>Install to your ChRIS server</b>}
bodyContent={() => (
<div>
<p>This is the only version of this plugin.</p>
<p>
Copy and Paste the URL below into your ChRIS Admin Dashboard
to install this plugin.
</p>
<br />
<InstallButton/>
</div>
)
}
</GridItem>
</Grid>
</Tab>
</Tabs>
)}
>
<Button isBlock style={{ fontSize: '1.125em' }}>
<DownloadIcon />
{' '}
Install to ChRIS
</Button>
</Popover>
</div>
<div className="plugin-body-detail-section">
<h4>Repository</h4>
<a href={pluginData.public_repo}>
{pluginData.public_repo}
</a>
</div>

{
Array.isArray(pluginData.authors) &&
<div className="plugin-body-detail-section">
<h4>Contributors</h4>
{
pluginData.authors.map((author) => (
<a key={author} href={`#${author}`}>
<p>
<UserAltIcon />
{' '}
{author}
</p>
</a>
))
}

<br />
<a className="pf-m-link" href={`${pluginData.public_repo}/graphs/contributors`}>
View all contributors
</a>
</div>
}

{/* <div className="plugin-body-detail-section">
<h4>Plugin ID</h4>
{pluginData.id}
</div> */}

<div className="plugin-body-detail-section">
<h4>License</h4>
{ repoData ? repoData.license.name : pluginData.license }
</div>
<div className="plugin-body-detail-section">
<h4>Content Type</h4>
{pluginData.type}
</div>
<div className="plugin-body-detail-section">
<h4>Date added</h4>
{(new Date(pluginData.creation_date)).toDateString()}
</div>
</div>
</GridItem>
</Grid>
</Card>
</article>
</>
Expand All @@ -243,6 +271,9 @@ PluginBody.propTypes = {
type: PropTypes.string,
authorURL: PropTypes.string,
authors: PropTypes.arrayOf(PropTypes.string),
versions: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.any), PropTypes.any
])
}).isRequired,
};

Expand Down