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

Migate Run Validators page to react #10652

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

danieljames-dj
Copy link
Member

This is part of migrating all panel pages to react

Comment on lines +54 to +62
validators = params.require(:selectedValidators).split(',').map(&:constantize)
apply_fix_when_possible = params.require(:applyFixWhenPossible)

results_validator = ResultsValidators::CompetitionsResultsValidator.new(
validators,
check_real_results: true,
apply_fixes: apply_fix_when_possible,
)
results_validator.validate(competition_ids)
Copy link
Member

Choose a reason for hiding this comment

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

As useful as constantize is, you gotta be careful with when and how you use it because it can potentially lead to vulnerabilities. In this context, I'm wondering: Why didn't you use the existing result_validation_form.rb that is also used in the previous running_validators hook?

Copy link
Member Author

Choose a reason for hiding this comment

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

I didn't use the result_validation_form.rb because it was having too many things. I agree those were good, but I feel that if I forcefully use that model, it may not be so clean. So just took the above two lines from that.

I just now saw couple of validations from the model which are also relevant, I've now implemented those validations in the client side.

I understand the risk of constantize, I now see how the result_validation_form is doing it - I have now changed to a similar logic, so no more use of constantize.

Also, now I think technically result_validation_form.rb is not needed anymore as it was used to support the rails ERB code, and that code is no longer there. So I've removed result_validation_form.rb after making necessary changes.


