Skip to content

Commit

Permalink
feat: dont record participant progress for launched studies in test mode
Browse files Browse the repository at this point in the history
  • Loading branch information
janukobytsch committed Aug 22, 2022
1 parent 1a09913 commit 2dc6a8c
Show file tree
Hide file tree
Showing 16 changed files with 71 additions and 46 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/firebase-hosting-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: "Bootstrap Workspace"
run: melos bootstrap
- name: "Build Web"
run: melos run build:web --no-select
run: melos run build:web --no-select --dart-define=ENV=.env.staging
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/firebase-hosting-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: "Bootstrap Workspace"
run: melos bootstrap
- name: "Build Web"
run: melos run build:web --no-select
run: melos run build:web --no-select --dart-define=ENV=.env.staging
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
Expand Down
7 changes: 7 additions & 0 deletions app/lib/models/app_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ class AppState {
bool isPreview = false;
bool previewInit = false;

/// Flag indicating whether the participant's progress should be tracked
///
/// We always track the participant's progress except when the study is
/// being viewed in test/preview mode while already launched (to avoid
/// mixing results from test users with actual participants)
bool get trackParticipantProgress => !(isPreview && selectedStudy.isRunning);

/// Context used for FlutterLocalNotificationsPlugin
BuildContext context;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ class CheckmarkTaskWidget extends StatefulWidget {

class _CheckmarkTaskWidgetState extends State<CheckmarkTaskWidget> {
Future<void> _handleCompletion(BuildContext context, Future<void> animation) async {
final model = context.read<AppState>();
final activeStudy = model.activeSubject;
final state = context.read<AppState>();
final activeStudy = state.activeSubject;
try {
await activeStudy.addResult<bool>(taskId: widget.task.id, result: true);
if (state.trackParticipantProgress) {
await activeStudy.addResult<bool>(taskId: widget.task.id, result: true);
}
await animation;
if (!mounted) return;
Navigator.pop(context, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ class _QuestionnaireTaskWidgetState extends State<QuestionnaireTaskWidget> {
dynamic response;

Future<void> _addQuestionnaireResult<T>(T response, BuildContext context) async {
final activeStudy = context.read<AppState>().activeSubject;
final state = context.read<AppState>();
final activeStudy = state.activeSubject;
try {
await activeStudy.addResult<T>(taskId: widget.task.id, result: response);
if (state.trackParticipantProgress) {
await activeStudy.addResult<bool>(taskId: widget.task.id, result: true);
}
if (!mounted) return;
Navigator.pop(context, true);
} on PostgrestError {
Expand Down
18 changes: 13 additions & 5 deletions core/lib/src/env/env.dart
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
import 'package:supabase/supabase.dart';

late SupabaseClient client;
late String supabaseUrl;
late String supabaseAnonKey;
late String? appUrl;
late String? projectGeneratorUrl;
late final SupabaseClient client;
late final String supabaseUrl;
late final String supabaseAnonKey;
late final String? appUrl;
late final String? projectGeneratorUrl;
late final String appDeepLink;
late final String designerDeepLink;
late final String authRedirectToUrl;

void setEnv(
String envSupabaseUrl,
String envSupabaseAnonKey, {
String? envAppUrl,
String? envProjectGeneratorUrl,
SupabaseClient? supabaseClient,
String? envAppDeepLink,
String? envDesignerDeepLink,
}) {
supabaseUrl = envSupabaseUrl;
supabaseAnonKey = envSupabaseAnonKey;
projectGeneratorUrl = envProjectGeneratorUrl;
appUrl = envAppUrl;
client = supabaseClient ?? SupabaseClient(supabaseUrl, supabaseAnonKey);
appDeepLink = envAppDeepLink ?? '';
designerDeepLink = envDesignerDeepLink ?? '';
authRedirectToUrl = designerDeepLink;
}
20 changes: 20 additions & 0 deletions core/lib/src/models/tables/study.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import '../models.dart';

part 'study.g.dart';

enum StudyStatus { draft, running, closed }

enum Participation { open, invite }

enum ResultSharing { public, private, organization }
Expand Down Expand Up @@ -202,4 +204,22 @@ class Study extends SupabaseObjectFunctions<Study> {
];
return const ListToCsvConverter().convert(resultsTable);
}

// - Status

StudyStatus get status {
if (published) {
return StudyStatus.running;
}
return StudyStatus.draft;
}

bool get isDraft => status == StudyStatus.draft;
bool get isRunning => status == StudyStatus.running;
// TODO: missing flag to indicate that study is completed & enrollment closed
bool get isClosed => false;

bool isReadonly(User user) {
return status != StudyStatus.draft || !canEdit(user);
}
}
4 changes: 2 additions & 2 deletions designer/lib/models/app_state.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:studyu_core/core.dart';
import 'package:studyu_flutter_common/studyu_flutter_common.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:studyu_core/env.dart' as env;

enum DesignerPage {
about,
Expand Down Expand Up @@ -156,7 +156,7 @@ class AppState extends ChangeNotifier {

Future<void> signInWithProvider(Provider provider, String scopes) async {
await Supabase.instance.client.auth
.signInWithProvider(provider, options: AuthOptions(scopes: scopes, redirectTo: authRedirectToUrl));
.signInWithProvider(provider, options: AuthOptions(scopes: scopes, redirectTo: env.authRedirectToUrl));
}

Future<void> signOut() async {
Expand Down
18 changes: 0 additions & 18 deletions designer_v2/lib/domain/study.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'package:studyu_core/core.dart';
import 'package:studyu_designer_v2/localization/string_hardcoded.dart';
import 'package:studyu_core/core.dart' as core;
import 'package:studyu_designer_v2/utils/extensions.dart';
import 'package:supabase_flutter/supabase_flutter.dart' as sb;

enum StudyActionType {
edit,
Expand All @@ -13,26 +12,9 @@ enum StudyActionType {
delete
}

// TODO: Add status field to core package domain model
enum StudyStatus { draft, running, closed }

typedef StudyID = String;
typedef MeasurementID = String;

extension StudyStatusX on core.Study {
StudyStatus get status {
// TODO: missing a flag to indicate a study has been completed & participation is closed
if (published) {
return StudyStatus.running;
}
return StudyStatus.draft;
}

bool isReadonly(sb.User user) {
return status != StudyStatus.draft || !canEdit(user);
}
}

typedef InterventionProvider = Intervention? Function(String id);

extension StudyHelpers on core.Study {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:studyu_core/core.dart';
import 'package:studyu_designer_v2/features/study/study_base_state.dart';
import 'package:studyu_designer_v2/repositories/model_repository.dart';
import 'package:studyu_flutter_common/studyu_flutter_common.dart';
import 'package:studyu_core/env.dart' as env;

class StudyTestControllerState extends StudyControllerBaseState {
const StudyTestControllerState({
Expand All @@ -18,7 +18,7 @@ class StudyTestControllerState extends StudyControllerBaseState {
if (!canTest || !study.hasValue) {
return '';
}
String appUrl = "$appDeepLink";
String appUrl = env.appDeepLink;
appUrl += "?mode=preview&session=${Uri.encodeComponent(serializedSession)}";
appUrl += "&studyid=$studyId";
return appUrl;
Expand Down
4 changes: 2 additions & 2 deletions designer_v2/lib/repositories/auth_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import 'package:studyu_designer_v2/services/shared_prefs.dart';
import 'package:studyu_designer_v2/utils/behaviour_subject.dart';
import 'package:studyu_designer_v2/utils/debug_print.dart';
import 'package:studyu_designer_v2/utils/exceptions.dart';
import 'package:studyu_flutter_common/studyu_flutter_common.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart' as riverpod;
import 'package:studyu_core/env.dart' as env;

abstract class IAuthRepository extends IAppDelegate {
// - Authentication
Expand Down Expand Up @@ -135,7 +135,7 @@ class AuthRepository implements IAuthRepository {
@override
Future<bool> resetPasswordForEmail({required String email}) async {
final res = await authClient.api.resetPasswordForEmail(email,
options: AuthOptions(redirectTo: authRedirectToUrl));
options: AuthOptions(redirectTo: env.authRedirectToUrl));
if (res.error != null) {
throw StudyUException(res.error!.message);
}
Expand Down
4 changes: 3 additions & 1 deletion flutter_common/lib/envs/.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
STUDYU_SUPABASE_URL=https://efeapuvwaxtxnlkzlajv.supabase.co
STUDYU_SUPABASE_PUBLIC_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlhdCI6MTYyNTUwODMyOCwiZXhwIjoxOTQxMDg0MzI4fQ.PUirsx5Zzhj3akaStc5Djid0aAVza3ELoZ5XUTqM91A
STUDYU_PROJECT_GENERATOR_URL=https://studyu-project-generator-2zro3rzera-ew.a.run.app
STUDYU_APP_URL="https://studyu-app.web.app/#/"
STUDYU_APP_URL="https://studyu-app.web.app/#/"
STUDYU_APP_DEEPLINK_URL=
STUDYU_DESIGNER_DEEPLINK_URL=
4 changes: 3 additions & 1 deletion flutter_common/lib/envs/.env.local
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
STUDYU_SUPABASE_URL=https://efeapuvwaxtxnlkzlajv.supabase.co
STUDYU_SUPABASE_PUBLIC_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlhdCI6MTYyNTUwODMyOCwiZXhwIjoxOTQxMDg0MzI4fQ.PUirsx5Zzhj3akaStc5Djid0aAVza3ELoZ5XUTqM91A
STUDYU_PROJECT_GENERATOR_URL=http://localhost:8080
STUDYU_APP_URL="http://localhost:3001/#/"
STUDYU_APP_URL="http://localhost:3001/#/"
STUDYU_APP_DEEPLINK_URL=http://localhost:3001/#/
STUDYU_DESIGNER_DEEPLINK_URL=
2 changes: 2 additions & 0 deletions flutter_common/lib/envs/.env.selfhost
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ STUDYU_SUPABASE_URL=http://localhost:8000
STUDYU_SUPABASE_PUBLIC_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE
STUDYU_PROJECT_GENERATOR_URL=http://localhost:8080
STUDYU_APP_URL=http://localhost:8081
STUDYU_APP_DEEPLINK_URL=http://localhost:8081
STUDYU_DESIGNER_DEEPLINK_URL=
4 changes: 3 additions & 1 deletion flutter_common/lib/envs/.env.staging
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
STUDYU_SUPABASE_URL=https://rzxnjlfzycwnaayubbeo.supabase.co
STUDYU_SUPABASE_PUBLIC_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InJ6eG5qbGZ6eWN3bmFheXViYmVvIiwicm9sZSI6ImFub24iLCJpYXQiOjE2NTY1MTM1MTcsImV4cCI6MTk3MjA4OTUxN30.OGqe_zCQIUImHc5YwN5S0PljMTdhT4Jtb8VK9eGtE-4
STUDYU_PROJECT_GENERATOR_URL=https://studyu-project-generator-2zro3rzera-ew.a.run.app
STUDYU_APP_URL="https://studyu-app.web.app/#/"
STUDYU_APP_URL="https://app2.studyu.health/"
STUDYU_APP_DEEPLINK_URL=https://app2.studyu.health/
STUDYU_DESIGNER_DEEPLINK_URL=https://designer2.studyu.health/
9 changes: 2 additions & 7 deletions flutter_common/lib/src/utils/env_loader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,6 @@ String envFilePath() {
return env.isNotEmpty ? '$envsAssetPath/$env' : '$envsAssetPath/.env';
}

const appDeepLink = 'https://studyu-app-v2.web.app';
const designerDeepLink = 'https://studyu-designer-v2.web.app';

// GoTrue redirectTo strips /#/ from URL, therefore we need to use the default set in supabase
//String? authRedirectToUrl = kIsWeb ? null : designerDeepLink;
String authRedirectToUrl = designerDeepLink;

Future<void> loadEnv() async {
await dotenv.load(fileName: envFilePath());
final supabaseUrl = dotenv.env['STUDYU_SUPABASE_URL'];
Expand All @@ -34,5 +27,7 @@ Future<void> loadEnv() async {
envAppUrl: dotenv.env['STUDYU_APP_URL'],
envProjectGeneratorUrl: dotenv.env['STUDYU_PROJECT_GENERATOR_URL'],
supabaseClient: Supabase.instance.client,
envAppDeepLink: dotenv.env['STUDYU_APP_DEEPLINK_URL'],
envDesignerDeepLink: dotenv.env['STUDYU_DESIGNER_DEEPLINK_URL'],
);
}

0 comments on commit 2dc6a8c

Please sign in to comment.