aboutsummaryrefslogtreecommitdiffstats
path: root/timetask
AgeCommit message (Collapse)Author
2018-01-22buildSubmissionParams(): Change time format to U.S.change-field-format-to-US-localisationTeddy Wing
The TimeTask form now requires U.S. localisation for the time. This means that decimal values are no longer submitted as "4,5" for four and a half hours. Instead, it must be written "4.5".
2018-01-22buildSubmissionParams(): Change date format to U.S.Teddy Wing
The TimeTask form now requires U.S. instead of European date localisation. This swaps the date and month fields so that the month appears first.
2018-01-22SubmitTimeEntry(): Log HTTP responseshow-http-response-when-time-emtry-submission-failsTeddy Wing
The previous error message wasn't useful for determining the cause of the error. It just said there was a problem, but provided no additional information. Append the HTTP response body from TimeTask to the error message so users can see what they had a problem with.
2017-06-04Move HTTP response body errors into http.goTeddy Wing
Take the errors in `main()` that check the response body contents for known error strings and put them in their respective functions in "timetask/http.go". Didn't really make sense to me that these functions were returning HTTP responses that we weren't really using in a meaningful way. Instead they should just do their thing and let us know if there was a problem. That includes checking to see if there were any non-standard errors, like the ones we had custom-built. Now all that handling and error-making is self-contained, which feels much nicer.
2017-06-04RequestModules(): Pretty print modulesTeddy Wing
Parse the module XML with `ModuleParseXML()`. Take the resulting `[]Module` slice and use it to generate a string of the following format: ID Module 55555 R&D 77777 Sprint 1 222222 Sprint 2 This string is what gets printed to the console, which makes it rather easy to read the modules that are available for the given project and grab the appropriate ID to put into your config file.
2017-06-04Change `ParseXML()` name to `ModuleParseXML()`Teddy Wing
Prefix the function name to make it more obvious what it relates to. Since this function lives in the `timetask` module and will be used in contexts that have nothing to do with Modules.
2017-06-04Add module.go for parsing Module XMLTeddy Wing
A new function that parses the XML returned by the `RequestModules()` function. It provides a `Module` type that allows us to interact with modules more easily in code. The `ParseXML()` function will take an XML string and return a slice of `Module`s. Added a test just to facilitate development. Wasn't able to find an easy way to compare slices in Go, so just printed the values and checked the result visually. Not a useful test for future use, but it served its purpose. Eventually it would be nice to find a way to compare structs and have a real pass/fail condition.
2017-06-03TestLogin(): Fix `Login()` assignment mismatchTeddy Wing
`Login()` now returns 3 values. Update the test.
2017-06-03Add an option to list "Modules" (sprints & their IDs)Teddy Wing
Sprints will change with time while the other IDs of a project will stay the same. Thus sprints, which live in the `Module` field, must be updated regularly. In order to facilitate that updating, instead of requiring users to get those IDs directly from the TimeTask website every time, have them use this command to get the names of sprints and their IDs. They can then update the ID manually in their config file. This code makes a request to the endpoint that returns module IDs for the site (the site queries this via AJAX to update its interface). The result of the request is some XML containing the modules and their IDs. For now I'm just printing this out. We'll want to parse the XML and display it in a nicer way.
2017-06-03buildSubmissionParams(): Fix time string replacement bugTeddy Wing
We ran into a bug where submitting "7" as the time spent would become "700" on the site. This was because our `n` value of 0 wasn't replacing the "." in the string. Thus "7.00" became "7.00" after the replacement. Not right. I misunderstood what that argument was doing and what the word "empty" in the documentation meant. Change the `n` value to replace all "."s in the string.
2017-06-03Change `TimeEntry.Time` to a `float64`Teddy Wing
I had forgotten that time spent can be a decimal. Make this field a float and change related code accordingly: * --time flag * `NewTimeEntry()` `time` argument * `buildSubmissionParams()` can't use `strconv.Itoa` as that's an integer function. Instead we use `FormatFloat`. Truncate time parsing to two decimal places because to me that seems like enough. Who's going to say they spent `0.324` hours on something? Also, in order to be able to properly submit values to TimeTask (at least on the edition I use), the times must be written in European/French format, with commas (`,`) as decimal separators. Do a string replace to get this, as the float formatter will give us a period (`.`) separator.
2017-06-03main.go;http.go: Remove commented unused importsTeddy Wing
2017-06-03Run gofmt on all project filesTeddy Wing
2017-06-03Move 'fields.go' to 'project.go'Teddy Wing
Get rid of all the old commented Fields code. It's no longer used and is no longer relevant. Furthermore, since the only thing left in this file is the `Project` struct, rename the file to 'project.go'.
2017-06-03Remove generator.go, templates/ directoryTeddy Wing
These are not needed in the new world where we only submit a single time entry at a time and entry parameters are filled in on the command line. My guess is we'll likely have some sort of generator in the future to create the initial `config.toml` file, but that won't contain any logic-based data. My guess is we'll probably be able to just stick it in a template string right inside a *.go file.
2017-06-03http_test.go: Skip Login() testTeddy Wing
Because it makes a network request. I originally wrote this to test the Login function while developing so it wasn't a big deal, but we really don't want to run this type of test in normal situations.
2017-06-03buildSubmissionParams(): Add `f_entryIndexes` paramTeddy Wing
The param needs to be present in the request in order for it to be considered. Add it back in (we had it before 810b140b4a29b1159e76b51b90b9be7d22df1c3e) with only the `0` index being sent in the request. This is because we're only submitting a single time entry, the 0th one. (Other parameters end with a '0'.)
2017-06-03Initial stab at submitting time entries for realTeddy Wing
main.go: * Login as the configured user (haven't yet handled making `PasswordCmd` an actual shell command) * Create a test time entry * Submit that time entry using `SubmitTimeEntry()` http.go: * Create a `baseURL` global that stores the base TimeTask URL to make requests to * Return an `http.Client` from `Login()` that can then be passed to `SubmitTimeEntry()` to reuse the login session. Needed to return a pointer to allow us to return `nil` from the first error handler in the function. Don't like that at all, but we're just trying to get it to work at this point. * Actually make an HTTP POST request in `SubmitTimeEntry()` using the given HTTP Client and existing time entry submission params * Take an `http.Client` argument in `SubmitTimeEntry()` to allow us to use a logged-in session to POST. Otherwise we'd be locked out. * Change `v` variable to `values` in `SubmitTimeEntry()` for better readability
2017-06-03SubmitTimeEntry(): Remove `Profile` & `Project` argumentsTeddy Wing
Now that `Profile` and `Project` have been subsumed into `TimeEntry` (f017c462593496efbc0810ec2603da49a2e3d9d8), these arguments should no longer be here and their data should come from `TimeEntry` instead.
2017-06-03Project: Remove `Time` fieldTeddy Wing
Time spent on a project can be variable from day to day. The time shouldn't be stored on the project, and should no longer be passed in config.toml. Instead it should be a part of `TimeEntry`, which it now is.
2017-06-03Add `NewTimeEntry()`Teddy Wing
A new function that creates a `TimeEntry` build from a `Profile`, `Project`, and a few other parameters. Makes it a bit easier to create `TimeEntry`ies. Additionally, add a `PersonID` field to `TimeEntry` so we can pass it around as a self-contained thing without worrying about having to pass a `Profile` along with it.
2017-06-03http.go: Replace `SubmitTimeEntries` with `SubmitTimeEntry`Teddy Wing
A slightly altered function that only submits a single time entry and uses our new `Profile`, `Project`, and `TimeEntry` types.
2017-06-03main.go: Add `Profile` to `Config`Teddy Wing
Require the config.toml file to come with a `[profile]` hash. This allows us to get the "person_id" for correct submission to TimeTask. Additionally, add a TOML tag to `PersonID` in `Profile` to allow it to be decoded.
2017-06-03Project: Add a TOML tag for the WorkType fieldTeddy Wing
Otherwise the TOML decoder didn't know how to parse it.
2017-06-03buildSubmissionParams(): Support new `TimeEntry`; Submit single entryTeddy Wing
Change the function to use our new `TimeEntry` type, which doesn't demand asking for IDs as it already has them built in. Additionally, remove the loop here as we only want to submit a single time entry at a time. Add a new `Profile` type that holds onto the user's person_id. Forgot that existed. We'll have users fill that into their config.toml file.
2017-06-03http.go: Restore `SubmitTimeEntries` & `buildSubmissionParams`Teddy Wing
Uncomment these functions. Looks like they'll still be useful after all. Just need a little munging to fit them into the usage of submitting a single time entry and using our new `Project` and `TimeEntry` types.
2017-06-03time_entry.go: Rewrite `TimeEntry` type for the new eraTeddy Wing
Change [Client, Project, Module, Task, WorkType] fields to `int`s instead of strings. In the new era, with config2.toml, these fields will be populated directly with the proper int IDs from TimeTask. Thus these fields need to be `int`s. Get rid of the `UnmarshalYAML` function as in the new era we won't be submitting time entries by YAML file. Instead they will be submitted directly via command line arguments (plus the IDs coming from the config file).
2017-06-03Create a new Project typeTeddy Wing
This corresponds to a "project" entry in the new config2.toml file. (See 13c84cd9973458750305c72a919cf921d9b22b04). Instead of decoding generic `interface{}`s as projects from the TOML, make them a real type. The reason why we're using `int`s where we used to use strings is that the new TOML format will have users write IDs directly in the config file, instead of having the program automatically search for those IDs and use them as we had previously designed. Maybe we'll bring that functionality back at some point, but for now it's too bothersome to implement and I don't consider it worth the trouble.
2017-06-03Comment out all the things!Teddy Wing
Half get rid of a lot of code. I don't like and don't want to use our old field types. Get rid of them and the code in 'http.go' that depends on them. Also get rid of the time entry submission code in 'main.go' as that's going to be redone.
2017-03-12GenerateWeeklyTimesheet: Auto-fill the date with all days in the weekTeddy Wing
Get Monday's date from the current week using the When library (which provides natural language date parsing, making it super easy to get a time object for Monday). Then when creating the `TimeEntry`ies for the generator, fill in Monday–Friday's dates in the output.
2017-03-12Add GenerateWeeklyTimesheet()Teddy Wing
A function to generate a weekly time sheet. Add a new `defaults` key to the config.yml file. Looks like this: defaults: client: project: module: task: work_type: time: billable: This will be used to fill in default values when a timesheet is generated.
2017-03-12TimeEntry.UnmarshalYAML: Don't error if date empty stringTeddy Wing
The date is allowed to be empty in the config defaults hash. Don't error if it is.
2017-03-12SubmitTimeEntries: Add required paramsTeddy Wing
These tell the Time Task form endpoint that we're submitting a multiple-time submission request.
2017-03-12Change all `uint` types to `int`Teddy Wing
Because `strings.Itoa` is so much easier to call than `strconv.ParseUint`, and I needed to parse ints into strings to build the URL params in `buildSubmissionParams` (17f4ecc63615e3f3bef21a80f15e7c7b0e0cffa1).
2017-03-12http.go: Add `buildSubmissionParams` functionTeddy Wing
Function that takes a list of `TimeEntry`ies and builds the necessary URL params for submission to the Time Task form endpoint.
2017-03-12fields.go: Get rid of unused `thingsByName` functionTeddy Wing
Not relevant. See 89f766854443a6f7ae20c330547083fd0e075ba9.
2017-03-12fields.go: Add methods that allow us to extract objects by nameTeddy Wing
We want to be able to get Client, Project, etc. objects given their name. These functions will look through the fields or objects containing a list of the thing looked for and return if if its name matches the search string. Originally had the idea to generalise the body of the function, but had trouble making the types generic. Still on the table for later if we want to deduplicate the code. For now I'm leaving in the repetition because it works and I don't care with this project.
2017-03-12fields.go: Get rid of `IDName`Teddy Wing
Embedding this struct prevented us from correctly unmarshalling data into them. This is because they need to be created like: Client{IDName{ID: , Name: ,}} The fields can't be added in directly. Save ourselves the headache and just manually repeat the fields. So that importing works right.
2017-03-12TimeEntry: Add missing Module fieldTeddy Wing
Forgot to add this field originally. Do the same as when we added the `Time` field.
2017-03-12time_entry.go: Properly unmarshal Time fieldTeddy Wing
Fix 7a8db5312bbb43c986fbae7aa14960e22080b03b to ensure that the `Time` field actually gets unmarshalled into `TimeEntry` structs.
2017-03-12Make fields named structsTeddy Wing
We'll be needing to refer to these fields as named types, so create types for them and reference them in the config object.
2017-03-12time_entry.go: Add missing `Time` fieldTeddy Wing
Include billable hours field.
2017-03-12Parse timesheet filesTeddy Wing
Expect a timesheet file as the last argument to the program. Parse the contents into `TimeEntry` objects. `TimeEntry`ies will then be able to be POSTed to Time Task to submit times. The time entries input file is a YAML document in this format: - client: A client project: A project module: A module task: A task work_type: type date: 2017-03-06 time: 7 billable: true description: It contains an array where each element is a time entry. Had a lot of trouble parsing the date into a `time.Time`. Finally realised that my first and biggest problem was somehow I was importing `yaml.v1` instead of `yaml.v2`, and thus my `UnmarshalYAML` function was never getting called. Wanted a way to get the time as a string and parse it myself into a time. At first tried using an `UnmarshalText` function: type Time time.Time func (t *Time) UnmarshalText(text []byte) error { parsed, err := time.Parse("2006-01-02", string(text)) if err == nil { *t = Time(parsed) } return err } But in order to do that I had to make a type alias to `time.Time`. Doing so was not ideal, because then I'd have to convert my `Time` into a `time.Time` any time I wanted to use it for real. Ended up going with a suggestion from here: https://mlafeldt.github.io/blog/decoding-yaml-in-go/ Creating an auxiliary struct in `UnmarshalYAML` to unmarshal the date into a string and then parse it myself as a date. I don't really like it because it's a lot of ceremony just to parse one type myself, but can't come up with a better solution right now so there you have it.
2017-03-11TestLogin: Replace af83-specific textTeddy Wing
2017-03-11TestLogin: Do actual test checksTeddy Wing
Verify errors and check the response body to ensure successful login.
2017-03-11Get login workingTeddy Wing
Fill in the `Login` function to actually log in to Time Task. Pass credentials in via test command flags. Referenced https://gist.github.com/varver/f327ef9087ebf76aa4c4 for the cookie setup.
2017-03-11Initial commit. Test HTTP request.Teddy Wing
Make a sample GET request using `net/http`.