Skip to content

Add "Where's my project?" link to FW Lite and corresponding page to Lexbox#1650

Merged
rmunn merged 20 commits into
developfrom
feat/wheres-my-project
May 20, 2025
Merged

Add "Where's my project?" link to FW Lite and corresponding page to Lexbox#1650
rmunn merged 20 commits into
developfrom
feat/wheres-my-project

Conversation

@rmunn

@rmunn rmunn commented May 6, 2025

Copy link
Copy Markdown
Contributor

Fixes #1628.

  • Added a "Where's my project?" page to Lexbox which displays different content based on whether the user has a feature flag or not
  • Fleshed out the page content on "user has feature flag" version of the page, with proper instructions.
  • Added button on the "user doesn't have feature flag" version of page, that can send an email to Lexbox admins to ask for the feature flag to be added
  • Added a link to FW Lite that will link to the Lexbox page. TODO: Decide whether to only link to lexbox.org or whether to get the link location from an environment variable so local dev copies can override the location.

@rmunn rmunn self-assigned this May 6, 2025
@coderabbitai

coderabbitai Bot commented May 6, 2025

Copy link
Copy Markdown

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

This change introduces a "Where's my project?" help feature to the FW Lite home. It adds a help section with a link to explanatory content, implements a GraphQL mutation and supporting backend/frontend logic for users to request access to the FW Lite beta, and provides new email templates, localized text, and conditional UI based on feature flags.

Changes

Files/Paths Change Summary
backend/LexBoxApi/GraphQL/UserMutations.cs, Services/Email/EmailTemplates.cs, Services/Email/IEmailService.cs, Services/EmailService.cs Added a GraphQL mutation and backend logic to send a "Join FWLite Beta" request email, including new email template types and service methods.
frontend/schema.graphql, src/routes/(authenticated)/wheresMyProject/+page.ts Added GraphQL mutation schema and frontend function to trigger sending the beta request email.
frontend/src/lib/email/JoinFWLiteBetaRequest.svelte, src/routes/email/emails.ts Added new Svelte email template component and integrated it into the email template system.
frontend/src/lib/layout/FeatureFlagAlternateContent.svelte Introduced a component to render alternate content based on user feature flags.
frontend/src/routes/(authenticated)/wheresMyProject/+page.svelte Added a new authenticated page explaining project visibility and providing a beta request button if the user lacks the feature flag.
frontend/src/lib/i18n/locales/en.json Added new localization strings for the help section and the beta request email template.
frontend/viewer/src/home/HomeView.svelte Added a "Where's my project?" section with a link at the bottom of the FW Lite home page.

Assessment against linked issues

