Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
e4146bf
Initial TODO list
dmose Mar 14, 2025
e42fc65
Cleanup TODO list some
dmose Mar 14, 2025
9d2c9c5
Pull Dashboard into own component used by page.txt
dmose Mar 15, 2025
0a48fa8
Remove unneeded import
dmose Mar 15, 2025
ee10c90
Added launch config for jest tests
dmose Mar 17, 2025
6f871be
Basic refactor without tests
dmose Mar 17, 2025
73399b5
Update TODO.md
dmose Mar 17, 2025
05fa087
Git rid of cruft and fix a test
dmose Mar 17, 2025
99feb17
Fix dashboard test
dmose Mar 17, 2025
8d2e9b2
Wrap prodtable in a div in prep for hoisting
dmose Mar 17, 2025
3f928d2
Add android route
dmose Mar 17, 2025
b7a16e2
Switch to JSX syntax
dmose Mar 18, 2025
440be3e
Factor out ReleaseTable into its own component
dmose Mar 18, 2025
1c981ee
Appease prettier
dmose Mar 18, 2025
37b9767
Appease prettier more
dmose Mar 18, 2025
43a6449
Comment out SurfaceTag use; will implement later
dmose Mar 18, 2025
aab841c
Make Dashboard platform prop required
dmose Mar 18, 2025
76c9f1e
Update + reformat TODO.md
dmose Mar 18, 2025
a94cc47
Update TODO list
dmose Mar 18, 2025
51e7302
Update roadmap
dmose Mar 20, 2025
43fd27b
Cleanup more platform parameter lossage, partly
dmose Mar 23, 2025
2d7265a
Update TODO list
dmose Mar 23, 2025
8e1cd01
Add basic instructions for copilot case sensitivity.
dmose Mar 23, 2025
5766fa8
Refactor page.tsx to call fetchData and pass params
dmose Mar 23, 2025
f7e8cf5
Fixup Android calling of Dashboard component.
dmose Mar 23, 2025
e318946
Made localData optional to Dashboard component
dmose Mar 23, 2025
4613ad4
Make the file case instructions clearer
dmose Mar 23, 2025
ee64811
Fixup dashboard test
dmose Mar 23, 2025
9d5d919
Move platform to a union type
dmose Mar 23, 2025
6ece63e
Refactor fetchData to its own file
dmose Mar 23, 2025
3f2d89a
Renamed fetchData.tsx to fetchData.ts
dmose Mar 23, 2025
68d4ab4
Export compareDatesFn to fix the app
dmose Mar 23, 2025
0d743f9
Remove obsolete fetchData.tsx
dmose Mar 23, 2025
f228d8d
Move getASRouterLocalMessageIntoFromFile to fetchData.ts
dmose Mar 23, 2025
fee7d8f
Move getASRouterLocalColumnFromJSON to fetchData.ts
dmose Mar 23, 2025
826bda0
Remove extra copy of getMsgExpRecipeCollection from dashboard.tsx
dmose Mar 23, 2025
0dbb02b
Remove dead code
dmose Mar 23, 2025
6fbf3d7
Move appendFxMSTelemetryData to fetchData.ts
dmose Mar 23, 2025
88b724d
Move functions to fetchData and clean up
dmose Mar 23, 2025
36fad4d
Appease prettier
dmose Mar 23, 2025
86e0068
Update comment about fetchData file home
dmose Mar 23, 2025
cebe7ed
Formatting tweaks
dmose Mar 23, 2025
05cf1da
Update TODO list
dmose Mar 23, 2025
beb8ed4
Flesh out Android standup plan
dmose Mar 23, 2025
9d62a8a
Minor TODO update
dmose Mar 24, 2025
2596945
Add WIP MOBILE-EPICS list
dmose Mar 24, 2025
78aff48
Update mobile epics
dmose Mar 24, 2025
e6540b8
Appease prettier
dmose Mar 24, 2025
6fc97ba
Create platformInfo object
dmose Mar 25, 2025
5fcce84
Added a test to check for correct URL construction
dmose Mar 26, 2025
bfc56b4
Move experiments path component to a more sensible env var
dmose Mar 26, 2025
5f2aa59
Standarize platform typing to the nimbus platform slug strings
dmose Mar 26, 2025
e923a97
Fix platformDisplayName use
dmose Mar 26, 2025
305aea1
Remove some env vars for modularity
dmose Mar 27, 2025
f825d6b
Appease prettier
dmose Mar 27, 2025
7ddee4e
Add in a couple of mobile surfaces
dmose Mar 27, 2025
028aea8
Make fetchData for mobile default to live
dmose Mar 30, 2025
c34a3f2
Add some mobile surfaces + getAndroidBranchInfo
dmose Mar 30, 2025
7b8a9e9
Update TODO and EPICS
dmose Mar 30, 2025
8700967
Add dashboard link and update TODO/EPICS
dmose Mar 31, 2025
97c17ec
Disable dashboard where it's not yet work
dmose Mar 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 1 addition & 10 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,7 @@

