Skip to content

Commit baa42ad

Browse files
committed
🚨 fix linter warning
1 parent 2de6712 commit baa42ad

1 file changed

Lines changed: 136 additions & 136 deletions

File tree

js/lib/download.js

Lines changed: 136 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import Multilingualization from "./multilingualization.js";
2-
import { getTodayString, LOG_DATA_KEY, ROUNDING_UNIT_MINUTE_KEY, fetchHourFromTime, fetchMinFromTime, escapeHtml } from "./utils.js";
1+
import Multilingualization from './multilingualization.js';
2+
import { getTodayString, LOG_DATA_KEY, ROUNDING_UNIT_MINUTE_KEY, fetchHourFromTime, fetchMinFromTime, escapeHtml } from './utils.js';
33

44
const HTML_SUMMARY = 'html_summary';
55
const PLAINTEXT_LOG = 'plaintext_log';
@@ -14,39 +14,39 @@ const MARKDOWN_SUMMARY = 'markdown_summary';
1414
* @param {string} mimeType mime type
1515
*/
1616
export function download(outputDataString, extension = 'html', mimeType = 'text/html') {
17-
const blob = new Blob([outputDataString], { type: mimeType });
18-
const url = URL.createObjectURL(blob);
19-
const filename = Multilingualization.translate("app_name") + "_" + getTodayString() + "." + extension;
20-
21-
// Save download information to localStorage
22-
localStorage.setItem('downloadUrl', url);
23-
localStorage.setItem('downloadFilename', filename);
24-
25-
// Trigger an event to start the download
26-
const event = new CustomEvent('startDownload');
27-
window.dispatchEvent(event);
17+
const blob = new Blob([outputDataString], { type: mimeType });
18+
const url = URL.createObjectURL(blob);
19+
const filename = Multilingualization.translate('app_name') + '_' + getTodayString() + '.' + extension;
20+
21+
// Save download information to localStorage
22+
localStorage.setItem('downloadUrl', url);
23+
localStorage.setItem('downloadFilename', filename);
24+
25+
// Trigger an event to start the download
26+
const event = new CustomEvent('startDownload');
27+
window.dispatchEvent(event);
2828
}
2929

3030
// Add download event listener
3131
window.addEventListener('startDownload', () => {
32-
const url = localStorage.getItem('downloadUrl');
33-
const filename = localStorage.getItem('downloadFilename');
34-
35-
if (url && filename) {
36-
const a = document.createElement('a');
37-
a.href = url;
38-
a.download = filename;
39-
document.body.appendChild(a);
40-
a.click();
41-
document.body.removeChild(a);
42-
43-
// Release the URL after use
44-
URL.revokeObjectURL(url);
45-
46-
// Clear localStorage
47-
localStorage.removeItem('downloadUrl');
48-
localStorage.removeItem('downloadFilename');
49-
}
32+
const url = localStorage.getItem('downloadUrl');
33+
const filename = localStorage.getItem('downloadFilename');
34+
35+
if (url && filename) {
36+
const a = document.createElement('a');
37+
a.href = url;
38+
a.download = filename;
39+
document.body.appendChild(a);
40+
a.click();
41+
document.body.removeChild(a);
42+
43+
// Release the URL after use
44+
URL.revokeObjectURL(url);
45+
46+
// Clear localStorage
47+
localStorage.removeItem('downloadUrl');
48+
localStorage.removeItem('downloadFilename');
49+
}
5050
});
5151

