@beauraines/toggl-cli 0.10.12 → 0.10.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "es2021": true,
5
5
  "node": true
6
6
  },
7
- "extends": "standard",
7
+ "extends": "eslint:recommended",
8
8
  "overrides": [
9
9
  ],
10
10
  "parserOptions": {
package/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [0.10.13](https://github.com/beauraines/toggl-cli/compare/v0.10.12...v0.10.13) (2023-04-01)
6
+
7
+
8
+ ### Features
9
+
10
+ * Improve table layout ([4652fc3](https://github.com/beauraines/toggl-cli/commit/4652fc3f5e54ca6f0031dfcc035746147b028a5d)), closes [#56](https://github.com/beauraines/toggl-cli/issues/56)
11
+
5
12
  ### [0.10.12](https://github.com/beauraines/toggl-cli/compare/v0.10.11...v0.10.12) (2023-03-23)
6
13
 
7
14
  ### [0.10.11](https://github.com/beauraines/toggl-cli/compare/v0.10.10...v0.10.11) (2023-03-19)
package/cmds/ls.mjs CHANGED
@@ -40,11 +40,23 @@ export const handler = async function (argv) {
40
40
  })
41
41
 
42
42
  const table = new Table({
43
- head: ['description', 'start', 'stop', 'duration']
43
+ head: ['Description', 'Start', 'Stop', 'Duration'],
44
+ chars: { mid: '', 'left-mid': '', 'mid-mid': '', 'right-mid': '' }
44
45
  })
45
- for (const entry of report) {
46
- table.push([entry.description, entry.start, entry.stop, entry.duration])
46
+ for (let i = 0; i < report.length; i++) {
47
+ // First row chars
48
+ const chars = {
49
+ midMid: '┼',
50
+ mid: '─',
51
+ leftMid: '├',
52
+ rightMid: '┤'
53
+ }
54
+ const entry = report[i]
55
+ if (i === 0) {
56
+ table.push([entry.description, entry.start, entry.stop, entry.duration].map((content) => ({ content, chars })))
57
+ } else {
58
+ table.push([entry.description, entry.start, entry.stop, entry.duration])
59
+ }
47
60
  }
48
61
  console.log(table.toString())
49
- // console.table(report, ['description', 'start', 'stop', 'duration'])
50
62
  }
package/cmds/today.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import Client from '../client.js'
2
+ import chalk from 'chalk'
2
3
  import dayjs from 'dayjs'
3
4
  import { getWorkspace, getProjects, formatDuration, formatDurationAsTime } from '../utils.js'
4
5
  import dur from 'dayjs/plugin/duration.js'
@@ -79,10 +80,25 @@ function displayDailyReport (report, format) {
79
80
  case 'table':
80
81
  default:
81
82
  const table = new Table({
82
- head: ['Project', 'Duration']
83
+ head: ['Project', 'Duration'],
84
+ chars: { mid: '', 'left-mid': '', 'mid-mid': '', 'right-mid': '' }
83
85
  })
84
- for (const project of report) {
85
- table.push([project.project_name, project.duration_formatted])
86
+ for (let i = 0; i < report.length; i++) {
87
+ // First row chars
88
+ const chars = {
89
+ midMid: '┼',
90
+ mid: '─',
91
+ leftMid: '├',
92
+ rightMid: '┤'
93
+ }
94
+ const project = report[i]
95
+ if (i == 0) {
96
+ table.push([project.project_name, project.duration_formatted].map((content) => ({ content: chalk.grey(content), chars })))
97
+ } else if ( i == report.length - 1) {
98
+ table.push([project.project_name, project.duration_formatted].map((content) => ( {content: chalk.bold(content), chars })))
99
+ } else {
100
+ table.push([chalk.grey(project.project_name), chalk.grey(project.duration_formatted)])
101
+ }
86
102
  }
87
103
  console.log(table.toString())
88
104
  break
package/cmds/weekly.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import Client from '../client.js'
2
+ import chalk from 'chalk'
2
3
  import { getWorkspace, formatDuration, getProjectById } from '../utils.js'
3
4
  import dayjs from 'dayjs'
4
5
  import dur from 'dayjs/plugin/duration.js'
@@ -58,10 +59,25 @@ export const handler = async function (argv) {
58
59
 
59
60
  const head = Object.keys(reportData[0])
60
61
  const table = new Table({
61
- head
62
+ head,
63
+ chars: { mid: '', 'left-mid': '', 'mid-mid': '', 'right-mid': '' }
62
64
  })
63
- for (const project of reportData) {
64
- table.push(Object.values(project))
65
+ for (let i = 0; i < reportData.length; i++) {
66
+ // First row chars
67
+ const chars = {
68
+ midMid: '┼',
69
+ mid: '─',
70
+ leftMid: '├',
71
+ rightMid: '┤'
72
+ }
73
+ const project = reportData[i]
74
+ if (i == 0 ) {
75
+ table.push(Object.values(project).map((content) => ({ content: chalk.grey(content), chars })))
76
+ } else if ( i == reportData.length - 1) {
77
+ table.push(Object.values(project).map((content) => ( {content: chalk.bold(content), chars })))
78
+ } else {
79
+ table.push(Object.values(project).map((content) => ({ content: chalk.grey(content) })))
80
+ }
65
81
  }
66
82
  console.log(table.toString())
67
83
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beauraines/toggl-cli",
3
- "version": "0.10.12",
3
+ "version": "0.10.13",
4
4
  "description": "",
5
5
  "main": "cli.js",
6
6
  "bin": {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "scripts": {
10
10
  "test": "jest",
11
- "lint": "eslint . ./**/*.js ./**/*.js",
11
+ "lint": "eslint . ./**/*.js ./**/*.mjs",
12
12
  "lint:fix": "eslint . ./**/*.js ./**/*.mjs --fix",
13
13
  "release": "standard-version",
14
14
  "should-release": "should-release"
@@ -30,6 +30,7 @@
30
30
  },
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
+ "chalk": "^4.0.0",
33
34
  "cli-table3": "^0.6.3",
34
35
  "dayjs": "^1.11.6",
35
36
  "debug": "^4.3.4",
package/.env.foo DELETED
@@ -1,3 +0,0 @@
1
- TOGGL_API_TOKEN=1d0ef68975e582dae8d132190821e3a5
2
- TOGGL_DEFAULT_WORKSPACE_ID=403916
3
- TOGGL_TIMEZONE=America/Los_Angeles
package/database.js DELETED
@@ -1,70 +0,0 @@
1
- const homedir = require('os').homedir();
2
- const sqlite = require('sqlite');
3
- const sqlite3 = require('sqlite3');
4
- const {fileExists} = require('./helpers');
5
-
6
- /**
7
- * Opens the BurnDownStatus SQLite3 Database
8
- * @param file file name of the SQLite3 DB. If not provided, defaults to ${homedir}/BurnDownStatus.db
9
- * @returns SQLite database connection
10
- */
11
- async function getDBConnection(file) {
12
- file = file ? file : `${homedir}/BurnDownStatus.db`;
13
- if (!await fileExists(file)){
14
- console.error(`${file} not found`);
15
- process.exit(1);
16
- }
17
- const db = await sqlite.open({
18
- filename: `${homedir}/BurnDownStatus.db`,
19
- driver: sqlite3.Database
20
- });
21
- return db;
22
- }
23
-
24
- /**
25
- *
26
- * @param {Object} data The burndown data to be inserted into the Burndown database
27
- *
28
- * @returns {Object} The result of the database running the provided query
29
- */
30
- async function writeToDb(data) {
31
- // TODO should take db, query and values as parameters
32
- let db = await getDBConnection();
33
- let query = `insert into qa_burndown (date, qa_review_count, qa_validated_count) values (?,?,?) on conflict do update set qa_review_count = excluded.qa_review_count, qa_validated_count = excluded.qa_validated_count`;
34
-
35
- let values = [data.date, data.qa_review_count, data.qa_validated_count];
36
- let result = await db.run(query, values);
37
- await db.close();
38
- return result;
39
-
40
- }
41
-
42
-
43
- async function insert(database,table,data) {
44
- let db = await getDBConnection(database);
45
-
46
- let fields = Object.keys(data[0]).toString();
47
- let fieldsCount = Object.keys(data[0]).length;
48
- let valueSubstitution = Array(fieldsCount).fill('?').toString();
49
-
50
- //TODO figure out how to build upsert
51
- // on conflict do update set qa_review_count = excluded.qa_review_count, qa_validated_count = excluded.qa_validated_count`;
52
- let query = `insert into ${table} (${fields}) values (${valueSubstitution});`
53
- let result = []
54
- data.forEach(async (row) => {
55
- // TODO add try/catch for SQL error errno and code
56
- // TODO switch to db.exec() for more meaningful response
57
- let response = await db.run(query,Object.values(row));
58
- result.push(response);
59
- });
60
- await db.close();
61
- // TODO clean up result
62
- return result;
63
- }
64
-
65
-
66
- module.exports = {
67
- getDBConnection,
68
- writeToDb,
69
- insert
70
- }
package/helpers.js DELETED
@@ -1,72 +0,0 @@
1
- const fs = require('fs');
2
-
3
- /**
4
- * Converts a string to Title Case, using whitespace as the delimiter
5
- * @param {String} str String to convert
6
- * @returns The string converted to title case
7
- */
8
- function toTitleCase(str) {
9
- return str.replace(
10
- /\w\S*/g,
11
- function(txt) {
12
- return txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase();
13
- }
14
- );
15
- }
16
-
17
- /**
18
- * Removes newline characters \r and/or \n from a string
19
- * @param {string} string to remove newlines from
20
- * @returns string
21
- */
22
- function stripNewLines(string) {
23
- return string.replace(/\r|\n/g, '');
24
- }
25
-
26
- /**
27
- * Checks to see if the specified file exists
28
- * @param {string} filePath fully qualified path and filename
29
- * @returns Boolean
30
- */
31
- async function fileExists(filePath) {
32
- return fs.existsSync(filePath);
33
- }
34
-
35
- /**
36
- * Asynchronously reads the entire file contents and returns it.
37
- * @param {string} filePath fully qualified path and filename
38
- * @returns any
39
- */
40
- async function readFile(filePath) {
41
- return fs.readFileSync(filePath,{ encoding: 'utf8', flag: 'r' });
42
- }
43
-
44
- /**
45
- * Groups an array by specified properties and sums other specified properties
46
- *
47
- * https://stackoverflow.com/questions/46794232/group-objects-by-multiple-properties-in-array-then-sum-up-their-values
48
- *
49
- * @param {Array} arr Array of Objects to aggregate
50
- * @param {Array} groupKeys keys to group by
51
- * @param {Array} sumKeys keys of properties to sum by
52
- * @returns Array of Objects
53
- */
54
- function groupAndSum(arr, groupKeys, sumKeys){
55
- return Object.values(
56
- arr.reduce((acc,curr)=>{
57
- const group = groupKeys.map(k => curr[k]).join('-');
58
- acc[group] = acc[group] || Object.fromEntries(
59
- groupKeys.map(k => [k, curr[k]]).concat(sumKeys.map(k => [k, 0])));
60
- sumKeys.forEach(k => acc[group][k] += curr[k]);
61
- return acc;
62
- }, {})
63
- );
64
- }
65
-
66
- module.exports = {
67
- groupAndSum,
68
- toTitleCase,
69
- fileExists,
70
- stripNewLines,
71
- readFile
72
- }
package/toggl.credentials DELETED
@@ -1,5 +0,0 @@
1
- {
2
- "token": "1d0ef68975e582dae8d132190821e3a5",
3
- "defaultWorkspaceId": "403916",
4
- "timezone": "America/Los_Angeles"
5
- }