Add preview stack

This commit is contained in:
Hillel Coren 2020-11-12 15:34:49 +02:00
parent 307f1c2369
commit d5adb825e3
10 changed files with 106 additions and 22 deletions

View File

@ -309,6 +309,9 @@ Serializers _$serializers = (new Serializers().toBuilder()
..addBuilderFactory(
const FullType(BuiltList, const [const FullType(String)]),
() => new ListBuilder<String>())
..addBuilderFactory(
const FullType(BuiltList, const [const FullType(EntityType)]),
() => new ListBuilder<EntityType>())
..addBuilderFactory(
const FullType(
BuiltList, const [const FullType(ExpenseCategoryEntity)]),
@ -428,8 +431,7 @@ Serializers _$serializers = (new Serializers().toBuilder()
BuiltList, const [const FullType(InvoiceHistoryEntity)]),
() => new ListBuilder<InvoiceHistoryEntity>())
..addBuilderFactory(
const FullType(BuiltList, const [const FullType(LanguageEntity)]),
() => new ListBuilder<LanguageEntity>())
const FullType(BuiltList, const [const FullType(LanguageEntity)]), () => new ListBuilder<LanguageEntity>())
..addBuilderFactory(const FullType(BuiltList, const [const FullType(PaymentEntity)]), () => new ListBuilder<PaymentEntity>())
..addBuilderFactory(const FullType(BuiltList, const [const FullType(PaymentTermEntity)]), () => new ListBuilder<PaymentTermEntity>())
..addBuilderFactory(const FullType(BuiltList, const [const FullType(PaymentTypeEntity)]), () => new ListBuilder<PaymentTypeEntity>())

View File