5252
/**
@@ -57,40 +57,40 @@ window.addEventListener('startDownload', () => {
5757
* @returns {string} Formatted log HTML
5858
*/
5959
export function generateFormattedLog(log, mins) {
60-
const sections = [
61-
{ title: HTML_SUMMARY, content: toHtml(log, mins) },
62-
{ title: PLAINTEXT_LOG, content: log, isCode: true },
63-
{ title: MARKDOWN_SUMMARY, content: toMarkdown(log, mins), isCode: true }
64-
];
65-
66-
return `<html><head>
67-
<meta charset="UTF-8">
68-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
69-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
70-
<title>${Multilingualization.translate("log_viewer")}</title>
71-
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/js/bootstrap.bundle.min.js" integrity="sha512-i9cEfJwUwViEPFKdC1enz4ZRGBj8YQo6QByFTF92YXHi7waCqyexvRD75S5NVTsSiTv7rKWqG9Y5eFxmRsOn0A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
72-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0-alpha1/css/bootstrap.min.css" integrity="sha512-72OVeAaPeV8n3BdZj7hOkaPSEk/uwpDkaGyP4W2jSzAC8tfiO4LMEDWoL3uFp5mcZu+8Eehb4GhZWFwvrss69Q==" crossorigin="anonymous" referrerpolicy="no-referrer" />
73-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
60+
const sections = [
61+
{ title: HTML_SUMMARY, content: toHtml(log, mins) },
62+
{ title: PLAINTEXT_LOG, content: log, isCode: true },
63+
{ title: MARKDOWN_SUMMARY, content: toMarkdown(log, mins), isCode: true }
64+
];
65+
66+
return `<html><head>
67+
<meta charset='UTF-8'>
68+
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
69+
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
70+
<title>${Multilingualization.translate('log_viewer')}</title>
71+
<script src='https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/js/bootstrap.bundle.min.js' integrity='sha512-i9cEfJwUwViEPFKdC1enz4ZRGBj8YQo6QByFTF92YXHi7waCqyexvRD75S5NVTsSiTv7rKWqG9Y5eFxmRsOn0A==' crossorigin='anonymous' referrerpolicy='no-referrer'></script>
72+
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0-alpha1/css/bootstrap.min.css' integrity='sha512-72OVeAaPeV8n3BdZj7hOkaPSEk/uwpDkaGyP4W2jSzAC8tfiO4LMEDWoL3uFp5mcZu+8Eehb4GhZWFwvrss69Q==' crossorigin='anonymous' referrerpolicy='no-referrer' />
73+
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css' integrity='sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==' crossorigin='anonymous' referrerpolicy='no-referrer' />
7474
</head><body>
7575
${sections.map(section => `
7676
<h2>${Multilingualization.translate(section.title)}</h2>
77-
<i id="${section.title}-copy" class="fa-sharp fa-regular fa-copy btn btn-outline-secondary d-none"
78-
data-bs-trigger="manual" data-bs-toggle="tooltip" data-bs-placement="top" title="copy!"></i>
77+
<i id='${section.title}-copy' class='fa-sharp fa-regular fa-copy btn btn-outline-secondary d-none'
78+
data-bs-trigger='manual' data-bs-toggle='tooltip' data-bs-placement='top' title='copy!'></i>
7979
<div>
80-
${section.isCode ? `<pre><code id="${section.title}-source">${section.content}</code></pre>` : section.content}
80+
${section.isCode ? `<pre><code id='${section.title}-source'>${section.content}</code></pre>` : section.content}
8181
</div>
8282
`).join('')}
8383
<script>
84-
(async()=>{const e=await(navigator?.permissions?.query({name:"clipboard-write"}));"granted"!==e?.state&&"prompt"!==e?.state||document.querySelectorAll("#${HTML_SUMMARY}-copy,#${PLAINTEXT_LOG}-copy,#${MARKDOWN_SUMMARY}-copy").forEach((e=>{const t=new bootstrap.Tooltip(e);e.classList.remove("d-none"),e.addEventListener("click",(async e=>{let a;e.preventDefault(),e.stopPropagation(),(a=document.querySelector(\`#\${e.target.id.replace("-copy","-source")}\`).textContent),"${HTML_SUMMARY}-copy"===e.target.id&&(a=a.replace(/\\n\\n/g,"<></>").replace(/\\n/g,"\\t").replace(/<><\\/>/g,"\\n")),await(navigator?.clipboard?.writeText(a.trim())),t.show(),setTimeout((()=>t.hide()),1e3)}))}))})();
84+
(async()=>{const e=await(navigator?.permissions?.query({name:'clipboard-write'}));'granted'!==e?.state&&'prompt'!==e?.state||document.querySelectorAll('#${HTML_SUMMARY}-copy,#${PLAINTEXT_LOG}-copy,#${MARKDOWN_SUMMARY}-copy').forEach((e=>{const t=new bootstrap.Tooltip(e);e.classList.remove('d-none'),e.addEventListener('click',(async e=>{let a;e.preventDefault(),e.stopPropagation(),(a=document.querySelector(\`#\${e.target.id.replace('-copy','-source')}\`).textContent),'${HTML_SUMMARY}-copy'===e.target.id&&(a=a.replace(/\\n\\n/g,'<></>').replace(/\\n/g,'\\t').replace(/<><\\/>/g,'\\n')),await(navigator?.clipboard?.writeText(a.trim())),t.show(),setTimeout((()=>t.hide()),1e3)}))}))})();
8585
</script>
8686
</body></html>`;
8787
}
8888

8989
export async function downloadLog() {
90-
const log = localStorage.getItem(LOG_DATA_KEY);
91-
const mins = localStorage.getItem(ROUNDING_UNIT_MINUTE_KEY);
92-
const outputStr = generateFormattedLog(log, mins);
93-
download(outputStr);
90+
const log = localStorage.getItem(LOG_DATA_KEY);
91+
const mins = localStorage.getItem(ROUNDING_UNIT_MINUTE_KEY);
92+
const outputStr = generateFormattedLog(log, mins);
93+
download(outputStr);
9494
}
9595

9696
/**
@@ -101,54 +101,54 @@ export async function downloadLog() {
101101
* @returns {object} Category-wise summary data (json)
102102
*/
103103
export function parse(text, mins) {
104-
const TIME_LENGTH = 16;
105-
const FIELD_SEPARATOR = ";";
106-
const RECORD_SEPARATOR = "\n";
107-
108-
let timeStamp = [], obj = {};
109-
110-
// Convert log to JSON
111-
text.split(RECORD_SEPARATOR).forEach(line => {
112-
const time = line.slice(0, TIME_LENGTH);
113-
const junction = line.indexOf(FIELD_SEPARATOR);
114-
const category = junction < 0 ? line.slice(TIME_LENGTH) : line.slice(TIME_LENGTH, junction);
115-
const detail = junction < 0 ? '' : line.slice(junction + 1);
116-
117-
timeStamp.push({ "time": time, "category": category });
118-
if (!obj[category]) obj[category] = {};
119-
obj[category].time = 0;
120-
if (!obj[category].detail) obj[category].detail = [];
121-
obj[category].detail.push(detail);
122-
});
123-
124-
// Remove duplicates from work details
125-
Object.keys(obj).forEach(item => {
126-
obj[item].detail = Array.from(new Set(obj[item].detail)).join(", ");
127-
});
128-
129-
// Calculate work time in minutes
130-
for (let i = 1; i < timeStamp.length; i++) {
131-
const after = timeStamp[i].time;
132-
const before = timeStamp[i - 1].time;
133-
let hour = fetchHourFromTime(after) - fetchHourFromTime(before);
134-
if (hour < 0) {
135-
hour += 24;
136-
}
137-
let min = fetchMinFromTime(after) - fetchMinFromTime(before);
138-
// If crossing midnight
139-
if (min < 0) {
140-
hour -= 1;
141-
min += 60;
142-
}
143-
obj[timeStamp[i - 1].category].time += hour * 60 + min;
104+
const TIME_LENGTH = 16;
105+
const FIELD_SEPARATOR = ';';
106+
const RECORD_SEPARATOR = '\n';
107+
108+
let timeStamp = [], obj = {};
109+
110+
// Convert log to JSON
111+
text.split(RECORD_SEPARATOR).forEach(line => {
112+
const time = line.slice(0, TIME_LENGTH);
113+
const junction = line.indexOf(FIELD_SEPARATOR);
114+
const category = junction < 0 ? line.slice(TIME_LENGTH) : line.slice(TIME_LENGTH, junction);
115+
const detail = junction < 0 ? '' : line.slice(junction + 1);
116+
117+
timeStamp.push({ 'time': time, 'category': category });
118+
if (!obj[category]) obj[category] = {};
119+
obj[category].time = 0;
120+
if (!obj[category].detail) obj[category].detail = [];
121+
obj[category].detail.push(detail);
122+
});
123+
124+
// Remove duplicates from work details
125+
Object.keys(obj).forEach(item => {
126+
obj[item].detail = Array.from(new Set(obj[item].detail)).join(', ');
127+
});
128+
129+
// Calculate work time in minutes
130+
for (let i = 1; i < timeStamp.length; i++) {
131+
const after = timeStamp[i].time;
132+
const before = timeStamp[i - 1].time;
133+
let hour = fetchHourFromTime(after) - fetchHourFromTime(before);
134+
if (hour < 0) {
135+
hour += 24;
136+
}
137+
let min = fetchMinFromTime(after) - fetchMinFromTime(before);
138+
// If crossing midnight
139+
if (min < 0) {
140+
hour -= 1;
141+
min += 60;
144142
}
143+
obj[timeStamp[i - 1].category].time += hour * 60 + min;
144+
}
145145

146-
// Convert work time to ROUNDING_UNIT time
147-
Object.keys(obj).forEach(item => {
148-
obj[item].round = Math.floor(obj[item].time / 60) + Number((Math.round(obj[item].time % 60 / mins) * mins / 60).toFixed(2));
149-
});
146+
// Convert work time to ROUNDING_UNIT time
147+
Object.keys(obj).forEach(item => {
148+
obj[item].round = Math.floor(obj[item].time / 60) + Number((Math.round(obj[item].time % 60 / mins) * mins / 60).toFixed(2));
149+
});
150150

151-
return obj;
151+
return obj;
152152
}
153153

154154
/**
@@ -159,43 +159,43 @@ export function parse(text, mins) {
159159
* @returns {string} HTML table
160160
*/
161161
export function toHtml(log, mins) {
162-
const dataJson = parse(log, mins);
163-
const breakMark = "^";
164-
let sum = 0;
165-
let total = 0;
166-
let output =
167-
`</head><body><table class="table table-striped-columns"><thead class="table-light"><thead class="table-light">
162+
const dataJson = parse(log, mins);
163+
const breakMark = '^';
164+
let sum = 0;
165+
let total = 0;
166+
let output =
167+
`</head><body><table class='table table-striped-columns'><thead class='table-light'><thead class='table-light'>
168168
<tr>
169-
<th class="text-center">${Multilingualization.translate("work_category")}</th>
170-
<th class="text-center">${Multilingualization.translate("work_detail")}</th>
171-
<th class="text-center">${Multilingualization.translate("work_time_hour")}</th>
172-
<th class="text-center">${Multilingualization.translate("work_time_min")}</th>
169+
<th class='text-center'>${Multilingualization.translate('work_category')}</th>
170+
<th class='text-center'>${Multilingualization.translate('work_detail')}</th>
171+
<th class='text-center'>${Multilingualization.translate('work_time_hour')}</th>
172+
<th class='text-center'>${Multilingualization.translate('work_time_min')}</th>
173173
</tr>
174-
</thead><tbody id="${HTML_SUMMARY}-source" class="table-group-divider">`;
174+
</thead><tbody id='${HTML_SUMMARY}-source' class='table-group-divider'>`;
175175

176-
for (const category of Object.keys(dataJson).sort()) {
177-
output +=
178-
`<tr>
176+
for (const category of Object.keys(dataJson).sort()) {
177+
output +=
178+
`<tr>
179179
<td>${escapeHtml(category) ? escapeHtml(category) : '-'}</td>
180180
<td>${escapeHtml(dataJson[category].detail) ? escapeHtml(dataJson[category].detail) : ' '}</td>
181-
<td class="text-end">${dataJson[category].round}</td>
182-
<td class="text-end">${dataJson[category].time}</td>
181+
<td class='text-end'>${dataJson[category].round}</td>
182+
<td class='text-end'>${dataJson[category].time}</td>
183183
</tr>`;
184-
if (category[0] != breakMark) sum += dataJson[category].time;
185-
total += dataJson[category].time;
186-
}
184+
if (category[0] != breakMark) sum += dataJson[category].time;
185+
total += dataJson[category].time;
186+
}
187187

188-
const sumStr = Multilingualization.translate("work_time_actual") + ": " + (Math.floor(sum / 60) + Number((Math.round(sum % 60 / mins) * mins / 60).toFixed(2))) + " h";
189-
const totalStr = Multilingualization.translate("work_time_total") + ": " + (Math.floor(total / 60) + Number((Math.round(total % 60 / mins) * mins / 60).toFixed(2))) + " h";
188+
const sumStr = Multilingualization.translate('work_time_actual') + ': ' + (Math.floor(sum / 60) + Number((Math.round(sum % 60 / mins) * mins / 60).toFixed(2))) + ' h';
189+
const totalStr = Multilingualization.translate('work_time_total') + ': ' + (Math.floor(total / 60) + Number((Math.round(total % 60 / mins) * mins / 60).toFixed(2))) + ' h';
190190

191-
output +=
192-
`</tbody></table>
191+
output +=
192+
`</tbody></table>
193193
<p>
194194
${sumStr} (${sum} ${Multilingualization.translate('mins')})<br>
195195
${totalStr} (${total} ${Multilingualization.translate('mins')})</p>
196196
`;
197197

198-
return output;
198+
return output;
199199
}
200200

201201
/**
@@ -206,23 +206,23 @@ ${totalStr} (${total} ${Multilingualization.translate('mins')})</p>
206206
* @returns {string} Markdown table
207207
*/
208208
export function toMarkdown(log, mins) {
209-
const dataJson = parse(log, mins);
210-
const breakMark = "^";
211-
let sum = 0;
212-
let total = 0;
213-
let output =
214-
`${Multilingualization.translate("work_category")} | ${Multilingualization.translate("work_detail")} | ${Multilingualization.translate("work_time_hour")} | ${Multilingualization.translate("work_time_min")}
209+
const dataJson = parse(log, mins);
210+
const breakMark = '^';
211+
let sum = 0;
212+
let total = 0;
213+
let output =
214+
`${Multilingualization.translate('work_category')} | ${Multilingualization.translate('work_detail')} | ${Multilingualization.translate('work_time_hour')} | ${Multilingualization.translate('work_time_min')}
215215
--- | --- | --: | --:
216216
`;
217217

218-
for (const category of Object.keys(dataJson).sort()) {
219-
output += `${escapeHtml(category)} | ${escapeHtml(dataJson[category].detail)} | ${dataJson[category].round} | ${dataJson[category].time}\n`;
220-
if (category[0] != breakMark) sum += dataJson[category].time;
221-
total += dataJson[category].time;
222-
}
218+
for (const category of Object.keys(dataJson).sort()) {
219+
output += `${escapeHtml(category)} | ${escapeHtml(dataJson[category].detail)} | ${dataJson[category].round} | ${dataJson[category].time}\n`;
220+
if (category[0] != breakMark) sum += dataJson[category].time;
221+
total += dataJson[category].time;
222+
}
223223

224-
output += `\n${Multilingualization.translate("work_time_actual")}: ` + (Math.floor(sum / 60) + Number((Math.round(sum % 60 / mins) * mins / 60).toFixed(2))) + ` h (${sum} ${Multilingualization.translate('mins')})`;
225-
output += `\n${Multilingualization.translate("work_time_total")}: ` + (Math.floor(total / 60) + Number((Math.round(total % 60 / mins) * mins / 60).toFixed(2))) + ` h (${total} ${Multilingualization.translate('mins')})`;
224+
output += `\n${Multilingualization.translate('work_time_actual')}: ` + (Math.floor(sum / 60) + Number((Math.round(sum % 60 / mins) * mins / 60).toFixed(2))) + ` h (${sum} ${Multilingualization.translate('mins')})`;
225+
output += `\n${Multilingualization.translate('work_time_total')}: ` + (Math.floor(total / 60) + Number((Math.round(total % 60 / mins) * mins / 60).toFixed(2))) + ` h (${total} ${Multilingualization.translate('mins')})`;
226226

227-
return output;
227+
return output;
228228
}

0 commit comments

Comments
 (0)