Skip to content

Conversation

@DanielRyanSmith
Copy link
Collaborator

Part of #5496

(This ended up being more work than I realized)

This change updates the existing logic for displaying the outdated feature banner and moves it to a utility function so that it can be used on any page.

Copy link
Collaborator

@jcscottiii jcscottiii left a comment

Choose a reason for hiding this comment

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

This is a fantastic refactoring! Moving the complex stale-banner logic out of the component and into a dedicated, reusable utility in utils.ts is a great architectural improvement. The new functions are well-structured, and the comprehensive test suite in utils_test.ts is excellent.

I saw your discussion about using an interface for shippingDateInfo versus a class or a plain object. You absolutely made the right call. Using an interface is the idiomatic best practice here. It provides strong type-safety and documents the data shape without the overhead of a class instance, which is ideal for handling plain data from a JSON API.

I have a few suggestions, mostly focused on tightening up the TypeScript typings to make this new module even more robust and maintainable. Overall, this is a really strong contribution.

* Returns a warning banner TemplateResult if a feature is considered outdated,
* otherwise returns null.
* @param {Feature} feature The feature object.
* @param {closestShippingDateInfo} shippingInfo The shipping information from findClosestShippingDate.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggestion: This is a .ts file, so we should use TypeScript's explicit type annotations for function parameters instead of relying on JSDoc. Could we add the : Feature type to the feature parameter here? This would improve type safety and editor support. This comment applies to all the new functions added in this PR (isShippedFeatureOutdatedForAuthor, isShippedFeatureOutdatedForAll, etc.), which are also missing explicit types for their feature and other parameters.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've updated this to now use the types effectively. This did, however, chain into a lot of other changes, since the tests required more thorough values to make sure the variables were properly typed. Then, other components that previously used some of these existing functions also needed updating. This even uncovered that there were some data type discrepancies in the Feature type definition, so there's a lot of updates coming with this change. 🙂

* @returns {boolean} True if the banner should be shown for all users.
*/
function isShippedFeatureOutdatedForAll(
feature,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same thing. Add the types.

* @returns {boolean} True if the banner should be shown for an author.
*/
function isShippedFeatureOutdatedForAuthor(
feature,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same thing around adding the types instead of relying on jsdocs

* and booleans for isUpcoming and hasShipped.
*/
export async function findClosestShippingDate(
channels,
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should import the Channels and StageDict from cs-client.js and use those

* @returns {boolean} True if the upcoming feature is outdated, false otherwise.
*/
function isUpcomingFeatureOutdated(
feature,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same thing for adding the types

}

// Represent two months grace period.
const nineWeekPeriod = 9 * 7 * 24 * 60 * 60 * 1000;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggestion: This is a great use of a fixed week count to approximate a "two-month" period. To make the code a little more self-documenting, what do you think about extracting the magic number into a named constant? We could also clarify the comment slightly.

For example, we could define this at the top of the file:

// A 9-week grace period used to approximate 2 months for shipped features.
const SHIPPED_FEATURE_OUTDATED_GRACE_PERIOD = 9 * 7 * 24 * 60 * 60 * 1000;

And then use the constant here. This would make the purpose of the value immediately clear at the point of use.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated!

assert.isNull(result);
});

it('should return a banner if accurate_as_of is missing for upcoming', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggestion: This test case name, 'should return a banner if accurate_as_of is missing for upcoming', is a little ambiguous. It correctly tests that a banner is shown, but it's not immediately obvious why. What do you think about renaming it to something like 'should return upcoming banner if accurate_as_of is missing' and adding a brief comment inside the test explaining that a missing accurate_as_of date is considered outdated for an upcoming feature? It would make the intent clearer for future maintainers.

Copy link
Collaborator

@jcscottiii jcscottiii left a comment

Choose a reason for hiding this comment

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

LGTM overall. Some nits around adding more types instead of relying on js docs (JS Docs are great for .js files). I know this was a Refactor with existing stuff. but since we are moving things around, those nits could help out in general.

Also, apologies for the Gemini review. It placed comments in the wrong location. I went back and added what I thought was relevant and resolved other ones.

@DanielRyanSmith DanielRyanSmith added this pull request to the merge queue Oct 21, 2025
Merged via the queue into main with commit e734f86 Oct 21, 2025
7 of 8 checks passed
@DanielRyanSmith DanielRyanSmith deleted the refactor-stale-feature-banner branch October 21, 2025 00:57
@jrobbins jrobbins mentioned this pull request Oct 23, 2025
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