Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ability to view specific date range within Pomodoro history #335

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,4 @@ Marinara is open source software and is built by volunteers from around the worl
- [Iosif Dan](https://github.com/danutiosif): Romanian translation
- [Brian L](https://github.com/brianl9995): Spanish translation
- [Wesley Matos](https://github.com/wricke): Portuguese (Brazil) translation
- [Pat Finnigan](https://github.com/finnigantime): History Tab enhancement
12 changes: 12 additions & 0 deletions package/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,18 @@
"message": "Finish a Pomodoro to see your history",
"description": "Placeholder for history heatmap when no Pomodoros have been completed. Shown on the settings-history page."
},
"history_date_range": {
"message": "History Date Range",
"description": "Title for section for selecting the [start, end] date range of Pomodoro history data to display. Shown on the settings-history page."
},
"history_date_range_start": {
"message": "Start",
"description": "Label for the Date input for the start of the date range of Pomodoro history data to display. Shown on the settings-history page."
},
"history_date_range_end": {
"message": "End",
"description": "Label for the Date input for the end of the date range of Pomodoro history data to display. Shown on the settings-history page."
},
"daily_tooltip": {
"message": "$pomodoros$ between $start$—$end$",
"description": "Tooltip for daily distribution chart. Shown on the settings-history page.",
Expand Down
9 changes: 9 additions & 0 deletions src/Messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,15 @@ class Messages
get history() {
return chrome.i18n.getMessage('history', []);
}
get history_date_range() {
return chrome.i18n.getMessage('history_date_range', []);
}
get history_date_range_start() {
return chrome.i18n.getMessage('history_date_range_start', []);
}
get history_date_range_end() {
return chrome.i18n.getMessage('history_date_range_end', []);
}
get history_empty_placeholder() {
return chrome.i18n.getMessage('history_empty_placeholder', []);
}
Expand Down
28 changes: 19 additions & 9 deletions src/background/History.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,27 +112,37 @@ class History
});
}

async stats(since) {
async stats(since, dateRangeStart, dateRangeEnd) {
return this.mutex.exclusive(async () => {
let { pomodoros } = await this.storage.get('pomodoros');
let filteredPomodoros = pomodoros;
if (dateRangeStart) {
filteredPomodoros = filteredPomodoros.filter(p => +History.date(p) > +(new Date(dateRangeStart)));
}

if (dateRangeEnd) {
filteredPomodoros = filteredPomodoros.filter(p => +History.date(p) < +(new Date(dateRangeEnd)));
}

let total = pomodoros.length;
let delta = total === 0 ? 0 : (new Date() - History.date(pomodoros[0]));
let total = filteredPomodoros.length;
let start = History.date(filteredPomodoros[0]);
let delta = total === 0 ? 0 : (new Date() - start);
let dayCount = Math.max(delta / 1000 / 60 / 60 / 24, 1);
let weekCount = Math.max(dayCount / 7, 1);
let monthCount = Math.max(dayCount / (365.25 / 12), 1);

return {
day: this.countSince(pomodoros, History.today),
start: start,
day: this.countSince(filteredPomodoros, History.today),
dayAverage: total / dayCount,
week: this.countSince(pomodoros, History.thisWeek),
week: this.countSince(filteredPomodoros, History.thisWeek),
weekAverage: total / weekCount,
month: this.countSince(pomodoros, History.thisMonth),
month: this.countSince(filteredPomodoros, History.thisMonth),
monthAverage: total / monthCount,
period: this.countSince(pomodoros, new Date(since)),
period: this.countSince(filteredPomodoros, new Date(since)),
total: total,
daily: this.dailyGroups(pomodoros, since),
pomodoros: pomodoros.map(p => +History.date(p))
daily: this.dailyGroups(filteredPomodoros, since),
pomodoros: filteredPomodoros.map(p => +History.date(p))
};
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/background/Services.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ class HistoryService extends Service
this.history = history;
}

async getStats(since) {
return await this.history.stats(since);
async getStats(since, dateRangeStart, dateRangeEnd) {
return await this.history.stats(since, dateRangeStart, dateRangeEnd);
}

async getCSV() {
Expand Down
75 changes: 73 additions & 2 deletions src/options/History.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@
<div class="bucket">{{ M.total }}</div>
</div>
</div>
<section class="date-range-selection">
<div class="title">
<h2>{{ M.history_date_range }}</h2>
</div>
<div class="date-row">
<div class="date-row-label">{{ M.history_date_range_start }}</div>
<input class="date" type="date" id="history-start" name="start" v-model="dateRangeStartString" />
</div>
<div class="date-row">
<div class="date-row-label">{{ M.history_date_range_end }}</div>
<input class="date" type="date" id="history-end" name="end" v-model="dateRangeEndString" />
</div>
</section>
<section class="day-distribution chart">
<div class="title">
<h2>{{ M.daily_distribution }}</h2>
Expand Down Expand Up @@ -126,6 +139,17 @@
display: inline;
font-weight: normal;
}
.date-row {
display: flex;
flex-direction: row;
margin: 8px;
}
.date-row-label {
width: 120px;
}
.date-range-selection .date {
width: 220px;
}
.day-distribution .options input {
display: none;
}
Expand Down Expand Up @@ -201,16 +225,54 @@ import DayDistribution from './DayDistribution';
import WeekDistribution from './WeekDistribution';
import M from '../Messages';

function pad(num) {
return num >= 10 ? num : `0${num}`;
}

function toFormattedString(inputDate) {
if (!inputDate) return;

let y = inputDate.getFullYear();
let m = inputDate.getMonth();
let d = inputDate.getDate();
return `${y}-${pad(m+1)}-${pad(d)}`;
}

export default {
data() {
return {
historyClient: new HistoryClient(),
pomodoroClient: new PomodoroClient(),
stats: null,
historyStart: null,
dayDistributionBucketSize: 30
dayDistributionBucketSize: 30,
dateRangeStart: null,
dateRangeEnd: null
};
},
computed: {
dateRangeStartString: {
get() {
return toFormattedString(this.dateRangeStart);
},
set(newVal) {
this.dateRangeStart = new Date(newVal);
this.updateStats();
}
},
dateRangeEndString: {
get() {
return toFormattedString(this.dateRangeEnd);
},
set(newVal) {
this.dateRangeEnd = new Date(newVal);

// add 1 day, so that we include pomodoros on dateRangeEnd
this.dateRangeEnd.setDate(this.dateRangeEnd.getDate() + 1);
this.updateStats();
}
}
},
async mounted() {
this.updateStats();
this.pomodoroClient.on('expire', () => {
Expand Down Expand Up @@ -266,8 +328,17 @@ export default {
// Start at the first Sunday at least 39 weeks (~9 months) ago.
start.setDate(start.getDate() - 273);
start.setDate(start.getDate() - start.getDay());
this.stats = await this.historyClient.getStats(+start);
this.stats = await this.historyClient.getStats(+start, this.dateRangeStart, this.dateRangeEnd);
this.historyStart = start;

// Initialize dateRangeStart and dateRangeEnd after we have fetched
// stats for the first time.
if (this.dateRangeStart === null) {
this.dateRangeStart = new Date(this.stats.start);
}
if (this.dateRangeEnd === null) {
this.dateRangeEnd = now;
}
}
},
filters: {
Expand Down