Skip to content

Commit 4520ed7

Browse files
committed
Semi
1 parent dda353e commit 4520ed7

File tree

9 files changed

+176
-70
lines changed

9 files changed

+176
-70
lines changed

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"javascript.format.insertSpaceBeforeFunctionParenthesis": true,
1313
"files.eol": "\n",
1414
"cSpell.words": [
15+
"Arrayable",
1516
"Auths",
1617
"countup",
1718
"daterange",

src/app/components/Report/ReportTable/columns/FocusColumn.tsx

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

8+
import TooltipWrapper from "@app/components/common/TooltipWrapper"
89
import { t } from "@app/locale"
10+
import { periodFormatter } from "@app/util/time"
11+
import { ElTableRowScope } from "@src/element-ui/table"
912
import { Effect, ElTableColumn } from "element-plus"
1013
import { defineComponent } from "vue"
11-
import { periodFormatter } from "@app/util/time"
1214
import CompositionTable from '../../CompositionTable'
13-
import { ElTableRowScope } from "@src/element-ui/table"
1415
import { useReportFilter } from "../../context"
15-
import TooltipWrapper from "@app/components/common/TooltipWrapper"
1616

1717
const _default = defineComponent(() => {
1818
const filter = useReportFilter()

src/app/echarts.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import { BarChart, EffectScatterChart, HeatmapChart, LineChart, PieChart, ScatterChart } from "echarts/charts"
22
import {
33
GridComponent,
4+
LegendComponent,
45
TitleComponent,
56
TooltipComponent,
67
VisualMapComponent,
7-
LegendComponent,
88
} from "echarts/components"
99
import { use } from "echarts/core"
10-
import { SVGRenderer } from "echarts/renderers"
10+
import { CanvasRenderer } from "echarts/renderers"
1111

1212
export const initEcharts = () => {
1313
use([
14-
SVGRenderer,
14+
CanvasRenderer,
1515
GridComponent, TooltipComponent, TitleComponent, VisualMapComponent, LegendComponent,
1616
BarChart, PieChart, LineChart, HeatmapChart, ScatterChart, EffectScatterChart,
1717
])

src/hooks/useEcharts.ts

Lines changed: 10 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,61 +5,15 @@
55
* This software is released under the MIT License.
66
* https://opensource.org/licenses/MIT
77
*/
8-
9-
import { ElLoading } from "element-plus"
10-
import { type Ref, onMounted, ref, isRef, watch } from "vue"
11-
import { AriaComponentOption, ComposeOption, init, ECharts } from "echarts"
12-
import { useWindowSize } from "@vueuse/core"
138
import accessibilityHelper from "@service/components/accessibility-helper"
9+
import { processAria, processRtl } from "@util/chart"
10+
import { useWindowSize } from "@vueuse/core"
11+
import { AriaComponentOption, ComposeOption, ECharts, init } from "echarts"
12+
import { ElLoading } from "element-plus"
13+
import { type Ref, isRef, onMounted, ref, watch } from "vue"
1414

1515
type BaseEchartsOption = ComposeOption<AriaComponentOption>
1616

17-
export const generateAriaOption = async (): Promise<AriaComponentOption> => {
18-
const { chartDecal } = await accessibilityHelper.getOption() || {}
19-
if (!chartDecal) {
20-
return { enabled: false }
21-
}
22-
const color = "rgba(0, 0, 0, 0.2)"
23-
return {
24-
enabled: true,
25-
decal: {
26-
show: true,
27-
decals: [{
28-
color,
29-
dashArrayX: [1, 0],
30-
dashArrayY: [2, 5],
31-
rotation: .5235987755982988,
32-
}, {
33-
color,
34-
symbol: 'circle',
35-
dashArrayX: [[8, 8], [0, 8, 8, 0]],
36-
dashArrayY: [6, 0],
37-
symbolSize: .8,
38-
}, {
39-
color,
40-
dashArrayX: [1, 0],
41-
dashArrayY: [4, 3],
42-
rotation: -.7853981633974483
43-
}, {
44-
color,
45-
dashArrayX: [[6, 6], [0, 6, 6, 0]],
46-
dashArrayY: [6, 0],
47-
}, {
48-
color,
49-
dashArrayX: [[1, 0], [1, 6]],
50-
dashArrayY: [1, 0, 6, 0],
51-
rotation: .7853981633974483,
52-
}, {
53-
color,
54-
symbol: 'triangle',
55-
dashArrayX: [[9, 9], [0, 9, 9, 0]],
56-
dashArrayY: [7, 2],
57-
symbolSize: .75,
58-
}]
59-
}
60-
}
61-
}
62-
6317
export abstract class EchartsWrapper<BizOption, EchartsOption> {
6418
protected instance: ECharts
6519
/**
@@ -83,8 +37,11 @@ export abstract class EchartsWrapper<BizOption, EchartsOption> {
8337
const biz = this.lastBizOption
8438
const option = await this.generateOption(biz) as (EchartsOption & BaseEchartsOption)
8539
if (!option) return
86-
const aria = await generateAriaOption()
87-
option.aria = aria
40+
41+
const { chartDecal } = await accessibilityHelper.getOption() || {}
42+
processAria(option, chartDecal)
43+
processRtl(option)
44+
8845
this.instance.setOption(option, { notMerge: false })
8946
}
9047

src/i18n/index.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import { getUILanguage } from "@api/chrome/i18n"
99
import optionService from "@service/option-service"
10+
import { setLocale, setRtl } from "@util/document"
1011

1112
/**
1213
* Not to import this one if not necessary
@@ -112,11 +113,9 @@ function handleLocaleOption(option: timer.option.AllOption) {
112113
} else {
113114
locale = localOption as timer.Locale
114115
}
115-
if (typeof window !== 'undefined' && window?.document) {
116-
const htmlEl = document.getElementsByTagName("html")?.[0]
117-
htmlEl?.setAttribute?.("data-locale", locale)
118-
htmlEl?.setAttribute('dir', 'rtl')
119-
}
116+
117+
setLocale(locale)
118+
locale === 'en' && setRtl()
120119
}
121120

122121
/**

src/popup/components/chart/index.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@ import OptionDatabase from "@db/option-database"
1212
import { PopupQueryResult } from "@popup/common"
1313
import { defaultStatistics } from "@util/constant/option"
1414
import { PieChart } from "echarts/charts"
15-
import { LegendComponent, TitleComponent, ToolboxComponent, TooltipComponent } from "echarts/components"
15+
import { AriaComponent, LegendComponent, TitleComponent, ToolboxComponent, TooltipComponent } from "echarts/components"
1616
import { init, use } from "echarts/core"
17-
import { SVGRenderer } from "echarts/renderers"
17+
import { CanvasRenderer } from "echarts/renderers"
1818
import handleClick from "./click-handler"
1919
import { pieOptions } from "./option"
20+
import accessibilityHelper from "@service/components/accessibility-helper"
21+
import { processAria, processRtl } from "@util/chart"
2022

2123
// Register echarts
22-
use([TitleComponent, ToolboxComponent, TooltipComponent, LegendComponent, SVGRenderer, PieChart])
24+
use([TitleComponent, ToolboxComponent, TooltipComponent, LegendComponent, AriaComponent, CanvasRenderer, PieChart])
2325

2426
const optionDatabase = new OptionDatabase(chrome.storage.local)
2527

@@ -44,9 +46,15 @@ export const handleRestore = (handler: () => void) => {
4446
// Store
4547
let _queryResult: PopupQueryResult
4648

47-
function renderChart(queryResult: PopupQueryResult) {
49+
async function renderChart(queryResult: PopupQueryResult) {
4850
_queryResult = queryResult
49-
pie.setOption(pieOptions({ ...queryResult, displaySiteName }, chartContainer), true, false)
51+
const option = pieOptions({ ...queryResult, displaySiteName }, chartContainer)
52+
53+
const { chartDecal } = await accessibilityHelper.getOption() || {}
54+
processAria(option, chartDecal)
55+
processRtl(option)
56+
57+
pie.setOption(option, true, false)
5058
}
5159

5260
export default renderChart

src/util/chart.ts

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import type { AriaComponentOption, ComposeOption, GridComponentOption, LegendComponentOption, PieSeriesOption, SeriesOption } from "echarts"
2+
import { isRtl } from "./document"
3+
4+
export const processAria = (option: ComposeOption<AriaComponentOption>, chartDecal: boolean) => {
5+
if (!option) return
6+
const ariaOption = generateAriaOption(chartDecal)
7+
option.aria = ariaOption
8+
}
9+
10+
const generateAriaOption = (chartDecal: boolean): AriaComponentOption => {
11+
if (!chartDecal) {
12+
return { enabled: false }
13+
}
14+
const color = "rgba(0, 0, 0, 0.2)"
15+
return {
16+
enabled: true,
17+
decal: {
18+
show: true,
19+
decals: [{
20+
color,
21+
dashArrayX: [1, 0],
22+
dashArrayY: [2, 5],
23+
rotation: .5235987755982988,
24+
}, {
25+
color,
26+
symbol: 'circle',
27+
dashArrayX: [[8, 8], [0, 8, 8, 0]],
28+
dashArrayY: [6, 0],
29+
symbolSize: .8,
30+
}, {
31+
color,
32+
dashArrayX: [1, 0],
33+
dashArrayY: [4, 3],
34+
rotation: -.7853981633974483
35+
}, {
36+
color,
37+
dashArrayX: [[6, 6], [0, 6, 6, 0]],
38+
dashArrayY: [6, 0],
39+
}, {
40+
color,
41+
dashArrayX: [[1, 0], [1, 6]],
42+
dashArrayY: [1, 0, 6, 0],
43+
rotation: .7853981633974483,
44+
}, {
45+
color,
46+
symbol: 'triangle',
47+
dashArrayX: [[9, 9], [0, 9, 9, 0]],
48+
dashArrayY: [7, 2],
49+
symbolSize: .75,
50+
}]
51+
}
52+
}
53+
}
54+
55+
export const processRtl = (option: unknown) => {
56+
if (!isRtl() || !option) return
57+
58+
const { grid, legend, series } = option as ComposeOption<
59+
| GridComponentOption | LegendComponentOption
60+
| PieSeriesOption
61+
>
62+
processArrayLike(grid, processGridRtl)
63+
processArrayLike(legend, processLegendRtl)
64+
processArrayLike(series, processSeriesRtl)
65+
}
66+
67+
const processArrayLike = <T,>(arr: T | T[], processor: (t: T) => void) => {
68+
if (!arr) return
69+
if (Array.isArray(arr)) {
70+
arr.filter(e => !!e).forEach(processor)
71+
} else {
72+
processor?.(arr)
73+
}
74+
}
75+
76+
const processGridRtl = (option: GridComponentOption) => {
77+
// Swap right and left
78+
swapPosition(option)
79+
}
80+
81+
const processLegendRtl = (option: LegendComponentOption) => {
82+
swapPosition(option)
83+
swapAlign(option, 'align')
84+
}
85+
86+
const processSeriesRtl = (option: PieSeriesOption) => {
87+
if (option.type === 'pie') {
88+
const center = option.center
89+
if (!Array.isArray(center)) return
90+
const left = center[0]
91+
if (typeof left !== 'string' || !left.endsWith('%')) return
92+
try {
93+
const originPercentStr = left.substring(0, left.length - 1)
94+
const originPercent = left.includes('.') ? parseFloat(originPercentStr) : parseInt(originPercentStr)
95+
center[0] = `${100 - originPercent}%`
96+
} catch (ignored) { }
97+
}
98+
}
99+
100+
const swapAlign = <K extends string>(option: { [k in K]?: 'right' | 'left' | 'auto' }, key: K) => {
101+
const { [key]: align } = option || {}
102+
if (align === 'left') {
103+
option[key] = 'right'
104+
} else if (align === 'right') {
105+
option[key] = 'left'
106+
}
107+
}
108+
109+
const swapPosition = (option: { left?: string | number, right?: string | number }) => {
110+
const right = option.right
111+
option.right = option.left
112+
option.left = right
113+
}

src/util/document.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export const setRtl = () => {
2+
if (hasNotDoc()) return
3+
const htmlEl = document.getElementsByTagName("html")?.[0]
4+
htmlEl?.setAttribute('dir', 'rtl')
5+
}
6+
7+
export const setLocale = (locale: timer.Locale) => {
8+
if (hasNotDoc()) return
9+
const htmlEl = document.getElementsByTagName("html")?.[0]
10+
htmlEl?.setAttribute('data-locale', locale)
11+
}
12+
13+
const hasNotDoc = () => {
14+
if (typeof window === 'undefined') return
15+
return !window?.document
16+
}
17+
18+
export const isRtl = (): boolean => {
19+
if (hasNotDoc()) return false
20+
const htmlEl = document.getElementsByTagName("html")?.[0]
21+
return htmlEl?.getAttribute('dir') === 'rtl'
22+
}

src/util/time.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* https://opensource.org/licenses/MIT
66
*/
77

8+
import { isRtl } from "./document"
9+
810
/**
911
* Copyright (c) 2017-present PanJiaChen
1012
*
@@ -91,7 +93,11 @@ export function formatPeriod(milliseconds: number, message: { hourMsg: string, m
9193
* @return (xx+h)(xx+m)xx+s
9294
*/
9395
export function formatPeriodCommon(milliseconds: number): string {
94-
const defaultMessage = {
96+
const defaultMessage = isRtl() ? {
97+
hourMsg: 's {second} m {minute} h {hour}',
98+
minuteMsg: 's {second} m {minute}',
99+
secondMsg: 's {second}',
100+
} : {
95101
hourMsg: '{hour} h {minute} m {second} s',
96102
minuteMsg: '{minute} m {second} s',
97103
secondMsg: '{second} s',

0 commit comments

Comments
 (0)