Skip to content
12 changes: 12 additions & 0 deletions src/backend/api/backend.did
Original file line number Diff line number Diff line change
Expand Up @@ -317,11 +317,22 @@ type GetMyProposalReviewRequest = record {
proposal_id : text;
};

type GetMyProposalReviewSummaryRequest = record {
proposal_id : text;
};

type GetMyProposalReviewResponse = variant {
ok : ProposalReviewWithId;
err : Err;
};

type GetMyProposalReviewSummaryResponse = variant {
ok : record {
summary_markdown : text;
};
err : Err;
};

type ProposalReviewCommit = record {
proposal_review_id : text;
user_id : text;
Expand Down Expand Up @@ -404,6 +415,7 @@ service : {
create_proposal_review_image : (CreateProposalReviewImageRequest) -> (CreateProposalReviewImageResponse);
delete_proposal_review_image : (DeleteProposalReviewImageRequest) -> (DeleteProposalReviewImageResponse);
get_my_proposal_review : (GetMyProposalReviewRequest) -> (GetMyProposalReviewResponse) query;
get_my_proposal_review_summary : (GetMyProposalReviewSummaryRequest) -> (GetMyProposalReviewSummaryResponse) query;
create_proposal_review_commit : (CreateProposalReviewCommitRequest) -> (CreateProposalReviewCommitResponse);
update_proposal_review_commit : (UpdateProposalReviewCommitRequest) -> (UpdateProposalReviewCommitResponse);
delete_proposal_review_commit : (DeleteProposalReviewCommitRequest) -> (DeleteProposalReviewCommitResponse);
Expand Down
2 changes: 2 additions & 0 deletions src/backend/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod log;
mod proposal;
mod proposal_review;
mod proposal_review_commit;
mod proposal_review_summary;
mod result;
mod user_profile;

Expand All @@ -13,5 +14,6 @@ pub use log::*;
pub use proposal::*;
pub use proposal_review::*;
pub use proposal_review_commit::*;
pub use proposal_review_summary::*;
pub use result::*;
pub use user_profile::*;
11 changes: 11 additions & 0 deletions src/backend/api/src/proposal_review_summary.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use candid::{CandidType, Deserialize};

#[derive(Debug, Clone, CandidType, Deserialize, PartialEq, Eq)]
pub struct GetMyProposalReviewSummaryRequest {
pub proposal_id: String,
}

#[derive(Debug, Clone, CandidType, Deserialize, PartialEq, Eq)]
pub struct GetMyProposalReviewSummaryResponse {
pub summary_markdown: String,
}
31 changes: 28 additions & 3 deletions src/backend/impl/src/controllers/proposal_review_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ use crate::{
use backend_api::{
ApiError, ApiResult, CreateProposalReviewImageRequest, CreateProposalReviewImageResponse,
CreateProposalReviewRequest, CreateProposalReviewResponse, DeleteProposalReviewImageRequest,
GetMyProposalReviewRequest, GetMyProposalReviewResponse, GetProposalReviewRequest,
GetProposalReviewResponse, ListProposalReviewsRequest, ListProposalReviewsResponse,
UpdateProposalReviewRequest,
GetMyProposalReviewRequest, GetMyProposalReviewResponse, GetMyProposalReviewSummaryRequest,
GetMyProposalReviewSummaryResponse, GetProposalReviewRequest, GetProposalReviewResponse,
ListProposalReviewsRequest, ListProposalReviewsResponse, UpdateProposalReviewRequest,
};
use candid::Principal;
use ic_cdk::*;
Expand Down Expand Up @@ -92,6 +92,17 @@ fn get_my_proposal_review(
.into()
}

#[query]
fn get_my_proposal_review_summary(
request: GetMyProposalReviewSummaryRequest,
) -> ApiResult<GetMyProposalReviewSummaryResponse> {
let calling_principal = caller();

ProposalReviewController::default()
.get_my_proposal_review_summary(calling_principal, request)
.into()
}

struct ProposalReviewController<A: AccessControlService, P: ProposalReviewService> {
access_control_service: A,
proposal_review_service: P,
Expand Down Expand Up @@ -199,6 +210,20 @@ impl<A: AccessControlService, P: ProposalReviewService> ProposalReviewController
.get_my_proposal_review(calling_principal, request)
}

fn get_my_proposal_review_summary(
&self,
calling_principal: Principal,
request: GetMyProposalReviewSummaryRequest,
) -> Result<GetMyProposalReviewSummaryResponse, ApiError> {
self.access_control_service
.assert_principal_not_anonymous(&calling_principal)?;
self.access_control_service
.assert_principal_is_reviewer(&calling_principal)?;

self.proposal_review_service
.get_my_proposal_review_summary(calling_principal, request)
}

fn delete_proposal_review_image(
&self,
calling_principal: Principal,
Expand Down
5 changes: 5 additions & 0 deletions src/backend/impl/src/fixtures/commit_sha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@ pub fn commit_sha_a() -> CommitSha {
pub fn commit_sha_b() -> CommitSha {
CommitSha::try_from("47d98477c6c59e570e2220aab433b0943b326ef8").unwrap()
}

#[fixture]
pub fn commit_sha_c() -> CommitSha {
CommitSha::try_from("e62e328fa193e73fbb7562458d719f311c25d455").unwrap()
}
6 changes: 3 additions & 3 deletions src/backend/impl/src/fixtures/proposal_review_commit.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rstest::*;

use crate::repositories::{ProposalReviewCommit, ReviewCommitState};
use crate::repositories::{ProposalReviewCommit, ReviewCommitState, ReviewedCommitState};

use super::{commit_sha_a, commit_sha_b, date_time_a, proposal_review_id, user_id};

Expand All @@ -12,11 +12,11 @@ pub fn proposal_review_commit_reviewed() -> ProposalReviewCommit {
created_at: date_time_a(),
last_updated_at: None,
commit_sha: commit_sha_a(),
state: ReviewCommitState::Reviewed {
state: ReviewCommitState::Reviewed(ReviewedCommitState {
matches_description: Some(true),
comment: Some("Review commit comment".to_string()),
highlights: vec![],
},
}),
}
}

Expand Down
12 changes: 7 additions & 5 deletions src/backend/impl/src/mappings/proposal_review_commit.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use crate::repositories::{ProposalReviewCommit, ProposalReviewCommitId, ReviewCommitState};
use crate::repositories::{
ProposalReviewCommit, ProposalReviewCommitId, ReviewCommitState, ReviewedCommitState,
};

impl From<ReviewCommitState> for backend_api::ReviewCommitState {
fn from(proposal_review_commit_state: ReviewCommitState) -> Self {
match proposal_review_commit_state {
ReviewCommitState::Reviewed {
ReviewCommitState::Reviewed(ReviewedCommitState {
matches_description,
comment,
highlights,
} => backend_api::ReviewCommitState::Reviewed {
}) => backend_api::ReviewCommitState::Reviewed {
matches_description,
comment,
highlights,
Expand All @@ -24,11 +26,11 @@ impl From<backend_api::ReviewCommitState> for ReviewCommitState {
matches_description,
comment,
highlights,
} => ReviewCommitState::Reviewed {
} => ReviewCommitState::Reviewed(ReviewedCommitState {
matches_description,
comment,
highlights,
},
}),
backend_api::ReviewCommitState::NotReviewed => ReviewCommitState::NotReviewed,
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ mod tests {
use super::*;
use crate::{
fixtures::{self, commit_sha_a, commit_sha_b, uuid_a, uuid_b},
repositories::ReviewCommitState,
repositories::{ReviewCommitState, ReviewedCommitState},
};
use rstest::*;

Expand Down Expand Up @@ -507,11 +507,11 @@ mod tests {
#[fixture]
fn updated_proposal_review_commit() -> ProposalReviewCommit {
ProposalReviewCommit {
state: ReviewCommitState::Reviewed {
state: ReviewCommitState::Reviewed(ReviewedCommitState {
matches_description: Some(false),
comment: Some("Updated comment".to_string()),
highlights: vec![],
},
}),
..fixtures::proposal_review_commit_not_reviewed()
}
}
Expand Down
13 changes: 12 additions & 1 deletion src/backend/impl/src/repositories/types/proposal_review.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{borrow::Cow, ops::RangeBounds};
use std::{borrow::Cow, fmt::Display, ops::RangeBounds};

use backend_api::ApiError;
use candid::{CandidType, Decode, Deserialize, Encode};
Expand Down Expand Up @@ -26,6 +26,17 @@ pub enum ProposalVote {
No = 2,
}

impl Display for ProposalVote {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let val = match self {
ProposalVote::Unspecified => "-",
ProposalVote::Yes => "ADOPTED",
ProposalVote::No => "REJECTED",
};
write!(f, "{}", val)
}
}

#[derive(Debug, CandidType, Deserialize, Clone, PartialEq, Eq)]
pub struct ProposalReview {
pub proposal_id: ProposalId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{borrow::Cow, ops::RangeBounds};
use std::{borrow::Cow, fmt::Display, ops::RangeBounds};

use backend_api::ApiError;
use candid::{CandidType, Decode, Deserialize, Encode};
Expand All @@ -11,13 +11,40 @@ use super::{CommitSha, DateTime, ProposalReviewId, UserId, Uuid};

pub type ProposalReviewCommitId = Uuid;

#[derive(Debug, CandidType, Deserialize, Clone, PartialEq, Eq)]
pub struct ReviewedCommitState {
pub matches_description: Option<bool>,
pub comment: Option<String>,
pub highlights: Vec<String>,
}

impl Display for ReviewedCommitState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut commit_details = format!(
"Matches description: {}",
self.matches_description
.map(|b| b.to_string())
.unwrap_or_else(|| "Unanswered".to_string()),
);
if let Some(comment) = self.comment.as_ref() {
if !comment.is_empty() {
commit_details = format!("{}\nComment: {}", commit_details, comment);
}
}
if !self.highlights.is_empty() {
commit_details = format!(
"{}\nHighlights: {}",
commit_details,
self.highlights.join(", ")
);
}
write!(f, "{}", commit_details)
}
}

#[derive(Debug, CandidType, Deserialize, Clone, PartialEq, Eq)]
pub enum ReviewCommitState {
Reviewed {
matches_description: Option<bool>,
comment: Option<String>,
highlights: Vec<String>,
},
Reviewed(ReviewedCommitState),
NotReviewed,
}

Expand All @@ -39,6 +66,14 @@ impl ProposalReviewCommit {
pub fn is_not_reviewed(&self) -> bool {
matches!(&self.state, ReviewCommitState::NotReviewed)
}

pub fn reviewed_state(&self) -> Option<&ReviewedCommitState> {
if let ReviewCommitState::Reviewed(state) = &self.state {
Some(state)
} else {
None
}
}
}

impl Storable for ProposalReviewCommit {
Expand Down Expand Up @@ -174,4 +209,42 @@ mod tests {

assert_eq!(key, deserialized_key);
}

#[rstest]
fn reviewed_commit_state_display_impl() {
let mut state = ReviewedCommitState {
matches_description: None,
comment: None,
highlights: vec![],
};

assert_eq!(state.to_string(), "Matches description: Unanswered");

state.matches_description = Some(false);
assert_eq!(state.to_string(), "Matches description: false");

state.matches_description = Some(true);
assert_eq!(state.to_string(), "Matches description: true");

state.comment = Some("".to_string());
assert_eq!(state.to_string(), "Matches description: true");

state.comment = Some("test".to_string());
assert_eq!(
state.to_string(),
"Matches description: true\nComment: test"
);

state.highlights = vec!["test".to_string()];
assert_eq!(
state.to_string(),
"Matches description: true\nComment: test\nHighlights: test"
);

state.highlights = vec!["test1".to_string(), "test2".to_string()];
assert_eq!(
state.to_string(),
"Matches description: true\nComment: test\nHighlights: test1, test2"
);
}
}
Loading
Loading