Skip to content

Commit 28c6fd3

Browse files
committed
Merge branch 'main' into qr
2 parents 2356285 + da15a27 commit 28c6fd3

File tree

23 files changed

+251
-252
lines changed

23 files changed

+251
-252
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,5 @@ coverage
2626

2727
package-lock.json
2828
aaa
29+
30+
user-chart.svg

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ All notable changes to Time Tracker will be documented in this file.
44

55
It is worth mentioning that the release time of each change refers to the time when the installation package is submitted to the webstore. It is about one week for Edge to moderate packages, while only 1-2 days for Chrome and Firefox.
66

7+
## [2.5.2] - 2024-11-03
8+
9+
- Fixed a bug of Firefox v132
10+
11+
## [2.5.1] - 2024-11-01
12+
13+
- Fixed some bugs
14+
715
## [2.5.0] - 2024-10-19
816

917
- Supported RTL and Arabic

doc/dev-guide.md

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,50 +4,54 @@
44

55
使用到的技术栈有:
66

7-
* [webpack](https://github.com/webpack/webpack) + [TypeScript](https://github.com/microsoft/TypeScript)
8-
* [Vue3 (Composition API)](https://vuejs.org/api/#:~:text=defineCustomElement()-,Composition%20API,-setup())
9-
* [sass](https://github.com/sass/sass)
10-
* [Element Plus](https://element-plus.gitee.io/)
11-
* [echarts](https://github.com/apache/echarts)
7+
- [webpack](https://github.com/webpack/webpack) + [TypeScript](https://github.com/microsoft/TypeScript)
8+
- [Vue3 (Composition API)](<https://vuejs.org/api/#:~:text=defineCustomElement()-,Composition%20API,-setup()>)
9+
- [sass](https://github.com/sass/sass)
10+
- [Element Plus](https://element-plus.gitee.io/)
11+
- [echarts](https://github.com/apache/echarts)
1212

1313
以及 [Chrome Extension 开发文档](https://developer.chrome.com/docs/webstore/),目前 manifest 的版本 Chrome 和 Edge 使用的使 v3, Firefox 使用的是 v2。请注意接口兼容。
1414

1515
还集成了一些免费的开源工具:
1616

17-
* 单元测试工具 [jest](https://jestjs.io/docs/getting-started)
18-
* 单元测试覆盖率 [Codecov](https://app.codecov.io/gh/sheepzh/timer)
19-
* 代码质量检测 [CODEBEAT](https://codebeat.co/projects/github-com-sheepzh-timer-main)
20-
* 多语言翻译管理 [Crowdin](https://crowdin.com/project/timer-chrome-edge-firefox)
17+
- 单元测试工具 [jest](https://jestjs.io/docs/getting-started)
18+
- 单元测试覆盖率 [Codecov](https://app.codecov.io/gh/sheepzh/timer)
19+
- 代码质量检测 [CODEBEAT](https://codebeat.co/projects/github-com-sheepzh-timer-main)
20+
- 多语言翻译管理 [Crowdin](https://crowdin.com/project/timer-chrome-edge-firefox)
2121

2222
## 2. 开发步骤
2323

2424
1. fork 自己的仓库
2525
2. 安装依赖
26+
2627
```shell
2728
npm install
2829
```
30+
2931
3. 创建对应的需求分支
3032
4. code
3133
5. run 开发环境
32-
首先执行命令
34+
首先执行命令
35+
3336
```shell
3437
npm run dev
3538
# 在 Firefox 中测试
3639
npm run dev:firefox
37-
# Optional to fix some error caused by node-sass
38-
npm rebuild node-sass
3940
```
4041

4142
项目根目录下会输出两个文件夹,dist_dev 和 firefox_dev。
4243

4344
然后根据测试浏览器的不同导入不同的文件夹到浏览器中:
4445

45-
* Chrome 和 Edge 导入 dist_dev 文件夹
46-
* Firefox 导入 firefox_dev 文件夹下的 manifest.json 文件。
46+
- Chrome 和 Edge 导入 dist_dev 文件夹
47+
- Firefox 导入 firefox_dev 文件夹下的 manifest.json 文件。
48+
4749
6. 运行单元测试
50+
4851
```shell
4952
npm run test
5053
```
54+
5155
7. 提交代码,并 PR 主仓库的 main 分支
5256

5357
## 3. 应用架构设计
@@ -107,10 +111,12 @@ project
107111
## 5. 代码格式
108112

109113
请使用 VSCode 自带的代码格式工具,请<u>**禁用 Prettier Eslint**</u> 等格式化工具
110-
* 尽量使用单引号
111-
* 在符合语法正确情况下,尽量保持代码简洁
112-
* 行尾无分号
113-
* 换行符使用 LF (\n),Windows 下需要执行以下指令关闭警告
114+
115+
- 尽量使用单引号
116+
- 在符合语法正确情况下,尽量保持代码简洁
117+
- 行尾无分号
118+
- 换行符使用 LF (\n),Windows 下需要执行以下指令关闭警告
119+
114120
```
115121
git config core.autocrlf false
116122
```

package.json

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "timer",
3-
"version": "2.5.0",
3+
"version": "2.5.2",
44
"description": "Time tracker",
55
"homepage": "https://www.wfhg.cc",
66
"scripts": {
@@ -24,16 +24,16 @@
2424
},
2525
"license": "MIT",
2626
"devDependencies": {
27-
"@babel/plugin-transform-modules-commonjs": "^7.25.7",
28-
"@babel/preset-env": "^7.25.8",
29-
"@crowdin/crowdin-api-client": "^1.38.0",
30-
"@types/chrome": "0.0.278",
31-
"@types/copy-webpack-plugin": "^10.1.0",
27+
"@babel/plugin-transform-modules-commonjs": "^7.25.9",
28+
"@babel/preset-env": "^7.26.0",
29+
"@crowdin/crowdin-api-client": "^1.39.0",
30+
"@types/chrome": "0.0.280",
31+
"@types/copy-webpack-plugin": "^10.1.3",
3232
"@types/decompress": "^4.2.7",
3333
"@types/echarts": "^4.9.22",
3434
"@types/generate-json-webpack-plugin": "^0.3.7",
35-
"@types/jest": "^29.5.13",
36-
"@types/node": "^22.7.6",
35+
"@types/jest": "^29.5.14",
36+
"@types/node": "^22.8.7",
3737
"@types/psl": "^1.1.3",
3838
"@types/punycode": "^2.1.4",
3939
"@types/webpack": "^5.28.5",
@@ -43,36 +43,36 @@
4343
"copy-webpack-plugin": "^12.0.2",
4444
"css-loader": "^7.1.2",
4545
"decompress": "^4.2.1",
46-
"eslint": "^9.12.0",
46+
"eslint": "^9.14.0",
4747
"filemanager-webpack-plugin": "^8.0.0",
4848
"generate-json-webpack-plugin": "^2.0.0",
49-
"html-webpack-plugin": "^5.6.2",
49+
"html-webpack-plugin": "^5.6.3",
5050
"jest": "^29.7.0",
5151
"jest-environment-jsdom": "^29.7.0",
52-
"mini-css-extract-plugin": "^2.9.1",
52+
"mini-css-extract-plugin": "^2.9.2",
5353
"postcss": "^8.4.47",
5454
"postcss-loader": "^8.1.1",
5555
"postcss-rtlcss": "^5.5.0",
56-
"sass": "^1.80.2",
57-
"sass-loader": "^16.0.2",
56+
"sass": "^1.80.6",
57+
"sass-loader": "^16.0.3",
5858
"style-loader": "^4.0.0",
5959
"ts-jest": "^29.2.5",
6060
"ts-loader": "^9.5.1",
6161
"ts-node": "^10.9.2",
6262
"tsconfig-paths": "^4.2.0",
63-
"tslib": "^2.8.0",
63+
"tslib": "^2.8.1",
6464
"typescript": "5.6.3",
6565
"url-loader": "^4.1.1",
66-
"webpack": "^5.95.0",
66+
"webpack": "^5.96.1",
6767
"webpack-bundle-analyzer": "^4.10.2",
6868
"webpack-cli": "^5.1.4"
6969
},
7070
"dependencies": {
7171
"@element-plus/icons-vue": "^2.3.1",
72-
"@vueuse/core": "^11.1.0",
72+
"@vueuse/core": "^11.2.0",
7373
"countup.js": "^2.8.0",
7474
"echarts": "^5.5.1",
75-
"element-plus": "2.8.6",
75+
"element-plus": "2.8.7",
7676
"js-base64": "^3.7.7",
7777
"punycode": "^2.3.1",
7878
"stream-browserify": "^3.0.0",

script/user-chart/render.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import {
77
GistForm,
88
updateGist
99
} from "@api/gist"
10-
import { filenameOf, getExistGist, validateTokenFromEnv } from "./common"
1110
import { EChartsType, init } from "echarts"
11+
import { writeFileSync } from "fs"
1212
import { exit } from "process"
13+
import { filenameOf, getExistGist, validateTokenFromEnv } from "./common"
1314

1415
const ALL_BROWSERS: Browser[] = ['firefox', 'edge', 'chrome']
1516

@@ -210,6 +211,7 @@ async function main(): Promise<void> {
210211
const chartData = preProcess(originData)
211212
// 3. render csv
212213
const svg = render2Svg(chartData)
214+
writeFileSync('user-chart.svg', svg, 'utf-8')
213215
// 4. upload
214216
await upload2Gist(token, svg)
215217
// 5. finish

src/api/gist.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ async function post<T, R>(token: string, uri: string, body?: R): Promise<T> {
6363
}
6464
})
6565
const result = await response.json()
66-
if (response.status === 200) {
66+
const { status } = response
67+
if (status >= 200 && status < 300) {
6768
// Clear cache if success to request
6869
GET_CACHE.clear()
6970
return result as T

src/app/components/Analysis/components/Summary/Calendar/Wrapper.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
import { t } from "@app/locale"
88
import { periodFormatter } from "@app/util/time"
99
import { EchartsWrapper } from "@hooks/useEcharts"
10-
import { locale } from "@i18n"
10+
import weekHelper from "@service/components/week-helper"
1111
import { groupBy, rotate } from "@util/array"
1212
import { getRegularTextColor, getSecondaryTextColor } from "@util/style"
13-
import { formatTime, getAllDatesBetween, getWeeksAgo, parseTime } from "@util/time"
13+
import { formatTime, getAllDatesBetween, MILL_PER_WEEK, parseTime } from "@util/time"
1414
import {
1515
ComposeOption,
1616
EffectScatterSeriesOption,
@@ -148,11 +148,11 @@ export type BizOption = {
148148
class Wrapper extends EchartsWrapper<BizOption, EcOption> {
149149
isSizeSensitize = true
150150

151-
protected generateOption({ rows = [], timeFormat }: BizOption): EcOption | Promise<EcOption> {
151+
protected async generateOption({ rows = [], timeFormat }: BizOption): Promise<EcOption> {
152152
const width = this.getDomWidth()
153-
const weekNum = getWeekNum(width)
153+
const colNum = getWeekNum(width)
154154
const endTime = new Date()
155-
const startTime = getWeeksAgo(endTime, locale === "zh_CN", weekNum)
155+
const [startTime,] = await weekHelper.getWeekDate(endTime.getTime() - MILL_PER_WEEK * (colNum - 1))
156156
const allDates = getAllDatesBetween(startTime, endTime)
157157
const value = groupBy(rows, r => r.date, l => l?.[0]?.focus)
158158
const data: _Value[] = []
@@ -163,12 +163,9 @@ class Wrapper extends EchartsWrapper<BizOption, EcOption> {
163163
const x = colIndex, y = 7 - (1 + weekDay)
164164
data.push([x, y, dailyMills, date])
165165
})
166+
const weekStart = await weekHelper.getRealWeekStart()
166167
const weekDays = (t(msg => msg.calendar.weekDays)?.split?.('|') || []).reverse()
167-
if (locale !== "zh_CN") {
168-
// Let Sunday last
169-
// Saturday to Sunday
170-
rotate(weekDays, 1)
171-
}
168+
rotate(weekDays, weekStart, true)
172169
return optionOf(data, weekDays, timeFormat, width)
173170
}
174171
}

src/app/components/Dashboard/components/Calendar/Wrapper.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,24 @@
66
*/
77
import type {
88
ComposeOption,
9-
TooltipComponentOption, GridComponentOption, VisualMapComponentOption,
10-
ScatterSeriesOption, HeatmapSeriesOption,
9+
GridComponentOption,
10+
HeatmapSeriesOption,
11+
ScatterSeriesOption,
12+
TooltipComponentOption,
13+
VisualMapComponentOption,
1114
} from "echarts"
1215

13-
import { EchartsWrapper } from "@hooks/useEcharts"
14-
import { formatPeriodCommon, getAllDatesBetween, MILL_PER_HOUR, MILL_PER_MINUTE } from "@util/time"
15-
import { groupBy, rotate } from "@util/array"
16+
import { createTabAfterCurrent } from "@api/chrome/tab"
1617
import { t } from "@app/locale"
17-
import { getPrimaryTextColor } from "@util/style"
18-
import { getAppPageUrl } from "@util/constant/url"
1918
import { REPORT_ROUTE } from "@app/router/constants"
20-
import { createTabAfterCurrent } from "@api/chrome/tab"
2119
import { getStepColors } from "@app/util/echarts"
22-
import { locale } from "@i18n"
2320
import { cvt2LocaleTime } from "@app/util/time"
21+
import { EchartsWrapper } from "@hooks/useEcharts"
22+
import weekHelper from "@service/components/week-helper"
23+
import { groupBy, rotate } from "@util/array"
24+
import { getAppPageUrl } from "@util/constant/url"
25+
import { getPrimaryTextColor } from "@util/style"
26+
import { formatPeriodCommon, getAllDatesBetween, MILL_PER_HOUR, MILL_PER_MINUTE } from "@util/time"
2427

2528
type _Value = [
2629
x: number,
@@ -197,7 +200,7 @@ function handleClick(value: _Value): void {
197200
class Wrapper extends EchartsWrapper<BizOption, EcOption> {
198201
protected isSizeSensitize: boolean = true
199202

200-
protected generateOption(option: BizOption): EcOption | Promise<EcOption> {
203+
protected async generateOption(option: BizOption): Promise<EcOption> {
201204
if (!option) return {}
202205

203206
const { startTime, endTime, value } = option
@@ -211,11 +214,8 @@ class Wrapper extends EchartsWrapper<BizOption, EcOption> {
211214
data.push([x, y, dailyMills, date])
212215
})
213216
const weekDays = (t(msg => msg.calendar.weekDays)?.split?.('|') || []).reverse()
214-
if (locale !== "zh_CN") {
215-
// Let Sunday last
216-
// Saturday to Sunday
217-
rotate(weekDays, 1)
218-
}
217+
const weekStart = await weekHelper.getRealWeekStart()
218+
weekStart && rotate(weekDays, weekStart, true)
219219
return optionOf(data, weekDays, this.getDom())
220220
}
221221

src/app/components/Dashboard/components/Calendar/index.tsx

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,22 @@
55
* https://opensource.org/licenses/MIT
66
*/
77

8+
import { t } from "@app/locale"
89
import { useRequest } from "@hooks"
910
import { useEcharts } from "@hooks/useEcharts"
10-
import { locale } from "@i18n"
11+
import weekHelper from "@service/components/week-helper"
1112
import statService from "@service/stat-service"
12-
import { getWeeksAgo, MILL_PER_HOUR } from "@util/time"
13-
import { defineComponent } from "vue"
14-
import Wrapper, { BizOption } from "./Wrapper"
1513
import { groupBy, sum } from "@util/array"
16-
import { t } from "@app/locale"
14+
import { formatTimeYMD, MILL_PER_DAY, MILL_PER_HOUR } from "@util/time"
15+
import { computed, defineComponent } from "vue"
1716
import ChartTitle from "../../ChartTitle"
17+
import Wrapper, { BizOption } from "./Wrapper"
1818

19-
const WEEK_NUM = 53
20-
21-
const titleText = (option: BizOption) => {
22-
const { value } = option || {}
23-
const totalMills = sum(Object.values(value || {}))
19+
const titleText = (option: Result) => {
20+
const { value, yearAgo } = option || {}
21+
const start = formatTimeYMD(yearAgo)
22+
const statValues = Object.entries(value || {}).filter(([date]) => date.localeCompare(start) >= 0).map(([, v]) => v)
23+
const totalMills = sum(statValues)
2424
const totalHours = Math.floor(totalMills / MILL_PER_HOUR)
2525
return t(msg => totalHours
2626
? msg.dashboard.heatMap.title0
@@ -29,21 +29,25 @@ const titleText = (option: BizOption) => {
2929
)
3030
}
3131

32-
const fetchData = async (): Promise<BizOption> => {
32+
type Result = BizOption & { yearAgo: Date }
33+
34+
const fetchData = async (): Promise<Result> => {
3335
const endTime = new Date()
34-
const startTime: Date = getWeeksAgo(endTime, locale === "zh_CN", WEEK_NUM)
36+
const yearAgo = new Date(endTime.getTime() - MILL_PER_DAY * 365)
37+
const [startTime] = await weekHelper.getWeekDate(yearAgo)
3538
const items = await statService.select({ date: [startTime, endTime], sort: "date" })
3639
const value = groupBy(
3740
items,
3841
i => i.date,
3942
list => sum(list?.map(i => i.focus ?? 0))
4043
)
41-
return { value, startTime, endTime }
44+
return { value, startTime, endTime, yearAgo }
4245
}
4346

4447
const _default = defineComponent(() => {
4548
const { data } = useRequest(fetchData)
46-
const { elRef } = useEcharts(Wrapper, data)
49+
const biz = computed(() => (data.value as BizOption))
50+
const { elRef } = useEcharts(Wrapper, biz)
4751

4852
return () => (
4953
<div class="calendar-container">

0 commit comments

Comments
 (0)