export default async function getCompetitionList(startDate, endDate, maxLimit) {
const { data } = await fetchJsonOrError(
`${apiV0Urls.competitions.listIndex}?start=${startDate}&end=${endDate}&per_page=${maxLimit}`,
Copy link
Member

Choose a reason for hiding this comment

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

Why are you not using the admin_validation_competitions_path URL from the old jQuery form?
Don't get me wrong, I would love it if we can switch to (semi-)public APIs, but I just really want to make sure they return the same results.

Copy link
Member

Choose a reason for hiding this comment

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

One advantage of a custom path would be that you can serialize only the names, and avoid sending (or even loading from the DB) any unnecessary extra data.

Copy link
Member Author

Choose a reason for hiding this comment

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

I didn't think of the admin_validation_competitions_path actually. But as part of one more cleanup, I actually removed ResultValidationForm, and hence all it's usages which includes admin_validation_competitions_path as well. But I've now created a new API to fetch the count of competitions. Hope that is fine.

Comment on lines +46 to +50
[
<a href={competitionUrl(validationData.competition_id)}>
{validationData.competition_id}
</a>
{'] '}
Copy link
Member

Choose a reason for hiding this comment

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

Why do you need the []? Are they absolutely essential for user communication?

Copy link
Member Author

Choose a reason for hiding this comment

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

The users are WRT, it will look clean if the competition is added at the beginning of the validation info.

Copy link
Member

Choose a reason for hiding this comment

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

Huh, interesting that the [ above is acceptable but ] is not. Are there HTML codes (similar to &apost;) that you could use?

Copy link
Member Author

@danieljames-dj danieljames-dj left a comment

Choose a reason for hiding this comment

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

Thanks for the detailed review, @gregorbg. One of the main change that I did post last commit is that I removed result_validation_form. I'm not sure if you are against it, but just to strengthen my argument, I like to highlight that the reason I felt to remove result_validation_form is because this was a helper model for the rails UI, and the rails UI no longer exists, and everything done inside result_validation_form can now be done in 2-3 lines.

Comment on lines +54 to +62
validators = params.require(:selectedValidators).split(',').map(&:constantize)
apply_fix_when_possible = params.require(:applyFixWhenPossible)

results_validator = ResultsValidators::CompetitionsResultsValidator.new(
validators,
check_real_results: true,
apply_fixes: apply_fix_when_possible,
)
results_validator.validate(competition_ids)
Copy link
Member Author

Choose a reason for hiding this comment

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

I didn't use the result_validation_form.rb because it was having too many things. I agree those were good, but I feel that if I forcefully use that model, it may not be so clean. So just took the above two lines from that.

I just now saw couple of validations from the model which are also relevant, I've now implemented those validations in the client side.

I understand the risk of constantize, I now see how the result_validation_form is doing it - I have now changed to a similar logic, so no more use of constantize.

Also, now I think technically result_validation_form.rb is not needed anymore as it was used to support the rails ERB code, and that code is no longer there. So I've removed result_validation_form.rb after making necessary changes.

import runValidatorsForCompetitionsInRange from './api/runValidatorsForCompetitionsInRange';
import ValidationOutput from './ValidationOutput';

const validatorNameReadable = (validatorName) => validatorName.split('::')[1];
Copy link
Member Author

Choose a reason for hiding this comment

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

I have changed the logic for the validator name, so this is no longer there.

Comment on lines +46 to +50
[
<a href={competitionUrl(validationData.competition_id)}>
{validationData.competition_id}
</a>
{'] '}
Copy link
Member Author

Choose a reason for hiding this comment

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

The users are WRT, it will look clean if the competition is added at the beginning of the validation info.

Comment on lines 72 to 73
queryKey: ['competitionCountInRange'],
queryFn: runValidatorsForCompetitions,
Copy link
Member Author

Choose a reason for hiding this comment

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

Ya it was a copy-paste, I forgot to change the key. I've anyway changed to useMutation as you suggested, so no longer relevant.

} = useQuery({
queryKey: ['competitionCountInRange'],
queryFn: runValidatorsForCompetitions,
enabled: false,
Copy link
Member Author

Choose a reason for hiding this comment

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

Changed.

Comment on lines +40 to +46
def competition_count
start_date = params.require(:startDate)
end_date = params.require(:endDate)

count = Competition.where("start_date >= ? AND end_date <= ?", start_date, end_date).count
render json: { count: count }
end
Copy link
Member

Choose a reason for hiding this comment

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

This is a highly specific endpoint for internal uses, I'd rather not have that as part of the public API.

Comment on lines +75 to +80
Competition.over
.not_cancelled
.where(start_date: start_date..)
.where(start_date: ..end_date)
.order(:start_date)
.ids
Copy link
Member

Choose a reason for hiding this comment

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

Can you combine this with the logic for competition_count above?
Like, have some competitions_between(start, end) method which returns Competition.over.not_cancelled.where(...).order(...) and then one endpoint returns competitions_between(foo, bar).count and the other one returns competitions_between(foo, bar).ids

Copy link
Member

Choose a reason for hiding this comment

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

This seems like the perfect use case for an AR scope by the way :)

end

def validators_for_competitions_in_range
range = JSON.parse(params.require(:competitionRange)).transform_keys(&:to_sym)
Copy link
Member

Choose a reason for hiding this comment

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

...Why are you not simply passing in startDate and endDate as params directly?

Comment on lines +17 to +19
queryKey: ['competitionCountInRange', range?.startDate, range?.endDate],
queryFn: () => getCompetitionCount(range?.startDate, range?.endDate),
enabled: bothDatesAreSelected,
Copy link
Member

Choose a reason for hiding this comment

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

If the query is only enabled when both dates are selected, then you should be able to drop the ? at least from the queryFn


const RUN_VALIDATORS_QUERY_CLIENT = new QueryClient();

export default function CompetitionRangeSelector({ range, setRange }) {
Copy link
Member

Choose a reason for hiding this comment

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

Why are you passing in range instead of just passing the dates separately?

Comment on lines +46 to +50
[
<a href={competitionUrl(validationData.competition_id)}>
{validationData.competition_id}
</a>
{'] '}
Copy link
Member

Choose a reason for hiding this comment

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

Huh, interesting that the [ above is acceptable but ] is not. Are there HTML codes (similar to &apost;) that you could use?

Comment on lines +13 to +17
if (!validationOutput) {
return (
<Message>Please run the validators to see the output.</Message>
);
}
Copy link
Member

Choose a reason for hiding this comment

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

What if the validators have been run but still didn't give any output?

return (
<>
{Object.entries(listByGroup).map(([group, list]) => (
<Fragment key={group}>
Copy link
Member

Choose a reason for hiding this comment

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

Instead of Fragment, you could consider wrapping this in a Message. SemUI Messages have info, warning and error states with nice color codings :)

Comment on lines +46 to +90
function ValidationErrorOutput({ validationOutput, showCompetitionNameOnOutput }) {
const hasResults = validationOutput.has_results;
const hasErrors = validationOutput.errors.length > 0;

if (!hasErrors) {
if (hasResults) {
return <p>No error detected in the results.</p>;
}
return <p>No results for the competition yet.</p>;
}

return (
<>
<p>Please fix the errors below:</p>
<ValidationListView
validations={validationOutput.errors}
showCompetitionNameOnOutput={showCompetitionNameOnOutput}
type="error"
/>
</>
);
}

function ValidationWarningOutput({ validationOutput, showCompetitionNameOnOutput }) {
const hasResults = validationOutput.has_results;
const hasWarning = validationOutput.warnings.length > 0;

if (!hasWarning) {
if (hasResults) {
return <p>No warning detected in the results.</p>;
}
return <p>No results for the competition yet.</p>;
}

return (
<>
<p>Please pay attention to the warnings below:</p>
<ValidationListView
validations={validationOutput.warnings}
showCompetitionNameOnOutput={showCompetitionNameOnOutput}
type="warning"
/>
</>
);
}
Copy link
Member

Choose a reason for hiding this comment

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

Quite a lot of repetition, any chance to unify this?
You could consider changing the English texts a little, like No messages of type ${type} detected in the results, to make reusing the components a bit easier


export default async function getCompetitionCount(startDate, endDate) {
const { data } = await fetchJsonOrError(viewUrls.competitions.countInRange(startDate, endDate));
return data?.count;
Copy link
Member

Choose a reason for hiding this comment

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

Hm, now you're accessing the data already again. If only the count is so important, then why not just return it directly from the backend?
(Yes, numbers by themselves are valid JSON. Not everything has to be {} or [] on top level)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants