-
Notifications
You must be signed in to change notification settings - Fork 6
SCAL-262671 : Refactor fullheight code #268
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
base: main
Are you sure you want to change the base?
Conversation
🎉 Snyk checks have passed. No issues have been found so far.✅ security/snyk check is complete. No issues have been found. (View Details) ✅ license/snyk check is complete. No issues have been found. (View Details) |
/gemini review |
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.
Code Review
This pull request is a well-executed refactoring of the "full height" functionality. By extracting this logic into a dedicated FullHeight
class, you've improved code organization, separation of concerns, and maintainability. The changes are consistently applied across both AppEmbed
and LiveboardEmbed
, and the addition of a new test suite for the FullHeight
class is a great touch that ensures the refactored code is well-tested.
I have a few suggestions to further enhance the code quality, mainly around removing some leftover code from the refactoring and improving type safety.
Overall, great work on this refactoring!
private sendFullHeightLazyLoadData = () => { | ||
const data = calculateVisibleElementData(this.iFrame); | ||
this.trigger(HostEvent.VisibleEmbedCoordinates, data); | ||
} | ||
|
||
/** | ||
* This is a handler for the RequestVisibleEmbedCoordinates event. | ||
* It is used to send the visible coordinates data to the host application. | ||
* @param data The event payload | ||
* @param responder The responder function | ||
*/ | ||
private requestVisibleEmbedCoordinatesHandler = (data: MessagePayload, responder: any) => { | ||
logger.info('Sending RequestVisibleEmbedCoordinates', data); | ||
const visibleCoordinatesData = calculateVisibleElementData(this.iFrame); | ||
responder({ type: EmbedEvent.RequestVisibleEmbedCoordinates, data: visibleCoordinatesData }); | ||
} |
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.
These methods, sendFullHeightLazyLoadData
and requestVisibleEmbedCoordinatesHandler
, appear to be duplicates of logic that now resides in the new FullHeight
class. Since AppEmbed
delegates full-height handling to fullHeightClient
, these methods seem to be unused within AppEmbed
. Removing them would eliminate code duplication and prevent potential confusion.
} = this.viewConfig; | ||
|
||
let params = {}; | ||
let params: any = {}; |
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.
Using any
for the params
variable bypasses TypeScript's type checking. To improve type safety and code clarity, consider using a more specific type. Record<string, any>
would be more explicit about the object's shape, making it clearer that this is a dictionary-like object.
let params: any = {}; | |
let params: Record<string, any> = {}; |
*/ | ||
protected getEmbedParams() { | ||
let params = {}; | ||
let params: any = {}; |
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.
Similar to other parts of the codebase, the params
variable is typed as any
. Using a more explicit type like Record<string, any>
would improve code clarity and type safety, making it clearer that this is a dictionary-like object.
let params: any = {}; | |
let params: Record<string, any> = {}; |
commit: |
/gemini review |
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.
Code Review
This pull request refactors the fullHeight
functionality by extracting the logic into a new FullHeight
class. This is a good improvement for code organization and separation of concerns. The tests have also been moved to a new spec file, which is appropriate.
However, I've found a few critical issues in the new FullHeight
class that could lead to incorrect behavior or runtime errors, particularly related to how fallback heights are calculated. There are also some minor documentation and encapsulation improvements suggested. Please review the comments for details.
private updateIFrameHeight = (data: MessagePayload) => { | ||
const viewConfig = this.getViewConfig(); | ||
this.setIFrameHeight(Math.max(data.data, viewConfig.defaultHeight)); | ||
this.sendFullHeightLazyLoadData(); | ||
}; |
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 implementation has a couple of critical issues:
-
Potential
NaN
height: IfviewConfig.defaultHeight
is not provided (e.g., forAppEmbed
), it will beundefined
.Math.max(number, undefined)
results inNaN
, which will set an invalid height on the iframe. -
Regression for
AppEmbed
: The original logic forAppEmbed
usediframe.scrollHeight
as a fallback height. This logic has been lost in the refactoring, which can lead to incorrect height calculations forAppEmbed
.
Here's a suggestion that addresses both issues by checking the component type and providing safe fallbacks.
const viewConfig = this.getViewConfig();
const isAppEmbed = viewConfig.embedComponentType === 'AppEmbed';
const fallbackHeight = isAppEmbed ? (this.getIframe()?.scrollHeight || 0) : (viewConfig.defaultHeight || 500);
this.setIFrameHeight(Math.max(data.data, fallbackHeight));
this.sendFullHeightLazyLoadData();
src/full-height.ts
Outdated
} | ||
this.setIFrameHeight(frameHeight || viewConfig.defaultHeight); |
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 may result in setIFrameHeight
being called with undefined
if frameHeight
and viewConfig.defaultHeight
are both not provided. This can cause issues with the iframe's height.
You should use this.defaultHeight
as a fallback, which is correctly initialized in the constructor to handle this case.
this.setIFrameHeight(frameHeight || this.defaultHeight);
src/full-height.ts
Outdated
* Sets the height of the iframe | ||
* @param height The height in pixels | ||
*/ | ||
protected setIFrameHeight(height: number | string): void { |
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 flag is used to enable the full height lazy load data. | ||
* | ||
* @example | ||
* ```js |
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.
/gemini review |
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.
Code Review
An excellent refactoring effort! Abstracting the fullHeight
logic into a dedicated FullHeight
class significantly improves code reuse and maintainability by removing duplicated code from AppEmbed
and LiveboardEmbed
. The use of dependency injection to provide the FullHeight
class with the necessary context from the embed components is well-executed.
I've identified a critical issue regarding how the iframe height is calculated, which could lead to errors. I've also noted a regression where LiveboardEmbed
loses its default height, and a few minor improvements for maintainability. Please see my detailed comments below.
Once these issues are addressed, this will be a solid improvement to the codebase.
private updateIFrameHeight = (data: MessagePayload) => { | ||
const viewConfig = this.getViewConfig(); | ||
this.setIFrameHeight(Math.max(data.data, viewConfig.defaultHeight)); | ||
this.sendFullHeightLazyLoadData(); | ||
}; |
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.
There's a potential issue in the updateIFrameHeight
method. The viewConfig.defaultHeight
can be undefined
if it's not provided by the consumer. When this happens, Math.max(number, undefined)
will result in NaN
, which is then passed to setIFrameHeight
. This will set an invalid height on the iframe and break the full-height functionality.
You should provide a fallback value to prevent this. A simple fallback is 0
, but note that the previous implementation for AppEmbed
used iframe.scrollHeight
, which might be a more desirable behavior to preserve.
private updateIFrameHeight = (data: MessagePayload) => {
const viewConfig = this.getViewConfig();
// Use a fallback for defaultHeight to prevent NaN.
const fallbackHeight = viewConfig.defaultHeight || 0;
this.setIFrameHeight(Math.max(data.data, fallbackHeight));
this.sendFullHeightLazyLoadData();
};
src/full-height.ts
Outdated
// Communicate with the embed | ||
// |
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.
The file-level comment is a bit vague. To improve clarity for future maintainers, it would be beneficial to provide a more descriptive comment that explains the purpose of the FullHeight
class.
// Communicate with the embed | |
// | |
// This file contains the FullHeight class, which encapsulates the logic for | |
// handling full-height embeds. It is designed to be reused by different embed | |
// components like AppEmbed and LiveboardEmbed to avoid code duplication. |
src/full-height.ts
Outdated
* Sets the height of the iframe | ||
* @param height The height in pixels | ||
*/ | ||
protected setIFrameHeight(height: number | string): void { |
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.
The setIFrameHeight
method is declared as protected
, but it appears to be used only within the FullHeight
class. To improve encapsulation and clearly define the class's public API, it's better to make it private
.
protected setIFrameHeight(height: number | string): void { | |
private setIFrameHeight(height: number | string): void { |
* ``` | ||
*/ | ||
defaultHeight?: number; | ||
export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewConfig, LiveboardAppEmbedViewConfig, FullHeightViewConfig { |
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 full height configs can be added in LiveboardAppEmbedViewConfig
- it is common for liveboard and full app configs.
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.
we should not have LiveboardAppEmbedViewConfig itself, we should have feature configs and liveboard should extend those
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.
Feature configs are also there, but single common configs of app embed and liveboard, i have created this config.
We can keep the feature config and add in the LiveboardAppEmbedViewConfig
for common or AllEmbedConfig
for app embed.
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 what i meant it is , we should not keep full stuff there cause this could be supported in future as well to other embeds.
this.on(EmbedEvent.EmbedIframeCenter, this.embedIframeCenter); | ||
this.on(EmbedEvent.RequestVisibleEmbedCoordinates, this.requestVisibleEmbedCoordinatesHandler); | ||
this.fullHeightClient = new FullHeight({ | ||
getIframe: () => this.iFrame, |
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.
Maybe just pass the instance of liveboardEmbed here, and create these constructs inside the constructor? These constructs are very specific to the embed instance anyway, and this parts seems a little duplicated.
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 did that before but that just creates a circular reference
FullHeight -> embed -> FullHeight
No description provided.