-
-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
Worktime tracking for the organization level. #19808
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for PR! Looks beautiful :)
All queries must be rewritten using xorm query builder and need to add filter to calculate and show only data from repositories user has access to (with issue/pr rights?). We should have function that return such conditions imho
Thank you, lafriks :) 😊
OK, if I must :) I'll do it when I'll have some time. Hopefully within a week.
Hmm, currently the whole functionality is restricted to organization "owners" (by checking My thinking was that I would rather NOT let people see partial (invalid) data, since the risk that such invalid data gets sent out in an invoice etc by somebody who don't have full rights to see everything within an organization is too high. So I'm double-checking with you: would you consider the current "limited to owners" restriction enough, or still want additional permission check in the query? |
The permission checking shouldn't be done by a helper helper, this should rather be done at router-level. So in this case you want to move the three lines in web.go to the group that starts from line 640, which already includes the owner checking. |
As @Gusted said it's in the wrong place and that's why I did not notice that it's only for owner team members. Yes you understand correctly owner users will have full access to all org repositories. If we leave it that only owners have access to this than it does not need that check in queries. My use case would be that owner would be either lead developer of the team or devops team. Project manager who would be interested in this tab usually have read rights to all repos (and write rights to issues) thus he would not see this. But that's totally I don't mind seeing done in the future as other PR to improve this feature. |
Thanks for the laser-precise advice, @Gusted, will do! I totally see your point @lafriks. If (as you say) it's OK to deal with the more precise permissions in a future PR, then for simplicity's sake I'd rather leave this particular PR as "owner-only" (but change it of course as per Gusted's recommendation). I will |
28cde92
to
44669f4
Compare
Just two small questions:
Thanks in advance! |
Since this PR sent after v1.17 feature freezed, let's wait to merge after v1.17 release. Of course, I think we can re-review it at any time when maintainers have free time. |
Thanks, I'll be requesting re-review then. (Github is a bit confusing for me regarding the right etiquette and the request UI) |
Dear @lafriks and @Gusted, I just couldn't bear not having tests on the correctness of the queries, so I refactored a bit and added tests. Hope you don't mind. P.s.: The build failed with P.s.2: I think Github erroneously keeps "1 change requested" on this ticket, because the change was done – maybe it was confused by the rebase at the same time? Anyway, I will leave this PR alone for now -- feel free to review (all change requests were completed) and to merge at the right time! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make sure you have translated words and use the correct keys for those. The HTML part of this PR really need some tidying up to do.
routers/web/org/times.go
Outdated
Name string `xorm:"name"` | ||
SumTime int64 `xorm:"sumtime"` | ||
} | ||
|
||
// resultTimesByMilestones is a struct for DB query results | ||
type resultTimesByMilestones struct { | ||
RepoName string `xorm:"reponame"` | ||
Name string `xorm:"name"` | ||
ID string `xorm:"id"` | ||
SumTime int64 `xorm:"sumtime"` | ||
HideRepoName bool `xorm:"-"` | ||
} | ||
|
||
// resultTimesByMembers is a struct for DB query results | ||
type resultTimesByMembers struct { | ||
Name string `xorm:"name"` | ||
SumTime int64 `xorm:"sumtime"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usually you only use xorm
tags for struct that will be stored into the database. Xorm should be able to figure out by itself which row corresponds to a field(if not, then add a xorm tag).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed. To let Xorm figure out by itself, the query builder part was also touched (sumtime
=> sum_time
, so it recognizes SumTime
, etc.
routers/web/org/times.go
Outdated
ctx.Data["RangeTo"] = to | ||
|
||
// Prepare unix time values for SQL | ||
gfrom, err := time.Parse("2006-01-02", from) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does the g
represent in the variable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It stands for "Go", as in Go's Time object. The variable named from
above is of String type, and here we convert to Go's Time. It's a temporary variable that is needed for the handling of err
from the Parse
function. Changed it to from2
.
Thanks for the detailed review - I haven't disappeared, I'll do the requested changes when I have some time! |
Dear @Gusted, I've finally got around to make the changes you requested. It's not completely clear to me whether it should be me or you who "resolve" the conversations, so I erred on the side of "resolving" the trivial ones, and leaving open the ones where you might want to see the responses. One particular thing: please review my use of |
Codecov Report
@@ Coverage Diff @@
## main #19808 +/- ##
=======================================
Coverage ? 46.91%
=======================================
Files ? 975
Lines ? 135113
Branches ? 0
=======================================
Hits ? 63394
Misses ? 63960
Partials ? 7759
Continue to review full report at Codecov.
|
routers/web/org/times.go
Outdated
|
||
// parseTimes contains functionality that is required in all these functions, | ||
// like parsing the date from the request, setting default dates, etc. | ||
func parseTimes(ctx *context.Context) (unixfrom, unixto int64, err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parseOrgTimes
.
routers/web/org/times.go
Outdated
func parseTimes(ctx *context.Context) (unixfrom, unixto int64, err error) { | ||
// View variables | ||
ctx.Data["PageIsOrgTimes"] = true | ||
ctx.Data["AppSubURL"] = setting.AppSubURL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't be set by this function.
// Show only the first RepoName, for nicer output. | ||
prevreponame := "" | ||
for i := 0; i < len(results); i++ { | ||
res := &results[i] | ||
if prevreponame == res.RepoName { | ||
res.HideRepoName = true | ||
} | ||
prevreponame = res.RepoName | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be moved outside this function.
routers/web/org/times.go
Outdated
} | ||
|
||
// getTimesByRepos fetches data from DB to serve TimesByRepos. | ||
func getTimesByRepos(unixfrom, unixto, orgid int64) (results []resultTimesByRepos, err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These kind of functions lives in models/
directory. routers/
is just connecting all the functions and do the nice things with the data.
routers/web/web.go
Outdated
m.Get("/by_repos", org.TimesByRepos) | ||
m.Get("/by_members", org.TimesByMembers) | ||
m.Get("/by_milestones", org.TimesByMilestones) | ||
}, context.OrgAssignment(true, true)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
}, context.OrgAssignment(true, true)) | |
}, context.OrgAssignment(false, true)) |
Only org admin should be able to see it right?
templates/org/menu.tmpl
Outdated
@@ -21,6 +21,11 @@ | |||
<div class="ui black label">{{.NumTeams}}</div> | |||
{{end}} | |||
</a> | |||
{{if .IsOrganizationOwner}} | |||
<a class="{{if $.PageIsOrgTimes}}active{{end}} item" href="{{$.OrgLink}}/times/by_repos"> | |||
{{svg "octicon-clock"}} {{$.i18n.Tr "org.worktime"}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please change all occurences of $.i18n.Tr
to $.locale.Tr
9f70fae
to
eef5842
Compare
e4847ac
to
53b460b
Compare
53b460b
to
be5783e
Compare
This looks mighty useful! Other than rebasing, are the changes required at this point only style-related? |
Thank you for the kind words, @bard! :) Nice comments like yours keep open source projects alive. But, unfortunately, no. What is asked is another (the 5th) refactoring of the code. Also, the Now, it's normal to have 1-2 rounds of change requests on a PR -- it is very important to keep the structure of a project consistent, enforce style so it's easy for everyone to touch each part, etc. The problem is that when there were already 5 rounds, AND each round is asking for NEW things to change which were NOT mentioned before, I see no point in doing the integration work again, since there is no guarantee that it will not be in vain again. I unfortunately don't have THIS much free time on my hand. :( I've already spent about four times as much time complying with review requests as on the original feature itself... The code still stands contributed, if someone is willing to integrate it in a way that satisfies the code stewards, that's great, I would be the most happy -- I too, still believe that this would increase the value of Sorry. |
Thanks for your time! What a pity this cannot be merged ASAP. I wish someone could pick it and continue. |
…first parameter of the function.
f041678
to
bd60f63
Compare
OK, I'm giving this another try, because you guys were so nice. I've rebased it, implemented the last change request, and the build is passing. If there are any more change requests, say so, but please try to ask in one batch, not with a thousand cuts, please? Thanks :) |
Thank you a lot for your work and your effort! That's such a wonderful feature! |
@lunny @delvh (paging because I see you in the PR, sorry if you're not the ones I should @): looking at this and #23113, both in limbo, it seems that time tracking in general in Gitea is on hold. Obviously I'm among those here who believe that small additions in this area would yield disproportionately high end user value — teams wouldn't have to find, integrate, and maintain a separate time tracking solution — but I respect that no software can be everything to everyone. Any chance we could have the maintaners' view on the time tracking story in Gitea? At least we can let the wish go for good if necessary. |
The problems I have with time tracking are the following:
|
That's fair. You see value in this (ancillary, I agree) area, but there are more urgent issues from the core area, and the lack of RFC process makes it difficult to achieve a well-integrated change, and the size of proposed changes makes it difficult to assess for impact and review. I guess that for things to progress in the short term it would take either someone who has both a good understanding of the code base and a carefully thought-out story for project management that maintainers agree with (unlikely, as that sounds more like a core contributor and core contributors already have their hands full), or changes that are tiny and incremental enough that are easy to review and assess as well-fitting (I don't know if features in this area can actually be shaped this way). Not great news obviously it helps a lot with setting expectations, so thank you for chiming in. |
Dear Gitea team,
first of all, thanks for the great work you're doing with this project.
I'm planning to introduce Gitea at a client site, and noticed that while there is time recording, there are no project-manager-friendly reports to actually make use of that data, as were also mentioned by others in #4870 #8684 and #13531.
Since I had a little time last weekend, I had put together something that I hope to be a useful contribution to this great project (while of course useful for me too).
This PR adds a new "Worktime" tab to the Organisation level. There is a date range selector (by default set to the current month), and there are three possible views:
Happy to receive any feedback!
There are several possible future improvements of course (predefined date ranges, charts, a member time sheet, matrix of repos/members, etc) but I hope that even in this relatively simple state this would be useful to lots of people.
Keep up the good work!
Kristof