-
Notifications
You must be signed in to change notification settings - Fork 16
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
4791 add report versioning #5533
Conversation
Bundle size differenceComparing this PR to
|
version: report.version, | ||
code: report.code, | ||
})?; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm not very happy with logic here, do you mind doing a self review of the changes and existing logic in this file and seeing how it can/should be simplified ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Andrei,
I was wondering about just upserting all reports regardless of if they were older versions than the one existing on the server.
Is this what you're thinking? Or are you thinking refactoring but keeping the current logic?
return 0; | ||
}; | ||
|
||
export const useLatestReportList = ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Front end should be report version agnostic, this should be back end logic
Also add unique is_custom identifier to id
pub fn find_one_by_code_and_version( | ||
&self, | ||
code: &str, | ||
version: &str, | ||
) -> Result<Option<ReportRow>, RepositoryError> { | ||
let result = report_dsl::report | ||
.filter(report_dsl::code.eq(code)) | ||
.filter(report_dsl::version.eq(version)) | ||
.first(self.connection.lock().connection()) | ||
.optional()?; | ||
Ok(result) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing as not anymore
pub fn mock_report_g() -> ReportRow { | ||
inline_init(|r: &mut ReportRow| { | ||
r.id = "mock_report_g".to_string(); | ||
r.version = "2.3.0".to_string(); | ||
r.is_custom = true; | ||
r.code = "report_with_custom_option".to_string(); | ||
}) | ||
} | ||
|
||
pub fn mock_report_h() -> ReportRow { | ||
inline_init(|r: &mut ReportRow| { | ||
r.id = "mock_report_h".to_string(); | ||
r.version = "2.3.1".to_string(); | ||
r.is_custom = false; | ||
r.code = "report_with_custom_option".to_string(); | ||
}) | ||
} | ||
|
||
pub fn mock_report_i() -> ReportRow { | ||
inline_init(|r: &mut ReportRow| { | ||
r.id = "mock_report_i".to_string(); | ||
r.version = "2.8.2".to_string(); | ||
r.is_custom = true; | ||
r.code = "report_with_custom_option".to_string(); | ||
}) | ||
} | ||
|
||
pub fn mock_report_j() -> ReportRow { | ||
inline_init(|r: &mut ReportRow| { | ||
r.id = "mock_report_j".to_string(); | ||
r.version = "3.0.1".to_string(); | ||
r.is_custom = false; | ||
r.code = "report_with_custom_option".to_string(); | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added extra cases to test for prioritising is_custom reports
let reports_to_show_meta_data = report_filter_method( | ||
repo.query_meta_data(Some(filter.clone()), None)?, | ||
app_version, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added querying all for metadata first with a sub selection of code, version, id, and is_custom. I thought this would help if our report list gets long and we aren't wanting to query all reports and filter out later.
Later we can collect the ids, and query all report data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added querying all for metadata first with a sub selection of code, version, id, and is_custom. I thought this would help if our report list gets long and we aren't wanting to query all reports and filter out later.
That's awesome, thank you
Ok(reports) | ||
} | ||
|
||
fn report_filter_method( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a feeling this logic could be more concise. However, after taking some time to think about it, I figure it is not worth spending time on now given we are only passing around report_meta_data
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, really easy to read and performant, thank you. There is a lot to like about this, abstraction for readability, the reports_of_code and
custom_reports_of_code` reduces the cognitive load (one step at a time)
The only improvement I can think of, the query_meta_data could return a domain object, with a little bit of mapping after .load
, to get the version number (from_str) and store it into that domain object (reduce mapping in compare_major_minor and in find_latest_report)
}; | ||
|
||
use crate::{ | ||
diesel_macros::{apply_equal_filter, apply_sort_no_case}, | ||
schema_from_row, FormSchema, FormSchemaRow, | ||
}; | ||
use crate::{EqualFilter, Pagination, Sort, StringFilter}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have removed pagination as we won't use it for these queries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking very good, a joy to review. At some point we need to document this a bit more, wondering if it should be done inline in code, or as a separate .md
file
let filter = filter | ||
.unwrap_or_default() | ||
.r#type(ReportType::OmSupply.equal_to()); | ||
Ok(repo.query(pagination, Some(filter.clone()), sort)?) | ||
|
||
let reports_to_show_meta_data = report_filter_method( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better to return report_ids to show (that feels a bit more clear to me), maybe it's personal preference, how does it sound to you ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I like that too - will amend
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let reports_to_show_meta_data = report_filter_method( | ||
repo.query_meta_data(Some(filter.clone()), None)?, | ||
app_version, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added querying all for metadata first with a sub selection of code, version, id, and is_custom. I thought this would help if our report list gets long and we aren't wanting to query all reports and filter out later.
That's awesome, thank you
} | ||
} | ||
} | ||
Ok(query |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's so good !
Ok(reports) | ||
} | ||
|
||
fn report_filter_method( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, really easy to read and performant, thank you. There is a lot to like about this, abstraction for readability, the reports_of_code and
custom_reports_of_code` reduces the cognitive load (one step at a time)
The only improvement I can think of, the query_meta_data could return a domain object, with a little bit of mapping after .load
, to get the version number (from_str) and store it into that domain object (reduce mapping in compare_major_minor and in find_latest_report)
and update tests
Cheers! I am thinking in report .md file might be good? It documents a lot of other report editing how-tos, which would be accompanied by report version changes. |
and update tests
Have added better explanation in .md file, and added from_domain mapping to remove need for version mapping in meta data. |
@@ -93,6 +93,26 @@ impl Default for ReportRow { | |||
} | |||
} | |||
|
|||
#[derive(Clone, Insertable, Queryable, Debug, PartialEq, Eq, AsChangeset, Selectable)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can default here so you don't need to impl default (:
.map(|r| r.id) | ||
.collect(), | ||
)); | ||
let filter = ReportFilter::new().id(EqualFilter::equal_any(reports_to_show_meta_data)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this variable name doesn't make that much sense now
let mut report = reports | ||
.clone() | ||
.into_iter() | ||
.filter(|r| r.id == result.clone().into_iter().next().unwrap()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result.first/pop().unwrap()
@@ -21,6 +22,25 @@ pub struct Report { | |||
pub argument_schema: Option<FormSchema>, | |||
} | |||
|
|||
#[derive(Debug, Clone, PartialEq)] | |||
pub struct ReportMetaData { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
our domain object are composites atm, we don't really copy them (a bit less mapping and less to change when new fields are added)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So should just have Version as another key (of type Version)
.filter(|r| { | ||
compare_major_minor(Version::from_str(&r.version), &app_version) != Ordering::Greater | ||
}) | ||
.filter(|r| compare_major_minor(r.version.clone(), &app_version) != Ordering::Greater) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why clone ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks great thanks
Fixes #4791
π©π»βπ» What does this PR do?
Two parts:
There is a unique case which could casue issues where if a db has a report version later than the app version, you wouldn't be able to upload older report versions. But I don't think we need to worry about that.
π Any notes for the reviewer?
You can test this report with this database which includes a number of report versions and is_custom combinations:
central_test.sqlite.zip
π§ͺ Testing
π Documentation