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

Expressions optimization and streamlining #861

Merged
merged 33 commits into from
Jan 27, 2023
Merged

Conversation

olemartinorg
Copy link
Contributor

@olemartinorg olemartinorg commented Jan 25, 2023

Description

Marking this as a product feature, because it opens up a few more things:

  • I've tested out setting title and tableTitle in textResourceBindings via expressions now, which did not work correctly before (at least it crashed the app for me when I tested on earlier versions).
  • Some things may be more consistent and as-expected after this change. Such as text resources for title when displaying a component in a Summary (which did not always seem to look up variables in text resources before, but does now).
  • It should now be a lot more performant to use expressions overall, and less error-prone. Some needs (such as Variables in text. Empty variables in will display path to datasource. #754) are not as pressing anymore, as it's fairly easy to work around them using expressions (that, as mentioned, sometimes caused the app to crash before).

With that said, some bullet points detailing some of the more technical changes here:

  • Instead of useExpressions() and useExpressionsForComponent(), most expressions are now evaluated once in the ExprContext (which just loads resolvedNodesInLayouts() and provides the result to all child components via two new hooks - useExprContext() and useResolvedNode()). This is what gives us the much-needed performance boost.
  • Overall, more usage of the node hierarchy instead of constructing and manipulating component definitions/objects directly. This is especially true in Summary, where the node hierarchy now replaces most component config wrangling.
  • The node hierarchy could resolve expressions before, but it had no functionality to ensure that some expressions (such as edit.deleteButton) were evaluated per-row (as this is a property on the Group component, but could have different results per-row). Now, instead of just a default value (if the expression fails to evaluate), you have to pass in a configuration for every possible expression. This configuration tells the expression engine if an expression should be evaluated per-row or not, so expressions like edit.deleteButton will stay unresolved in the Group component and will be evaluated and available in the node.item.row[123].groupExpressions.edit.deleteButton property instead (for each row index). This also fixes an issue where these expressions were being resolved in unrelated code, and could end up failing (because, for example, a component lookup was not available when not in a row context), resulting in an error message in the developer console.

Related Issue(s)

Verification

  • Manual testing
    • I have tested these changes manually
      • Manually test the new PDF generator (we should have cypress tests for the automatic PDF layout)
      • Manually test some prominent/production apps side-by-side with an older version
    • Creator of the original issue (or service owner) has been contacted for manual testing
    • No testing done/necessary
  • Automated tests
    • Unit test(s) have been added
    • Cypress E2E test(s) have been added updated
    • No automatic tests are needed here (this carries no functional changes, only minor new features that did not exist anymore. Tests were only changed to bootstrap correctly for them to work properly, but they were a much-needed aid when making these changes in order to verify existing functionality did not change. I have plans to add tests for some of the new functionality I noticed was working after this change.)
    • I want someone to help me make some tests
  • User documentation @ altinn-studio-docs
    • Has been updated
    • No changes/updates needed
  • Changes/additions to component properties
    • Changes are reflected in both src/layout/layout.d.ts and layout.schema.v1.json, and these are all backwards-compatible
    • No changes made
  • Support in Altinn Studio
    • Issue(s) created for support in Studio
    • This change/feature does not require any changes to Altinn Studio
  • Sprint board
    • The original issue (or this PR itself) has been added to the Team Apps project and to the current sprint board

Ole Martin Handeland added 30 commits January 16, 2023 13:17
…d to find the current layout for some reason - and the error resulted in a TypeError on the console.
… than just the default value returned by an expression (for that property). This is one of the steps needed to make resolveNodesInLayouts() work per-row for repeating groups, which is also a step in the right direction when "caching" expression results using a React context as a resolved nodes provider.
…). This adds a new groupExpressions property for each row object (where only the properties that contained expressions, and were resolved per-row are added).
…now just does a lookup in the new ExprContext (which contains the full hierarchy). This makes usage much faster, as we've calculated all expressions in advance. This model should also replace useExpressions().
…being resolved in a top-level context (using the ExprContext). Lots of stuff is bound to fail hard right now, as this refactor is just barely holding its own weight.
…lvedNodesInLayout, they did not have their textResourceBindings resolved and replaced - making text bindings using variables inside repeating groups not work properly. Fixing this by adding that functionality to the hierarchy. Removing the test and simplifying the hook in a way where it doesn't really need unit-testing.
…ctacularly when I rewrote GenericComponent, potentially because the 'layout' property disappeared for some reason (not sure if Likert is nesting GenericComponent or what is happening). Mixing in passed props (but overwriting with evaluated layout properties) seems to fix it.
…the state was not being set correctly in redux. Also marking rows as potentially undefined. They aren't when listing out each value, but you should always do null-checking when accessing a row by index.
…assed through the component properties alone, while not being present in the redux layout state.
…behave the same as in createRepeatingGroupComponents()
…mmaryGroupComponent did not match the actual likert repeating group rows. This happened because the component id did not include the correct row index suffix, so the node lookup returned the first row instead of the specific row.
…to be found when looking for the legacy component
# Conflicts:
#	src/features/form/containers/GroupContainer.tsx
#	src/features/form/containers/RepeatingGroupsEditContainer.tsx
…n the 'children' property, as well as prevent it from sorting groups last. This new variant might also be a bit faster, is shorter, and hopefully easier to understand. This is one of the steps needed to fix the summary.ts cypress test, as rewriting to use nodes revealed the hierarchy also changed the order from the definition in the layout structure.
…d preferably be replaced by the LayoutNode/hierarchy tools
…ed as repeating, and SummaryGroupComponent never really cared about that until now.
@olemartinorg olemartinorg added the kind/product-feature Pull requests containing new features label Jan 25, 2023
…o using node layouts instead of flat layouts, proper component IDs, exposing ExprContext everywhere (but making it undefined when it's not possible to construct it).
@olemartinorg olemartinorg marked this pull request as ready for review January 26, 2023 10:18
Copy link
Member

@bjosttveit bjosttveit left a comment

Choose a reason for hiding this comment

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

Looks good as far as I can tell 😅

@olemartinorg
Copy link
Contributor Author

@bjosttveit Yup, sorry, it's a huge change that affects everything... The fact that you spotted that multiPageIndex thing means you probably looked more closely at this than I would! 🥳

# Conflicts:
#	src/layout/Likert/RepeatingGroupsLikertContainer.tsx
@sonarqubecloud
Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 13 Code Smells

73.8% 73.8% Coverage
0.0% 0.0% Duplication

@olemartinorg olemartinorg merged commit 353453c into main Jan 27, 2023
@olemartinorg olemartinorg deleted the bug/expr-per-group branch January 27, 2023 12:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/product-feature Pull requests containing new features
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Instance with many repeating group wont open
2 participants