Skip to content

Commit 957347a

Browse files
authored
Merge pull request #3 from Fiveneves/fiveneves
add colorful canlendar
2 parents 99674fb + 0a97d64 commit 957347a

File tree

15 files changed

+247
-222
lines changed

15 files changed

+247
-222
lines changed

src/components/Bars.tsx

+3-22
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { useEffect, useRef } from 'react';
22
import { formatNum } from '../helpers/formatter';
33
import * as echarts from 'echarts';
4-
4+
import { getInterval, judgeInterval } from '../helpers/judge-interval';
55
const LIGHT_THEME = {
66
FG_COLOR: '#24292f',
77
BG_COLOR: '#ffffff',
@@ -28,10 +28,7 @@ interface BarsProps {
2828

2929
const Bars = (props: BarsProps): JSX.Element => {
3030
const { theme, height, legend1, legend2, yName1, yName2, data1, data2, onClick } = props;
31-
const startTime = Number(data1[0][0].split('-')[0]);
32-
const endTime = Number(data1[data1.length - 1][0].split('-')[0]);
33-
const timeLength = endTime - startTime;
34-
const minInterval = timeLength > 2 ? 365 * 24 * 3600 * 1000 : 30 * 3600 * 24 * 1000;
31+
const { timeLength, minInterval } = getInterval(data1);
3532
const divEL = useRef(null);
3633

3734
const TH = theme == 'light' ? LIGHT_THEME : DARK_THEME;
@@ -155,23 +152,7 @@ const Bars = (props: BarsProps): JSX.Element => {
155152
let chartDOM = divEL.current;
156153
const instance = echarts.getInstanceByDom(chartDOM as any);
157154
if (instance) {
158-
if (timeLength > 2) {
159-
instance.on('dataZoom', (params: any) => {
160-
let option = instance.getOption() as {
161-
xAxis: { minInterval?: any }[];
162-
};
163-
const startValue = params.batch[0].start;
164-
const endValue = params.batch[0].end;
165-
let minInterval: number;
166-
if (startValue == 0 && endValue == 100) {
167-
minInterval = 365 * 24 * 3600 * 1000;
168-
} else {
169-
minInterval = 30 * 24 * 3600 * 1000;
170-
}
171-
option.xAxis[0].minInterval = minInterval;
172-
instance.setOption(option);
173-
});
174-
}
155+
judgeInterval(instance, option, timeLength);
175156
instance.setOption(option);
176157
if (onClick) {
177158
instance.on('click', (params) => {

src/helpers/judge-interval.ts

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
export function getInterval(data: any) {
2+
const startTime = Number(data[0][0].split('-')[0]);
3+
const endTime = Number(data[data.length - 1][0].split('-')[0]);
4+
const timeLength = endTime - startTime;
5+
const minInterval = timeLength > 2 ? 365 * 24 * 3600 * 1000 : 30 * 3600 * 24 * 1000;
6+
return { timeLength, minInterval };
7+
}
8+
9+
export function judgeInterval(instance: any, option: any, timeLength: number) {
10+
if (timeLength > 2) {
11+
instance.on('dataZoom', (params: any) => {
12+
let option = instance.getOption() as {
13+
xAxis: { minInterval?: any }[];
14+
};
15+
const startValue = params.batch[0].start;
16+
const endValue = params.batch[0].end;
17+
let minInterval: number;
18+
if (startValue == 0 && endValue == 100) {
19+
minInterval = 365 * 24 * 3600 * 1000;
20+
} else {
21+
minInterval = 30 * 24 * 3600 * 1000;
22+
}
23+
option.xAxis[0].minInterval = minInterval;
24+
instance.setOption(option);
25+
});
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.ant-color-picker-trigger {
2+
min-width: 10px !important;
3+
padding: 0 !important;
4+
margin-right: 4px;
5+
border: none !important;
6+
}
7+
8+
.ant-color-picker-color-block {
9+
width: 10px !important;
10+
min-width: 10px !important;
11+
height: 10px !important;
12+
}
13+
14+
.ant-color-picker-color-block-inner {
15+
width: 10px !important;
16+
min-width: 10px !important;
17+
height: 10px !important;
18+
border-radius: 3px !important;
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import features from '../../../../feature-manager';
2+
import waitFor from '../../../../helpers/wait-for';
3+
4+
import React from 'react';
5+
import { render } from 'react-dom';
6+
import { ColorPicker } from 'antd';
7+
import $ from 'jquery';
8+
import * as pageDetect from 'github-url-detection';
9+
10+
import './index.scss'; // 需要引入自定义的样式来覆盖antd ColorPicker的默认样式,后面展开说明
11+
12+
const featureId = features.getFeatureID(import.meta.url);
13+
14+
// const CALENDAR_LEVEL_COLORS = [
15+
// '#ebedf0',
16+
// '#ffedf9',
17+
// '#ffc3eb',
18+
// '#ff3ebf',
19+
// '#c70085',
20+
// ];
21+
//
22+
// const changeLevelColor = (level: number, color: string) => {
23+
// const root = document.documentElement;
24+
// if (level === 0) {
25+
// root.style.setProperty(`--color-calendar-graph-day-bg`, color);
26+
// } else {
27+
// root.style.setProperty(`--color-calendar-graph-day-L${level}-bg`, color);
28+
// }
29+
// };
30+
31+
let colors = ['#ebedf0', '#ffedf9', '#ffc3eb', '#ff3ebf', '#c70085'];
32+
33+
const changeLevelColor = async (level: number, color: string) => {
34+
const root = document.documentElement;
35+
if (level === 0) {
36+
root.style.setProperty(`--color-calendar-graph-day-bg`, color);
37+
} else {
38+
root.style.setProperty(`--color-calendar-graph-day-L${level}-bg`, color);
39+
}
40+
// Save to storage
41+
const newColors = [...colors];
42+
newColors[level] = color;
43+
await chrome.storage.local.set({
44+
calendar_level_colors: newColors,
45+
});
46+
};
47+
48+
const replaceLegendToColorPicker = async (
49+
level: number,
50+
defaultColor: string
51+
) => {
52+
const legendSelector = `#contribution-graph-legend-level-${level}`; // 选择器selector是用于定位DOM元素的字符串
53+
await waitFor(() => $(legendSelector).length > 0); // init函数运行的时候,页面中某些元素不一定已经加载完毕,经过测试,日历图加载时机比较靠后,因此需要waitFor一下,不然后面的操作都是无用的
54+
const $legend = $(legendSelector);
55+
const container = $('<div></div>');
56+
render(
57+
<ColorPicker
58+
defaultValue={defaultColor}
59+
size="small"
60+
onChange={(color, hex) => changeLevelColor(level, hex)}
61+
/>, // 选择新颜色后会调用changeLevelColor改变格子颜色
62+
container[0]
63+
); // 将React组件渲染为真实的DOM元素
64+
$legend.replaceWith(container); // 使用jQuery的replaceWith方法将图例格子替换为ColorPicker
65+
};
66+
67+
// const init = async (): Promise<void> => {
68+
// for (let i = 0; i < CALENDAR_LEVEL_COLORS.length; i++) {
69+
// changeLevelColor(i, CALENDAR_LEVEL_COLORS[i]); // 初始化时就按照给定的颜色改变日历格子的颜色
70+
// await replaceLegendToColorPicker(i, CALENDAR_LEVEL_COLORS[i]);
71+
// }
72+
// };
73+
74+
const init = async (): Promise<void> => {
75+
// Load colors from storage
76+
colors =
77+
(await chrome.storage.local.get('calendar_level_colors'))[
78+
// (await localStorage.get('calendar_level_colors'))[
79+
'calendar_level_colors'
80+
] || colors;
81+
82+
for (let i = 0; i < colors.length; i++) {
83+
changeLevelColor(i, colors[i]);
84+
replaceLegendToColorPicker(i, colors[i]);
85+
}
86+
};
87+
88+
const restore = async () => {
89+
console.log('restore colorful-calendar');
90+
};
91+
92+
features.add(featureId, {
93+
asLongAs: [pageDetect.isUserProfile],
94+
awaitDomReady: false,
95+
init,
96+
restore,
97+
});

src/pages/ContentScripts/features/repo-fork-tooltip/ForkChart.tsx

+3-22
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as echarts from 'echarts';
33

44
import { formatNum, numberWithCommas } from '../../../../helpers/formatter';
55
import { min } from 'lodash-es';
6-
6+
import { getInterval, judgeInterval } from '../../../../helpers/judge-interval';
77
const LIGHT_THEME = {
88
FG_COLOR: '#24292F',
99
BG_COLOR: '#ffffff',
@@ -29,10 +29,7 @@ interface ForkChartProps {
2929

3030
const ForkChart = (props: ForkChartProps): JSX.Element => {
3131
const { theme, width, height, data } = props;
32-
const startTime = Number(data[0][0].split('-')[0]);
33-
const endTime = Number(data[data.length - 1][0].split('-')[0]);
34-
const timeLength = endTime - startTime;
35-
const minInterval = timeLength > 2 ? 365 * 24 * 3600 * 1000 : 30 * 3600 * 24 * 1000;
32+
const { timeLength, minInterval } = getInterval(data);
3633
const divEL = useRef(null);
3734

3835
const TH = theme == 'light' ? LIGHT_THEME : DARK_THEME;
@@ -140,23 +137,7 @@ const ForkChart = (props: ForkChartProps): JSX.Element => {
140137
let chartDOM = divEL.current;
141138
const instance = echarts.getInstanceByDom(chartDOM as any);
142139
if (instance) {
143-
if (timeLength > 2) {
144-
instance.on('dataZoom', (params: any) => {
145-
let option = instance.getOption() as {
146-
xAxis: { minInterval?: any }[];
147-
};
148-
const startValue = params.batch[0].start;
149-
const endValue = params.batch[0].end;
150-
let minInterval: number;
151-
if (startValue == 0 && endValue == 100) {
152-
minInterval = 365 * 24 * 3600 * 1000;
153-
} else {
154-
minInterval = 30 * 24 * 3600 * 1000;
155-
}
156-
option.xAxis[0].minInterval = minInterval;
157-
instance.setOption(option);
158-
});
159-
}
140+
judgeInterval(instance, option, timeLength);
160141
instance.setOption(option);
161142
}
162143
}, []);

src/pages/ContentScripts/features/repo-header-labels/ActivityChart.tsx

+3-22
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react';
22
import * as echarts from 'echarts';
33

44
import { formatNum, numberWithCommas } from '../../../../helpers/formatter';
5-
5+
import { getInterval, judgeInterval } from '../../../../helpers/judge-interval';
66
const LIGHT_THEME = {
77
FG_COLOR: '#24292F',
88
BG_COLOR: '#ffffff',
@@ -28,10 +28,7 @@ interface ActivityChartProps {
2828

2929
const ActivityChart = (props: ActivityChartProps): JSX.Element => {
3030
const { theme, width, height, data } = props;
31-
const startTime = Number(data[0][0].split('-')[0]);
32-
const endTime = Number(data[data.length - 1][0].split('-')[0]);
33-
const timeLength = endTime - startTime;
34-
const minInterval = timeLength > 2 ? 365 * 24 * 3600 * 1000 : 30 * 3600 * 24 * 1000;
31+
const { timeLength, minInterval } = getInterval(data);
3532
const divEL = useRef(null);
3633

3734
const TH = theme == 'light' ? LIGHT_THEME : DARK_THEME;
@@ -139,23 +136,7 @@ const ActivityChart = (props: ActivityChartProps): JSX.Element => {
139136
let chartDOM = divEL.current;
140137
const instance = echarts.getInstanceByDom(chartDOM as any);
141138
if (instance) {
142-
if (timeLength > 2) {
143-
instance.on('dataZoom', (params: any) => {
144-
let option = instance.getOption() as {
145-
xAxis: { minInterval?: any }[];
146-
};
147-
const startValue = params.batch[0].start;
148-
const endValue = params.batch[0].end;
149-
let minInterval: number;
150-
if (startValue == 0 && endValue == 100) {
151-
minInterval = 365 * 24 * 3600 * 1000;
152-
} else {
153-
minInterval = 30 * 24 * 3600 * 1000;
154-
}
155-
option.xAxis[0].minInterval = minInterval;
156-
instance.setOption(option);
157-
});
158-
}
139+
judgeInterval(instance, option, timeLength);
159140
instance.setOption(option);
160141
}
161142
}, []);

src/pages/ContentScripts/features/repo-header-labels/ContributorChart.tsx

+3-22
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react';
22
import * as echarts from 'echarts';
33

44
import { formatNum, numberWithCommas } from '../../../../helpers/formatter';
5-
5+
import { getInterval, judgeInterval } from '../../../../helpers/judge-interval';
66
const LIGHT_THEME = {
77
FG_COLOR: '#24292F',
88
BG_COLOR: '#ffffff',
@@ -28,10 +28,7 @@ interface ContributorChartProps {
2828

2929
const ContributorChart = (props: ContributorChartProps): JSX.Element => {
3030
const { theme, width, height, data } = props;
31-
const startTime = Number(data[0][0].split('-')[0]);
32-
const endTime = Number(data[data.length - 1][0].split('-')[0]);
33-
const timeLength = endTime - startTime;
34-
const minInterval = timeLength > 2 ? 365 * 24 * 3600 * 1000 : 30 * 3600 * 24 * 1000;
31+
const { timeLength, minInterval } = getInterval(data);
3532
const divEL = useRef(null);
3633
const TH = theme == 'light' ? LIGHT_THEME : DARK_THEME;
3734

@@ -138,23 +135,7 @@ const ContributorChart = (props: ContributorChartProps): JSX.Element => {
138135
let chartDOM = divEL.current;
139136
const instance = echarts.getInstanceByDom(chartDOM as any);
140137
if (instance) {
141-
if (timeLength > 2) {
142-
instance.on('dataZoom', (params: any) => {
143-
let option = instance.getOption() as {
144-
xAxis: { minInterval?: any }[];
145-
};
146-
const startValue = params.batch[0].start;
147-
const endValue = params.batch[0].end;
148-
let minInterval: number;
149-
if (startValue == 0 && endValue == 100) {
150-
minInterval = 365 * 24 * 3600 * 1000;
151-
} else {
152-
minInterval = 30 * 24 * 3600 * 1000;
153-
}
154-
option.xAxis[0].minInterval = minInterval;
155-
instance.setOption(option);
156-
});
157-
}
138+
judgeInterval(instance, option, timeLength);
158139
instance.setOption(option);
159140
}
160141
}, []);

src/pages/ContentScripts/features/repo-header-labels/OpenRankChart.tsx

+3-22
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react';
22
import * as echarts from 'echarts';
33

44
import { formatNum, numberWithCommas } from '../../../../helpers/formatter';
5-
5+
import { getInterval, judgeInterval } from '../../../../helpers/judge-interval';
66
const LIGHT_THEME = {
77
FG_COLOR: '#24292F',
88
BG_COLOR: '#ffffff',
@@ -28,10 +28,7 @@ interface OpenRankChartProps {
2828

2929
const OpenRankChart = (props: OpenRankChartProps): JSX.Element => {
3030
const { theme, width, height, data } = props;
31-
const startTime = Number(data[0][0].split('-')[0]);
32-
const endTime = Number(data[data.length - 1][0].split('-')[0]);
33-
const timeLength = endTime - startTime;
34-
const minInterval = timeLength > 2 ? 365 * 24 * 3600 * 1000 : 30 * 3600 * 24 * 1000;
31+
const { timeLength, minInterval } = getInterval(data);
3532
const divEL = useRef(null);
3633

3734
const TH = theme == 'light' ? LIGHT_THEME : DARK_THEME;
@@ -139,23 +136,7 @@ const OpenRankChart = (props: OpenRankChartProps): JSX.Element => {
139136
let chartDOM = divEL.current;
140137
const instance = echarts.getInstanceByDom(chartDOM as any);
141138
if (instance) {
142-
if (timeLength > 2) {
143-
instance.on('dataZoom', (params: any) => {
144-
let option = instance.getOption() as {
145-
xAxis: { minInterval?: any }[];
146-
};
147-
const startValue = params.batch[0].start;
148-
const endValue = params.batch[0].end;
149-
let minInterval: number;
150-
if (startValue == 0 && endValue == 100) {
151-
minInterval = 365 * 24 * 3600 * 1000;
152-
} else {
153-
minInterval = 30 * 24 * 3600 * 1000;
154-
}
155-
option.xAxis[0].minInterval = minInterval;
156-
instance.setOption(option);
157-
});
158-
}
139+
judgeInterval(instance, option, timeLength);
159140
instance.setOption(option);
160141
}
161142
}, []);

0 commit comments

Comments
 (0)