Skip to content

Commit 3da0ba4

Browse files
committed
Add chart js and prepare for donut chart
1 parent 3d34bcb commit 3da0ba4

File tree

13 files changed

+305
-157
lines changed

13 files changed

+305
-157
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
"script:zip": "powershell scripts/zip.ps1"
1515
},
1616
"dependencies": {
17-
"vue": "^3.2.47"
17+
"chart.js": "^4.3.0",
1818
"date-fns": "^2.30.0",
19+
"vue": "^3.2.47",
20+
"vue-chartjs": "^5.2.0"
1921
},
2022
"devDependencies": {
2123
"@types/webextension-polyfill": "^0.10.0",

pnpm-lock.yaml

Lines changed: 43 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/assets/css/main.css

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
:root {
22
--main-color: #6ebf5d;
33
--popup-header: #f3f3f3;
4-
--progress-bar: #a6afa3;
4+
--progress-bar: #6ebf5d;
55
}
66
::-webkit-scrollbar-track {
77
border-radius: 10px;
@@ -42,6 +42,11 @@ body {
4242
.text-center {
4343
text-align: center;
4444
}
45+
.no-data{
46+
text-align: center;
47+
font-size: 16px;
48+
font-weight: 600;
49+
}
4550
.tabs {
4651
}
4752
.tabs input[name='tab-control'] {

src/components/DonutChart.vue

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<template>
2+
<div class="chart">
3+
<Doughnut :data="data" :options="options" :plugins="plugins" />
4+
</div>
5+
</template>
6+
7+
<script lang="ts">
8+
export default {
9+
name: 'DonutChart',
10+
};
11+
</script>
12+
13+
<script lang="ts" setup>
14+
import { Doughnut } from 'vue-chartjs';
15+
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js';
16+
17+
const props = defineProps<{
18+
time: number[];
19+
labels: string[];
20+
}>();
21+
22+
ChartJS.register(ArcElement, Tooltip, Legend);
23+
24+
const data = {
25+
labels: props.labels,
26+
datasets: [
27+
{
28+
backgroundColor: [
29+
'#5668e2',
30+
'#8a56e2',
31+
'#cf56e2',
32+
'#e256ae',
33+
'#e25668',
34+
'#e28956',
35+
'#e2cf56',
36+
'#d0ff82',
37+
'#aee256',
38+
'#68e256',
39+
],
40+
data: props.time,
41+
},
42+
],
43+
};
44+
45+
const options = {
46+
responsive: true,
47+
maintainAspectRatio: false,
48+
layout: {
49+
padding: 0,
50+
},
51+
plugins: {
52+
legend: {
53+
position: 'right',
54+
},
55+
legendDistance: {
56+
padding: 50,
57+
},
58+
},
59+
};
60+
61+
const plugins = [
62+
{
63+
id: 'legendDistance',
64+
beforeInit(chart: any, args: any, opts: any) {
65+
const originalFit = chart.legend.fit;
66+
chart.legend.fit = function fit() {
67+
originalFit.bind(chart.legend)();
68+
this.width += opts.padding || 0;
69+
};
70+
},
71+
},
72+
];
73+
</script>
74+
75+
<style scoped>
76+
.chart {
77+
height: 230px;
78+
margin: -10px 0 10px 0;
79+
}
80+
</style>

src/components/TabItem.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const styleForProgressBar = computed(() => `width: ${percent}%`);
5656
padding: 7px;
5757
border: 1px transparent solid;
5858
border-radius: 10px;
59-
margin: 10px;
59+
margin: 5px 15px;
6060
display: flex;
6161
justify-content: flex-start;
6262
align-items: center;

src/components/TabItemHeader.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const summaryTimeString = computed(() => convertSummaryTimeToString(props.summar
3939
}
4040
p {
4141
font-size: 14px;
42-
margin: 5px;
42+
margin: 0;
4343
}
4444
.time {
4545
font-size: 16px;

src/components/TabList.vue

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
<template>
2-
<TabItemHeader
3-
:listType="type"
4-
:summaryTime="summaryTime"
5-
:countOfSites="countOfSites"
6-
:firstDay="firstDay"
7-
/>
8-
<TabItem v-for="(tab, i) of tabs" :key="i" :tab="tab" :summaryTime="summaryTime" />
2+
<div class="no-data" v-if="countOfSites == undefined || countOfSites == 0">No data</div>
3+
<div v-else>
4+
<DonutChart :time="timeForChart" :labels="sitesForChart" />
5+
<TabItemHeader
6+
:listType="type"
7+
:summaryTime="summaryTime"
8+
:countOfSites="countOfSites"
9+
:firstDay="firstDay"
10+
/>
11+
<TabItem v-for="(tab, i) of tabs" :key="i" :tab="tab" :summaryTime="summaryTime" />
12+
</div>
913
</template>
1014

1115
<script lang="ts">
@@ -18,6 +22,7 @@ export default {
1822
import { computed, onMounted, ref } from 'vue';
1923
import TabItem from '../components/TabItem.vue';
2024
import TabItemHeader from '../components/TabItemHeader.vue';
25+
import DonutChart from '../components/DonutChart.vue';
2126
import { injectTabsRepository } from '../repository/inject-tabs-repository';
2227
import { Tab } from '../entity/tab';
2328
import { todayLocalDate } from '../utils/today';
@@ -28,30 +33,42 @@ const props = defineProps<{
2833
}>();
2934
3035
const tabs = ref<Tab[]>();
31-
const summaryTime = computed(() => {
32-
const summaryTimeList = tabs.value?.map(function (tab) {
33-
return tab.days.find(day => day.date === todayLocalDate())!.summary;
34-
});
35-
return summaryTimeList != undefined
36-
? summaryTimeList.reduce(function (a, b) {
37-
return a + b;
38-
})
39-
: 0;
40-
});
4136
42-
const countOfSites = computed(() => tabs.value?.length);
37+
const timeForChart = ref<number[]>();
38+
const sitesForChart = ref<string[]>();
39+
40+
const summaryTime = ref<number>();
41+
42+
const countOfSites = computed(() => (tabs.value != undefined ? tabs.value.length : 0));
43+
4344
const firstDay = computed(() => {
4445
if (props.type == TypeOfList.All) return;
4546
});
4647
4748
onMounted(async () => {
4849
const repo = await injectTabsRepository();
4950
let unSortedTabs = repo.getTodayTabs();
50-
tabs.value = unSortedTabs?.sort(function (a: Tab, b: Tab) {
51+
tabs.value = unSortedTabs.sort(function (a: Tab, b: Tab) {
5152
return (
5253
b.days.find(s => s.date === todayLocalDate())!.summary -
5354
a.days.find(s => s.date === todayLocalDate())!.summary
5455
);
5556
});
57+
58+
const summaryTimeList = tabs.value?.map(function (tab) {
59+
return tab.days.find(day => day.date === todayLocalDate())!.summary;
60+
});
61+
const siteList = tabs.value?.map(function (tab) {
62+
return tab.url;
63+
});
64+
timeForChart.value = summaryTimeList?.slice(0, 10);
65+
sitesForChart.value = siteList?.slice(0, 10);
66+
67+
summaryTime.value =
68+
summaryTimeList != undefined && summaryTimeList.length > 0
69+
? summaryTimeList.reduce(function (a, b) {
70+
return a + b;
71+
})
72+
: 0;
5673
});
5774
</script>

src/compositions/black-list.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
import { injecStorage } from "../storage/inject-storage";
2-
import { StorageParams } from "../storage/storage-params";
3-
import { isDomainEquals } from "../utils/common";
4-
import { extractHostname } from "./extract-hostname";
1+
import { injecStorage } from '../storage/inject-storage';
2+
import { StorageParams } from '../storage/storage-params';
3+
import { isDomainEquals } from '../utils/common';
4+
import { extractHostname } from './extract-hostname';
55

6-
export async function isInBlackList(url: string): Promise<boolean>{
7-
const storage = injecStorage();
8-
const blackList = await storage.getValue(StorageParams.BLACK_LIST) as string[];
9-
return blackList?.find(x => isDomainEquals(extractHostname(x), extractHostname(url))) !== undefined;
10-
}
6+
export async function isInBlackList(url: string): Promise<boolean> {
7+
const storage = injecStorage();
8+
const blackList = (await storage.getValue(StorageParams.BLACK_LIST)) as string[];
9+
return (
10+
blackList?.find(x => isDomainEquals(extractHostname(x), extractHostname(url))) !== undefined
11+
);
12+
}

src/compositions/set-badge.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
1-
import Browser from "webextension-polyfill";
1+
import Browser from 'webextension-polyfill';
22

33
export interface BadgeState {
4-
color: BadgeColor;
5-
tabId: number;
6-
text: string;
4+
color: BadgeColor;
5+
tabId: number;
6+
text: string;
77
}
88

99
export enum BadgeColor {
10-
red = '#fdb8b8',
11-
green = '#6ec05e',
12-
none = '#000'
10+
red = '#fdb8b8',
11+
green = '#6ec05e',
12+
blue = '#1a73e8',
13+
none = '#000',
1314
}
1415

1516
export function useBadge(badge: BadgeState): void {
16-
Browser.action.setBadgeBackgroundColor({ color: badge.color })
17-
Browser.action.setBadgeText({
18-
tabId: badge.tabId,
19-
text: badge.text
20-
});
21-
}
17+
Browser.action.setBadgeBackgroundColor({ color: badge.color });
18+
Browser.action.setBadgeText({
19+
tabId: badge.tabId,
20+
text: badge.text,
21+
});
22+
}

0 commit comments

Comments
 (0)