Skip to content

Fix/better feature group nav #1216

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
8 changes: 8 additions & 0 deletions admin-frontend/open_admin_app/lib/api/client_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,10 @@ class ManagementRepositoryClientBloc implements Bloc {
}
}

void setCurrentEnvId(String? eaid) {
streamValley.currentEnvId = eaid;
}

void setCurrentAid(String? aid) {
streamValley.currentAppId = aid;
}
Expand All @@ -453,6 +457,10 @@ class ManagementRepositoryClientBloc implements Bloc {
return streamValley.currentAppId;
}

String? getCurrentEnvId() {
return streamValley.currentEnvId;
}

void setPerson(Person p) {
prefs.setEmail(p.email!);
// print("set person $p and org $organization");
Expand Down
66 changes: 52 additions & 14 deletions admin-frontend/open_admin_app/lib/common/fh_shared_prefs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ abstract class FHSharedPrefsContract {
Future<String?> currentPortfolioId();
Future<void> setCurrentPortfolioId(String? id);
Future<String?> currentApplicationId();
Future<String?> currentEnvId();
Future<void> setCurrentApplicationId(String? id);
Future<void> setPortfolioAndApplicationId(String? portfolioId, String? applicationId);
Future<void> setCurrentEnvId(String? id);

Future<void> setPortfolioAndApplicationId(
String? portfolioId, String? applicationId);
// store the portfolio and return the application id
Future<Application?> setPortfolio(Portfolio portfolio);
}
Expand All @@ -32,10 +36,15 @@ class FHSharedPrefs extends FHSharedPrefsContract {
}

@override
Future<String?> currentApplicationId() async => await _prefs?.currentApplicationId();
Future<String?> currentApplicationId() async =>
await _prefs?.currentApplicationId();

@override
Future<String?> currentEnvId() async => await _prefs?.currentEnvId();

@override
Future<String?> currentPortfolioId() async => await _prefs?.currentPortfolioId();
Future<String?> currentPortfolioId() async =>
await _prefs?.currentPortfolioId();

@override
Future<bool?> getBool(String key) async => await _prefs?.getBool(key);
Expand All @@ -47,37 +56,50 @@ class FHSharedPrefs extends FHSharedPrefsContract {
Future<int?> getInt(String key) async => await _prefs?.getInt(key);

@override
Future<void> saveBool(String key, bool value) async => await _prefs?.saveBool(key, value);
Future<void> saveBool(String key, bool value) async =>
await _prefs?.saveBool(key, value);

@override
Future<void> saveInt(String key, int value) async => await _prefs?.saveInt(key, value);
Future<void> saveInt(String key, int value) async =>
await _prefs?.saveInt(key, value);

@override
Future<void> setCurrentApplicationId(String? id) async => await _prefs?.setCurrentApplicationId(id);
Future<void> setCurrentApplicationId(String? id) async =>
await _prefs?.setCurrentApplicationId(id);

@override
Future<void> setCurrentPortfolioId(String? id) async => await _prefs?.setCurrentPortfolioId(id);
Future<void> setCurrentPortfolioId(String? id) async =>
await _prefs?.setCurrentPortfolioId(id);

@override
Future<void> setEmail(String value) async => await _prefs?.setEmail(value);

@override
Future<void> setPortfolioAndApplicationId(String? portfolioId, String? applicationId) async => await _prefs?.setPortfolioAndApplicationId(portfolioId, applicationId);
Future<void> setPortfolioAndApplicationId(
String? portfolioId, String? applicationId) async =>
await _prefs?.setPortfolioAndApplicationId(portfolioId, applicationId);

@override
Future<Application?> setPortfolio(Portfolio portfolio) async => await _prefs?.setPortfolio(portfolio);
Future<Application?> setPortfolio(Portfolio portfolio) async =>
await _prefs?.setPortfolio(portfolio);

void saveCurrentRoute(String json) => _prefs?.saveCurrentRoute(json);

@override
Future<String?> getString(String key) async => await _prefs?.getString(key);

@override
Future<void> saveString(String key, String? value) async => _prefs?.saveString(key, value);
Future<void> saveString(String key, String? value) async =>
_prefs?.saveString(key, value);

@override
Future<void> setCurrentEnvId(String? id) async =>
await _prefs?.setCurrentEnvId(id);
}

const _keyEmail = 'lastUsername';
const _keyApplicationId = 'currentAid';
const _keyEnvId = 'currentEid';
const _keyPortfolioId = 'currentPid';
const _keyCurrentRoute = 'current-route';

Expand Down Expand Up @@ -132,13 +154,25 @@ class _FHSharedPrefs extends FHSharedPrefsContract {
await _prefs.setBool(key, value);
}

@override
Future<String?> currentEnvId() async => _prefs.getString(_keyEnvId);

@override
Future<String?> currentApplicationId() async =>
_prefs.getString(_keyApplicationId);
_prefs.getString(_keyApplicationId);

@override
Future<String?> currentPortfolioId() async =>
_prefs.getString(_keyPortfolioId);

@override
Future<String?> currentPortfolioId() async => _prefs.getString(_keyPortfolioId);
Future<void> setCurrentEnvId(String? id) async {
if (id == null) {
await _prefs.remove(_keyEnvId);
} else {
await _prefs.setString(_keyEnvId, id);
}
}

@override
Future<void> setCurrentApplicationId(String? id) async {
Expand All @@ -159,7 +193,8 @@ class _FHSharedPrefs extends FHSharedPrefsContract {
}

@override
Future<void> setPortfolioAndApplicationId(String? portfolioId, String? applicationId) async {
Future<void> setPortfolioAndApplicationId(
String? portfolioId, String? applicationId) async {
await setCurrentPortfolioId(portfolioId);
await setCurrentApplicationId(applicationId);
}
Expand All @@ -174,7 +209,10 @@ class _FHSharedPrefs extends FHSharedPrefsContract {
}

final appId = await currentApplicationId();
final app = appId == null ? portfolio.applications[0] : portfolio.applications.firstWhere((a) => a.id == appId, orElse: () => portfolio.applications[0]);
final app = appId == null
? portfolio.applications[0]
: portfolio.applications.firstWhere((a) => a.id == appId,
orElse: () => portfolio.applications[0]);

if (app.id != appId) {
await setCurrentApplicationId(app.id);
Expand Down
50 changes: 40 additions & 10 deletions admin-frontend/open_admin_app/lib/common/stream_valley.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,13 @@ typedef FindApplicationsFunc = Future<List<Application>> Function(
final _log = Logger('stream-valley');

final ReleasedPortfolio nullPortfolio = ReleasedPortfolio(
portfolio: Portfolio(name: 'null-portfolio', id: '', description: '', version: -1),
portfolio:
Portfolio(name: 'null-portfolio', id: '', description: '', version: -1),
currentPortfolioOrSuperAdmin: false);

final ReleasedApplication nullApplication =
ReleasedApplication(application: Application(name: 'null-app', id: '', version: -1, portfolioId: ''));
final ReleasedApplication nullApplication = ReleasedApplication(
application:
Application(name: 'null-app', id: '', version: -1, portfolioId: ''));

class StreamValley {
late ManagementRepositoryClientBloc mrClient;
Expand Down Expand Up @@ -79,12 +81,17 @@ class StreamValley {
Stream<List<WebhookTypeDetail>?> get webhookTypeStream =>
_webhookTypesSource.stream;
final _currentAppSource = BehaviorSubject.seeded(nullApplication);
final _currentEnvIdSource = BehaviorSubject<String?>();

String? get currentAppId => _currentAppSource.value.isNull() ? null : _currentAppSource.value.application.id;
String? get currentAppId => _currentAppSource.value.isNull()
? null
: _currentAppSource.value.application.id;
String? get currentEnvId => _currentEnvIdSource.valueOrNull;

Stream<bool> get rocketTrigger => _rocketTriggerSource.stream;
Stream<String?> get currentAppIdStream => _currentAppSource.stream
.map((app) => app.isNull() ? null : app.application.id);
Stream<String?> get currentEnvIdStream => _currentEnvIdSource.stream;
final _currentPortfolioApplicationsSource =
BehaviorSubject<List<Application>>.seeded([]);
final _currentPortfolioGroupsSource = BehaviorSubject<List<Group>>.seeded([]);
Expand All @@ -105,7 +112,8 @@ class StreamValley {
? _currentPortfolioSource.value
: nullPortfolio;

String? get currentPortfolioId => currentPortfolio.isNull() ? null : currentPortfolio.portfolio.id;
String? get currentPortfolioId =>
currentPortfolio.isNull() ? null : currentPortfolio.portfolio.id;

final _globalRefresherSource = BehaviorSubject<String?>();

Expand Down Expand Up @@ -140,15 +148,20 @@ class StreamValley {

// the portfolio has changed and the app isn't in the portfolio
final appId = await prefs.currentApplicationId();
final envId = await prefs.currentEnvId();
_currentEnvIdSource.add(envId);
if (_currentAppSource.hasValue &&
!portfolioUpdate.portfolio.applications
.any((app) => app.id == currentAppId || app.id == appId)) {
_log.fine(
"resetting appid here as $currentAppId not in ${portfolioUpdate.portfolio.applications.map((e) => e.id)}");
"resetting appid and envId here as $currentAppId not in ${portfolioUpdate.portfolio.applications.map((e) => e.id)}");
if (portfolioUpdate.portfolio.applications.isEmpty) {
currentAppId = null;
currentEnvId = null;
} else {
currentAppId = portfolioUpdate.portfolio.applications.first.id;
currentEnvId = portfolioUpdate
.portfolio.applications.first.environments.first.id;
}
}
}
Expand All @@ -173,6 +186,18 @@ class StreamValley {

bool get hasCurrentPortfolio => currentPortfolio != nullPortfolio;

set currentEnvId(String? currentEnvId) {
if (currentEnvId != _currentEnvIdSource.valueOrNull) {
_log.fine("Env ID set to $currentEnvId");
prefs.setCurrentEnvId(currentEnvId);
_currentEnvIdSource.add(currentEnvId);

if (currentEnvId == null) {
_currentEnvIdSource.add(null);
}
}
}

set apiClient(ManagementRepositoryClientBloc mrClient) {
this.mrClient = mrClient;
// print("reset permissions client");
Expand Down Expand Up @@ -218,6 +243,9 @@ class StreamValley {
if (!_currentAppSource.value.isNull()) {
if (_currentApplicationEnvironmentsSource.hasListener) {
getCurrentApplicationEnvironments();
prefs.setCurrentEnvId(
null); // unset current env ID since the application has changed
_currentEnvIdSource.add(null);
}
}
}
Expand All @@ -241,7 +269,7 @@ class StreamValley {
}

Future<void> _portfolioChanged(Portfolio found) async {
_log.fine('Accepted portfolio id change, triggering');
_log.fine('Accepted portfolio id change');

final app = await prefs.setPortfolio(found);
_currentPortfolioSource.add(ReleasedPortfolio(
Expand All @@ -252,13 +280,15 @@ class StreamValley {
_routeCheckPortfolioSource.add(found);

if (currentAppId != app?.id) {
_log.fine("setting to ${app?.id}");
_log.fine("Setting App ID to ${app?.id} as a result of portfolio change");
currentAppId = app?.id;
}

_currentEnvIdSource.add(null);
}

Stream<String?> get currentPortfolioIdStream =>
_currentPortfolioSource.stream.map((p) => p.isNull() ? null : p.portfolio.id);
Stream<String?> get currentPortfolioIdStream => _currentPortfolioSource.stream
.map((p) => p.isNull() ? null : p.portfolio.id);

Stream<ReleasedApplication> get currentAppStream => _currentAppSource.stream;

Expand Down
29 changes: 29 additions & 0 deletions admin-frontend/open_admin_app/lib/config/route_handlers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'package:open_admin_app/routes/create_user_route.dart';
import 'package:open_admin_app/routes/edit_admin_service_account_route.dart';
import 'package:open_admin_app/routes/edit_application_strategy_route.dart';
import 'package:open_admin_app/routes/edit_user_route.dart';
import 'package:open_admin_app/routes/feature_group_settings_route.dart';
import 'package:open_admin_app/routes/feature_groups_route.dart';
import 'package:open_admin_app/routes/features_overview_route.dart';
import 'package:open_admin_app/routes/home_route.dart';
Expand All @@ -31,6 +32,7 @@ import 'package:open_admin_app/widgets/application-strategies/edit_application_s
import 'package:open_admin_app/widgets/apps/apps_bloc.dart';
import 'package:open_admin_app/widgets/apps/manage_app_bloc.dart';
import 'package:open_admin_app/widgets/apps/manage_service_accounts_bloc.dart';
import 'package:open_admin_app/widgets/feature-groups/feature_group_bloc.dart';
import 'package:open_admin_app/widgets/feature-groups/feature_groups_bloc.dart';
import 'package:open_admin_app/widgets/features/per_application_features_bloc.dart';
import 'package:open_admin_app/widgets/group/group_bloc.dart';
Expand Down Expand Up @@ -270,6 +272,33 @@ class RouteCreator {
}
}

Widget editFeatureGroupStrategyValues(mrBloc,
{Map<String, List<String?>> params = const {}}) {
final fgBloc = FeatureGroupsBloc(mrBloc);
if (params['appid'] == null ||
params['appid']!.elementAt(0) == null ||
params['groupid'] == null ||
params['groupid']!.elementAt(0) == null ||
params['envid'] == null ||
params['envid']!.elementAt(0) == null) {
return SizedBox(
height: 600,
child: notFound(mrBloc),
);
} else {
return BlocProvider<FeatureGroupsBloc>(
creator: (BuildContext context, BlocCreatorBag bag) => fgBloc,
child: BlocProvider<FeatureGroupBloc>(
creator: (context, bag) => FeatureGroupBloc(
fgBloc,
params['groupid']!.elementAt(0) ?? "",
params['envid']!.elementAt(0) ?? "",
params['appid']!.elementAt(0) ?? ""),
child: const FeatureGroupSettingsRoute(),
));
}
}

Widget serviceEnvsHandler(ManagementRepositoryClientBloc mrBloc,
{Map<String, List<String>>? params}) {
return BlocProvider<ServiceAccountEnvBloc>(
Expand Down
4 changes: 4 additions & 0 deletions admin-frontend/open_admin_app/lib/config/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ class Routes {
router.define('/feature-groups',
routeSlots: [RouteSlot.portfolio],
handler: handleRouteChangeRequest(routeCreator.featureGroups));
router.define('/edit-feature-group-strategy-values',
routeSlots: [RouteSlot.portfolio],
handler: handleRouteChangeRequest(
routeCreator.editFeatureGroupStrategyValues));
// NEVER EVER use /features as that is reserved for use by the Edge app
router.define(routeNameFeatureDashboard,
routeSlots: [RouteSlot.portfolio],
Expand Down
Loading
Loading