Skip to content
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
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
);
};

/**
* 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