Skip to content

Commit

Permalink
Merge pull request #2578 from objectcomputing/feature-2574/2024-08-29…
Browse files Browse the repository at this point in the history
…---ReviewPeriodDateRange

Feature 2574/2024 08 29   review period date range
  • Loading branch information
mkimberlin authored Sep 2, 2024
2 parents 8506130 + 7428599 commit 24364f1
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,36 @@ public class ReviewPeriod {
@JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime closeDate;

@Nullable
@Column(name = "period_start_date")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime periodStartDate;

@Nullable
@Column(name = "period_end_date")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime periodEndDate;

public ReviewPeriod(String name, ReviewStatus reviewStatus, @Nullable UUID reviewTemplateId,
@Nullable UUID selfReviewTemplateId, @Nullable LocalDateTime launchDate,
@Nullable LocalDateTime selfReviewCloseDate, @Nullable LocalDateTime closeDate) {
@Nullable LocalDateTime selfReviewCloseDate, @Nullable LocalDateTime closeDate,
@Nullable LocalDateTime periodStartDate, @Nullable LocalDateTime periodEndDate) {
this.name = name;
this.reviewStatus = reviewStatus;
this.reviewTemplateId = reviewTemplateId;
this.selfReviewTemplateId = selfReviewTemplateId;
this.launchDate = launchDate;
this.selfReviewCloseDate = selfReviewCloseDate;
this.closeDate = closeDate;
this.periodStartDate = periodStartDate;
this.periodEndDate = periodEndDate;
}

@Override
public int hashCode() {
return Objects.hash(id, name, reviewStatus, reviewTemplateId, selfReviewTemplateId, launchDate, selfReviewCloseDate, closeDate);
return Objects.hash(id, name, reviewStatus, reviewTemplateId, selfReviewTemplateId, launchDate, selfReviewCloseDate, closeDate, this.periodStartDate, this.periodEndDate);
}

@Override
Expand All @@ -103,6 +118,8 @@ public String toString() {
", launchDate=" + launchDate +
", selfReviewCloseDate=" + selfReviewCloseDate +
", closeDate=" + closeDate +
", periodStartDate=" + periodStartDate +
", periodEndDate=" + periodEndDate +
'}';
}

Expand All @@ -114,6 +131,7 @@ public boolean equals(Object o) {
return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(reviewStatus, that.reviewStatus) &&
Objects.equals(reviewTemplateId, that.reviewTemplateId) && Objects.equals(selfReviewTemplateId, that.selfReviewTemplateId) &&
Objects.equals(launchDate, that.launchDate) && Objects.equals(selfReviewCloseDate, that.selfReviewCloseDate) &&
Objects.equals(closeDate, that.closeDate);
Objects.equals(closeDate, that.closeDate) && Objects.equals(periodStartDate, that.periodStartDate) && Objects.equals(periodEndDate, that.periodEndDate)
;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,19 @@ public class ReviewPeriodCreateDTO {
@JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime closeDate;

@Nullable
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime periodStartDate;

@Nullable
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime periodEndDate;

public ReviewPeriod convertToEntity(){
return new ReviewPeriod(this.name, this.reviewStatus, this.reviewTemplateId,
this.selfReviewTemplateId, this.launchDate, this.selfReviewCloseDate, this.closeDate);
this.selfReviewTemplateId, this.launchDate, this.selfReviewCloseDate, this.closeDate,
this.periodStartDate, this.periodEndDate);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE review_periods ADD COLUMN period_start_date TIMESTAMP;
ALTER TABLE review_periods ADD COLUMN period_end_date TIMESTAMP;
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,28 @@ public interface ReviewPeriodFixture extends RepositoryFixture {
default ReviewPeriod createADefaultReviewPeriod() {
return getReviewPeriodRepository().save(new ReviewPeriod("Period of Time", ReviewStatus.OPEN, null, null,
LocalDateTime.now().truncatedTo(ChronoUnit.MILLIS), LocalDateTime.now().plusDays(1).truncatedTo(ChronoUnit.MILLIS),
LocalDateTime.now().plusDays(2).truncatedTo(ChronoUnit.MILLIS)));
LocalDateTime.now().plusDays(2).truncatedTo(ChronoUnit.MILLIS)
, LocalDateTime.now().minusDays(30).truncatedTo(ChronoUnit.MILLIS), LocalDateTime.now().minusDays(1).truncatedTo(ChronoUnit.MILLIS)));
}

default ReviewPeriod createADefaultReviewPeriod(ReviewStatus reviewStatus) {
return getReviewPeriodRepository().save(new ReviewPeriod("Period of Time", reviewStatus, null, null,
LocalDateTime.now().truncatedTo(ChronoUnit.MILLIS), LocalDateTime.now().plusDays(1).truncatedTo(ChronoUnit.MILLIS),
LocalDateTime.now().plusDays(2).truncatedTo(ChronoUnit.MILLIS)));
LocalDateTime.now().plusDays(2).truncatedTo(ChronoUnit.MILLIS)
, LocalDateTime.now().minusDays(30).truncatedTo(ChronoUnit.MILLIS), LocalDateTime.now().minusDays(1).truncatedTo(ChronoUnit.MILLIS)));
}

