Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
9847279
feat: bulk import csv and json functionality
Codebmk May 13, 2026
b980810
feat: add reusable file upload component
Codebmk May 13, 2026
df61667
visibility of required asterisk on input field
Codebmk May 13, 2026
537f1da
visibility of required asterisk on select field
Codebmk May 13, 2026
b5588ea
file management
Codebmk May 13, 2026
254ba7e
custom network, categories, tags input fields
Codebmk May 13, 2026
1655584
preview uploaded file components
Codebmk May 13, 2026
0bd6dac
Merge branch 'staging' into ft-bulk-import
Codebmk May 14, 2026
e0a366a
Update-Cohort-Management-Module-to-use-InfoBanners
BwanikaRobert May 25, 2026
8256403
feat(grids): Replace all toast-based feedback in grid management comp…
BwanikaRobert May 25, 2026
2127f4d
fix(grids): await mutateAsync in edit grid details try/catch
BwanikaRobert May 25, 2026
3a779b8
fix: remove deprecated execCommand clipboard fallback and sanitize HT…
BwanikaRobert May 26, 2026
91d34b6
fix: changelog.md according to copilot
BwanikaRobert May 26, 2026
0222d09
fix: sanitize HTML error responses across all paths in getApiErrorMes…
BwanikaRobert May 26, 2026
cb4d90e
refactor(grids): replace magic setTimeout value with named AFTER_DIAL…
BwanikaRobert May 26, 2026
e64f777
update the changelog.md to match the new changes
BwanikaRobert May 26, 2026
f58a335
refactor(getApiErrorMessage): rename sanitize to fallbackIfHtml for c…
BwanikaRobert May 26, 2026
c101221
fix: declare useState and useForm before hooks that reference their s…
BwanikaRobert May 26, 2026
de855f1
refactor(grids): extract useDeferredBanner hook to replace repeated s…
BwanikaRobert May 26, 2026
316fed8
refactor(grids): extract useDeferredBanner hook to replace repeated s…
BwanikaRobert May 26, 2026
bbbda65
fix: guard empty/whitespace error messages and unify generic fallback…
BwanikaRobert May 26, 2026
c7fb264
fix: add missing useEffect in details cars after refactor
BwanikaRobert May 26, 2026
750e371
Update analytics production image tag
github-actions[bot] May 26, 2026
eec75d9
fix: gate posthog analytics events
Mozart299 May 27, 2026
a683740
Merge pull request #3534 from BwanikaRobert/Update-Grid-Management-Mo…
Baalmart May 27, 2026
ed03ef7
Merge pull request #3541 from airqo-platform/fix/posthog-analytics-ga…
Baalmart May 27, 2026
098228a
Merge branch 'staging' into ft-bulk-import
Codebmk May 27, 2026
3e23b61
Update changelog.md
Codebmk May 27, 2026
d442f67
Use banners for bulk import feedback
Codebmk May 27, 2026
9aa8d08
resolve type error
Codebmk May 27, 2026
10648bc
Improve CSV header normalization in import modal
Codebmk May 27, 2026
39c5e65
Handle empty CSV uploads in device import
Codebmk May 27, 2026
42ed6c7
Validate duplicate field mappings in import
Codebmk May 27, 2026
923c2e6
Reset file input and simplify onChange
Codebmk May 27, 2026
45f35f6
Use semantic text-destructive for required asterisks
Codebmk May 27, 2026
016428d
Remove Content-Type header from bulk upload
Codebmk May 27, 2026
d4b5ea4
Merge pull request #3544 from airqo-platform/ft-bulk-import
Baalmart May 27, 2026
69ecf72
Update vertex staging image tag to stage-d4b5ea4a-1779884389
github-actions[bot] May 27, 2026
7c6556d
Merge branch 'staging' into Update-Cohort-Management-Module-to-use-In…
BwanikaRobert May 27, 2026
90ef600
Make page satisfaction banner float and responsive
Codebmk May 27, 2026
34342d9
Update changelog.md
Codebmk May 27, 2026
eda08a5
Make satisfaction banner click-through
Codebmk May 27, 2026
734307e
Move bottom padding from inner container to main
Codebmk May 27, 2026
de228b4
Update page-satisfaction-banner.tsx
Codebmk May 27, 2026
b6fb9d3
Update page-satisfaction-banner.tsx
Codebmk May 27, 2026
b9163f9
Update page-satisfaction-banner.tsx
Codebmk May 27, 2026
e1a4253
Merge pull request #3545 from airqo-platform/hf-fixed-page-satisfacti…
Baalmart May 27, 2026
53eccb1
Update vertex staging image tag to stage-e1a42537-1779908075
github-actions[bot] May 27, 2026
5438f78
refactor(cohorts): replace raw setTimeout banner pattern with useDefe…
BwanikaRobert May 27, 2026
cb35fcc
Update changelog.md to match changes in the cohort files
BwanikaRobert May 27, 2026
2a25994
Merge branch 'staging' into Update-Cohort-Management-Module-to-use-In…
BwanikaRobert May 27, 2026
47b00d8
fix(cohorts): correct invalidateQueries key shape in 3 mutation hooks
BwanikaRobert May 27, 2026
488300a
refactor(cohorts): adopt useDeferredBanner
BwanikaRobert May 27, 2026
43e6bce
Enhance feedback details and authentication handling
OchiengPaul442 May 28, 2026
3d7b2ea
Add screenshot_url and app fields to SubmitFeedbackRequest interface
OchiengPaul442 May 28, 2026
804907a
Refactor feedback metadata handling for improved readability and stru…
OchiengPaul442 May 28, 2026
799327c
refactor: rename useDeferredBanner useBannerWithDelay across all cons…
BwanikaRobert May 28, 2026
3975f01
refactor(devices): migrate raw setTimeout banners to useBannerWithDelay
BwanikaRobert May 28, 2026
1708f63
Implement group switch overlay and enhance user state management for …
OchiengPaul442 May 28, 2026
0f22961
Refactor Toast component to enhance structure and add progress bar fu…
OchiengPaul442 May 28, 2026
4e33dd8
Fix GroupSwitchOverlay to clear pending group switch on invalid date …
OchiengPaul442 May 28, 2026
fdb0eb9
Fix handleGroupSwitch to properly encode organizationSlug in destinat…
OchiengPaul442 May 28, 2026
97e1744
Update changelog.md
Codebmk May 28, 2026
b599537
Merge pull request #3546 from BwanikaRobert/Update-Cohort-Management-…
Baalmart May 28, 2026
aafccf5
Add app filter to feedback list for enhanced filtering options
OchiengPaul442 May 28, 2026
bafe9ba
Update ToastCard component to use rounded-md for improved styling
OchiengPaul442 May 28, 2026
26dda3a
Add authRequired field to device import
Codebmk May 28, 2026
c610871
Merge pull request #3547 from airqo-platform/feedback-update
Baalmart May 28, 2026
ee1c9b5
Update next platform staging image tag to stage-c6108716-1779973112
github-actions[bot] May 28, 2026
f74b8aa
Refactor error handling in ImportDeviceModal to use showBanner for us…
Codebmk May 28, 2026
1c7c72c
Update changelog.md
Codebmk May 28, 2026
a2e7ac3
Enhance ImportDeviceModal to validate authRequired values and display…
Codebmk May 28, 2026
519fb0d
Merge pull request #3550 from airqo-platform/add-auth-required
Baalmart May 28, 2026
3d0d01e
Update vertex staging image tag to stage-519fb0d9-1779974964
github-actions[bot] May 28, 2026
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
2 changes: 1 addition & 1 deletion k8s/platform/k8s-aks/airqo-platform/values-prod.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
replicaCount: 1
image:
repository: airqoacr.azurecr.io/airqo-next-platform
tag: prod-af0ab60b-1779433383
tag: prod-7a79b32d-1779824819
pullPolicy: IfNotPresent
imagePullSecrets: []
nameOverride: ''
Expand Down
2 changes: 1 addition & 1 deletion k8s/platform/k8s-aks/airqo-platform/values-stage.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
replicaCount: 1
image:
repository: airqoacr.azurecr.io/airqo-stage-next-platform
tag: stage-914339bc-1779771489
tag: stage-c6108716-1779973112
pullPolicy: IfNotPresent
imagePullSecrets: []
nameOverride: ''
Expand Down
2 changes: 1 addition & 1 deletion k8s/vertex/k8s-aks/airqo-vertex/values-stage.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
replicaCount: 2
image:
repository: airqoacr.azurecr.io/airqo-stage-vertex
tag: stage-46aa9de2-1779519609
tag: stage-519fb0d9-1779974964
pullPolicy: IfNotPresent
imagePullSecrets: []
nameOverride: ''
Expand Down
2 changes: 1 addition & 1 deletion src/mobile/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ void main() async {
final postHogConfig = PostHogConfig(postHogApiKey);
postHogConfig.host = postHogHost;
postHogConfig.debug = !kReleaseMode;
postHogConfig.captureApplicationLifecycleEvents = true;
postHogConfig.captureApplicationLifecycleEvents = false;
postHogConfig.personProfiles = PostHogPersonProfiles.always;
try {
await Posthog().setup(postHogConfig);
Expand Down
6 changes: 3 additions & 3 deletions src/mobile/lib/src/app/auth/bloc/auth_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> with UiLoggy {
await authRepository.loginWithEmailAndPassword(
event.username, event.password);

await AnalyticsService().trackUserLoggedIn();
final userId =
await AuthHelper.getCurrentUserId(suppressGuestWarning: true);
if (userId != null) {
Expand All @@ -97,6 +96,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> with UiLoggy {
userProperties: {'email': event.username},
);
}
await AnalyticsService().trackUserLoggedIn();
GlobalAuthManager.instance.resetSessionExpiredGuard();
emit(AuthLoaded(AuthPurpose.login));
} catch (e) {
Expand All @@ -119,7 +119,6 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> with UiLoggy {
emit(AuthLoading());
try {
await authRepository.registerWithEmailAndPassword(event.model);
await AnalyticsService().trackUserRegistered();
final userId =
await AuthHelper.getCurrentUserId(suppressGuestWarning: true);
if (userId != null) {
Expand All @@ -128,6 +127,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> with UiLoggy {
userProperties: {'email': event.model.email ?? ''},
);
}
await AnalyticsService().trackUserRegistered();
GlobalAuthManager.instance.resetSessionExpiredGuard();
emit(AuthLoaded(AuthPurpose.register));
} catch (e) {
Expand Down Expand Up @@ -198,12 +198,12 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> with UiLoggy {
emit(AuthLoading());
try {
await socialAuthRepository.loginWithProvider(event.provider);
await AnalyticsService().trackUserLoggedIn(method: event.provider);
final userId =
await AuthHelper.getCurrentUserId(suppressGuestWarning: true);
if (userId != null) {
await AnalyticsService().setUserIdentity(userId: userId);
}
await AnalyticsService().trackUserLoggedIn(method: event.provider);
GlobalAuthManager.instance.resetSessionExpiredGuard();
loggy.info('OAuth login successful via ${event.provider}');
emit(AuthLoaded(AuthPurpose.login));
Expand Down
4 changes: 4 additions & 0 deletions src/mobile/lib/src/app/shared/services/analytics_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ class AnalyticsService with UiLoggy {
String eventName, {
Map<String, Object>? properties,
}) async {
if (!FeatureFlagService.instance.isAnalyticsEnabled) {
return;
}

try {
await Posthog().capture(
eventName: eventName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class FeatureFlagService with UiLoggy {

bool isEnabled(AppFeatureFlag flag) => _flags[flag] ?? false;

bool get isAnalyticsEnabled => isEnabled(AppFeatureFlag.researchMode);

Future<void> reloadFlags() async {
try {
await Posthog().reloadFeatureFlags();
Expand Down
2 changes: 2 additions & 0 deletions src/platform/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
"version": "3.7.0",
"private": true,
"scripts": {
"clean:next": "node -e \"const fs=require('node:fs'); try { fs.rmSync('.next',{recursive:true,force:true,maxRetries:10,retryDelay:200}); } catch (error) { if (error && typeof error === 'object' && 'code' in error && (error.code === 'EPERM' || error.code === 'EBUSY')) { console.warn('[clean:next] Skipping .next cleanup because the directory is locked:', error.code); } else { throw error; } }\"",
"dev": "next dev",
"build": "next build",
"prebuild": "yarn clean:next",
"postbuild": "node -e \"const fs=require('node:fs'); const path=require('node:path'); const projectRoot=process.cwd(); const standaloneRoot=path.join(projectRoot,'.next','standalone'); const publicSource=path.join(projectRoot,'public'); const publicTarget=path.join(standaloneRoot,'public'); const staticSource=path.join(projectRoot,'.next','static'); const staticTarget=path.join(standaloneRoot,'.next','static'); const copyDirectory=(source,target)=>{ if(!fs.existsSync(source)) return false; fs.mkdirSync(path.dirname(target),{recursive:true}); fs.rmSync(target,{recursive:true,force:true}); fs.cpSync(source,target,{recursive:true}); return true; }; if(!fs.existsSync(standaloneRoot)){ throw new Error(`Standalone output not found at ${standaloneRoot}. Run 'yarn build' first.`); } copyDirectory(publicSource, publicTarget); copyDirectory(staticSource, staticTarget);\"",
"start": "node -e \"const { loadEnvConfig } = require('@next/env'); loadEnvConfig(process.cwd()); process.env.HOSTNAME='localhost'; require('./.next/standalone/server.js')\"",
"lint": "next lint",
Expand Down
Loading
Loading