Split report by reviewer via modal ( Frontend Side Only )#1227
Split report by reviewer via modal ( Frontend Side Only )#1227MitanOmar wants to merge 3 commits into
Conversation
5089d6b to
7ccb9e9
Compare
|
|
||
| get canSplitReport() { | ||
| return ( | ||
| this.id.length === 1 && |
There was a problem hiding this comment.
This is one of many coming conditions that should be applied before allowing split report,
and the first condition that the selected reports for edit have to be one
There was a problem hiding this comment.
What is id here? why are we taking its length? isn't id usually an increasing number? (for like records)
There was a problem hiding this comment.
Ahhh, that's cursed, maybe rename it to ids or reports/reportIds? (that would greatly improve readability)
| @action | ||
| handleClick(e) { | ||
| if (e.target.id === this.id) { | ||
| if (e.target.id === this.id && this.args.closeOnBackdropClick !== false) { |
There was a problem hiding this comment.
this is for disable interactivity with the background, so no one will accidentally close the modal
There was a problem hiding this comment.
What would be the usecase for that?
There was a problem hiding this comment.
user experience preferred after collection opinions from the team
There was a problem hiding this comment.
No I mean, of this implementation, why not have the browser handle this for us
| @tracked newTask = null; | ||
| @tracked newComment = ""; | ||
| @tracked newDuration = moment.duration(); | ||
|
|
||
| @tracked oldTask = null; | ||
| @tracked oldComment = ""; | ||
| @tracked oldDuration = moment.duration(); |
There was a problem hiding this comment.
Is there a reason you didn't use models here?
There was a problem hiding this comment.
do you mean passing a reference from parent to child ( Split Report Component ) ?
There was a problem hiding this comment.
I meant using ember-data models, for boith?
There was a problem hiding this comment.
it's not the final version yet, this part was done after a request of making a demo.
and this was easier for quick demo, let's see later what will be the final results
15465ad to
222964c
Compare
222964c to
3e880b8
Compare
|
you might want to rebase ^^ |
4be047f to
2cb6db4
Compare
|
@g-kedev fyi: the modified information is sent to endpoint in case that you prepared another endpoint, or expected it somewhere else, just comment here, and i will modify the URL in the frontend |
| @tracked newTask = null; | ||
| @tracked newComment = ""; | ||
| @tracked newDuration = Duration.fromMillis(0); | ||
|
|
||
| @tracked oldTask = null; | ||
| @tracked oldComment = ""; | ||
| @tracked oldDuration = Duration.fromMillis(0); |
There was a problem hiding this comment.
If we're not going to use ember data models, you could have these as a separate data structure, to improve readability and maintainability :)
class Report {
@tracked
task = null;
@tracked
comment = "";
@tracked
duration = Duration.fromMillis(0);
};
export default class SplitReportModal extends Component {
report = new Report();
newReport = new Report();
[...]
}What's the rationale for not using ember data models?
There was a problem hiding this comment.
because it need deep watching of the changes of the model.
and this was easier for implementation, and also more clear for reviewer
There was a problem hiding this comment.
so what about using a native class with @tracked attributes? (instead of the model)
| @action | ||
| onSetOldTask(task) { | ||
| this.oldTask = task; | ||
| } | ||
|
|
||
| @action | ||
| onSetNewTask(task) { | ||
| this.newTask = task; | ||
| } |
There was a problem hiding this comment.
you could inline these in the template with fn (mut this.newTask), or fn (mut this.splitReport.task)
which is what I personally prefer (for readability)
| @action | ||
| onNewDurationChange(value) { | ||
| const totalMs = this.oldDuration.as("milliseconds"); | ||
| const ms = Math.min(value?.as("milliseconds") ?? 0, totalMs); | ||
| this.newDuration = Duration.fromMillis(Math.max(ms, 0)); | ||
| } | ||
|
|
||
| @action | ||
| onRemainingDurationChange(value) { | ||
| const totalMs = this.oldDuration.as("milliseconds"); | ||
| const remainingMs = Math.min(value?.as("milliseconds") ?? 0, totalMs); | ||
| this.newDuration = Duration.fromMillis(Math.max(totalMs - remainingMs, 0)); | ||
| } |
There was a problem hiding this comment.
You set newDuration in both of these 🤔
Consider adding a comment or two to explain what is happening here.
There's likely a much neater way to implement this, maybe @derrabauke has some ideas?
| get isValidSplit() { | ||
| if (!this.newTask) return false; | ||
| if (!this.newDuration || this.newDuration.as("milliseconds") <= 0) { | ||
| return false; | ||
| } | ||
| if ( | ||
| !this.oldDuration || | ||
| this.newDuration.as("milliseconds") >= this.oldDuration.as("milliseconds") | ||
| ) { | ||
| return false; | ||
| } | ||
| return true; | ||
| } |
There was a problem hiding this comment.
Have you considered using ember-changeset-validations? (see ember/frontend/app/validators/datetime.js)
| await this.fetch.fetch(`/api/v1/reports/${reportId}/split`, { | ||
| method: "POST", | ||
| body: { | ||
| old_report: { | ||
| task: this.oldTask.id, | ||
| comment: this.oldComment, | ||
| duration: durationTransform.serialize(this.remainingOldDuration), | ||
| }, | ||
| new_report: { | ||
| task: this.newTask.id, | ||
| comment: this.newComment, | ||
| duration: durationTransform.serialize(this.newDuration), | ||
| }, | ||
| }, | ||
| }); |
There was a problem hiding this comment.
I would imagine ember data could help us here? Like you could probably create an ember data model for this (not quite sure how well this would work)
Maybe @derrabauke has some input/pointers?
32e26c0 to
f324e6b
Compare
|
@derrabauke @c0rydoras @Jana90JL @g-kedev @trowik |
1c38efb to
18a0b32
Compare
5bd342a to
af01923
Compare
af01923 to
694185a
Compare
| get canSplitReport() { | ||
| return ( | ||
| this.id?.length === 1 && | ||
| this.abilities.can( | ||
| "editSync report", | ||
| this.intersection.lastSuccessful.value.model, | ||
| ) | ||
| ); | ||
| return this.id?.length === 1; | ||
| } |
There was a problem hiding this comment.
refactor: remove the validation if the current user is a reviewer
AFAICT this just fully removes the validation?
nit: refactor(frontend): instead of refactor:
|
instead of |
@MitanOmar Endpoint is correct. The data structure is a little different, here is an example: |
694185a to
b13607e
Compare
Why not use a |
b13607e to
f15c50c
Compare
Since the data is nested, I wasn't sure how to validate the fields via the serializer attributes, but I created a second data serializer so it can use said attribute-validation. |
f15c50c to
f51c0d9
Compare
| class ReportDataSerializer(serializers.Serializer): | ||
| comment = serializers.CharField() | ||
| duration = serializers.DurationField() | ||
| task_id = serializers.IntegerField() |
There was a problem hiding this comment.
I'm fairly sure you could use some RelatedField or sth like that for task_id
There was a problem hiding this comment.
Adjusted it, now it uses ResourceRelatedField.
| if not original_report: | ||
| raise ValidationError(_("Original report doesn't exist")) |
There was a problem hiding this comment.
No it already gets caught before it reaches this point, removed it.
| new_report_task = Task.objects.get(id=new_report.get("task_id")) | ||
| updated_report_task = Task.objects.get(id=updated_report.get("task_id")) |
There was a problem hiding this comment.
To get the billed flag from the project afterwards.
If you're asking why to put it in a variable: To get the id also from the object, thought it would be nicer than taking it from the request, since we have to get the object anyway AFAICT (for the reason above).
e03b3f2 to
1617db3
Compare
1617db3 to
d58bac4
Compare
| class ReportDataSerializer(Serializer): | ||
| comment = serializers.CharField() | ||
| duration = serializers.DurationField() | ||
| task = ResourceRelatedField(queryset=Task.objects.all()) |
There was a problem hiding this comment.
maybe we could use Task.objects.filter(archived=False) instead of Task.objects.all() here 🤔
a part of #1121
Original report in the left, and new one in the rightnew reportto beSecond ReportTask Selectionof the original reportfloat start