-
-
-
-
-
-
+
+
+
+
+
diff --git a/src/components/DashboadContainer.vue b/src/components/DashboadContainer.vue
new file mode 100644
index 0000000..c56c334
--- /dev/null
+++ b/src/components/DashboadContainer.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/NoDataByDays.vue b/src/components/NoDataByDays.vue
new file mode 100644
index 0000000..836d1bd
--- /dev/null
+++ b/src/components/NoDataByDays.vue
@@ -0,0 +1,17 @@
+
+
+ {{ t('noData.message') }}
+
+
+
+
+
+
diff --git a/src/components/TabItem.vue b/src/components/TabItem.vue
index 9e3aa68..c0db64d 100644
--- a/src/components/TabItem.vue
+++ b/src/components/TabItem.vue
@@ -1,11 +1,32 @@
-
+
-
-
{{ url }}
+
+
{{ url }}
+
+
+
+
+
+
+
{{ summaryTimeForTab }}
@@ -37,7 +58,9 @@ import BadgeIcons from './BadgeIcons.vue';
import { convertSummaryTimeToString } from '../utils/converter';
import { getPercentage } from '../utils/common';
import { CurrentTabItem } from '../dto/currentTabItem';
-import { TypeOfList, TypeOfUrl } from '../utils/enums';
+import { SettingsTab, TypeOfList, TypeOfUrl } from '../utils/enums';
+import { openPage } from '../utils/open-page';
+import { getTypeOfUrl } from '../utils/get-type-of-url';
const { t } = useI18n();
@@ -47,9 +70,9 @@ const props = defineProps<{
listType: TypeOfList;
}>();
-const typeOfUrl = computed(() =>
- props.item.url.startsWith('file:') ? TypeOfUrl.Document : TypeOfUrl.WebSite,
-);
+const isShowCmdButtons = ref
();
+
+const typeOfUrl = computed(() => getTypeOfUrl(props.item.url));
const url = computed(() =>
typeOfUrl.value == TypeOfUrl.Document
@@ -75,6 +98,10 @@ function openUrl(url: string) {
} else showWarningMessage.value = true;
}
+async function openStats(url: string) {
+ await openPage(SettingsTab.WebsiteStats, url);
+}
+
const showWarningMessage = ref();
@@ -91,12 +118,21 @@ const showWarningMessage = ref();
.tab-item:hover {
border: 1px rgb(202, 202, 202) solid;
}
+
+.tab-item .links {
+ display: inline-block;
+ margin: 0;
+ cursor: pointer;
+ margin: 0 5px;
+}
+.tab-item .links .link {
+ vertical-align: middle;
+}
.tab-item .url {
font-size: 15px;
font-weight: 600;
cursor: pointer;
overflow-wrap: anywhere;
- max-width: 80%;
display: inline-block;
}
.tab-item .url:hover {
diff --git a/src/components/WebsiteStats.vue b/src/components/WebsiteStats.vue
new file mode 100644
index 0000000..7368467
--- /dev/null
+++ b/src/components/WebsiteStats.vue
@@ -0,0 +1,144 @@
+
+
+
+
+

+
+
+
+
+
+ {{ t('noDataForPeriod.message') }}
+
+
+ {{ label }}
+
+
+
+
+
+
+
+ {{ tab?.url }}
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/WebsiteStatsDetails.vue b/src/components/WebsiteStatsDetails.vue
new file mode 100644
index 0000000..e205021
--- /dev/null
+++ b/src/components/WebsiteStatsDetails.vue
@@ -0,0 +1,67 @@
+
+
+
+
{{ t('allTime.message') }}
+
+ {{ convertSummaryTimeToString(details.summaryTime) }}
+
+
+
+
{{ t('sessions.message') }}
+
+ {{ details.sessions }}
+
+
+
+
{{ t('averageDailyUsage.message') }}
+
+ {{ convertSummaryTimeToString(details.averageTime) }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/compositions/useTabListByDays.ts b/src/compositions/useTabListByDays.ts
index e755c76..0e8525c 100644
--- a/src/compositions/useTabListByDays.ts
+++ b/src/compositions/useTabListByDays.ts
@@ -26,6 +26,7 @@ export async function useTabListByDays(
days: [],
averageTime: 0,
summaryTime: 0,
+ sessions: 0,
};
unSortedTabsByDays.forEach(tab => {
@@ -40,6 +41,7 @@ export async function useTabListByDays(
day: day.date,
tabs: [],
time: day.summary,
+ sessions: day.counter,
};
dayTab.tabs.push({
favicon: tab.favicon,
@@ -50,6 +52,7 @@ export async function useTabListByDays(
daysTabs.push(dayTab);
} else {
dayTab.time += day.summary;
+ dayTab.sessions += day.counter;
dayTab.tabs.push({
favicon: tab.favicon,
url: tab.url,
@@ -77,11 +80,18 @@ export async function useTabListByDays(
return a + b;
});
+ const totalSessions = daysTabs
+ .map(x => x.sessions)
+ .reduce(function (a, b) {
+ return a + b;
+ });
+
const averageTime = Math.round(summaryTime / daysTabs.length);
return {
days: daysTabs,
summaryTime: summaryTime,
averageTime: averageTime,
+ sessions: totalSessions,
};
}
diff --git a/src/compositions/useTabStatsByDays.ts b/src/compositions/useTabStatsByDays.ts
new file mode 100644
index 0000000..e85b03a
--- /dev/null
+++ b/src/compositions/useTabStatsByDays.ts
@@ -0,0 +1,94 @@
+import { CurrentTabItem } from '../dto/currentTabItem';
+import { DayTabs, TabListByDays } from '../dto/tabListSummary';
+import { injectTabsRepository } from '../repository/inject-tabs-repository';
+import { isSameDay } from 'date-fns';
+
+export async function useTabStatsByDays(
+ dateFrom: Date,
+ dateTo: Date,
+ domain: string,
+): Promise {
+ const repo = await injectTabsRepository();
+ const tab = repo.getTab(domain);
+ let daysTabs: DayTabs[] = [];
+
+ if (tab == undefined) return null;
+
+ const isTheSameDay = isSameDay(dateFrom, dateTo);
+
+ const unSortedTabsByDays = isTheSameDay
+ ? tab.days.filter(s => isSameDay(new Date(s.date), dateFrom))
+ : tab.days.filter(s => new Date(s.date) >= dateFrom && new Date(s.date) <= dateTo);
+
+ if (unSortedTabsByDays.length == 0)
+ return {
+ days: [],
+ averageTime: 0,
+ summaryTime: 0,
+ sessions: 0,
+ };
+
+ unSortedTabsByDays.forEach(tabDay => {
+ if (
+ (new Date(tabDay.date) >= dateFrom && new Date(tabDay.date) <= dateTo) ||
+ (isTheSameDay && isSameDay(new Date(tabDay.date), dateFrom))
+ ) {
+ let dayTab = daysTabs.find(x => x.day == tabDay.date);
+ if (dayTab == undefined) {
+ dayTab = {
+ day: tabDay.date,
+ tabs: [],
+ time: tabDay.summary,
+ sessions: tabDay.counter,
+ };
+ dayTab.tabs.push({
+ favicon: tab.favicon,
+ url: tab.url,
+ sessions: tabDay.counter,
+ summaryTime: tabDay.summary,
+ });
+ daysTabs.push(dayTab);
+ } else {
+ dayTab.time += tabDay.summary;
+ dayTab.sessions += tabDay.counter;
+ dayTab.tabs.push({
+ favicon: tab.favicon,
+ url: tab.url,
+ sessions: tabDay.counter,
+ summaryTime: tabDay.summary,
+ });
+ }
+ }
+ });
+
+ daysTabs.sort(function (a, b) {
+ return new Date(a.day).valueOf() - new Date(b.day).valueOf();
+ });
+
+ daysTabs.forEach(dayTab => {
+ dayTab.tabs.sort(function (a: CurrentTabItem, b: CurrentTabItem) {
+ return b.summaryTime - a.summaryTime;
+ });
+ });
+
+ const summaryTime = daysTabs
+ .map(x => x.time)
+ .reduce(function (a, b) {
+ return a + b;
+ });
+
+ const totalSessions = daysTabs
+ .map(x => x.sessions)
+ .reduce(function (a, b) {
+ return a + b;
+ });
+
+ const averageTime = Math.round(summaryTime / daysTabs.length);
+
+ return {
+ days: daysTabs,
+ summaryTime: summaryTime,
+ averageTime: averageTime,
+ sessions: totalSessions,
+ };
+}
diff --git a/src/dto/tabListSummary.ts b/src/dto/tabListSummary.ts
index f68266b..400fa39 100644
--- a/src/dto/tabListSummary.ts
+++ b/src/dto/tabListSummary.ts
@@ -33,10 +33,12 @@ export interface TabListByDays {
days: DayTabs[];
averageTime: number;
summaryTime: number;
+ sessions: number;
}
export interface DayTabs {
day: string;
tabs: CurrentTabItem[];
time: number;
+ sessions: number;
}
diff --git a/src/pages/Dashboard.vue b/src/pages/Dashboard.vue
index e682046..cf7187c 100644
--- a/src/pages/Dashboard.vue
+++ b/src/pages/Dashboard.vue
@@ -10,7 +10,7 @@
type="radio"
id="timeIntervalChart-tab"
name="settings-group"
- :checked="selectedTab == SettingsTab.Dashboard"
+ :checked="selectedTab == SettingsTab.Dashboard || selectedTab == SettingsTab.WebsiteStats"
v-on:change="selectTab(SettingsTab.Dashboard)"
/>
@@ -129,11 +133,12 @@ import Limits from '../components/Limits.vue';
import DailyNotifications from '../components/Notifications.vue';
import About from '../components/About.vue';
import { SettingsTab } from '../utils/enums';
-import Dashboad from '../components/Dashboad.vue';
+import DashboadContainer from '../components/DashboadContainer.vue';
const { t } = useI18n();
const selectedTab = ref
();
+const selectedWebsite = ref();
onMounted(() => {
const urlObj = new URL(location.href);
@@ -146,6 +151,12 @@ onMounted(() => {
case 'settings':
selectedTab.value = SettingsTab.GeneralSettings;
break;
+ case 'website-stats':
+ selectedTab.value = SettingsTab.WebsiteStats;
+ const domain = urlObj.searchParams.get('website');
+ if (domain != null && domain != '') selectedWebsite.value = domain;
+ else selectedTab.value = SettingsTab.Dashboard;
+ break;
}
} else selectedTab.value = selectedTab.value = SettingsTab.Dashboard;
});
diff --git a/src/pages/Popup.vue b/src/pages/Popup.vue
index 65477f5..285586e 100644
--- a/src/pages/Popup.vue
+++ b/src/pages/Popup.vue
@@ -74,31 +74,14 @@