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

Task4: Circle of contributors #851

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';

const DataNotFound = () => {
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
color: 'var(--color-fg-muted)',
}}
>
<h3>Data Not Found</h3>
<div style={{ width: '300px', margin: '2em' }}>
<p>Possible reasons are:</p>
<ul style={{ marginLeft: '1em' }}>
<li>This repository is too new, so its data has not been generated</li>
<li>This repository is not active enough, so its data are not generated</li>
</ul>
</div>
</div>
);
};

export default DataNotFound;
Comment on lines +1 to +26
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's move the src/pages/ContentScripts/features/repo-networks/DataNotFound.tsx to src/pages/ContentScripts/components and use it from there. It is important to reuse code instead of duplicate them

77 changes: 77 additions & 0 deletions src/pages/ContentScripts/features/contributor_button/index.tsx
MrH233 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* This module is responsible for enhancing the contributor list on the GitHub repository page.
* It uses React to render the contributor list and fetches additional network data through the API.
*/

import React, { useState, useEffect } from 'react';
import { render } from 'react-dom';
import $ from 'jquery';
import View from './view';
import { getRepoName } from '../../../../helpers/get-repo-info';
import { getDeveloperNetwork, getRepoNetwork } from '../../../../api/repo';
import features from '../../../../feature-manager';
import * as pageDetect from 'github-url-detection';
import elementReady from 'element-ready';

// Global variables are used to store the repository name and network data for sharing between different functions.
// Define global variables to store the repository name and network data.
let repoName: string;
let developerNetworks: any;
let repoNetworks: any;
let target: any;

// Get the feature ID of the current module for feature management.
const featureId = features.getFeatureID(import.meta.url);

/**
* Asynchronously fetch network data of the repository developer and the repository.
*/
const getData = async () => {
developerNetworks = await getDeveloperNetwork(repoName);
repoNetworks = await getRepoNetwork(repoName);
};

/**
* Replace the contributor list with a React component.
* @param target The target element to be replaced.
*/
const renderTo = (target: HTMLElement) => {
const originalHTML = target.innerHTML;

render(
<React.Fragment>
<View developerNetwork={developerNetworks} target={originalHTML} />
</React.Fragment>,
document.querySelector('.list-style-none.d-flex.flex-wrap.mb-n2') as HTMLElement
);
};

MrH233 marked this conversation as resolved.
Show resolved Hide resolved
/**
* Initialize the feature, including fetching the repository name and data, and replacing the contributor list.
*/
const init = async (): Promise<void> => {
repoName = getRepoName();
const targetElement = document.querySelector('.list-style-none.d-flex.flex-wrap.mb-n2') as HTMLElement;
await getData();
renderTo(targetElement);
};

/**
* Restore the feature when the page is refreshed or navigated, reload the data and render the list.
*/
const restore = async () => {
if (repoName !== getRepoName()) {
repoName = getRepoName();
await getData();
}
$('div.ReactModalPortal').remove();
renderTo(target);
};

// Add the feature to the feature manager, configure the initialization and restore functions.
features.add(featureId, {
// asLongAs: [pageDetect.isUserProfile],
awaitDomReady: false,
init,
restore,
});
95 changes: 95 additions & 0 deletions src/pages/ContentScripts/features/contributor_button/view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React, { useState, useEffect } from 'react';
import ReactModal from 'react-modal';
import Graph from '../../../../components/Graph';
import optionsStorage, { HypercrxOptions, defaults } from '../../../../options-storage';
import { useTranslation } from 'react-i18next';
import '../../../../helpers/i18n';

// Define the time period for the developer and the repository
const DEVELOPER_PERIOD = 90;
const REPO_PERIOD = 90;

// Define the Props interface, including the developer network and the target HTML
interface Props {
developerNetwork: any;
target: any;
}

const borderStyle = {
'margin-top': '0',
};

// Define the chart style
const graphStyle = {
width: '296px',
height: '400px',
};

const targetStyle = {
width: '296px',
height: '80px',
display: 'flex',
'justify-content': 'flex-start',
'align-items': 'flex-start',
'align-content': 'flex-start',
'flex-wrap': 'wrap',
};

const buttonStyle = {
margin: '-5px 0px 10px 0px',
padding: '6px 14px',
'font-size': '14px',
'font-family': 'inherit',
'font-weight': '500',
'box-shadow':
'var(--button-default-shadow-resting, var(--color-btn-shadow, 0 1px 0 rgba(27, 31, 36, 0.04))), var(--button-default-shadow-inset, var(--color-btn-inset-shadow, inset 0 1px 0 rgba(255, 255, 255, 0.25)))',
'border-radius': '6px',
'border-width': '1px',
'border-style': 'solid',
'border-image': 'initial',
'border-color':
'var(--button-default-borderColor-rest, var(--button-default-borderColor-rest, var(--color-btn-border, rgba(27, 31, 36, 0.15))))',
'text-decoration': 'none',
};

// Define the View component
const View = ({ developerNetwork, target }: Props): JSX.Element => {
// Define state variables, including options, whether to show the chart, and whether to show the repository network
const [options, setOptions] = useState<HypercrxOptions>(defaults);
const [showGraph, setShowGraph] = useState(true);
const [showRepoNetwork, setShowRepoNetwork] = useState(false);

// Use the translation function
const { t, i18n } = useTranslation();

// Use the useEffect hook to handle side effects, including fetching options and changing the language
useEffect(() => {
(async function () {
setOptions(await optionsStorage.getAll());
i18n.changeLanguage(options.locale);
})();
}, [options.locale]);

// Return JSX elements, including a button and a conditionally rendered chart or target HTML
Comment on lines +55 to +73
Copy link
Collaborator

Choose a reason for hiding this comment

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

I like your comments, but some of these are not needed. Let's remove the comments here and similar simple comments elsewhere. Thanks!

return (
<div>
<button onClick={() => setShowGraph(!showGraph)} style={buttonStyle}>
{showGraph ? 'Contributor List' : 'Developer Collaboration Network'}
</button>
{showGraph ? (
<div className="hypertrons-crx-border hypertrons-crx-container">
<div className="d-flex flex-wrap flex-items-center" style={{ margin: '0 0 0 0', padding: '0' }}>
<div style={{ margin: '0 0 0 0', padding: '0', display: 'block' }}>
<Graph data={developerNetwork} style={graphStyle} />
</div>
</div>
</div>
) : (
<div dangerouslySetInnerHTML={{ __html: target }} style={targetStyle} />
)}
</div>
);
};

// Export the View component
export default View;
2 changes: 1 addition & 1 deletion src/pages/ContentScripts/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import './index.scss';

import './features/contributor_button';
import './features/repo-activity-openrank-trends';
import './features/developer-activity-openrank-trends';
import './features/repo-header-labels';
Expand Down
Loading