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

[To Main] DESENG-643: Final changes for engagement loader optimizations #2558

Merged
merged 17 commits into from
Jul 24, 2024

Conversation

NatSquared
Copy link
Contributor

Issue #: 🎟️ DESENG-643

Description of changes:

  • Feature Rerouted engagement components to use useRouteLoaderData instead of making direct calls to services.
    • Authorized engagement listing page is now working, complete with filter, search, and pagination
    • Authorized view engagement is fully working with widgets
    • Authorized edit engagement is fully working (including custom data)
    • Authorized create engagement is mostly working, with the exception of edit updates
      • TODO: users should be redirected to edit page once engagement is created
    • Unauthenticated homepage is working with engagements

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the met-public license (Apache 2.0).

@NatSquared NatSquared requested a review from Baelx July 17, 2024 22:13
Copy link
Collaborator

@Baelx Baelx 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 all the great work @jareth-whitney ! There may be some opportunities to optimize code in a few places. However, all that I'll ask to change for sure is the commented-out code. Could you please review instances of it and determine if that code is needed for later or should be removed. If it's the former, then we typically add an accompanying comment to let folks know it's needed.

As mentioned, we're not actually merging this PR and Nat will be continuing the work on this. Instead of making any code changes, you could just signal to her what needs to change, if anything, and she can do it later in the course of her work

const { metadata } = !isCreate
? (useRouteLoaderData('single-engagement') as { metadata: Promise<EngagementMetadata[]> })
: noRouteLoaders;
const { taxa } = !isCreate
Copy link
Collaborator

Choose a reason for hiding this comment

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

@jareth-whitney You may be able to reduce a lot of the code by doing something like:

Suggested change
const { taxa } = !isCreate
let engagement: Promise<Engagement[]>, content<EngagementContent[]>, metadata<EngagementMetadata[]>, taxa<MetadataTaxon[]>;
if (isCreate) {
engagement = useRouteLoaderData('single-engagement');
content = useRouteLoaderData('single-engagement');
//... etc.
}

Copy link
Contributor

Choose a reason for hiding this comment

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

It needs to be destructured due to the way the loader is structured, outputting different values as object properties. Of course, this could be changed.

if (!isCreate && isNaN(Number(engagementId))) {
navigate('/');
}

if (isCreate) {
if (isCreate && !engagementId) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe I'm misreading this but wouldn't the existence of isCreate imply that there's no loaded engagement ID?

Copy link
Contributor

Choose a reason for hiding this comment

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

There is a weird third state for the engagement form (besides create and edit) where the creation form is filled out and the user presses "Save and Continue". The create page is essentially functioning as an edit page. I mentioned this in the new ticket, and that users should just be directly redirected to the edit page when hitting "save and continue".

Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh okay I think I see where the weirdness is - because we need to make an early save? And to the user it still appears as if they're "creating" the engagement for the first time.

It sounds like this is work for the new ticket you were mentioning but in my mind, if the engagement is created, and the form the user uses is functionally identical to the edit form, I feel like we should set isCreate to false. Or maybe rename it to something that better illustrates the particular way we create new engagements in the app.

setIsNewEngagement(!savedEngagement.id);
setSavedBannerImageFileName(engagement.banner_filename);

if (bannerImage) setBannerImage(null);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you provide a bit of context for this line? If there's a bannerImage loaded then unset it?

Copy link
Contributor

Choose a reason for hiding this comment

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

This was existing code, I'm not sure why it's showing up as a new edit. Possibly due to restructuring of the file?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh okay, fair enough!

@@ -52,7 +52,7 @@ export const ContentTabs: React.FC = () => {
return;
}
await deleteEngagementContent(savedEngagement.id, tab_id);
await fetchEngagementContents();
// await fetchEngagementContents();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this commented-out code needed for later?

Copy link
Contributor

Choose a reason for hiding this comment

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

No it can be removed, I missed it.

@@ -31,8 +30,8 @@ export const EngagementContentContext = createContext<EngagementContentProps>({
},
});

const CREATE = 'create';
Copy link
Collaborator

Choose a reason for hiding this comment

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

I know that setting this constant replicates a pattern from ActionContext but I feel like there isn't much value in doing so if the variable is only used once.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes I was just following the previous pattern so this could be used as a string value when it's actually needed.

key: 'name',
value: '',
});
const [searchText, setSearchText] = useState('');
const [engagements, setEngagements] = useState<Engagement[]>([]);
const { engagements } = useRouteLoaderData('engagement-listing') as { engagements: Engagement[] };
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there a reason you need to type cast the return value as an object and then destructure engagements? Would you be able to do:

Suggested change
const { engagements } = useRouteLoaderData('engagement-listing') as { engagements: Engagement[] };
const engagements = useRouteLoaderData('engagement-listing') as Engagement[];

Copy link
Contributor

Choose a reason for hiding this comment

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

Due to the nature of the loader component, everything is assigned a property, thus the destructuring here. Of course, this could be changed.

setPaginationOptions(paginationOptions)
}
paginationOptions={paginationOptions}
// loading={tableLoading}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this commented code need to be here?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this could be revisited. I believe I disabled it because it was highjacking the page (infinite loading) until I disabled it, but it could be reintegrated.

const sort_key = searchParams.get('sort_key');
const sort_order = searchParams.get('sort_order');
const search_text = searchParams.get('search_text');
const engagement_status = searchParams.get('engagement_status')?.split('_');
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can searchParams.get('engagement_status') ever be an empty string? If so, Number(status) on line 21 below will output 0. Just want to ensure that that's the expected behaviour

Copy link
Contributor

Choose a reason for hiding this comment

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