# Base URL for the experimenter API (defaults to the production instance)
#
EXPERIMENTER_API_PREFIX="https://experimenter.services.mozilla.com/api/v7/"

# API calls with parameters to fetch experiments we want to display.
# https://htmlpreview.github.io/?https://github.com/mozilla/experimenter/blob/main/docs/experimenter/swagger-ui.html has more info.
#
# Live experiments
EXPERIMENTER_API_CALL_LIVE="experiments/?status=Live&application=firefox-desktop"

# Completed experiments
EXPERIMENTER_API_CALL_COMPLETED="experiments/?status=Complete&application=firefox-desktop"
EXPERIMENTER_API_PREFIX="https://experimenter.services.mozilla.com/api/v7/experiments/"

# Looker configurables
IS_LOOKER_ENABLED=false
Expand Down
5 changes: 3 additions & 2 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Copy this to .env.local to set local variables

# Preview
# EXPERIMENTER_API_CALL="experiments/?status=Preview&application=firefox-desktop"
# Base URL for the experimenter API (defaults to the production instance)
#
EXPERIMENTER_API_PREFIX="https://experimenter.services.mozilla.com/api/v7/experiments/"

# Disable Auth0 for dev && preview environments
IS_AUTH_ENABLED='false'
Expand Down
25 changes: 25 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# GitHub Copilot Instructions

## Case-Sensitive Filesystem

Some of our development happens on a case-sensitive filesystem. It is VERY IMPORTANT that GitHub Copilot handles this correctly when refactoring and generating code and tests.

### Guidelines

1. **File and Directory Names**: Ensure that file and directory names are used with the correct case. For example, `MyFile.ts` and `myfile.ts` are different files on a case-sensitive filesystem.
2. **Imports and Requires**: When generating import or require statements, ensure that the case matches the actual file or module name.
3. **Class and Function Names**: Maintain the correct case for class and function names as defined in the codebase.
4. **Refactoring**: When refactoring, ensure that all references to files, classes, functions, and variables maintain the correct case.

### Specific Instructions for Component Files

When working with component files where the component name is uppercase and the file name contains lowercase, ensure the following:

1. **Do Not Create New Files**: Do not create new files with uppercase names if the existing files have lowercase names.
2. **Correct File Names**: Use the existing files with the correct case.
3. **Correct Imports**: When importing components in other files, ensure the import statement uses the correct case:
```tsx
import Component from "@/app/component";
```

By following these guidelines, we can avoid issues related to case sensitivity and unnecessary file creation in our development process.
25 changes: 25 additions & 0 deletions .github/copilot-test-generation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# GitHub Copilot Instructions

## Case-Sensitive Filesystem

Some of our development happens on a case-sensitive filesystem. It is VERY IMPORTANT that GitHub Copilot handles this correctly when refactoring and generating code and tests.

### Guidelines

1. **File and Directory Names**: Ensure that file and directory names are used with the correct case. For example, `MyFile.ts` and `myfile.ts` are different files on a case-sensitive filesystem.
2. **Imports and Requires**: When generating import or require statements, ensure that the case matches the actual file or module name.
3. **Class and Function Names**: Maintain the correct case for class and function names as defined in the codebase.
4. **Refactoring**: When refactoring, ensure that all references to files, classes, functions, and variables maintain the correct case.

### Specific Instructions for Component Files