default ReviewPeriod createASecondaryReviewPeriod() {
return getReviewPeriodRepository().save(new ReviewPeriod("Period of Play", ReviewStatus.OPEN, null, null,
LocalDateTime.now().truncatedTo(ChronoUnit.MILLIS), LocalDateTime.now().plusDays(1).truncatedTo(ChronoUnit.MILLIS),
LocalDateTime.now().plusDays(2).truncatedTo(ChronoUnit.MILLIS)));
LocalDateTime.now().plusDays(2).truncatedTo(ChronoUnit.MILLIS)
, LocalDateTime.now().minusDays(30).truncatedTo(ChronoUnit.MILLIS), LocalDateTime.now().minusDays(1).truncatedTo(ChronoUnit.MILLIS)));
}

default ReviewPeriod createAClosedReviewPeriod() {
return getReviewPeriodRepository().save(new ReviewPeriod("Period of Closure", ReviewStatus.CLOSED, null, null,
LocalDateTime.now().truncatedTo(ChronoUnit.MILLIS), LocalDateTime.now().plusDays(1).truncatedTo(ChronoUnit.MILLIS),
LocalDateTime.now().plusDays(2).truncatedTo(ChronoUnit.MILLIS)));
LocalDateTime.now().plusDays(2).truncatedTo(ChronoUnit.MILLIS)
, LocalDateTime.now().minusDays(30).truncatedTo(ChronoUnit.MILLIS), LocalDateTime.now().minusDays(1).truncatedTo(ChronoUnit.MILLIS)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ void testReviewPeriodCreateDTOSerialization() throws JsonProcessingException {
reviewPeriodCreateDTO.setLaunchDate(LocalDateTime.now());
reviewPeriodCreateDTO.setSelfReviewCloseDate(LocalDateTime.now());
reviewPeriodCreateDTO.setCloseDate(LocalDateTime.now());
reviewPeriodCreateDTO.setPeriodStartDate(LocalDateTime.now());
reviewPeriodCreateDTO.setPeriodEndDate(LocalDateTime.now());

final HttpRequest<ReviewPeriodCreateDTO> request = HttpRequest.
POST("/", reviewPeriodCreateDTO).basicAuth(ADMIN_ROLE, ADMIN_ROLE);
Expand All @@ -212,6 +214,14 @@ void testReviewPeriodCreateDTOSerialization() throws JsonProcessingException {
String expectedCloseDateFormat = objectMapper.readTree(expectedJson).get("closeDate").asText();
String actualCloseDateFormat = objectMapper.readTree(actualJson).get("closeDate").asText();
assertEquals(expectedCloseDateFormat, actualCloseDateFormat);

String expectedPeriodStartDateFormat = objectMapper.readTree(expectedJson).get("periodStartDate").asText();
String actualPeriodStartDateFormat = objectMapper.readTree(actualJson).get("periodStartDate").asText();
assertEquals(expectedPeriodStartDateFormat, actualPeriodStartDateFormat);

String expectedPeriodEndDateFormat = objectMapper.readTree(expectedJson).get("periodEndDate").asText();
String actualPeriodEndDateFormat = objectMapper.readTree(actualJson).get("periodEndDate").asText();
assertEquals(expectedPeriodEndDateFormat, actualPeriodEndDateFormat);
}

@Test
Expand All @@ -222,6 +232,8 @@ void testReviewPeriodCreateDTOSerializationForbiddenWithoutPermission() throws J
reviewPeriodCreateDTO.setLaunchDate(LocalDateTime.now());
reviewPeriodCreateDTO.setSelfReviewCloseDate(LocalDateTime.now());
reviewPeriodCreateDTO.setCloseDate(LocalDateTime.now());
reviewPeriodCreateDTO.setPeriodStartDate(LocalDateTime.now());
reviewPeriodCreateDTO.setPeriodEndDate(LocalDateTime.now());

final HttpRequest<ReviewPeriodCreateDTO> request = HttpRequest.
POST("/", reviewPeriodCreateDTO).basicAuth(MEMBER_ROLE, MEMBER_ROLE);
Expand All @@ -237,13 +249,17 @@ void testPOSTCreateAReviewPeriodWithTimelines() {
LocalDateTime launchDate = LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS);
LocalDateTime selfReviewCloseDate = LocalDateTime.now().plusDays(1).truncatedTo(ChronoUnit.MILLIS);
LocalDateTime closeDate = LocalDateTime.now().plusDays(2).truncatedTo(ChronoUnit.MILLIS);
LocalDateTime periodStartDate = LocalDateTime.now().minusDays(30).truncatedTo(ChronoUnit.MILLIS);
LocalDateTime periodEndDate = LocalDateTime.now().minusDays(1).truncatedTo(ChronoUnit.MILLIS);

ReviewPeriodCreateDTO reviewPeriodCreateDTO = new ReviewPeriodCreateDTO();
reviewPeriodCreateDTO.setName("reincarnation");
reviewPeriodCreateDTO.setReviewStatus(ReviewStatus.OPEN);
reviewPeriodCreateDTO.setLaunchDate(launchDate);
reviewPeriodCreateDTO.setSelfReviewCloseDate(selfReviewCloseDate);
reviewPeriodCreateDTO.setCloseDate(closeDate);
reviewPeriodCreateDTO.setPeriodStartDate(periodStartDate);
reviewPeriodCreateDTO.setPeriodEndDate(periodEndDate);

final HttpRequest<ReviewPeriodCreateDTO> request = HttpRequest.
POST("/", reviewPeriodCreateDTO).basicAuth(ADMIN_ROLE, ADMIN_ROLE);
Expand All @@ -259,20 +275,26 @@ void testPOSTCreateAReviewPeriodWithTimelines() {
assertEquals(reviewPeriodCreateDTO.getLaunchDate(), body.getLaunchDate());
assertEquals(reviewPeriodCreateDTO.getSelfReviewCloseDate(), body.getSelfReviewCloseDate());
assertEquals(reviewPeriodCreateDTO.getCloseDate(), body.getCloseDate());
assertEquals(reviewPeriodCreateDTO.getPeriodStartDate(), body.getPeriodStartDate());
assertEquals(reviewPeriodCreateDTO.getPeriodEndDate(), body.getPeriodEndDate());
}

@Test
void testPOSTCreateAReviewPeriodWithTimelinesForbiddenWithoutPermission() {
LocalDateTime launchDate = LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS);
LocalDateTime selfReviewCloseDate = LocalDateTime.now().plusDays(1).truncatedTo(ChronoUnit.MILLIS);
LocalDateTime closeDate = LocalDateTime.now().plusDays(2).truncatedTo(ChronoUnit.MILLIS);
LocalDateTime periodStartDate = LocalDateTime.now().minusDays(30).truncatedTo(ChronoUnit.MILLIS);
LocalDateTime periodEndDate = LocalDateTime.now().minusDays(1).truncatedTo(ChronoUnit.MILLIS);

ReviewPeriodCreateDTO reviewPeriodCreateDTO = new ReviewPeriodCreateDTO();
reviewPeriodCreateDTO.setName("reincarnation");
reviewPeriodCreateDTO.setReviewStatus(ReviewStatus.OPEN);
reviewPeriodCreateDTO.setLaunchDate(launchDate);
reviewPeriodCreateDTO.setSelfReviewCloseDate(selfReviewCloseDate);
reviewPeriodCreateDTO.setCloseDate(closeDate);
reviewPeriodCreateDTO.setPeriodStartDate(periodStartDate);
reviewPeriodCreateDTO.setPeriodEndDate(periodEndDate);

final HttpRequest<ReviewPeriodCreateDTO> request = HttpRequest.
POST("/", reviewPeriodCreateDTO).basicAuth(MEMBER_ROLE, MEMBER_ROLE);
Expand Down Expand Up @@ -511,6 +533,14 @@ void testReviewPeriodSerialization() throws JsonProcessingException {
String expectedCloseDateFormat = objectMapper.readTree(expectedJson).get("closeDate").asText();
String actualCloseDateFormat = objectMapper.readTree(actualJson).get("closeDate").asText();
assertEquals(expectedCloseDateFormat, actualCloseDateFormat);

String expectedPeriodStartDateFormat = objectMapper.readTree(expectedJson).get("periodStartDate").asText();
String actualPeriodStartDateFormat = objectMapper.readTree(actualJson).get("periodStartDate").asText();
assertEquals(expectedPeriodStartDateFormat, actualPeriodStartDateFormat);

String expectedPeriodEndDateFormat = objectMapper.readTree(expectedJson).get("periodEndDate").asText();
String actualPeriodEndDateFormat = objectMapper.readTree(actualJson).get("periodEndDate").asText();
assertEquals(expectedPeriodEndDateFormat, actualPeriodEndDateFormat);
}

@Test
Expand Down Expand Up @@ -613,4 +643,4 @@ void deleteReviewPeriodWithFeedbackRequests() {
responseException.getMessage()
);
}
}
}
43 changes: 40 additions & 3 deletions web-ui/src/components/reviews/TeamReviews.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,30 @@ const TeamReviews = ({ onBack, periodId }) => {
updateReviewPeriodDates(newPeriod);
};