Objective Addressed Explanation
Add "Where's my project?" link to FW Lite home page (#1628)
Link should explain why/how to get project to show up (#1628)
Provide help content for missing projects (#1628)
Allow user to request beta access if not enabled (#1628)

Poem

A bunny hopped to FW Lite’s home,
“Where’s my project?” it did groan.
A shiny link appeared below,
With help and answers in tow.
If beta’s locked, just click and see—
An email request hops out with glee!
🐇✨


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions

github-actions Bot commented May 6, 2025

Copy link
Copy Markdown
Contributor

UI unit Tests

12 tests  +12   12 ✅ +12   0s ⏱️ ±0s
 4 suites + 4    0 💤 ± 0 
 1 files   + 1    0 ❌ ± 0 

Results for commit 98bf5af. ± Comparison against base commit c14e896.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented May 6, 2025

Copy link
Copy Markdown
Contributor

C# Unit Tests

116 tests  +116   116 ✅ +116   10s ⏱️ +10s
 17 suites + 17     0 💤 ±  0 
  1 files   +  1     0 ❌ ±  0 

Results for commit 98bf5af. ± Comparison against base commit c14e896.

♻️ This comment has been updated with latest results.

@rmunn rmunn force-pushed the feat/wheres-my-project branch from d28b5c6 to ec415b3 Compare May 8, 2025 02:14
@rmunn

rmunn commented May 8, 2025

Copy link
Copy Markdown
Contributor Author

Have now rebased on top of develop to pull in the now-merged Svelte 5 migration. That didn't have many effects on this PR, I just had to change one case of on:click to onclick.

@rmunn

rmunn commented May 9, 2025

Copy link
Copy Markdown
Contributor Author

Going to wait until #1652 is merged before continuing to work on this one, so that I can catch any other on:event uses that need to be changed to onEvent.

@rmunn

rmunn commented May 13, 2025

Copy link
Copy Markdown
Contributor Author

Rebasing on top of #1652 for now so I can continue to make progress on this PR.

@rmunn rmunn force-pushed the feat/wheres-my-project branch from 0377194 to 2c40d60 Compare May 13, 2025 03:38
@rmunn

rmunn commented May 13, 2025

Copy link
Copy Markdown
Contributor Author

Never mind that rebase, it makes this PR look unmanageable. There were no merge conflicts anyway so it's not a problem to be based off develop, it won't harm my ability to merge #1652 if this one gets merged first.

@rmunn rmunn force-pushed the feat/wheres-my-project branch from f22ed8a to 20387b4 Compare May 13, 2025 04:07
@rmunn rmunn marked this pull request as ready for review May 13, 2025 04:10

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (7)
frontend/src/lib/layout/FeatureFlagAlternateContent.svelte (2)

17-17: Consider providing context for the eslint-disable comment.

While the eslint-disable is likely needed, it would be helpful to add a short explanation of why this rule needs to be disabled to help future developers understand the reasoning.

-<!-- eslint-disable-next-line @typescript-eslint/no-unsafe-argument -->
+<!-- eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- Snippet functions are properly typed but ESLint cannot verify this -->

14-14: Consider adding a default value for children to avoid potential null errors.

Since children is optional and used in line 19 with the null coalescing operator, you might want to provide a default empty function to avoid potential errors in case both hasFlagContent and children are undefined.

-let { flag, missingFlagContent, hasFlagContent, children }: Props = $props();
+let { flag, missingFlagContent, hasFlagContent, children = () => '' }: Props = $props();
frontend/src/routes/(authenticated)/wheresMyProject/+page.ts (2)

6-6: Remove underscore prefix from exported function.

The underscore prefix (_) conventionally indicates a private function, but this function is exported. Either keep it private (not exported) or remove the underscore.

-export async function _sendFWLiteBetaRequestEmail(userId: UUID, name: string): $OpResult<SendFwLiteBetaRequestEmailMutation> {
+export async function sendFWLiteBetaRequestEmail(userId: UUID, name: string): $OpResult<SendFwLiteBetaRequestEmailMutation> {

18-19: Fix indentation for consistency.

The indentation of __typename is inconsistent with surrounding code.

            errors {
-                __typename
+              __typename
              ... on Error {
frontend/src/routes/(authenticated)/wheresMyProject/+page.svelte (2)

9-9: Consider using project-specific UUID type definition.

Importing the UUID type from 'crypto' module might not be necessary if the project already has a UUID type definition. Check if there's a project-specific type definition that could be used instead.


31-32: Remove empty style block.

The empty style block doesn't serve any purpose and can be removed.

-<style>
-</style>
backend/LexBoxApi/GraphQL/UserMutations.cs (1)

53-53: Consider adding a more specific error message.

For improved debugging and user experience, consider adding a more descriptive message when throwing the UnauthorizedAccessException.

-        if (loggedInContext.User.Id != input.UserId) throw new UnauthorizedAccessException();
+        if (loggedInContext.User.Id != input.UserId) throw new UnauthorizedAccessException("User can only request beta access for themselves");
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e44fffb and 20387b4.

📒 Files selected for processing (12)
  • backend/LexBoxApi/GraphQL/UserMutations.cs (2 hunks)
  • backend/LexBoxApi/Services/Email/EmailTemplates.cs (2 hunks)
  • backend/LexBoxApi/Services/Email/IEmailService.cs (1 hunks)
  • backend/LexBoxApi/Services/EmailService.cs (1 hunks)
  • frontend/schema.graphql (4 hunks)
  • frontend/src/lib/email/JoinFWLiteBetaRequest.svelte (1 hunks)
  • frontend/src/lib/i18n/locales/en.json (2 hunks)
  • frontend/src/lib/layout/FeatureFlagAlternateContent.svelte (1 hunks)
  • frontend/src/routes/(authenticated)/wheresMyProject/+page.svelte (1 hunks)
  • frontend/src/routes/(authenticated)/wheresMyProject/+page.ts (1 hunks)
  • frontend/src/routes/email/emails.ts (5 hunks)
  • frontend/viewer/src/home/HomeView.svelte (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
backend/LexBoxApi/Services/EmailService.cs (2)
backend/LexBoxApi/Services/Email/IEmailService.cs (5)
  • Task (10-10)
  • Task (12-12)
  • Task (22-22)
  • Task (31-37)
  • Task (46-52)
backend/LexCore/Entities/User.cs (1)
  • User (5-57)
🪛 Biome (1.9.4)
frontend/src/lib/i18n/locales/en.json

[error] 671-671: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 671-671: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 673-674: Invalid escape sequence

Valid escape sequences are: \\, \/, /", \b\, \f, \n, \r, \t or any unicode escape sequence \uXXXX where X is hexedecimal number.

(parse)


[error] 673-674: Missing closing quote

The closing quote must be on the same line.

(parse)


[error] 674-674: expected , but instead found near

Remove near

(parse)


[error] 674-674: expected : but instead found the

Remove the

(parse)


[error] 674-674: expected , but instead found top

Remove top

(parse)


[error] 674-674: expected : but instead found of

Remove of

(parse)


[error] 674-674: expected , but instead found the

Remove the

(parse)


[error] 674-674: expected : but instead found page

Remove page

(parse)


[error] 674-674: unexpected character .

(parse)


[error] 674-675: Missing closing quote

The closing quote must be on the same line.

(parse)


[error] 675-675: expected , but instead found it

Remove it

(parse)


[error] 675-676: Missing closing quote

The closing quote must be on the same line.

(parse)


[error] 676-676: expected , but instead found "user_not_in_beta"

Remove "user_not_in_beta"

(parse)


[error] 676-677: Invalid escape sequence

Valid escape sequences are: \\, \/, /", \b\, \f, \n, \r, \t or any unicode escape sequence \uXXXX where X is hexedecimal number.

(parse)


[error] 676-677: Missing closing quote

The closing quote must be on the same line.

(parse)


[error] 677-677: expected , but instead found have

Remove have

(parse)


[error] 677-677: expected : but instead found chosen

Remove chosen

(parse)


[error] 677-677: expected , but instead found to

Remove to

(parse)


[error] 677-677: expected : but instead found be

Remove be

(parse)


[error] 677-677: expected , but instead found part

Remove part

(parse)


[error] 677-677: expected : but instead found of

Remove of

(parse)


[error] 677-677: expected , but instead found the

Remove the

(parse)


[error] 677-677: expected : but instead found beta

Remove beta

(parse)


[error] 677-677: unexpected character .

(parse)


[error] 677-677: Property key must be double quoted

(parse)


[error] 677-677: expected : but instead found click

Remove click

(parse)


[error] 677-677: expected , but instead found the

Remove the

(parse)


[error] 677-677: expected : but instead found button

Remove button

(parse)


[error] 677-677: expected , but instead found below

Remove below

(parse)


[error] 677-677: unexpected character \

(parse)


[error] 677-677: expected , but instead found n

Remove n

(parse)


[error] 677-678: unexpected character \

(parse)


[error] 678-678: expected , but instead found to

Remove to

(parse)


[error] 678-678: expected : but instead found ask

Remove ask

(parse)


[error] 678-678: expected , but instead found to

Remove to

(parse)


[error] 678-678: expected : but instead found join

Remove join

(parse)


[error] 678-678: expected , but instead found the

Remove the

(parse)


[error] 678-678: expected : but instead found beta

Remove beta

(parse)


[error] 678-678: expected , but instead found test

Remove test

(parse)


[error] 678-678: unexpected character .

(parse)


[error] 678-678: expected , but instead found Depending

Remove Depending

(parse)


[error] 678-678: expected : but instead found on

Remove on

(parse)


[error] 678-678: expected , but instead found what

Remove what

(parse)


[error] 678-678: expected : but instead found time

Remove time

(parse)


[error] 678-678: expected , but instead found zone

Remove zone

(parse)


[error] 678-678: expected : but instead found you

Remove you

(parse)


[error] 678-679: Missing closing quote

The closing quote must be on the same line.

(parse)


[error] 679-679: expected , but instead found to

Remove to

(parse)


[error] 679-679: expected : but instead found see

Remove see

(parse)


[error] 679-679: expected , but instead found your

Remove your

(parse)


[error] 679-679: expected : but instead found email

Remove email

(parse)


[error] 679-679: expected , but instead found and

Remove and

(parse)


[error] 679-679: expected : but instead found respond

Remove respond

(parse)


[error] 679-679: unexpected character .

(parse)


[error] 679-680: Missing closing quote

The closing quote must be on the same line.

(parse)


[error] 680-680: expected , but instead found "request_beta_access"

Remove "request_beta_access"

(parse)


[error] 681-681: Expected a property but instead found '}'.

Expected a property here.

(parse)


[error] 671-681: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Build API / publish-api
  • GitHub Check: Analyze (csharp)
  • GitHub Check: Build FW Lite and run tests
🔇 Additional comments (13)
frontend/src/lib/layout/FeatureFlagAlternateContent.svelte (1)

9-11: Clean implementation of conditional content rendering based on feature flags.

This component provides a flexible way to conditionally render content based on user feature flags. The API with optional snippet props gives good flexibility to consumers.

Also applies to: 18-21

frontend/viewer/src/home/HomeView.svelte (1)

209-217: Good addition of help content for users.

This section provides useful guidance to users who may not see their projects, improving the overall user experience.

backend/LexBoxApi/Services/Email/EmailTemplates.cs (1)

26-26: Proper extension of email templates.

The new email template type follows the existing patterns in the file and is well integrated with the current structure.

Also applies to: 45-45

frontend/src/lib/email/JoinFWLiteBetaRequest.svelte (1)

8-8:

Details

❓ Verification inconclusive

Consider security implications of email in query parameters.

Including email addresses in query parameters might expose sensitive user information in server logs, browser history, and referrer headers.

Consider using a POST form or a more secure approach for passing the email. If query parameters must be used, ensure server logs are appropriately configured to mask sensitive information.


🏁 Script executed:

#!/bin/bash
# Check if there are other instances of email addresses in query parameters
rg -g "*.ts" -g "*.svelte" "userEmail=\$\{encodeURIComponent\(" --no-heading

# Check for any email masking in logging configuration
rg -g "*.json" -g "*.config" "mask" --no-heading

Length of output: 126


Ensure secure handling of userEmail in URLs

We only found this instance and no masking configurations in logs:

  • Location: frontend/src/lib/email/JoinFWLiteBetaRequest.svelte (line 8)
    let approveUrl = new URL(
      `/admin/approveFWBetaRequest?userEmail=${encodeURIComponent(email)}`, 
      baseUrl
    );
  • No other userEmail=${encodeURIComponent( occurrences in .ts/.svelte files.
  • No masking settings detected in .json or .config files.

Recommendations:

  • Prefer sending sensitive data in the request body (POST) or via a session-bound token.
  • If a query parameter is unavoidable:
    • Implement server-side masking of email in logs.
    • Review/refine referrer policies and logging configuration to strip or obfuscate sensitive query fields.
frontend/schema.graphql (4)

278-278: LGTM: Mutation correctly declares required parameters and return type.

The sendFWLiteBetaRequestEmail mutation is properly declared with the necessary input parameter and return payload. Good use of the @cost directive for query complexity management.


497-500: LGTM: Payload type follows schema conventions.

The SendFWLiteBetaRequestEmailPayload type properly includes the meDto and errors fields, following the conventions established in other mutation payloads in the schema.


654-654: LGTM: Error union is correctly defined.

The SendFWLiteBetaRequestEmailError union appropriately includes common error types that might occur during the email sending process. This aligns with the error handling approach seen in other mutations.


1105-1108: LGTM: Input type contains necessary fields.

The SendFWLiteBetaRequestEmailInput is properly defined with the required userId and name fields, which matches the backend implementation in UserMutations.cs.

frontend/src/lib/i18n/locales/en.json (1)

750-754: LGTM: Email template localization strings look good.

The localization strings for the beta join request email are properly formatted and provide all necessary text elements for the email template.

frontend/src/routes/(authenticated)/wheresMyProject/+page.svelte (2)

16-29: LGTM: Page structure and feature flag handling look good.

The page correctly uses the FeatureFlagAlternateContent component to show different content based on whether the user has the "FwLiteBeta" feature flag. The layout follows established patterns with breadcrumb and title components.


25-25:

Details

✅ Verification successful

Verify event handler naming convention.

The PR comments mentioned changes from on:click to onclick due to Svelte 5 migration. Confirm that using onclick (rather than the Svelte-idiomatic on:click) is consistent with the project's current Svelte event handling conventions after the migration.


🏁 Script executed:

#!/bin/bash
# Check for other button components in the codebase to verify convention
echo "Checking Button component usage in the codebase..."
fd ".svelte$" frontend/src -x grep -l "Button" {} \; | xargs grep -l "on[cC]lick" | head -n 5 | xargs grep -A 1 -B 1 "on[cC]lick"

Length of output: 4422


Event handler naming convention verified. The codebase consistently uses onclick in Svelte components following the Svelte 5 migration, including <Button> and native <button> elements. No changes needed here.

backend/LexBoxApi/GraphQL/UserMutations.cs (2)

39-39: LGTM: Input record type is well-defined.

The SendFWLiteBetaRequestEmailInput record type correctly defines the required parameters for the mutation.


41-64: LGTM: Mutation implementation looks solid.

The implementation follows the established patterns for mutations in this class:

  • Proper authorization checks
  • Good error handling with appropriate exception types
  • Clean integration with the email service
  • Correct return of user data in the MeDto

Comment thread backend/LexBoxApi/Services/Email/IEmailService.cs Outdated
Comment thread frontend/viewer/src/home/HomeView.svelte Outdated
Comment thread backend/LexBoxApi/Services/EmailService.cs Outdated
Comment thread frontend/src/routes/email/emails.ts Outdated
Comment thread frontend/src/lib/i18n/locales/en.json
Serialization of C# enums was a little ambiguous when the name was
FWLite, so FwLite removes all ambiguity re how the name will end up.
@rmunn

rmunn commented May 13, 2025

Copy link
Copy Markdown
Contributor Author

The "Where's my project" link in the FW Lite homepage is a placeholder in need of suggestions for how to actually style it for UI consistency. @myieye - Got any suggestions for how I should implement it? See commit 20387b4 for how I added it.

EDIT: Forgot to mention that I'd had the idea of putting a "Where's my project?" link in only if the user is logged in (to whichever server) and no projects were returned. Currently I just have one link at the bottom of the page instead.

@hahn-kev

Copy link
Copy Markdown
Collaborator

@rmunn where's this issue at? Are you waiting for feedback from @myieye? or waiting for a review?

@myieye

myieye commented May 15, 2025

Copy link
Copy Markdown
Collaborator

I'm taking a look now

@myieye myieye left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I touched up the button styles/positions:

image.png

image.png

image.png

If no projects:

image.png

image.png

Comment thread backend/LexBoxApi/GraphQL/UserMutations.cs Outdated
Comment thread backend/LexBoxApi/GraphQL/UserMutations.cs Outdated
Comment thread frontend/src/lib/i18n/locales/en.json Outdated
Comment thread frontend/src/lib/i18n/locales/en.json Outdated
Comment thread frontend/src/routes/(authenticated)/wheresMyProject/+page.svelte Outdated
Comment thread frontend/src/routes/(authenticated)/wheresMyProject/+page.svelte Outdated
Comment thread frontend/src/lib/i18n/locales/en.json Outdated
Comment thread frontend/src/lib/email/JoinFwLiteBetaRequest.svelte Outdated
Comment thread frontend/src/lib/i18n/locales/en.json Outdated
rmunn added 2 commits May 19, 2025 17:17
Also notify user if they were already in the beta, in which case no
email was sent.
@rmunn

rmunn commented May 19, 2025

Copy link
Copy Markdown
Contributor Author

@myieye - All comments addressed EXCEPT the wording of the email as I was running out of time for the day. Would you like to take a stab at that one, just to get it done quicker? Otherwise I'll work on it tomorrow.

@myieye myieye left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks good to me.
Nice work @rmunn! 😎

@rmunn rmunn merged commit 784be48 into develop May 20, 2025
23 checks passed
@rmunn rmunn deleted the feat/wheres-my-project branch May 20, 2025 01:27
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.

Add "Where's my project?" to project list in FW Lite home

3 participants