diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index a7ba92fa..24917d3c 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -9,7 +9,7 @@ def home @upcoming_leaves = current_user.leaves.future.not_rejected.chronologic sprint_feedback = current_user.sprint_feedbacks.find_by(sprint: @sprint) if @sprint @daily_nerd_message = DailyNerdMessage.find_by(created_at: Time.zone.today.all_day, sprint_feedback:) || sprint_feedback.daily_nerd_messages.build if sprint_feedback - @needs_retro = current_user.sprint_feedbacks.sprint_past.retro_missing.first + @needs_retro_for = SprintFeedback.where(user: current_user).sprint_past.reverse_chronologic.limit(2).find { !_1.retro_completed? } end def offline diff --git a/app/controllers/sprint_feedbacks_controller.rb b/app/controllers/sprint_feedbacks_controller.rb index ccfe669b..dd006eee 100644 --- a/app/controllers/sprint_feedbacks_controller.rb +++ b/app/controllers/sprint_feedbacks_controller.rb @@ -14,17 +14,11 @@ def create ui.replace feedback.sprint end - def edit + def edit_retro end - def update - if @feedback.update feedback_update_attributes - @user = @feedback.user - ui.close_popover - ui.replace @feedback.sprint - else - render :edit, status: :unprocessable_entity - end + def update_retro + @feedback.update! feedback_update_attributes end def destroy diff --git a/app/frontend/components/checkbox/checkbox.scss b/app/frontend/components/checkbox/checkbox.scss new file mode 100644 index 00000000..7f2da4ed --- /dev/null +++ b/app/frontend/components/checkbox/checkbox.scss @@ -0,0 +1,15 @@ +.checkbox { + &__input { + display: block; + width: 20px; + height: 20px; + border: 1px solid currentColor; + + &:checked::before { + display: block; + content: 'X'; + width: 10px; + height: 10px; + } + } +} diff --git a/app/frontend/components/checkbox/checkbox.tsx b/app/frontend/components/checkbox/checkbox.tsx new file mode 100644 index 00000000..77811db9 --- /dev/null +++ b/app/frontend/components/checkbox/checkbox.tsx @@ -0,0 +1,92 @@ +import React, { ReactNode } from 'react'; + +import { Text } from '../text/text'; +import { FormField, useInputId } from '../form_field/form_field'; +import classnames from 'classnames'; +import './checkbox.scss'; + +interface Props extends FormField { + label?: ReactNode; +} + +export function Checkbox({ + name, + value, + ariaLabel, + placeholder, + required, + disabled, + readOnly, + inputId, + label, + touched, + errors, + onChange, + onBlur, + onFocus, +}: Props): JSX.Element { + inputId = useInputId(inputId); + return ( +
+
+
+ {label !== undefined && ( + + )} + + { + if (readOnly) { + event.preventDefault(); + return; + } + onChange?.(event.target.checked); + }} + onFocus={() => { + onFocus?.(); + }} + onBlur={() => { + onBlur?.(); + }} + placeholder={placeholder} + required={required} + disabled={disabled} + aria-label={ariaLabel} + /> + +
+ {touched && errors && ( +
+ {errors.map((error) => ( + {error} + ))} +
+ )} +
+
+ ); +} diff --git a/app/frontend/components/number_field/number_field.tsx b/app/frontend/components/number_field/number_field.tsx index 68c54e58..ecb8fac4 100644 --- a/app/frontend/components/number_field/number_field.tsx +++ b/app/frontend/components/number_field/number_field.tsx @@ -12,7 +12,7 @@ export function NumberField(props: Props): JSX.Element { Number(value)} + onChange={(value) => props.onChange?.(Number(value))} /> ); } diff --git a/app/frontend/locale/en.json b/app/frontend/locale/en.json index 71712b63..efa15494 100644 --- a/app/frontend/locale/en.json +++ b/app/frontend/locale/en.json @@ -6,7 +6,10 @@ "last_payments": "Last payments", "remaining_holidays": "Remaining holidays", "number_holidays_left": "You have %{count} days off left", - "payslip_archive": "archive" + "payslip_archive": "archive", + "missing_retro": "Retrospective Notes Missing", + "missing_retro_description": "You did not yet leave a rating for sprint %{title}.", + "leave_retro_notes": "Rate the sprint now" } }, "sprints": { @@ -18,6 +21,14 @@ "save": "Save" } }, + "sprint_feedbacks": { + "edit_retro": { + "skip": "Skip rating this sprint", + "rating": "Rating", + "text": "Text", + "save": "Save" + } + }, "users": { "index": { "title": "Users", diff --git a/app/models/sprint_feedback.rb b/app/models/sprint_feedback.rb index 83af367c..0e1f9781 100644 --- a/app/models/sprint_feedback.rb +++ b/app/models/sprint_feedback.rb @@ -30,6 +30,7 @@ class SprintFeedback < ApplicationRecord validates :retro_rating, numericality: {only_integer: true, in: 1..5}, allow_nil: true scope :ordered, -> { joins(:user).order("users.email ASC") } + scope :reverse_chronologic, -> { joins(:sprint).order("LOWER(sprints.sprint_during) DESC") } scope :retro_missing, -> { where(retro_rating: nil, skip_retro: false) } scope :retro_not_skipped, -> { where(skip_retro: false) } scope :sprint_past, -> { diff --git a/app/policies/sprint_feedback_policy.rb b/app/policies/sprint_feedback_policy.rb index a84a07e7..b24d1737 100644 --- a/app/policies/sprint_feedback_policy.rb +++ b/app/policies/sprint_feedback_policy.rb @@ -9,6 +9,14 @@ def create? hr? end + def edit_retro? + update? + end + + def update_retro? + update? + end + def update? hr? || record.user == user end diff --git a/app/views/pages/_daily_nerd_card.tsx b/app/views/pages/_daily_nerd_card.tsx index 6f66e4a0..1d8a911a 100644 --- a/app/views/pages/_daily_nerd_card.tsx +++ b/app/views/pages/_daily_nerd_card.tsx @@ -33,16 +33,24 @@ export function DailyNerdCard({ id, message }: Props): JSX.Element { }, }); return ( - -