@ -159,6 +159,16 @@ class RefreshData implements StartLoading {
final bool includeStatic;
}
class PreviewEntity {
const PreviewEntity({
this.entityType,
this.entityId,
});
final String entityId;
final EntityType entityType;
}
class ClearData {}
class RefreshDataFailure implements StopLoading {
@ -332,12 +342,28 @@ void viewEntitiesByType({
});
}
void viewEntity(
{BuildContext context,
BaseEntity entity,
bool force = false,
bool addToStack = false,
BaseEntity filterEntity}) =>
viewEntityById(
context: context,
entityId: entity.id,
entityType: entity.entityType,
force: force,
addToStack: addToStack,
filterEntity: filterEntity,
);
void viewEntityById({
BuildContext context,
String entityId,
EntityType entityType,
bool force = false,
bool showError = true,
bool addToStack = false,
BaseEntity filterEntity,
}) {
final store = StoreProvider.of<AppState>(context);
@ -350,6 +376,14 @@ void viewEntityById({
context: context,
force: force,
callback: () {
if (addToStack) {
store.dispatch(PreviewEntity(
entityId: entityId,
entityType: entityType,
));
return;
}
if (filterEntity != null &&
(uiState.filterEntityType != filterEntity.entityType ||
uiState.filterEntityId != filterEntity.id)) {
@ -549,19 +583,6 @@ void viewEntityById({
});
}
void viewEntity(
{BuildContext context,
BaseEntity entity,
bool force = false,
BaseEntity filterEntity}) =>
viewEntityById(
context: context,
entityId: entity.id,
entityType: entity.entityType,
force: force,
filterEntity: filterEntity,
);
void createEntityByType(
{BuildContext context, EntityType entityType, bool force = false}) {
final store = StoreProvider.of<AppState>(context);

View File

@ -714,7 +714,8 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
return '\n\nURL: ${authState.url}'
'\nRoute: ${uiState.currentRoute}'
'\nPrev: ${uiState.previousRoute}'
'\nPrevious: ${uiState.previousRoute}'
'\nPreview: ${uiState.previewStack}'
'\nIs Loaded: ${isLoaded ? 'Yes' : 'No'}'
'\nis Large: ${(company?.isLarge ?? false) ? 'Yes' : 'No'}'
'\nCompany: $companyUpdated${userCompanyState.isStale ? ' [S]' : ''}'

View File

@ -43,6 +43,9 @@ final editingContactReducer = combineReducers<ContactEntity>([
]);
final selectedIdReducer = combineReducers<String>([
TypedReducer<String, PreviewEntity>((selectedId, action) {
return action.entityId;
}),
TypedReducer<String, ViewClient>((selectedId, action) {
return action.clientId;
}),

View File

@ -137,6 +137,9 @@ List<String> filteredTasksSelector(
} else if (filterEntityType == EntityType.invoice &&
task.invoiceId != filterEntityId) {
return false;
} else if (filterEntityType == EntityType.user &&
task.assignedUserId != filterEntityId) {
return false;
}
} else if (task.clientId != null && !client.isActive) {
return false;

View File

@ -1,3 +1,4 @@
import 'package:built_collection/built_collection.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
@ -77,6 +78,7 @@ UIState uiReducer(UIState state, dynamic action) {
? state.previousRoute
: state.currentRoute
..currentRoute = currentRoute
..previewStack.replace(previewStackReducer(state.previewStack, action))
..productUIState.replace(productUIReducer(state.productUIState, action))
..clientUIState.replace(clientUIReducer(state.clientUIState, action))
..invoiceUIState.replace(invoiceUIReducer(state.invoiceUIState, action))
@ -284,3 +286,12 @@ Reducer<SettingsUIState> settingsUIReducer = combineReducers([
return state.rebuild((b) => b..tabIndex = action.tabIndex);
}),
]);
Reducer<BuiltList<EntityType>> previewStackReducer = combineReducers([
TypedReducer<BuiltList<EntityType>, PreviewEntity>((previewStack, action) {
return BuiltList(<EntityType>[
...previewStack.where((entityType) => entityType != action.entityType),
action.entityType
]);
}),
]);

View File

@ -1,3 +1,4 @@
import 'package:built_collection/built_collection.dart';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
@ -43,15 +44,14 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
filterClearedAt: 0,
currentRoute: currentRoute ?? LoginScreen.route,
previousRoute: '',
previewStack: BuiltList<EntityType>(),
dashboardUIState: DashboardUIState(),
productUIState: ProductUIState(),
clientUIState: ClientUIState(),
invoiceUIState: InvoiceUIState(),
// STARTER: constructor - do not remove comment
taskStatusUIState: TaskStatusUIState(),
expenseCategoryUIState: ExpenseCategoryUIState(),
recurringInvoiceUIState: RecurringInvoiceUIState(),
webhookUIState: WebhookUIState(),
tokenUIState: TokenUIState(),
@ -86,6 +86,8 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
String get previousRoute;
BuiltList<EntityType> get previewStack;
@nullable
String get filterEntityId;

View File

@ -27,6 +27,10 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
'previousRoute',
serializers.serialize(object.previousRoute,
specifiedType: const FullType(String)),
'previewStack',
serializers.serialize(object.previewStack,
specifiedType:
const FullType(BuiltList, const [const FullType(EntityType)])),
'filterClearedAt',
serializers.serialize(object.filterClearedAt,
specifiedType: const FullType(int)),
@ -150,6 +154,12 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
result.previousRoute = serializers.deserialize(value,
specifiedType: const FullType(String)) as String;
break;
case 'previewStack':
result.previewStack.replace(serializers.deserialize(value,
specifiedType: const FullType(
BuiltList, const [const FullType(EntityType)]))
as BuiltList<Object>);
break;
case 'filterEntityId':
result.filterEntityId = serializers.deserialize(value,
specifiedType: const FullType(String)) as String;
@ -289,6 +299,8 @@ class _$UIState extends UIState {
@override
final String previousRoute;
@override
final BuiltList<EntityType> previewStack;
@override
final String filterEntityId;
@override
final EntityType filterEntityType;
@ -354,6 +366,7 @@ class _$UIState extends UIState {
{this.selectedCompanyIndex,
this.currentRoute,
this.previousRoute,
this.previewStack,
this.filterEntityId,
this.filterEntityType,
this.filter,
@ -393,6 +406,9 @@ class _$UIState extends UIState {
if (previousRoute == null) {
throw new BuiltValueNullFieldError('UIState', 'previousRoute');
}
if (previewStack == null) {
throw new BuiltValueNullFieldError('UIState', 'previewStack');
}
if (filterClearedAt == null) {
throw new BuiltValueNullFieldError('UIState', 'filterClearedAt');
}
@ -487,6 +503,7 @@ class _$UIState extends UIState {
selectedCompanyIndex == other.selectedCompanyIndex &&
currentRoute == other.currentRoute &&
previousRoute == other.previousRoute &&
previewStack == other.previewStack &&
filterEntityId == other.filterEntityId &&
filterEntityType == other.filterEntityType &&
filter == other.filter &&
@ -539,7 +556,7 @@ class _$UIState extends UIState {
$jc(
$jc(
$jc(
$jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc(0, selectedCompanyIndex.hashCode), currentRoute.hashCode), previousRoute.hashCode), filterEntityId.hashCode), filterEntityType.hashCode), filter.hashCode), filterClearedAt.hashCode), dashboardUIState.hashCode), productUIState.hashCode), clientUIState.hashCode), invoiceUIState.hashCode), taskStatusUIState.hashCode), expenseCategoryUIState.hashCode),
$jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc(0, selectedCompanyIndex.hashCode), currentRoute.hashCode), previousRoute.hashCode), previewStack.hashCode), filterEntityId.hashCode), filterEntityType.hashCode), filter.hashCode), filterClearedAt.hashCode), dashboardUIState.hashCode), productUIState.hashCode), clientUIState.hashCode), invoiceUIState.hashCode), taskStatusUIState.hashCode), expenseCategoryUIState.hashCode),
recurringInvoiceUIState.hashCode),
webhookUIState.hashCode),
tokenUIState.hashCode),
@ -567,6 +584,7 @@ class _$UIState extends UIState {
..add('selectedCompanyIndex', selectedCompanyIndex)
..add('currentRoute', currentRoute)
..add('previousRoute', previousRoute)
..add('previewStack', previewStack)
..add('filterEntityId', filterEntityId)
..add('filterEntityType', filterEntityType)
..add('filter', filter)
@ -617,6 +635,12 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
set previousRoute(String previousRoute) =>
_$this._previousRoute = previousRoute;
ListBuilder<EntityType> _previewStack;
ListBuilder<EntityType> get previewStack =>
_$this._previewStack ??= new ListBuilder<EntityType>();
set previewStack(ListBuilder<EntityType> previewStack) =>
_$this._previewStack = previewStack;
String _filterEntityId;
String get filterEntityId => _$this._filterEntityId;
set filterEntityId(String filterEntityId) =>
@ -796,6 +820,7 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
_selectedCompanyIndex = _$v.selectedCompanyIndex;
_currentRoute = _$v.currentRoute;
_previousRoute = _$v.previousRoute;
_previewStack = _$v.previewStack?.toBuilder();
_filterEntityId = _$v.filterEntityId;
_filterEntityType = _$v.filterEntityType;
_filter = _$v.filter;
@ -852,6 +877,7 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
selectedCompanyIndex: selectedCompanyIndex,
currentRoute: currentRoute,
previousRoute: previousRoute,
previewStack: previewStack.build(),
filterEntityId: filterEntityId,
filterEntityType: filterEntityType,
filter: filter,
@ -884,6 +910,9 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
} catch (_) {
String _$failedField;
try {
_$failedField = 'previewStack';
previewStack.build();
_$failedField = 'dashboardUIState';
dashboardUIState.build();
_$failedField = 'productUIState';

View File

@ -83,9 +83,11 @@ class _EntityListTileState extends State<EntityListTile> {
icon: Icon(isHovered || isMobile(context)
? Icons.chevron_right
: Icons.filter_list),
onPressed: isHovered
? () => viewEntity(entity: widget.entity, context: context)
: () => null,
onPressed: () => viewEntity(
entity: widget.entity,
context: context,
addToStack: isDesktop(context),
),
color: isFilteredBy
? (state.prefState.enableDarkMode
? Colors.white

View File

@ -55,6 +55,7 @@ class _TaskOverviewState extends State<TaskOverview> {
final client = viewModel.client;
final company = viewModel.company;
final invoice = viewModel.state.invoiceState.map[task.invoiceId];
final user = viewModel.state.userState.map[task.assignedUserId];
final Map<String, String> fields = {
TaskFields.rate: formatNumber(task.rate, context, zeroIsNull: true),
@ -126,6 +127,15 @@ class _TaskOverviewState extends State<TaskOverview> {
]);
}
if (user != null) {
widgets.addAll([
EntityListTile(
entity: user,
isFilter: widget.isFilter,
),
]);
}
if (invoice != null) {
widgets.addAll([
EntityListTile(