Skip to content

Commit 0656a4c

Browse files
feat: add gitee percetor (hypertrons#964)
* feat: add gitee percetor * update
1 parent 5f87536 commit 0656a4c

8 files changed

Lines changed: 200 additions & 7 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React from 'react';
2+
import $ from 'jquery';
3+
import { createRoot } from 'react-dom/client';
4+
import features from '../../../../feature-manager';
5+
import isPerceptor from '../../../../helpers/is-perceptor';
6+
import View from './view';
7+
import isGitee from '../../../../helpers/is-gitee';
8+
9+
const featureId = features.getFeatureID(import.meta.url);
10+
11+
const renderTo = (container: any) => {
12+
createRoot(container).render(<View />);
13+
};
14+
15+
const init = async (): Promise<void> => {
16+
const uiContainer = $('.site-content > .ui.container');
17+
uiContainer.empty();
18+
19+
// create the new one: the percepter container
20+
const percepterContainer = document.createElement('div');
21+
percepterContainer.id = featureId;
22+
23+
uiContainer.append(percepterContainer);
24+
25+
renderTo(percepterContainer);
26+
};
27+
28+
features.add(featureId, {
29+
asLongAs: [isGitee, isPerceptor],
30+
awaitDomReady: false,
31+
init,
32+
});
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import elementReady from 'element-ready';
2+
import iconSvgPath from './icon-svg-path';
3+
import features from '../../../../feature-manager';
4+
import isPerceptor from '../../../../helpers/is-perceptor';
5+
import { isPublicRepo } from '../../../../helpers/get-gitee-repo-info';
6+
import isGitee from '../../../../helpers/is-gitee';
7+
8+
const featureId = features.getFeatureID(import.meta.url);
9+
10+
const addPerceptorTab = async (): Promise<void | false> => {
11+
// Wait for the secondary navigation menu to load
12+
const menuContainer = await elementReady('.ui.secondary.pointing.menu', { waitForChildren: false });
13+
if (!menuContainer) {
14+
return false;
15+
}
16+
17+
// Create the Perceptor tab based on the pipeline tab
18+
const pipelineTab = await elementReady('a.item[href*="/gitee_go"]', { waitForChildren: false });
19+
if (!pipelineTab) {
20+
return false;
21+
}
22+
23+
const perceptorTab = pipelineTab.cloneNode(true) as HTMLAnchorElement;
24+
perceptorTab.classList.remove('active');
25+
const perceptorHref = `${location.pathname}?redirect=perceptor`;
26+
perceptorTab.href = perceptorHref;
27+
perceptorTab.id = featureId;
28+
29+
// Replace the icon and text
30+
const iconElement = perceptorTab.querySelector('i.iconfont') as HTMLElement;
31+
if (iconElement) {
32+
iconElement.className = 'iconfont';
33+
iconElement.innerHTML = `<svg width="16" height="16" viewBox="0 0 16 16" style="margin-right: 4px">${iconSvgPath}</svg>`;
34+
}
35+
36+
// Clear existing text nodes
37+
perceptorTab.childNodes.forEach((node) => {
38+
if (node.nodeType === Node.TEXT_NODE) {
39+
node.remove();
40+
}
41+
});
42+
43+
// Add new text node
44+
const textNode = document.createTextNode('\nPerceptor\n');
45+
iconElement?.after(textNode);
46+
47+
// Add the Perceptor tab before the service dropdown
48+
const serviceDropdown = menuContainer.querySelector('.git-project-service');
49+
if (!serviceDropdown) {
50+
console.error('Failed to find the service dropdown');
51+
return false;
52+
}
53+
serviceDropdown.parentElement?.before(perceptorTab);
54+
};
55+
56+
const updatePerceptorTabHighlighting = async (): Promise<void> => {
57+
const perceptorTab = document.getElementById(featureId) as HTMLAnchorElement;
58+
if (!perceptorTab) return;
59+
60+
const allTabs = document.querySelectorAll('.ui.secondary.pointing.menu a.item');
61+
allTabs.forEach((tab) => tab.classList.remove('active'));
62+
perceptorTab.classList.add('active');
63+
};
64+
65+
const init = async (): Promise<void> => {
66+
await addPerceptorTab();
67+
if (isPerceptor()) {
68+
await updatePerceptorTabHighlighting();
69+
}
70+
};
71+
72+
features.add(featureId, {
73+
asLongAs: [isGitee, isPublicRepo],
74+
awaitDomReady: false,
75+
init,
76+
});

src/pages/ContentScripts/features/repo-activity-racing-bar/data.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import { avatarColorStore } from './AvatarColorStore';
22
import getGithubTheme from '../../../../helpers/get-github-theme';
3-
43
import type { BarSeriesOption, EChartsOption } from 'echarts';
54
import { orderBy, take } from 'lodash-es';
6-
7-
const theme = getGithubTheme();
5+
import isGithub from '../../../../helpers/is-github';
6+
const theme = isGithub() ? getGithubTheme() : 'light';
87
const DARK_TEXT_COLOR = 'rgba(230, 237, 243, 0.9)';
98

109
export interface RepoActivityDetails {
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import React from 'react';
2+
import $ from 'jquery';
3+
import features from '../../../../feature-manager';
4+
import isPerceptor from '../../../../helpers/is-perceptor';
5+
import { getRepoName, isPublicRepoWithMeta } from '../../../../helpers/get-gitee-repo-info';
6+
import { getActivityDetails } from '../../../../api/repo';
7+
import View from './view';
8+
import DataNotFound from '../repo-networks/DataNotFound';
9+
import { RepoActivityDetails } from './data';
10+
import { createRoot } from 'react-dom/client';
11+
import { getPlatform } from '../../../../helpers/get-platform';
12+
import isGitee from '../../../../helpers/is-gitee';
13+
const featureId = features.getFeatureID(import.meta.url);
14+
let repoName: string;
15+
let repoActivityDetails: RepoActivityDetails;
16+
let platform: string;
17+
let width = '80%';
18+
const getData = async () => {
19+
repoActivityDetails = await getActivityDetails(platform, repoName);
20+
};
21+
22+
const renderTo = (container: any) => {
23+
const root = createRoot(container);
24+
if (!repoActivityDetails) {
25+
root.render(<DataNotFound />);
26+
return;
27+
}
28+
root.render(<View currentRepo={repoName} width={width} repoActivityDetails={repoActivityDetails} />);
29+
};
30+
31+
const init = async (): Promise<void> => {
32+
platform = getPlatform();
33+
repoName = getRepoName();
34+
await getData();
35+
const container = document.createElement('div');
36+
container.id = featureId;
37+
// append before render so that the container has computed width
38+
$('#hypercrx-perceptor-slot-repo-activity-racing-bar').append(container);
39+
renderTo(container);
40+
};
41+
42+
const restore = async () => {
43+
// Clicking another repo link in one repo will trigger a turbo:visit,
44+
// so in a restoration visit we should be careful of the current repo.
45+
if (repoName !== getRepoName()) {
46+
repoName = getRepoName();
47+
}
48+
// rerender the chart or it will be empty
49+
renderTo($(`#${featureId}`)[0]);
50+
};
51+
52+
features.add(featureId, {
53+
asLongAs: [isGitee, isPerceptor, isPublicRepoWithMeta],
54+
awaitDomReady: false,
55+
init,
56+
restore,
57+
});

src/pages/ContentScripts/features/repo-activity-racing-bar/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const featureId = features.getFeatureID(import.meta.url);
1414
let repoName: string;
1515
let repoActivityDetails: RepoActivityDetails;
1616
let platform: string;
17+
let width = '100%';
1718
const getData = async () => {
1819
repoActivityDetails = await getActivityDetails(platform, repoName);
1920
};
@@ -24,7 +25,7 @@ const renderTo = (container: any) => {
2425
root.render(<DataNotFound />);
2526
return;
2627
}
27-
root.render(<View currentRepo={repoName} repoActivityDetails={repoActivityDetails} />);
28+
root.render(<View currentRepo={repoName} width={width} repoActivityDetails={repoActivityDetails} />);
2829
};
2930

3031
const init = async (): Promise<void> => {

src/pages/ContentScripts/features/repo-activity-racing-bar/view.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ import { useTranslation } from 'react-i18next';
1111
import '../../../../helpers/i18n';
1212
interface Props {
1313
currentRepo: string;
14+
width: string;
1415
repoActivityDetails: RepoActivityDetails;
1516
}
1617

17-
const View = ({ currentRepo, repoActivityDetails }: Props): JSX.Element => {
18+
const View = ({ currentRepo, width, repoActivityDetails }: Props): JSX.Element => {
1819
const [options, setOptions] = useState<HypercrxOptions>(defaults);
1920
const [speed, setSpeed] = useState<number>(1);
2021
const [playing, setPlaying] = useState<boolean>(false);
@@ -28,8 +29,8 @@ const View = ({ currentRepo, repoActivityDetails }: Props): JSX.Element => {
2829
}, [options.locale]);
2930

3031
return (
31-
<div>
32-
<div className="hypertrons-crx-border hypertrons-crx-container">
32+
<div style={{ display: 'flex', justifyContent: 'center' }}>
33+
<div className="hypertrons-crx-border hypertrons-crx-container" style={{ width: width }}>
3334
<div className="hypertrons-crx-title">
3435
<span>{t('component_projectRacingBar_title')}</span>
3536
<div className="hypertrons-crx-title-extra developer-tab">

src/pages/ContentScripts/index.scss

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
:root {
2+
--borderColor-default: #d1d9e0;
3+
--bgColor-inset: var(--bgColor-muted);
4+
--bgColor-muted: #f6f8fa;
5+
--fgColor-default: #1f2328;
6+
}
17
.hypertrons-crx-container {
28
margin-top: 24px !important;
39
overflow: auto;
@@ -165,3 +171,21 @@
165171
display: inline-block;
166172
margin-left: 4px;
167173
}
174+
175+
.flex-items-center {
176+
align-items: center !important;
177+
}
178+
179+
@media (min-width: 768px) {
180+
.col-md-8 {
181+
width: 66.66666664% !important;
182+
}
183+
}
184+
.col-12 {
185+
width: 100%;
186+
}
187+
@media (min-width: 768px) {
188+
.col-md-4 {
189+
width: 33.33333332% !important;
190+
}
191+
}

src/pages/ContentScripts/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ import './features/repo-pr-tooltip/gitee-index.tsx';
1414
import './features/repo-issue-tooltip';
1515
import './features/repo-issue-tooltip/gitee-index.tsx';
1616
import './features/perceptor-tab';
17+
import './features/perceptor-tab/gitee-index.tsx';
1718
import './features/perceptor-layout';
19+
import './features/perceptor-layout/gitee-index.tsx';
1820
import './features/repo-networks';
1921
import './features/developer-networks';
2022
import './features/oss-gpt';
2123
import './features/repo-activity-racing-bar';
24+
import './features/repo-activity-racing-bar/gitee-index.tsx';
2225
import './features/developer-hovercard-info';
2326
import './features/repo-sidebar-labels';
2427
import './features/fast-pr';

0 commit comments

Comments
 (0)