const handlePeriodStartDateChange = (val, period) => {
const newDate = val?.$d;
const isoDate = newDate?.toISOString() ?? null;
const newPeriod = { ...period, periodStartDate: isoDate };

// Clear dates that are not correctly ordered.
const periodEndDate = new Date(period.periodEndDate);
if (newDate > periodEndDate) newPeriod.periodEndDate = null;

updateReviewPeriodDates(newPeriod);
};

const handlePeriodEndDateChange = (val, period) => {
const newDate = val?.$d;
const isoDate = newDate?.toISOString() ?? null;
const newPeriod = { ...period, periodEndDate: isoDate };

// Clear dates that are not correctly ordered.
const periodStartDate = new Date(period.periodStartDate);
if (newDate < periodStartDate) newPeriod.periodStartDate = null;

updateReviewPeriodDates(newPeriod);
};

const loadReviews = useCallback(async () => {
let newSelfReviews = {};
let newReviews = {};
Expand Down Expand Up @@ -580,15 +604,16 @@ const TeamReviews = ({ onBack, periodId }) => {
const validateReviewPeriod = period => {
if (!period) return 'No review period was created.';
if (!period.launchDate) return 'No launch date was specified.';
if (!period.selfReviewCloseDate)
return 'No self-review date was specified.';
if (!period.selfReviewCloseDate) return 'No self-review date was specified.';
if (!period.closeDate) return 'No close date was specified.';
if (!period.periodStartDate) return 'No period-start-date was specified.';
if (!period.periodEndDate) return 'No period-end-date was specified.';
if (teamMembers.length === 0) return 'No members were added.';
const haveReviewers = teamMembers.every(
member => getReviewers(member).length > 0
);
if (!haveReviewers) return 'One or more members have no reviewer.';
return null; // no validtation errors
return null; // no validation errors
};

const updateReviewPeriodStatus = async reviewStatus => {
Expand Down Expand Up @@ -897,6 +922,18 @@ const TeamReviews = ({ onBack, periodId }) => {
label="Close Date"
disabled={!canUpdate}
/>
<DatePickerField
date={period.periodStartDate}
setDate={val => handlePeriodStartDateChange(val, period)}
label="Period Start Date"
disabled={!canUpdate}
/>
<DatePickerField
date={period.periodEndDate}
setDate={val => handlePeriodEndDateChange(val, period)}
label="Period End Date"
disabled={!canUpdate}
/>
</div>
{approvalButton()}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ const reviewPeriodStepperData = {
launchDate: '2024-05-03T15:53:56.673Z',
selfReviewCloseDate: '2024-05-03T15:53:56.673Z',
closeDate: '2024-05-03T15:53:56.673Z',
periodStartDate: '2024-04-01T00:00:00.000Z',
periodEndDate: '2024-05-01T00:00:00.000Z',
reviewTemplateId: 'd1e94b60-47c4-4945-87d1-4dc88f088e57',
selfReviewTemplateId: 'd1e94b60-47c4-4945-87d1-4dc88f088e57'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const reviewPeriod = {
launchDate: '2024-05-03T15:53:56.673Z',
selfReviewCloseDate: '2024-05-03T15:53:56.673Z',
closeDate: '2024-05-03T15:53:56.673Z',
periodStartDate: '2024-04-01T00:00:00.000Z',
periodEndDate: '2024-05-01T00:00:00.000Z',
reviewTemplateId: 'd1e94b60-47c4-4945-87d1-4dc88f088e57',
selfReviewTemplateId: 'd1e94b60-47c4-4945-87d1-4dc88f088e57'
};
Expand Down
8 changes: 6 additions & 2 deletions web-ui/src/components/reviews/periods/ReviewPeriods.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ const ReviewPeriods = ({ onPeriodSelected, mode }) => {
reviewStatus: ReviewStatus.PLANNING,
launchDate: null,
selfReviewCloseDate: null,
closeDate: null
closeDate: null,
periodStartDate: null,
periodEndDate: null
});
const [reviewStatus, setReviewStatus] = useState(ReviewStatus.CLOSED);
const [selfReviews, setSelfReviews] = useState({});
Expand Down Expand Up @@ -178,7 +180,9 @@ const ReviewPeriods = ({ onPeriodSelected, mode }) => {
reviewStatus: ReviewStatus.OPEN,
launchDate: null,
selfReviewCloseDate: null,
closeDate: null
closeDate: null,
periodStartDate: null,
periodEndDate: null
});
},
[
Expand Down

0 comments on commit 24364f1

Please sign in to comment.