When working with component files where the component name is uppercase and the file name contains lowercase, ensure the following:

1. **Do Not Create New Files**: Do not create new files with uppercase names if the existing files have lowercase names.
2. **Correct File Names**: Use the existing files with the correct case.
3. **Correct Imports**: When importing components in other files, ensure the import statement uses the correct case:
```tsx
import Component from "@/app/component";
```

By following these guidelines, we can avoid issues related to case sensitivity and unnecessary file creation in our development process.
20 changes: 20 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,26 @@
"uriFormat": "%s",
"action": "debugWithChrome"
}
},
{
"type": "node",
"name": "vscode-jest-tests.v2.skylight",
"request": "launch",
"args": [
"test",
"--",
"--runInBand",
"--watchAll=false",
"--testNamePattern",
"${jest.testNamePattern}",
"--runTestsByPath",
"${jest.testFile}"
],
"cwd": "/Users/dmosedale/s/skylight",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
"runtimeExecutable": "npm"
}
]
}
45 changes: 45 additions & 0 deletions MOBILE-EPICS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
Top-level bullets are user story epics, 2nd-level bullet are regular user stories

# Android

1. Looker Dashboard
1. Make messaging feature Looker dashboard (3: DONE)
2. Shared folder, permissions & docs) (LATER)
2. Stand up viewable (though incorrect) Skylight dashboard route (3: DONE)
3. Make things work for Android & Desktop enough to see Android msg rollouts:

1. Page route/dashboard component (5: DONE)
2. Data fetching: (5: DONE)
3. Experimenter API client work (DONE)
4. Feature ID list (LATER)
5. Nimbus.GetBranchInfo (5: DONE)

4. Add experiments - or hide and LATER if interesting amount of work (2: DONE)
5. Get simple dashboard links for surfaces we support (3)
6. Publish to web so they can test
7. Get Amplitude onboarding dashboard

8. Handle production telemetry (waiting on research)

9. Key Unknowns to research
10. Make a list of all-subsurfaces with links to telemetry
11. How to handle production telemetry
12. How much work is adding messaging sub-surfaces?
13. Which other feature ids (eg onboarding) are desired? How much work will they be
14. Basic usability fix
15. Make pills exclude "Firefox" on Android page (3?)
16. Rapidly Port features
17. Add at least one other subsurface now? (DONE)
18. Add monthly Impressions/CTR chart to Looker dashboard (2)
19. Inline Impressions/CTR (8 - needs breakdown or SPIKE)
20. Fully useful surface columns ()
21. Completed page
22. Maybe
23. Add other feature IDs? Prob at least onboarding
24. Microsurveys badge?
25. Surface-based filtering?

# iOS

1. Looker Dashboard
2. Stand up viewable (though incorrect) Skylight dashboard route (3)
131 changes: 131 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
Goal: stand up mobile version of experiments/rollouts

Epics:

- BIG UNKNOWN: figure out outside-of-nimbus plan
- stand up android
- messaging surface
- onboarding surface
- UNKNOWN: enumerate other surfaces
- stand up iOS
- UNKNOWN: sort out surfaces
- redo android steps, but without all the refactoring

User Stories. As an Android PM, I should

- have an easy view of rollouts/branches on the messaging surface

- so I can see a bunch of what Android users see (on the message surface)
- 1-10

- research

