Skip to content

Commit 631f578

Browse files
authored
Merge pull request kriskbx#42 from spamsch/project-names-not-starting-with-number-no-resolved
Project names not starting with number no resolved
2 parents 7355c0d + fce944a commit 631f578

File tree

21 files changed

+292
-70
lines changed

21 files changed

+292
-70
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
FROM node:8.2.1-alpine
22

3-
ENV GTT_VERSION 1.6.10
3+
ENV GTT_VERSION 1.7.2
44

55
RUN yarn global add --prefix /usr/local "gitlab-time-tracker@$GTT_VERSION"
66

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "gitlab-time-tracker",
3-
"version": "1.6.10",
3+
"version": "1.7.2",
44
"description": "A command line interface for GitLabs time tracking feature.",
55
"bugs": {
66
"url": "https://github.com/kriskbx/gitlab-time-tracker/issues"

readme.md

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ npm install -g gitlab-time-tracker
5555
```
5656

5757
Run the config command to create a config file and open it in your default editor.
58+
In linux terminal, you must set your preferred editor in the environment. For example, use `export EDITOR=vim` to edit the files with vim (put this in `.bashrc` or similar to have it always configured).
5859
If nothing happens, open the file manually: `~/.gtt/config.yml` - on Windows: `C:\Users\YourUserName\.gtt\config.yml`
5960

6061
```shell
@@ -484,6 +485,10 @@ token: abcdefghijklmnopqrst
484485
# defaults to false
485486
proxy: http://localhost:8080
486487

488+
# Don't check SSL certificate
489+
# defaults to false
490+
insecure: true
491+
487492
# Project
488493
# defaults to false
489494
project: namespace/projectname
@@ -543,15 +548,15 @@ hoursPerDay: 8
543548
issueColumns:
544549
- iid
545550
- title
546-
- estimation
551+
- total_estimate
547552

548553
# Include the given columns in the merge request table
549554
# See --merge_request_columns option for more information
550555
# defaults to iid, title, spent, total_estimate
551556
mergeRequestColumns:
552557
- iid
553558
- title
554-
- estimation
559+
- total_estimate
555560

556561
# Include the given columns in the time record table
557562
# See --record_columns option for more information
@@ -576,6 +581,16 @@ dateFormat: DD.MM.YYYY HH:mm:ss
576581
# defaults to "[%sign][%days>d ][%hours>h ][%minutes>m ][%seconds>s]"
577582
timeFormat: "[%sign][%days>d ][%hours>h ][%minutes>m ][%seconds>s]"
578583

584+
# Time format for different parts of the report
585+
# Instead of specifying one global time format you can specify one for every
586+
# part of the report and the log command
587+
timeFormat:
588+
log: "[%sign][%hours_overall]"
589+
stats: "[%sign][%days_overall]"
590+
issues: "[%sign][%hours_overall]"
591+
merge_requests: "[%sign][%hours_overall]"
592+
records: "[%sign][%days>d ][%hours>h ][%minutes>m ][%seconds>s]"
593+
579594
# Output type
580595
# Available: csv, table, markdown, pdf
581596
# defaults to table
@@ -593,6 +608,12 @@ includeLabels:
593608
- pending
594609
- approved
595610

611+
# Only works if using a local configuration file!
612+
# Extend the global configuration if set to true, pass a string to extend
613+
# the configuration file stored at the given path
614+
# defaults to true
615+
extend: true
616+
596617
# Change number of concurrent connections/http queries
597618
# Note: Handle with care, we don't want to spam GitLabs API too much
598619
# defaults to 10
@@ -602,11 +623,14 @@ _parallel: 20
602623
# defaults to 100
603624
_perPage: 100
604625

605-
# Only works if using a local configuration file!
606-
# Extend the global configuration if set to true, pass a string to extend
607-
# the configuration file stored at the given path
608-
# defaults to true
609-
extend: true
626+
# Verbose output
627+
_verbose: false
628+
629+
# Check access token validity up front
630+
_checkToken: false
631+
632+
# Skip parsing the issue/merge_request description for time records
633+
_skipDescriptionParsing: false
610634
```
611635
612636
### Time format
@@ -698,6 +722,23 @@ timeFormat: "[%sign][%minutes_overall]"
698722
1095
699723
```
700724

725+
##### `[%hours_overall:2]`, `[%days_overall:3]`
726+
727+
You can ceil any float value by adding the number of decimals to keep separated with a `:`.
728+
729+
**Example config:**
730+
731+
```yaml
732+
timeFormat: "[%sign][%hours_overall:2]"
733+
```
734+
735+
**Example outputs:**
736+
737+
```shell
738+
0,51
739+
18,25
740+
```
741+
701742
## how to use gtt as a library
702743

703744
Add as a dependency using yarn:
@@ -763,12 +804,6 @@ report.mergeRequests.forEach(mergeRequest => {
763804
It can include times outside the queried time frame. `spent` on the other hand
764805
is the total amount of time spent in the given time frame.
765806

766-
#### Why 'total spent' and 'spent' are showing different amounts.
767-
768-
gtt can only track time records from notes/comments. If you start your
769-
issue or merge request with `/spend [time]` in its description, gtt won't
770-
take it into consideration (for now).
771-
772807
## contributing
773808

774809
I would love to integrate unit testing in this project, but unfortunately my knowledge of
@@ -789,4 +824,4 @@ or already have done so. 💜
789824

790825
## license
791826

792-
GPL v2
827+
GPL v2

spec/include/config.spec.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,33 @@ describe('The config class', () => {
4242
});
4343
});
4444

45+
it('returns values from objects and falls back to the default', () => {
46+
let Config = new config(),
47+
objectsWithDefaults = ['timeFormat'],
48+
defaults = Object.assign({}, Config.data),
49+
stringData = 'booze',
50+
objectData = {
51+
foo: 'bar',
52+
baz: 'bar'
53+
};
54+
55+
objectsWithDefaults.forEach(key => {
56+
Config.set(key, objectData);
57+
58+
expect(Config.get(key, 'foo')).to.equal('bar');
59+
expect(Config.get(key, 'baz')).to.equal('bar');
60+
expect(Config.get(key, 'not_a_real_key')).to.equal(defaults[key]);
61+
62+
Config.set(key, stringData);
63+
64+
expect(Config.get(key, 'foo')).to.equal('booze');
65+
expect(Config.get(key, 'baz')).to.equal('booze');
66+
expect(Config.get(key, 'not_a_real_key')).to.equal('booze');
67+
});
68+
});
69+
4570
it('makes durations human readable', () => {
46-
let Config = new config,
71+
let Config = new config(),
4772
humanReadable = "1d 4h 30m 10s",
4873
seconds = 45010;
4974

src/gtt-log.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,17 @@ const Tasks = require('./include/tasks');
1111
program
1212
.option('--verbose', 'show verbose output')
1313
.option('--hours_per_day <hours>', 'hours per day for human readable time formats')
14+
.option('--time_format <time_format>', 'time format')
1415
.parse(process.argv);
1516

1617
Cli.verbose = program.verbose;
1718

18-
let config = new Config(__dirname)
19-
.set('hoursPerDay', program.hours_per_day),
20-
tasks = new Tasks(config);
19+
let config = new Config(__dirname).set('hoursPerDay', program.hours_per_day),
20+
tasks = new Tasks(config),
21+
timeFormat = config.set('timeFormat', program.time_format).get('timeFormat', 'log');
2122

2223
function toHumanReadable(input) {
23-
return Time.toHumanReadable(Math.ceil(input), config.get('hoursPerDay'), config.get('timeFormat'));
24+
return Time.toHumanReadable(Math.ceil(input), config.get('hoursPerDay'), timeFormat);
2425
}
2526

2627
tasks.log()

src/gtt-resume.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const program = require('commander');
2+
const colors = require('colors');
3+
const moment = require('moment');
4+
5+
const Config = require('./include/file-config');
6+
const Cli = require('./include/cli');
7+
const Tasks = require('./include/tasks');
8+
9+
program
10+
.arguments('[project]')
11+
.option('--verbose', 'show verbose output')
12+
.parse(process.argv);
13+
14+
Cli.verbose = program.verbose;
15+
16+
let config = new Config(process.cwd()).set('project', program.args[0]),
17+
tasks = new Tasks(config);
18+
19+
if (!config.get('project'))
20+
Cli.error('No project set');
21+
22+
tasks.resume()
23+
.then(frame => console.log(`Starting project ${config.get('project').magenta} ${frame.resource.type.blue} ${('#' + frame.resource.id).blue} at ${moment().format('HH:mm').green}`))
24+
.catch(error => Cli.error(error));

src/gtt-start.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ const Tasks = require('./include/tasks');
99
program
1010
.arguments('[project] [id]')
1111
.option('-t, --type <type>', 'specify resource type: issue, merge_request')
12+
.option('-m', 'shorthand for --type=merge_request')
13+
.option('-i', 'shorthand for --type=issue')
1214
.option('--verbose', 'show verbose output')
1315
.parse(process.argv);
1416

@@ -20,6 +22,12 @@ let config = new Config(process.cwd()),
2022
id = program.args.length === 1 ? parseInt(program.args[0]) : parseInt(program.args[1]),
2123
project = program.args.length === 2 ? program.args[0] : null;
2224

25+
if (program.I) {
26+
type = 'issue';
27+
} else if (program.M) {
28+
type = 'merge_request';
29+
}
30+
2331
if (program.args.length < 2 && !config.get('project'))
2432
Cli.error('No project set');
2533

src/gtt.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env node
22

3-
const version = '1.6.10';
3+
const version = '1.7.2';
44
const program = require('commander');
55

66
program
@@ -9,6 +9,7 @@ program
99
.command('create [project] [title]', 'start monitoring time for the given project and create a new issue or merge request with the given title')
1010
.command('status', 'shows if time monitoring is running')
1111
.command('stop', 'stop monitoring time')
12+
.command('resume [project]', 'resume monitoring time for last stopped record')
1213
.command('cancel', 'cancel and discard active monitoring time')
1314
.command('log', 'log recorded time records')
1415
.command('sync', 'sync local time records to GitLab')

src/include/cli.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ class cli {
241241

242242
if (this.data.project) return this.data.project;
243243

244-
let projects = _.uniq(_.filter(this.args, arg => !parseInt(arg)));
244+
let projects = _.uniq(_.filter(this.args, arg => !Number.isNaN(new Number(arg))));
245245
this.args = _.difference(this.args, projects);
246246

247247
return this.data.project = projects;

src/include/config.js

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
const moment = require('moment');
2+
const _ = require('underscore');
23

34
const Time = require('./../models/time');
45

56
const dates = ['from', 'to'];
7+
const objectsWithDefaults = ['timeFormat', 'columns'];
68
const defaults = {
79
type: 'project',
810
subgroups: false,
911
url: 'https://gitlab.com/api/v4',
1012
token: false,
1113
proxy: false,
14+
insecure: false,
1215
project: false,
1316
from: "1970-01-01",
1417
to: moment().format(),
@@ -36,7 +39,8 @@ const defaults = {
3639
_perPage: 100,
3740
_parallel: 10,
3841
_verbose: false,
39-
_checkToken: false
42+
_checkToken: false,
43+
_skipDescriptionParsing: false
4044
};
4145

4246
/**
@@ -47,7 +51,7 @@ class config {
4751
* construct
4852
*/
4953
constructor() {
50-
this.data = defaults;
54+
this.data = _.extend({}, defaults);
5155
}
5256

5357
/**
@@ -70,21 +74,27 @@ class config {
7074
/**
7175
* get a value by the given key
7276
* @param key
77+
* @param subKey
7378
* @returns {*}
7479
*/
75-
get(key) {
76-
if (!dates.includes(key)) return this.data[key];
80+
get(key, subKey = false) {
81+
if (dates.includes(key))
82+
return moment(this.data[key]);
7783

78-
return moment(this.data[key]);
84+
if (objectsWithDefaults.includes(key) && _.isObject(this.data[key]))
85+
return subKey && this.data[key][subKey] ? this.data[key][subKey] : defaults[key];
86+
87+
return this.data[key];
7988
}
8089

8190
/**
8291
* get a human readable version of the given time
8392
* @param input
93+
* @param timeFormat
8494
* @returns {string}
8595
*/
86-
toHumanReadable(input) {
87-
return Time.toHumanReadable(input, this.get('hoursPerDay'), this.get('timeFormat'));
96+
toHumanReadable(input, timeFormat = false) {
97+
return Time.toHumanReadable(input, this.get('hoursPerDay'), this.get('timeFormat', timeFormat));
8898
}
8999
}
90100

0 commit comments

Comments
 (0)