You've already forked immich
mirror of
https://github.com/immich-app/immich.git
synced 2025-07-16 07:24:40 +02:00
feat(web): improved user onboarding (#18782)
* wip * added user metadata key * wip * restructure onboarding system and add initial locale * update language card and fix translation updating * remove prints * new card formattings * fix cursed unmount effect * add OAuth route onboarding * remove required admin auth for onboarding * delete the hotwire button * update open-api files * delete import * fix failing oauth onboarding fields * fix e2e test * fix web e2e test * add onboarding to user registration e2e test * remove todo this was a holdover during dev and didn't get deleted * fix server small tests * use onDestroy to save settings rather than a bind:this * change to false for isOnboarded * fix other auth small test * provide type annotation in user factory metadata field * remove onboardingCompelted from UserDto * move translations to onboarding steps array and mark as derived so they update * break language selector out into its own component as per @danieldietzler suggestion * remove hello header on card * fix flixkering on server privacy card * label/id fixes * openapi --------- Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
10
mobile/openapi/lib/model/login_response_dto.dart
generated
10
mobile/openapi/lib/model/login_response_dto.dart
generated
@ -15,6 +15,7 @@ class LoginResponseDto {
|
||||
LoginResponseDto({
|
||||
required this.accessToken,
|
||||
required this.isAdmin,
|
||||
required this.isOnboarded,
|
||||
required this.name,
|
||||
required this.profileImagePath,
|
||||
required this.shouldChangePassword,
|
||||
@ -26,6 +27,8 @@ class LoginResponseDto {
|
||||
|
||||
bool isAdmin;
|
||||
|
||||
bool isOnboarded;
|
||||
|
||||
String name;
|
||||
|
||||
String profileImagePath;
|
||||
@ -40,6 +43,7 @@ class LoginResponseDto {
|
||||
bool operator ==(Object other) => identical(this, other) || other is LoginResponseDto &&
|
||||
other.accessToken == accessToken &&
|
||||
other.isAdmin == isAdmin &&
|
||||
other.isOnboarded == isOnboarded &&
|
||||
other.name == name &&
|
||||
other.profileImagePath == profileImagePath &&
|
||||
other.shouldChangePassword == shouldChangePassword &&
|
||||
@ -51,6 +55,7 @@ class LoginResponseDto {
|
||||
// ignore: unnecessary_parenthesis
|
||||
(accessToken.hashCode) +
|
||||
(isAdmin.hashCode) +
|
||||
(isOnboarded.hashCode) +
|
||||
(name.hashCode) +
|
||||
(profileImagePath.hashCode) +
|
||||
(shouldChangePassword.hashCode) +
|
||||
@ -58,12 +63,13 @@ class LoginResponseDto {
|
||||
(userId.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'LoginResponseDto[accessToken=$accessToken, isAdmin=$isAdmin, name=$name, profileImagePath=$profileImagePath, shouldChangePassword=$shouldChangePassword, userEmail=$userEmail, userId=$userId]';
|
||||
String toString() => 'LoginResponseDto[accessToken=$accessToken, isAdmin=$isAdmin, isOnboarded=$isOnboarded, name=$name, profileImagePath=$profileImagePath, shouldChangePassword=$shouldChangePassword, userEmail=$userEmail, userId=$userId]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'accessToken'] = this.accessToken;
|
||||
json[r'isAdmin'] = this.isAdmin;
|
||||
json[r'isOnboarded'] = this.isOnboarded;
|
||||
json[r'name'] = this.name;
|
||||
json[r'profileImagePath'] = this.profileImagePath;
|
||||
json[r'shouldChangePassword'] = this.shouldChangePassword;
|
||||
@ -83,6 +89,7 @@ class LoginResponseDto {
|
||||
return LoginResponseDto(
|
||||
accessToken: mapValueOfType<String>(json, r'accessToken')!,
|
||||
isAdmin: mapValueOfType<bool>(json, r'isAdmin')!,
|
||||
isOnboarded: mapValueOfType<bool>(json, r'isOnboarded')!,
|
||||
name: mapValueOfType<String>(json, r'name')!,
|
||||
profileImagePath: mapValueOfType<String>(json, r'profileImagePath')!,
|
||||
shouldChangePassword: mapValueOfType<bool>(json, r'shouldChangePassword')!,
|
||||
@ -137,6 +144,7 @@ class LoginResponseDto {
|
||||
static const requiredKeys = <String>{
|
||||
'accessToken',
|
||||
'isAdmin',
|
||||
'isOnboarded',
|
||||
'name',
|
||||
'profileImagePath',
|
||||
'shouldChangePassword',
|
||||
|
99
mobile/openapi/lib/model/onboarding_dto.dart
generated
Normal file
99
mobile/openapi/lib/model/onboarding_dto.dart
generated
Normal file
@ -0,0 +1,99 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class OnboardingDto {
|
||||
/// Returns a new [OnboardingDto] instance.
|
||||
OnboardingDto({
|
||||
required this.isOnboarded,
|
||||
});
|
||||
|
||||
bool isOnboarded;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is OnboardingDto &&
|
||||
other.isOnboarded == isOnboarded;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(isOnboarded.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'OnboardingDto[isOnboarded=$isOnboarded]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'isOnboarded'] = this.isOnboarded;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [OnboardingDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static OnboardingDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "OnboardingDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return OnboardingDto(
|
||||
isOnboarded: mapValueOfType<bool>(json, r'isOnboarded')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<OnboardingDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <OnboardingDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = OnboardingDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, OnboardingDto> mapFromJson(dynamic json) {
|
||||
final map = <String, OnboardingDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = OnboardingDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of OnboardingDto-objects as value to a dart map
|
||||
static Map<String, List<OnboardingDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<OnboardingDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = OnboardingDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'isOnboarded',
|
||||
};
|
||||
}
|
||||
|
99
mobile/openapi/lib/model/onboarding_response_dto.dart
generated
Normal file
99
mobile/openapi/lib/model/onboarding_response_dto.dart
generated
Normal file
@ -0,0 +1,99 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class OnboardingResponseDto {
|
||||
/// Returns a new [OnboardingResponseDto] instance.
|
||||
OnboardingResponseDto({
|
||||
required this.isOnboarded,
|
||||
});
|
||||
|
||||
bool isOnboarded;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is OnboardingResponseDto &&
|
||||
other.isOnboarded == isOnboarded;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(isOnboarded.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'OnboardingResponseDto[isOnboarded=$isOnboarded]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'isOnboarded'] = this.isOnboarded;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [OnboardingResponseDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static OnboardingResponseDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "OnboardingResponseDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return OnboardingResponseDto(
|
||||
isOnboarded: mapValueOfType<bool>(json, r'isOnboarded')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<OnboardingResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <OnboardingResponseDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = OnboardingResponseDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, OnboardingResponseDto> mapFromJson(dynamic json) {
|
||||
final map = <String, OnboardingResponseDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = OnboardingResponseDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of OnboardingResponseDto-objects as value to a dart map
|
||||
static Map<String, List<OnboardingResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<OnboardingResponseDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = OnboardingResponseDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'isOnboarded',
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user