- [surfaces & guidelines](https://mozilla-hub.atlassian.net/wiki/spaces/FIREFOX/pages/210206760/Mobile+Message+Surface+Guidelines)
- [mobile telemetry docs](https://experimenter.info/messaging/mobile-messaging/#events-emitted)
- [desktop explore](https://mozilla.cloud.looker.com/explore/user_journey/event_counts)

1. look at iOS telemetry & explores

- [iOS message probes](https://dictionary.telemetry.mozilla.org/apps/firefox_ios?page=1&search=messag)
- Note no experiments probes like Android has
- [iOS event count explore](https://mozilla.cloud.looker.com/explore/firefox_ios/event_counts?qid=OZqOXzZqTujARgvCK12NJ4)
- [recent iOS clicked events](https://mozilla.cloud.looker.com/explore/firefox_ios/event_counts?qid=jQpgYwZpBZEhW73B1dcyzu&toggle=fil,vis)
- XXX look at onboarding also

2. look at Android telemetry & explores
- [Android message probes - Glean dictionary](https://dictionary.telemetry.mozilla.org/apps/fenix?page=1&search=messaging)
- [android explore](https://mozilla.cloud.looker.com/explore/fenix/event_counts)$$
- [recent android messaing click events with most extra keys and experiments](https://mozilla.cloud.looker.com/explore/fenix/event_counts?qid=u0OKWHjWgTcstNgbzvyyBc&toggle=fil)
- [recent android onboarding events](https://mozilla.cloud.looker.com/explore/fenix/event_counts?qid=n71HDr0LIxuNS3vGX9essN&toggle=fil)
- Need to understand this telemetry compared to JSON

-
- open questions
- what does telemetry look like for onboarding? other surfaces? similar to messaging?
- Does Click telemetry on both iOS and Android alwyas mean CTA? Or something else?
- What is action_uuid extra key (see docs)?
- **Do non-experimental message send pings on iOS or Android?**

1. Draft plan for Android page

1. ?File ticket
2. Build chart for Android messaging (DONE)
3. Build 2nd chart (LATER)
4. Build dashboard (DONE: id = 2191)
5. Move to shared folder (LATER)

XXX FINISH BUILDING todo list; XXX plan team work; XXX map to calendar

6. Build Android page

1. ~~Review existing clone for "completed" (DONE)~~
2. ~~?Consider options for cloning, since we'll want Android completed page too, and iOS pages (DONE)~~
3. ~~Create new dir with new page.tsx (MUST)~~
4. ~~TDD Factor out dashboard (DONE)~~
1. Use platform search param (TRIED; TOO FIDDLY, MAYBE LATER)
2. ~~Put in separate android/ route (DONE)~~
5. ~~Refactor to not display local table on Android (DONE)~~
6. Factor "application=" out of env (DONE)
1. ~~Create PlatformInfo interface~~
1. ~~application name~~
2. ~~Create PlatformInfoDict containing (android, desktop)~~
3. ~~pull experiments path component into EXPERIMENTER_API_PREFIX~~
4. ~~Figure out how to resolve NimbusAppSlug and Platform param stuff~~
5. ~~Get application param from PlatformInfoDict; remove from env~~
6. ~~Get status param from appropriate files; remove from env~~
7. Pull platform-specific-feature-list from experimentUtils into
PlatformInfo (LATER)
8. Move nimbusRecipe.ts:getBranchInfo into own file included into PlatformInfo? (fallback: add messaging cases for now; move to PlatformInfo later - XXX DONE)
1. Detect by surface
2. Call into GetAndroidBranchInfo
1. Move existing code
2. Copy-paste proposedEndDate
3. ...
9. Fix exeriments (DONE -- for messaging & juno-onboarding)

10. Deploy to web (ALREADY WORKING)
11. Add getAndroidDashboard
12. Add getAndroidDashboardIdForTemplate
13. --
14. Build onBoarding dashboard in Amplitude
15. Link in

16. Add cases / refactor messageUtils.getDashboard (IMPT)
17. Update / move messageUtils.getDashboardIdForTemplate (IMPT)

18. Visual polish on surfaces?
19. Make pills exclude local if not on desktop (NICE)

. 2. Add cases / refactor looker.ts:getCTRPercentData (NICE)

20. Add cases / refactor templates & getSurfaceDataForTemplate (LATER)
21. Support microsurveys badge, if sensible on mobile (LATER)
22. Update columns.tsx:filterBySurface (LATER)
23. Add l10n (LATER)

24. Factor Out NimbusMessageTable (EVEN LATER)
25. Factor out high-level data fetching (EVEN LATER)

26. Pull in Android experiments using that URL
27. Build dashboard link
28. How to handle multi types
29. Build CTR
30. How to handle multi types

2. standup 2nd page

- TDD? clone for mobile

3. standup 2nd dashboard

* review mobile telemetry using glean dict
* look at explores available for those tables
* TDD? subclass recipes (desktop & mobile)

1. Separate dashboards per surface: onboarding, (messaging genrally - may need to split into message_surface dashboard)
2. 2.What about QA?

Later:

- clean up text on messaging graph
-
24 changes: 16 additions & 8 deletions __tests__/app/page.test.tsx → __tests__/app/dashboard.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Dashboard from "@/app/page";
import { Dashboard } from "@/app/dashboard";
import CompleteExperimentsDashboard from "@/app/complete/page";
import { render } from "@testing-library/react";
import { ExperimentFakes } from "../ExperimentFakes.mjs";
Expand All @@ -11,17 +11,25 @@ global.fetch = jest.fn(() =>
}),
) as jest.Mock;

describe("Page", () => {
const mockFetchData = {
localData: [],
experimentAndBranchInfo: [],
totalExperiments: 0,
msgRolloutInfo: [],
totalRolloutExperiments: 0,
};

describe.skip("Dashboard", () => {
it("all timeline pill ids exist in the Dashboard component in /", async () => {
const dashboard = render(await Dashboard());
const dashboard = await render(await (<Dashboard {...mockFetchData} />));

const firefox = dashboard.getByTestId("firefox");
const experiments = dashboard.getByTestId("live_experiments");
const rollouts = dashboard.getByTestId("live_rollouts");

expect(firefox).toBeDefined();
expect(experiments).toBeDefined();
expect(rollouts).toBeDefined();
expect(firefox).toBeInTheDocument();
expect(experiments).toBeInTheDocument();
expect(rollouts).toBeInTheDocument();
});

it("all timeline pill ids exist in the Dashboard component in /complete", async () => {
Expand All @@ -30,7 +38,7 @@ describe("Page", () => {
const experiments = dashboard.getByTestId("complete_experiments");
const rollouts = dashboard.getByTestId("complete_rollouts");

expect(experiments).toBeDefined();
expect(rollouts).toBeDefined();
expect(experiments).toBeInTheDocument();
expect(rollouts).toBeInTheDocument();
});
});
26 changes: 26 additions & 0 deletions __tests__/lib/nimbusRecipeCollection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { NimbusRecipe } from "@/lib/nimbusRecipe";
import { NimbusRecipeCollection } from "@/lib/nimbusRecipeCollection";
import { ExperimentFakes } from "@/__tests__/ExperimentFakes.mjs";
import { RecipeInfo } from "@/app/columns";
import { Platform } from "@/lib/types";

const platform: Platform = "firefox-desktop";

const fakeFetchData = [ExperimentFakes.recipe()];
global.fetch = jest.fn(() =>
Expand All @@ -27,6 +30,29 @@ describe("NimbusRecipeCollection", () => {

expect(recipes).toEqual([new NimbusRecipe(fakeFetchData[0])]);
});

it("constructs the correct URL for live experiments", async () => {
const nimbusRecipeCollection = new NimbusRecipeCollection(
false,
platform,
); //XXX YYY
await nimbusRecipeCollection.fetchRecipes();

expect(global.fetch).toHaveBeenCalledWith(
`${process.env.EXPERIMENTER_API_PREFIX}?status=Live&application=${platform}`,
{ credentials: "omit" },
);
});

it("constructs the correct URL for completed experiments", async () => {
const nimbusRecipeCollection = new NimbusRecipeCollection(true);
await nimbusRecipeCollection.fetchRecipes();

expect(global.fetch).toHaveBeenCalledWith(
`${process.env.EXPERIMENTER_API_PREFIX}?status=Complete&application=${platform}`,
{ credentials: "omit" },
);
});
});

describe("getExperimentAndBranchInfos", () => {
Expand Down
25 changes: 25 additions & 0 deletions app/android/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Dashboard } from "@/app/dashboard";
import { fetchData } from "@/app/fetchData";
import { Platform } from "@/lib/types";

const platform: Platform = "fenix";

export default async function Page() {
const {
localData,
experimentAndBranchInfo,
totalExperiments,
msgRolloutInfo,
totalRolloutExperiments,
} = await fetchData(platform);

return (
<Dashboard
platform={platform}
experimentAndBranchInfo={experimentAndBranchInfo}
totalExperiments={totalExperiments}
msgRolloutInfo={msgRolloutInfo}
totalRolloutExperiments={totalRolloutExperiments}
/>
);
}
Loading