Skip to content
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

Implementation/59721 add setedit reminder buttondialog to workpackage page #17341

Conversation

jjabari-op
Copy link
Collaborator

@jjabari-op jjabari-op self-assigned this Dec 3, 2024
@jjabari-op jjabari-op requested a review from akabiru December 3, 2024 16:07
Base automatically changed from implementation/59433-define-database-model-for-reminders to dev December 4, 2024 14:50
@akabiru akabiru added this to the 15.2.x milestone Dec 4, 2024
@akabiru akabiru added the feature label Dec 4, 2024
Copy link
Member

@akabiru akabiru left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite the feat, nicely done! 👏🏾 I've noted a few general issues

  • Missing unit test coverage for model, contract and API changes - annotated in the code
  • Missing API specification & tests
  • Several eslint and rubocop issues

UI Wise

  • Missing modal cancel button as per the design
    • Separately, it would be good to check with UX/Product if we can adopt "Remove reminder" instead of "Delete reminder" and "Schedule" instead of "Save" - from previous mention people seemed in favour of the idea
  • On hover of the "Set reminder icon" no label is displayed
  • The reminders clock icon is off-centered to the left

Kapture 2024-12-06 at 14 24 41

  • Content loader skeleton does not match the reminders UI
  • Duplicate form error messages
Screenshot 2024-12-06 at 11 03 09 AM
  • Unhandled 404 when reminder edit modal is open, and the reminder notification is created whilst it's still open (you can test this by creating a reminder in the next minute, open the edit modal and wait for the reminder notification to be created then attempt to edit it)
Screenshot 2024-12-06 at 11 00 29 AM
  • icon is smaller than counter
Screenshot 2024-12-09 at 2 02 10 PM

app/contracts/reminders/base_contract.rb Show resolved Hide resolved
Comment on lines +128 to +146
# At the form level, we split the date and time into two form fields.
# In order to be a bit more informative of which field is causing
# the remind_at attribute to be in the past/invalid, we need to
# remap the error attribute to the appropriate field.
def prepare_errors_from_result(service_result)
# We set the reminder here for "create" case
# as the record comes from the service.
@reminder = service_result.result
@errors = service_result.errors

case @errors.find { |error| error.attribute == :remind_at }&.type
when :blank
handle_blank_error
when :datetime_must_be_in_future
handle_future_error
end

@errors.delete(:remind_at)
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 I think this method and related calls would do well as an extracted simple PORO that can be unit tested- also reduce the perceived complexity on the controller

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 36 to 50
# Currently, reminders are personal, meaning
# they are only visible to the user who created them.
def self.visible(user)
where(creator: user)
end

def self.upcoming_and_visible_to(user)
visible_reminders = visible(user)
reminder_notifications_for_reminders = ReminderNotification.where(reminder: visible_reminders)

visible_reminders
.where(completed_at: nil)
.where.not(id: reminder_notifications_for_reminders.select(:reminder_id))
end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one covering these- 🟠 it would be worth add the corresponding model unit specs in https://github.com/opf/openproject/blob/dev/spec/models/reminder_spec.rb

Copy link
Member

@akabiru akabiru Dec 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Once the tests are added. I think the method to exclude reminders that have associated reminder notifications can be simplified via where.missing

Performance seems about the same faster - as the later results in no sub-queries and reads easier IMO

Suggested change
# Currently, reminders are personal, meaning
# they are only visible to the user who created them.
def self.visible(user)
where(creator: user)
end
def self.upcoming_and_visible_to(user)
visible_reminders = visible(user)
reminder_notifications_for_reminders = ReminderNotification.where(reminder: visible_reminders)
visible_reminders
.where(completed_at: nil)
.where.not(id: reminder_notifications_for_reminders.select(:reminder_id))
end
# Currently, reminders are personal, meaning
# they are only visible to the user who created them.
def self.visible(user)
where(creator: user)
end
def self.upcoming_and_visible_to(user)
visible(user)
.where(completed_at: nil)
.where.missing(:reminder_notifications)
end

Comment on lines 39 to 42
<svg:rect height="10" rx="2" ry="2" width="110" x="0" y="0"/>
<svg:rect height="10" rx="2" ry="2" width="25" x="120" y="0"/>
<svg:rect height="10" rx="2" ry="2" width="25" x="155" y="0"/>
<svg:rect height="25%" rx="2" ry="2" width="180" x="0" y="16"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 I noticed this content loader skeleton comes from the shares modal- could we ask design for one that matches the reminders modal?

map((collection:CollectionResource) => { return collection.total; }),
);
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Several eslint issues that need fixing

Comment on lines +70 to +85
this.reminderCount$ = merge(
this
.actions$
.ofType(reminderModalUpdated)
.pipe(
map((action) => action.workPackageId),
filter((id) => id === this.workPackage.id?.toString()),
startWith(null),
switchMap(() => this.countReminders()),
),
this.storeService.unread$
.pipe(
startWith(0),
switchMap(() => this.countReminders()),
),
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Why do we need to reference unread notifications? 🤔

Comment on lines +32 to +33
<turbo-frame
#frameElement
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one 👍🏾

lib/api/v3/reminders/reminders_api.rb Show resolved Hide resolved

describe "validations" do
it "renders errors on the date field or time field when the reminder is in the past" do
two_am = "02:00".to_time
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2024-12-06 at 2 09 25 PM

work_package_page.expect_no_reminder_button
end
end
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work on the feature specs! 👍🏾

@jjabari-op
Copy link
Collaborator Author

Thank you @akabiru for the comprehensive and detailed review! I'm on it! :)

@akabiru
Copy link
Member

akabiru commented Dec 10, 2024

@jjabari-op updating against dev as there were several recent CI stabalisation fixes that would be nice to have in

Copy link
Member

@akabiru akabiru left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥇

Comment on lines +128 to +146
# At the form level, we split the date and time into two form fields.
# In order to be a bit more informative of which field is causing
# the remind_at attribute to be in the past/invalid, we need to
# remap the error attribute to the appropriate field.
def prepare_errors_from_result(service_result)
# We set the reminder here for "create" case
# as the record comes from the service.
@reminder = service_result.result
@errors = service_result.errors

case @errors.find { |error| error.attribute == :remind_at }&.type
when :blank
handle_blank_error
when :datetime_must_be_in_future
handle_future_error
end

@errors.delete(:remind_at)
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lib/api/v3/reminders/reminders_api.rb Show resolved Hide resolved
@akabiru akabiru merged commit 5ab30ac into dev Dec 12, 2024
16 checks passed
@akabiru akabiru deleted the implementation/59721-add-setedit-reminder-buttondialog-to-workpackage-page branch December 12, 2024 09:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

3 participants