I can't speak to the specific output of engagement_status but the search filter was tested extensively and no issues came up. I would have to take a look at the code again to know for sure.

Copy link
Collaborator

Choose a reason for hiding this comment

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

No need to dive into it! Thanks for reassuring me

const contentSummary = content.then((response) =>
Promise.all(
response.map((content) => {
return content.content_type === 'Summary'
? getSummaryContent(content.id)
? getSummaryContent(Number(content.id)).then(convertArrayToSingleEntry)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is convertArrayToSingleEntry needed?

Suggested change
? getSummaryContent(Number(content.id)).then(convertArrayToSingleEntry)
? getSummaryContent(Number(content.id)).then(engagementSummaryContent => engagementSummaryContent[0])

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes it breaks when it's removed. Of course, this could be an inline function as well if you think this is too verbose.

@@ -233,12 +206,11 @@ export const ActionProvider = ({ children }: { children: JSX.Element | JSX.Eleme
}, [slug]);

useEffect(() => {
fetchEngagement();
// revalidator.revalidate();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Some more commented out code in this file - necessary going forward?

Copy link
Contributor

Choose a reason for hiding this comment

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

Nope, it can be removed.

Copy link
Contributor Author

@NatSquared NatSquared left a comment

Choose a reason for hiding this comment

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

Good work on this Jareth! I've poked at a few things but I'll be addressing any concerns in an upcoming PR to this branch :3

<Route path=":engagementId/comments/:dashboardType" element={<EngagementComments />} />
<Route path=":slug/dashboard/:dashboardType" element={<PublicDashboard />} />
<Route path=":engagementId/dashboard/:dashboardType" element={<PublicDashboard />} />
<Route path=":slug/comments/:dashboardType" element={<EngagementComments />} />
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This route structure could be improved a bit - anything with an :engagementId segment can be nested under the :engagmentId route after deleting that prefix. The :slug paths could be re-nested as well

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, good points Nat, I missed that.

@@ -12,7 +12,7 @@ import { RedirectLogin } from './RedirectLogin';
import withLanguageParam from './LanguageParam';
import { Navigate, Route } from 'react-router-dom';
import NotFound from './NotFound';
import ViewEngagement, { engagementLoader } from 'components/engagement/new/view';
import ViewEngagement, { engagementLoader } from 'components/engagement/new/view'; // TODO: Convert tenant calls to route loader
import { SurveyLoader } from 'components/survey/building/SurveyLoader';
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does this mean that tenant fetching should be deferred to the loader? Tenant info is already stored in the authentication slice

Copy link
Contributor

Choose a reason for hiding this comment

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

This looks to be an existing comment, not something from me. It's possible that you removed it from the main branch when you uploaded your tenant loader commit, but it was still present on my instance, and thus you're seeing it here.

paginationOptions?.page && url.searchParams.set('page', paginationOptions.page.toString());
paginationOptions?.size && url.searchParams.set('size', paginationOptions.size.toString());
paginationOptions?.sort_key &&
url.searchParams.set('sort_key', 'engagement.' + paginationOptions.sort_key.toString());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

nested_sort_key could probably be used here instead since it includes the model. prefix

Copy link
Contributor

Choose a reason for hiding this comment

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

Hm ok, I tried printing out the nested sort key value at first and it seems to function differently from the sort_key. Is this not a secondary sort?

@codecov-commenter
Copy link

codecov-commenter commented Jul 18, 2024

Codecov Report

Attention: Patch coverage is 78.26087% with 35 lines in your changes missing coverage. Please review.

Project coverage is 75.99%. Comparing base (085451b) to head (9b199b0).
Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2558      +/-   ##
==========================================
+ Coverage   75.96%   75.99%   +0.03%     
==========================================
  Files         609      609              
  Lines       21960    21924      -36     
  Branches     1711     1747      +36     
==========================================
- Hits        16682    16662      -20     
+ Misses       5015     4998      -17     
- Partials      263      264       +1     
Flag Coverage Δ
metapi 87.74% <0.00%> (ø)
metweb 64.75% <78.75%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Coverage Δ
...gagementFormTabs/EngagementContent/ContentTabs.tsx 79.01% <100.00%> (+2.18%) ⬆️
...ntFormTabs/EngagementContent/SummaryTabContent.tsx 87.50% <ø> (ø)
...agement/form/EngagementFormTabs/EngagementForm.tsx 88.13% <ø> (ø)
...ment/form/EngagementFormTabs/SurveyBlock/index.tsx 66.66% <100.00%> (+1.55%) ⬆️
...mponents/engagement/form/EngagementFormWrapper.tsx 100.00% <100.00%> (ø)
...agement/listing/AdvancedSearch/SearchComponent.tsx 86.84% <100.00%> (+3.50%) ⬆️
...components/engagement/view/widgets/WidgetBlock.tsx 100.00% <100.00%> (ø)
.../src/components/imageUpload/imageUploadContext.tsx 50.00% <100.00%> (+4.54%) ⬆️
met-web/src/services/engagementService/index.ts 31.81% <ø> (ø)
...api/services/engagement_summary_content_service.py 97.14% <0.00%> (ø)
... and 6 more

... and 9 files with indirect coverage changes

@NatSquared NatSquared marked this pull request as ready for review July 22, 2024 19:14
Copy link

sonarcloud bot commented Jul 24, 2024

@NatSquared NatSquared changed the title DESENG-643: Initial changes for engagement loader optimizations [To Main] DESENG-643: Final changes for engagement loader optimizations Jul 24, 2024
@NatSquared NatSquared merged commit bcbdcdc into main Jul 24, 2024
15 checks passed
@NatSquared NatSquared deleted the feature/DESENG-664 branch July 24, 2024 23:07
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.

4 participants