Designs
This commit is contained in:
parent
0729a5a785
commit
ebef3441aa
|
|
@ -0,0 +1,117 @@
|
||||||
|
import 'package:built_value/built_value.dart';
|
||||||
|
import 'package:built_collection/built_collection.dart';
|
||||||
|
import 'package:built_value/serializer.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
||||||
|
|
||||||
|
part 'design_model.g.dart';
|
||||||
|
|
||||||
|
abstract class DesignListResponse
|
||||||
|
implements Built<DesignListResponse, DesignListResponseBuilder> {
|
||||||
|
factory DesignListResponse([void updates(DesignListResponseBuilder b)]) =
|
||||||
|
_$DesignListResponse;
|
||||||
|
|
||||||
|
DesignListResponse._();
|
||||||
|
|
||||||
|
BuiltList<DesignEntity> get data;
|
||||||
|
|
||||||
|
static Serializer<DesignListResponse> get serializer =>
|
||||||
|
_$designListResponseSerializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class DesignItemResponse
|
||||||
|
implements Built<DesignItemResponse, DesignItemResponseBuilder> {
|
||||||
|
factory DesignItemResponse([void updates(DesignItemResponseBuilder b)]) =
|
||||||
|
_$DesignItemResponse;
|
||||||
|
|
||||||
|
DesignItemResponse._();
|
||||||
|
|
||||||
|
DesignEntity get data;
|
||||||
|
|
||||||
|
static Serializer<DesignItemResponse> get serializer =>
|
||||||
|
_$designItemResponseSerializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
class DesignFields {
|
||||||
|
static const String name = 'name';
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class DesignEntity extends Object
|
||||||
|
with BaseEntity
|
||||||
|
implements Built<DesignEntity, DesignEntityBuilder> {
|
||||||
|
|
||||||
|
factory DesignEntity() {
|
||||||
|
return _$DesignEntity._(
|
||||||
|
id: BaseEntity.nextId,
|
||||||
|
isChanged: false,
|
||||||
|
// STARTER: constructor - do not remove comment
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignEntity._();
|
||||||
|
|
||||||
|
String get displayName {
|
||||||
|
// STARTER: display name - do not remove comment
|
||||||
|
}
|
||||||
|
|
||||||
|
int compareTo(DesignEntity design, String sortField, bool sortAscending) {
|
||||||
|
int response = 0;
|
||||||
|
DesignEntity designA = sortAscending ? this : design;
|
||||||
|
DesignEntity designB = sortAscending ? design : this;
|
||||||
|
|
||||||
|
switch (sortField) {
|
||||||
|
// STARTER: sort switch - do not remove comment
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response == 0) {
|
||||||
|
// STARTER: sort default - do not remove comment
|
||||||
|
} else {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matchesSearch(String filter) {
|
||||||
|
if (filter == null || filter.isEmpty) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter = filter.toLowerCase();
|
||||||
|
|
||||||
|
// STARTER: filter - do not remove comment
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool matchesFilter(String filter) {
|
||||||
|
if (filter == null || filter.isEmpty) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter = filter.toLowerCase();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String matchesFilterValue(String filter) {
|
||||||
|
if (filter == null || filter.isEmpty) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter = filter.toLowerCase();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get listDisplayName => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
double get listDisplayAmount => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
FormatNumberType get listDisplayAmountType => null;
|
||||||
|
|
||||||
|
static Serializer<DesignEntity> get serializer => _$designEntitySerializer;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,598 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'design_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// BuiltValueGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
Serializer<DesignListResponse> _$designListResponseSerializer =
|
||||||
|
new _$DesignListResponseSerializer();
|
||||||
|
Serializer<DesignItemResponse> _$designItemResponseSerializer =
|
||||||
|
new _$DesignItemResponseSerializer();
|
||||||
|
Serializer<DesignEntity> _$designEntitySerializer =
|
||||||
|
new _$DesignEntitySerializer();
|
||||||
|
|
||||||
|
class _$DesignListResponseSerializer
|
||||||
|
implements StructuredSerializer<DesignListResponse> {
|
||||||
|
@override
|
||||||
|
final Iterable<Type> types = const [DesignListResponse, _$DesignListResponse];
|
||||||
|
@override
|
||||||
|
final String wireName = 'DesignListResponse';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<Object> serialize(Serializers serializers, DesignListResponse object,
|
||||||
|
{FullType specifiedType = FullType.unspecified}) {
|
||||||
|
final result = <Object>[
|
||||||
|
'data',
|
||||||
|
serializers.serialize(object.data,
|
||||||
|
specifiedType:
|
||||||
|
const FullType(BuiltList, const [const FullType(DesignEntity)])),
|
||||||
|
];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DesignListResponse deserialize(
|
||||||
|
Serializers serializers, Iterable<Object> serialized,
|
||||||
|
{FullType specifiedType = FullType.unspecified}) {
|
||||||
|
final result = new DesignListResponseBuilder();
|
||||||
|
|
||||||
|
final iterator = serialized.iterator;
|
||||||
|
while (iterator.moveNext()) {
|
||||||
|
final key = iterator.current as String;
|
||||||
|
iterator.moveNext();
|
||||||
|
final dynamic value = iterator.current;
|
||||||
|
switch (key) {
|
||||||
|
case 'data':
|
||||||
|
result.data.replace(serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(
|
||||||
|
BuiltList, const [const FullType(DesignEntity)]))
|
||||||
|
as BuiltList<Object>);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$DesignItemResponseSerializer
|
||||||
|
implements StructuredSerializer<DesignItemResponse> {
|
||||||
|
@override
|
||||||
|
final Iterable<Type> types = const [DesignItemResponse, _$DesignItemResponse];
|
||||||
|
@override
|
||||||
|
final String wireName = 'DesignItemResponse';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<Object> serialize(Serializers serializers, DesignItemResponse object,
|
||||||
|
{FullType specifiedType = FullType.unspecified}) {
|
||||||
|
final result = <Object>[
|
||||||
|
'data',
|
||||||
|
serializers.serialize(object.data,
|
||||||
|
specifiedType: const FullType(DesignEntity)),
|
||||||
|
];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DesignItemResponse deserialize(
|
||||||
|
Serializers serializers, Iterable<Object> serialized,
|
||||||
|
{FullType specifiedType = FullType.unspecified}) {
|
||||||
|
final result = new DesignItemResponseBuilder();
|
||||||
|
|
||||||
|
final iterator = serialized.iterator;
|
||||||
|
while (iterator.moveNext()) {
|
||||||
|
final key = iterator.current as String;
|
||||||
|
iterator.moveNext();
|
||||||
|
final dynamic value = iterator.current;
|
||||||
|
switch (key) {
|
||||||
|
case 'data':
|
||||||
|
result.data.replace(serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(DesignEntity)) as DesignEntity);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$DesignEntitySerializer implements StructuredSerializer<DesignEntity> {
|
||||||
|
@override
|
||||||
|
final Iterable<Type> types = const [DesignEntity, _$DesignEntity];
|
||||||
|
@override
|
||||||
|
final String wireName = 'DesignEntity';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<Object> serialize(Serializers serializers, DesignEntity object,
|
||||||
|
{FullType specifiedType = FullType.unspecified}) {
|
||||||
|
final result = <Object>[];
|
||||||
|
if (object.isChanged != null) {
|
||||||
|
result
|
||||||
|
..add('isChanged')
|
||||||
|
..add(serializers.serialize(object.isChanged,
|
||||||
|
specifiedType: const FullType(bool)));
|
||||||
|
}
|
||||||
|
if (object.createdAt != null) {
|
||||||
|
result
|
||||||
|
..add('created_at')
|
||||||
|
..add(serializers.serialize(object.createdAt,
|
||||||
|
specifiedType: const FullType(int)));
|
||||||
|
}
|
||||||
|
if (object.updatedAt != null) {
|
||||||
|
result
|
||||||
|
..add('updated_at')
|
||||||
|
..add(serializers.serialize(object.updatedAt,
|
||||||
|
specifiedType: const FullType(int)));
|
||||||
|
}
|
||||||
|
if (object.archivedAt != null) {
|
||||||
|
result
|
||||||
|
..add('archived_at')
|
||||||
|
..add(serializers.serialize(object.archivedAt,
|
||||||
|
specifiedType: const FullType(int)));
|
||||||
|
}
|
||||||
|
if (object.isDeleted != null) {
|
||||||
|
result
|
||||||
|
..add('is_deleted')
|
||||||
|
..add(serializers.serialize(object.isDeleted,
|
||||||
|
specifiedType: const FullType(bool)));
|
||||||
|
}
|
||||||
|
if (object.createdUserId != null) {
|
||||||
|
result
|
||||||
|
..add('user_id')
|
||||||
|
..add(serializers.serialize(object.createdUserId,
|
||||||
|
specifiedType: const FullType(String)));
|
||||||
|
}
|
||||||
|
if (object.assignedUserId != null) {
|
||||||
|
result
|
||||||
|
..add('assigned_user_id')
|
||||||
|
..add(serializers.serialize(object.assignedUserId,
|
||||||
|
specifiedType: const FullType(String)));
|
||||||
|
}
|
||||||
|
if (object.subEntityType != null) {
|
||||||
|
result
|
||||||
|
..add('entity_type')
|
||||||
|
..add(serializers.serialize(object.subEntityType,
|
||||||
|
specifiedType: const FullType(EntityType)));
|
||||||
|
}
|
||||||
|
if (object.id != null) {
|
||||||
|
result
|
||||||
|
..add('id')
|
||||||
|
..add(serializers.serialize(object.id,
|
||||||
|
specifiedType: const FullType(String)));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DesignEntity deserialize(Serializers serializers, Iterable<Object> serialized,
|
||||||
|
{FullType specifiedType = FullType.unspecified}) {
|
||||||
|
final result = new DesignEntityBuilder();
|
||||||
|
|
||||||
|
final iterator = serialized.iterator;
|
||||||
|
while (iterator.moveNext()) {
|
||||||
|
final key = iterator.current as String;
|
||||||
|
iterator.moveNext();
|
||||||
|
final dynamic value = iterator.current;
|
||||||
|
switch (key) {
|
||||||
|
case 'isChanged':
|
||||||
|
result.isChanged = serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(bool)) as bool;
|
||||||
|
break;
|
||||||
|
case 'created_at':
|
||||||
|
result.createdAt = serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(int)) as int;
|
||||||
|
break;
|
||||||
|
case 'updated_at':
|
||||||
|
result.updatedAt = serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(int)) as int;
|
||||||
|
break;
|
||||||
|
case 'archived_at':
|
||||||
|
result.archivedAt = serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(int)) as int;
|
||||||
|
break;
|
||||||
|
case 'is_deleted':
|
||||||
|
result.isDeleted = serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(bool)) as bool;
|
||||||
|
break;
|
||||||
|
case 'user_id':
|
||||||
|
result.createdUserId = serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(String)) as String;
|
||||||
|
break;
|
||||||
|
case 'assigned_user_id':
|
||||||
|
result.assignedUserId = serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(String)) as String;
|
||||||
|
break;
|
||||||
|
case 'entity_type':
|
||||||
|
result.subEntityType = serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(EntityType)) as EntityType;
|
||||||
|
break;
|
||||||
|
case 'id':
|
||||||
|
result.id = serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(String)) as String;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$DesignListResponse extends DesignListResponse {
|
||||||
|
@override
|
||||||
|
final BuiltList<DesignEntity> data;
|
||||||
|
|
||||||
|
factory _$DesignListResponse(
|
||||||
|
[void Function(DesignListResponseBuilder) updates]) =>
|
||||||
|
(new DesignListResponseBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
_$DesignListResponse._({this.data}) : super._() {
|
||||||
|
if (data == null) {
|
||||||
|
throw new BuiltValueNullFieldError('DesignListResponse', 'data');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DesignListResponse rebuild(
|
||||||
|
void Function(DesignListResponseBuilder) updates) =>
|
||||||
|
(toBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
@override
|
||||||
|
DesignListResponseBuilder toBuilder() =>
|
||||||
|
new DesignListResponseBuilder()..replace(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(other, this)) return true;
|
||||||
|
return other is DesignListResponse && data == other.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return $jf($jc(0, data.hashCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (newBuiltValueToStringHelper('DesignListResponse')
|
||||||
|
..add('data', data))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DesignListResponseBuilder
|
||||||
|
implements Builder<DesignListResponse, DesignListResponseBuilder> {
|
||||||
|
_$DesignListResponse _$v;
|
||||||
|
|
||||||
|
ListBuilder<DesignEntity> _data;
|
||||||
|
ListBuilder<DesignEntity> get data =>
|
||||||
|
_$this._data ??= new ListBuilder<DesignEntity>();
|
||||||
|
set data(ListBuilder<DesignEntity> data) => _$this._data = data;
|
||||||
|
|
||||||
|
DesignListResponseBuilder();
|
||||||
|
|
||||||
|
DesignListResponseBuilder get _$this {
|
||||||
|
if (_$v != null) {
|
||||||
|
_data = _$v.data?.toBuilder();
|
||||||
|
_$v = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(DesignListResponse other) {
|
||||||
|
if (other == null) {
|
||||||
|
throw new ArgumentError.notNull('other');
|
||||||
|
}
|
||||||
|
_$v = other as _$DesignListResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(void Function(DesignListResponseBuilder) updates) {
|
||||||
|
if (updates != null) updates(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
_$DesignListResponse build() {
|
||||||
|
_$DesignListResponse _$result;
|
||||||
|
try {
|
||||||
|
_$result = _$v ?? new _$DesignListResponse._(data: data.build());
|
||||||
|
} catch (_) {
|
||||||
|
String _$failedField;
|
||||||
|
try {
|
||||||
|
_$failedField = 'data';
|
||||||
|
data.build();
|
||||||
|
} catch (e) {
|
||||||
|
throw new BuiltValueNestedFieldError(
|
||||||
|
'DesignListResponse', _$failedField, e.toString());
|
||||||
|
}
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
replace(_$result);
|
||||||
|
return _$result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$DesignItemResponse extends DesignItemResponse {
|
||||||
|
@override
|
||||||
|
final DesignEntity data;
|
||||||
|
|
||||||
|
factory _$DesignItemResponse(
|
||||||
|
[void Function(DesignItemResponseBuilder) updates]) =>
|
||||||
|
(new DesignItemResponseBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
_$DesignItemResponse._({this.data}) : super._() {
|
||||||
|
if (data == null) {
|
||||||
|
throw new BuiltValueNullFieldError('DesignItemResponse', 'data');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DesignItemResponse rebuild(
|
||||||
|
void Function(DesignItemResponseBuilder) updates) =>
|
||||||
|
(toBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
@override
|
||||||
|
DesignItemResponseBuilder toBuilder() =>
|
||||||
|
new DesignItemResponseBuilder()..replace(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(other, this)) return true;
|
||||||
|
return other is DesignItemResponse && data == other.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return $jf($jc(0, data.hashCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (newBuiltValueToStringHelper('DesignItemResponse')
|
||||||
|
..add('data', data))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DesignItemResponseBuilder
|
||||||
|
implements Builder<DesignItemResponse, DesignItemResponseBuilder> {
|
||||||
|
_$DesignItemResponse _$v;
|
||||||
|
|
||||||
|
DesignEntityBuilder _data;
|
||||||
|
DesignEntityBuilder get data => _$this._data ??= new DesignEntityBuilder();
|
||||||
|
set data(DesignEntityBuilder data) => _$this._data = data;
|
||||||
|
|
||||||
|
DesignItemResponseBuilder();
|
||||||
|
|
||||||
|
DesignItemResponseBuilder get _$this {
|
||||||
|
if (_$v != null) {
|
||||||
|
_data = _$v.data?.toBuilder();
|
||||||
|
_$v = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(DesignItemResponse other) {
|
||||||
|
if (other == null) {
|
||||||
|
throw new ArgumentError.notNull('other');
|
||||||
|
}
|
||||||
|
_$v = other as _$DesignItemResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(void Function(DesignItemResponseBuilder) updates) {
|
||||||
|
if (updates != null) updates(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
_$DesignItemResponse build() {
|
||||||
|
_$DesignItemResponse _$result;
|
||||||
|
try {
|
||||||
|
_$result = _$v ?? new _$DesignItemResponse._(data: data.build());
|
||||||
|
} catch (_) {
|
||||||
|
String _$failedField;
|
||||||
|
try {
|
||||||
|
_$failedField = 'data';
|
||||||
|
data.build();
|
||||||
|
} catch (e) {
|
||||||
|
throw new BuiltValueNestedFieldError(
|
||||||
|
'DesignItemResponse', _$failedField, e.toString());
|
||||||
|
}
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
replace(_$result);
|
||||||
|
return _$result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$DesignEntity extends DesignEntity {
|
||||||
|
@override
|
||||||
|
final bool isChanged;
|
||||||
|
@override
|
||||||
|
final int createdAt;
|
||||||
|
@override
|
||||||
|
final int updatedAt;
|
||||||
|
@override
|
||||||
|
final int archivedAt;
|
||||||
|
@override
|
||||||
|
final bool isDeleted;
|
||||||
|
@override
|
||||||
|
final String createdUserId;
|
||||||
|
@override
|
||||||
|
final String assignedUserId;
|
||||||
|
@override
|
||||||
|
final EntityType subEntityType;
|
||||||
|
@override
|
||||||
|
final String id;
|
||||||
|
|
||||||
|
factory _$DesignEntity([void Function(DesignEntityBuilder) updates]) =>
|
||||||
|
(new DesignEntityBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
_$DesignEntity._(
|
||||||
|
{this.isChanged,
|
||||||
|
this.createdAt,
|
||||||
|
this.updatedAt,
|
||||||
|
this.archivedAt,
|
||||||
|
this.isDeleted,
|
||||||
|
this.createdUserId,
|
||||||
|
this.assignedUserId,
|
||||||
|
this.subEntityType,
|
||||||
|
this.id})
|
||||||
|
: super._();
|
||||||
|
|
||||||
|
@override
|
||||||
|
DesignEntity rebuild(void Function(DesignEntityBuilder) updates) =>
|
||||||
|
(toBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
@override
|
||||||
|
DesignEntityBuilder toBuilder() => new DesignEntityBuilder()..replace(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(other, this)) return true;
|
||||||
|
return other is DesignEntity &&
|
||||||
|
isChanged == other.isChanged &&
|
||||||
|
createdAt == other.createdAt &&
|
||||||
|
updatedAt == other.updatedAt &&
|
||||||
|
archivedAt == other.archivedAt &&
|
||||||
|
isDeleted == other.isDeleted &&
|
||||||
|
createdUserId == other.createdUserId &&
|
||||||
|
assignedUserId == other.assignedUserId &&
|
||||||
|
subEntityType == other.subEntityType &&
|
||||||
|
id == other.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return $jf($jc(
|
||||||
|
$jc(
|
||||||
|
$jc(
|
||||||
|
$jc(
|
||||||
|
$jc(
|
||||||
|
$jc(
|
||||||
|
$jc(
|
||||||
|
$jc($jc(0, isChanged.hashCode),
|
||||||
|
createdAt.hashCode),
|
||||||
|
updatedAt.hashCode),
|
||||||
|
archivedAt.hashCode),
|
||||||
|
isDeleted.hashCode),
|
||||||
|
createdUserId.hashCode),
|
||||||
|
assignedUserId.hashCode),
|
||||||
|
subEntityType.hashCode),
|
||||||
|
id.hashCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (newBuiltValueToStringHelper('DesignEntity')
|
||||||
|
..add('isChanged', isChanged)
|
||||||
|
..add('createdAt', createdAt)
|
||||||
|
..add('updatedAt', updatedAt)
|
||||||
|
..add('archivedAt', archivedAt)
|
||||||
|
..add('isDeleted', isDeleted)
|
||||||
|
..add('createdUserId', createdUserId)
|
||||||
|
..add('assignedUserId', assignedUserId)
|
||||||
|
..add('subEntityType', subEntityType)
|
||||||
|
..add('id', id))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DesignEntityBuilder
|
||||||
|
implements Builder<DesignEntity, DesignEntityBuilder> {
|
||||||
|
_$DesignEntity _$v;
|
||||||
|
|
||||||
|
bool _isChanged;
|
||||||
|
bool get isChanged => _$this._isChanged;
|
||||||
|
set isChanged(bool isChanged) => _$this._isChanged = isChanged;
|
||||||
|
|
||||||
|
int _createdAt;
|
||||||
|
int get createdAt => _$this._createdAt;
|
||||||
|
set createdAt(int createdAt) => _$this._createdAt = createdAt;
|
||||||
|
|
||||||
|
int _updatedAt;
|
||||||
|
int get updatedAt => _$this._updatedAt;
|
||||||
|
set updatedAt(int updatedAt) => _$this._updatedAt = updatedAt;
|
||||||
|
|
||||||
|
int _archivedAt;
|
||||||
|
int get archivedAt => _$this._archivedAt;
|
||||||
|
set archivedAt(int archivedAt) => _$this._archivedAt = archivedAt;
|
||||||
|
|
||||||
|
bool _isDeleted;
|
||||||
|
bool get isDeleted => _$this._isDeleted;
|
||||||
|
set isDeleted(bool isDeleted) => _$this._isDeleted = isDeleted;
|
||||||
|
|
||||||
|
String _createdUserId;
|
||||||
|
String get createdUserId => _$this._createdUserId;
|
||||||
|
set createdUserId(String createdUserId) =>
|
||||||
|
_$this._createdUserId = createdUserId;
|
||||||
|
|
||||||
|
String _assignedUserId;
|
||||||
|
String get assignedUserId => _$this._assignedUserId;
|
||||||
|
set assignedUserId(String assignedUserId) =>
|
||||||
|
_$this._assignedUserId = assignedUserId;
|
||||||
|
|
||||||
|
EntityType _subEntityType;
|
||||||
|
EntityType get subEntityType => _$this._subEntityType;
|
||||||
|
set subEntityType(EntityType subEntityType) =>
|
||||||
|
_$this._subEntityType = subEntityType;
|
||||||
|
|
||||||
|
String _id;
|
||||||
|
String get id => _$this._id;
|
||||||
|
set id(String id) => _$this._id = id;
|
||||||
|
|
||||||
|
DesignEntityBuilder();
|
||||||
|
|
||||||
|
DesignEntityBuilder get _$this {
|
||||||
|
if (_$v != null) {
|
||||||
|
_isChanged = _$v.isChanged;
|
||||||
|
_createdAt = _$v.createdAt;
|
||||||
|
_updatedAt = _$v.updatedAt;
|
||||||
|
_archivedAt = _$v.archivedAt;
|
||||||
|
_isDeleted = _$v.isDeleted;
|
||||||
|
_createdUserId = _$v.createdUserId;
|
||||||
|
_assignedUserId = _$v.assignedUserId;
|
||||||
|
_subEntityType = _$v.subEntityType;
|
||||||
|
_id = _$v.id;
|
||||||
|
_$v = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(DesignEntity other) {
|
||||||
|
if (other == null) {
|
||||||
|
throw new ArgumentError.notNull('other');
|
||||||
|
}
|
||||||
|
_$v = other as _$DesignEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(void Function(DesignEntityBuilder) updates) {
|
||||||
|
if (updates != null) updates(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
_$DesignEntity build() {
|
||||||
|
final _$result = _$v ??
|
||||||
|
new _$DesignEntity._(
|
||||||
|
isChanged: isChanged,
|
||||||
|
createdAt: createdAt,
|
||||||
|
updatedAt: updatedAt,
|
||||||
|
archivedAt: archivedAt,
|
||||||
|
isDeleted: isDeleted,
|
||||||
|
createdUserId: createdUserId,
|
||||||
|
assignedUserId: assignedUserId,
|
||||||
|
subEntityType: subEntityType,
|
||||||
|
id: id);
|
||||||
|
replace(_$result);
|
||||||
|
return _$result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||||
|
|
@ -33,11 +33,12 @@ class EntityType extends EnumClass {
|
||||||
static const EntityType payment = _$payment;
|
static const EntityType payment = _$payment;
|
||||||
static const EntityType group = _$group;
|
static const EntityType group = _$group;
|
||||||
static const EntityType user = _$user;
|
static const EntityType user = _$user;
|
||||||
|
|
||||||
static const EntityType company = _$company;
|
static const EntityType company = _$company;
|
||||||
static const EntityType gateway = _$gateway;
|
static const EntityType gateway = _$gateway;
|
||||||
static const EntityType gatewayToken = _$gatewayToken;
|
static const EntityType gatewayToken = _$gatewayToken;
|
||||||
static const EntityType invoiceItem = _$invoiceItem;
|
static const EntityType invoiceItem = _$invoiceItem;
|
||||||
|
static const EntityType design = _$design;
|
||||||
|
// STARTER: entity type - do not remove comment
|
||||||
static const EntityType quoteItem = _$quoteItem;
|
static const EntityType quoteItem = _$quoteItem;
|
||||||
static const EntityType contact = _$contact;
|
static const EntityType contact = _$contact;
|
||||||
static const EntityType vendorContact = _$vendorContact;
|
static const EntityType vendorContact = _$vendorContact;
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ const EntityType _$company = const EntityType._('company');
|
||||||
const EntityType _$gateway = const EntityType._('gateway');
|
const EntityType _$gateway = const EntityType._('gateway');
|
||||||
const EntityType _$gatewayToken = const EntityType._('gatewayToken');
|
const EntityType _$gatewayToken = const EntityType._('gatewayToken');
|
||||||
const EntityType _$invoiceItem = const EntityType._('invoiceItem');
|
const EntityType _$invoiceItem = const EntityType._('invoiceItem');
|
||||||
|
const EntityType _$design = const EntityType._('design');
|
||||||
const EntityType _$quoteItem = const EntityType._('quoteItem');
|
const EntityType _$quoteItem = const EntityType._('quoteItem');
|
||||||
const EntityType _$contact = const EntityType._('contact');
|
const EntityType _$contact = const EntityType._('contact');
|
||||||
const EntityType _$vendorContact = const EntityType._('vendorContact');
|
const EntityType _$vendorContact = const EntityType._('vendorContact');
|
||||||
|
|
@ -92,6 +93,8 @@ EntityType _$typeValueOf(String name) {
|
||||||
return _$gatewayToken;
|
return _$gatewayToken;
|
||||||
case 'invoiceItem':
|
case 'invoiceItem':
|
||||||
return _$invoiceItem;
|
return _$invoiceItem;
|
||||||
|
case 'design':
|
||||||
|
return _$design;
|
||||||
case 'quoteItem':
|
case 'quoteItem':
|
||||||
return _$quoteItem;
|
return _$quoteItem;
|
||||||
case 'contact':
|
case 'contact':
|
||||||
|
|
@ -150,6 +153,7 @@ final BuiltSet<EntityType> _$typeValues =
|
||||||
_$gateway,
|
_$gateway,
|
||||||
_$gatewayToken,
|
_$gatewayToken,
|
||||||
_$invoiceItem,
|
_$invoiceItem,
|
||||||
|
_$design,
|
||||||
_$quoteItem,
|
_$quoteItem,
|
||||||
_$contact,
|
_$contact,
|
||||||
_$vendorContact,
|
_$vendorContact,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import 'package:built_collection/built_collection.dart';
|
||||||
import 'package:built_value/built_value.dart';
|
import 'package:built_value/built_value.dart';
|
||||||
import 'package:built_value/serializer.dart';
|
import 'package:built_value/serializer.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/strings.dart';
|
import 'package:invoiceninja_flutter/utils/strings.dart';
|
||||||
|
|
||||||
export 'package:invoiceninja_flutter/data/models/client_model.dart';
|
export 'package:invoiceninja_flutter/data/models/client_model.dart';
|
||||||
export 'package:invoiceninja_flutter/data/models/company_model.dart';
|
export 'package:invoiceninja_flutter/data/models/company_model.dart';
|
||||||
export 'package:invoiceninja_flutter/data/models/credit_model.dart';
|
export 'package:invoiceninja_flutter/data/models/credit_model.dart';
|
||||||
|
|
@ -13,7 +12,9 @@ export 'package:invoiceninja_flutter/data/models/expense_model.dart';
|
||||||
export 'package:invoiceninja_flutter/data/models/invoice_model.dart';
|
export 'package:invoiceninja_flutter/data/models/invoice_model.dart';
|
||||||
export 'package:invoiceninja_flutter/data/models/payment_model.dart';
|
export 'package:invoiceninja_flutter/data/models/payment_model.dart';
|
||||||
export 'package:invoiceninja_flutter/data/models/product_model.dart';
|
export 'package:invoiceninja_flutter/data/models/product_model.dart';
|
||||||
|
export 'package:invoiceninja_flutter/data/models/design_model.dart';
|
||||||
export 'package:invoiceninja_flutter/data/models/project_model.dart';
|
export 'package:invoiceninja_flutter/data/models/project_model.dart';
|
||||||
|
//
|
||||||
export 'package:invoiceninja_flutter/data/models/static/country_model.dart';
|
export 'package:invoiceninja_flutter/data/models/static/country_model.dart';
|
||||||
export 'package:invoiceninja_flutter/data/models/static/currency_model.dart';
|
export 'package:invoiceninja_flutter/data/models/static/currency_model.dart';
|
||||||
export 'package:invoiceninja_flutter/data/models/static/date_format_model.dart';
|
export 'package:invoiceninja_flutter/data/models/static/date_format_model.dart';
|
||||||
|
|
|
||||||
|
|
@ -63,4 +63,3 @@ class QuoteFields {
|
||||||
static const String archivedAt = 'archivedAt';
|
static const String archivedAt = 'archivedAt';
|
||||||
static const String isDeleted = 'isDeleted';
|
static const String isDeleted = 'isDeleted';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,9 @@ import 'package:invoiceninja_flutter/redux/payment/payment_state.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/quote/quote_state.dart';
|
import 'package:invoiceninja_flutter/redux/quote/quote_state.dart';
|
||||||
|
|
||||||
// STARTER: import - do not remove comment
|
// STARTER: import - do not remove comment
|
||||||
|
import 'package:invoiceninja_flutter/data/models/design_model.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_state.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/data/models/credit_model.dart';
|
import 'package:invoiceninja_flutter/data/models/credit_model.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/credit/credit_state.dart';
|
import 'package:invoiceninja_flutter/redux/credit/credit_state.dart';
|
||||||
|
|
||||||
|
|
@ -112,6 +115,8 @@ part 'serializers.g.dart';
|
||||||
TaxRateItemResponse,
|
TaxRateItemResponse,
|
||||||
TaxRateListResponse,
|
TaxRateListResponse,
|
||||||
// STARTER: serializers - do not remove comment
|
// STARTER: serializers - do not remove comment
|
||||||
|
DesignEntity,
|
||||||
|
|
||||||
InvoiceEntity,
|
InvoiceEntity,
|
||||||
|
|
||||||
PaymentableEntity,
|
PaymentableEntity,
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,9 @@ Serializers _$serializers = (new Serializers().toBuilder()
|
||||||
..add(DatetimeFormatEntity.serializer)
|
..add(DatetimeFormatEntity.serializer)
|
||||||
..add(DatetimeFormatItemResponse.serializer)
|
..add(DatetimeFormatItemResponse.serializer)
|
||||||
..add(DatetimeFormatListResponse.serializer)
|
..add(DatetimeFormatListResponse.serializer)
|
||||||
|
..add(DesignEntity.serializer)
|
||||||
|
..add(DesignState.serializer)
|
||||||
|
..add(DesignUIState.serializer)
|
||||||
..add(DocumentEntity.serializer)
|
..add(DocumentEntity.serializer)
|
||||||
..add(DocumentItemResponse.serializer)
|
..add(DocumentItemResponse.serializer)
|
||||||
..add(DocumentListResponse.serializer)
|
..add(DocumentListResponse.serializer)
|
||||||
|
|
@ -383,6 +386,8 @@ Serializers _$serializers = (new Serializers().toBuilder()
|
||||||
..addBuilderFactory(const FullType(BuiltMap, const [const FullType(String), const FullType(PaymentTypeEntity)]), () => new MapBuilder<String, PaymentTypeEntity>())
|
..addBuilderFactory(const FullType(BuiltMap, const [const FullType(String), const FullType(PaymentTypeEntity)]), () => new MapBuilder<String, PaymentTypeEntity>())
|
||||||
..addBuilderFactory(const FullType(BuiltMap, const [const FullType(String), const FullType(CountryEntity)]), () => new MapBuilder<String, CountryEntity>())
|
..addBuilderFactory(const FullType(BuiltMap, const [const FullType(String), const FullType(CountryEntity)]), () => new MapBuilder<String, CountryEntity>())
|
||||||
..addBuilderFactory(const FullType(BuiltMap, const [const FullType(String), const FullType(InvoiceStatusEntity)]), () => new MapBuilder<String, InvoiceStatusEntity>())
|
..addBuilderFactory(const FullType(BuiltMap, const [const FullType(String), const FullType(InvoiceStatusEntity)]), () => new MapBuilder<String, InvoiceStatusEntity>())
|
||||||
|
..addBuilderFactory(const FullType(BuiltMap, const [const FullType(String), const FullType(DesignEntity)]), () => new MapBuilder<String, DesignEntity>())
|
||||||
|
..addBuilderFactory(const FullType(BuiltList, const [const FullType(String)]), () => new ListBuilder<String>())
|
||||||
..addBuilderFactory(const FullType(BuiltMap, const [const FullType(String), const FullType(DocumentEntity)]), () => new MapBuilder<String, DocumentEntity>())
|
..addBuilderFactory(const FullType(BuiltMap, const [const FullType(String), const FullType(DocumentEntity)]), () => new MapBuilder<String, DocumentEntity>())
|
||||||
..addBuilderFactory(const FullType(BuiltList, const [const FullType(String)]), () => new ListBuilder<String>())
|
..addBuilderFactory(const FullType(BuiltList, const [const FullType(String)]), () => new ListBuilder<String>())
|
||||||
..addBuilderFactory(const FullType(BuiltMap, const [const FullType(String), const FullType(ExpenseEntity)]), () => new MapBuilder<String, ExpenseEntity>())
|
..addBuilderFactory(const FullType(BuiltMap, const [const FullType(String), const FullType(ExpenseEntity)]), () => new MapBuilder<String, ExpenseEntity>())
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:core';
|
||||||
|
import 'package:invoiceninja_flutter/.env.dart';
|
||||||
|
import 'package:built_collection/built_collection.dart';
|
||||||
|
import 'package:invoiceninja_flutter/constants.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/serializers.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/web_client.dart';
|
||||||
|
|
||||||
|
class DesignRepository {
|
||||||
|
const DesignRepository({
|
||||||
|
this.webClient = const WebClient(),
|
||||||
|
});
|
||||||
|
|
||||||
|
final WebClient webClient;
|
||||||
|
|
||||||
|
Future<DesignEntity> loadItem(
|
||||||
|
Credentials credentials, String entityId) async {
|
||||||
|
final dynamic response = await webClient.get(
|
||||||
|
'${credentials.url}/designs/$entityId', credentials.token);
|
||||||
|
|
||||||
|
final DesignItemResponse designResponse =
|
||||||
|
serializers.deserializeWith(DesignItemResponse.serializer, response);
|
||||||
|
|
||||||
|
return designResponse.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<BuiltList<DesignEntity>> loadList(
|
||||||
|
Credentials credentials, int updatedAt) async {
|
||||||
|
String url = credentials.url + '/designs?';
|
||||||
|
|
||||||
|
if (updatedAt > 0) {
|
||||||
|
url += '&updated_at=${updatedAt - kUpdatedAtBufferSeconds}';
|
||||||
|
}
|
||||||
|
|
||||||
|
final dynamic response = await webClient.get(url, credentials.token);
|
||||||
|
|
||||||
|
final DesignListResponse designResponse =
|
||||||
|
serializers.deserializeWith(DesignListResponse.serializer, response);
|
||||||
|
|
||||||
|
return designResponse.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<DesignEntity>> bulkAction(
|
||||||
|
Credentials credentials, List<String> ids, EntityAction action) async {
|
||||||
|
var url = credentials.url + '/designs/bulk?';
|
||||||
|
if (action != null) {
|
||||||
|
url += '&action=' + action.toString();
|
||||||
|
}
|
||||||
|
final dynamic response = await webClient.post(url, credentials.token,
|
||||||
|
data: json.encode({'ids': ids}));
|
||||||
|
|
||||||
|
final DesignListResponse designResponse =
|
||||||
|
serializers.deserializeWith(DesignListResponse.serializer, response);
|
||||||
|
|
||||||
|
return designResponse.data.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<DesignEntity> saveData(Credentials credentials, DesignEntity design,
|
||||||
|
[EntityAction action]) async {
|
||||||
|
final data = serializers.serializeWith(DesignEntity.serializer, design);
|
||||||
|
dynamic response;
|
||||||
|
|
||||||
|
if (design.isNew) {
|
||||||
|
response = await webClient.post(
|
||||||
|
credentials.url + '/designs', credentials.token,
|
||||||
|
data: json.encode(data));
|
||||||
|
} else {
|
||||||
|
var url = credentials.url + '/designs/' + design.id.toString();
|
||||||
|
if (action != null) {
|
||||||
|
url += '?action=' + action.toString();
|
||||||
|
}
|
||||||
|
response =
|
||||||
|
await webClient.put(url, credentials.token, data: json.encode(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
final DesignItemResponse designResponse =
|
||||||
|
serializers.deserializeWith(DesignItemResponse.serializer, response);
|
||||||
|
|
||||||
|
return designResponse.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -51,6 +51,12 @@ import 'package:sentry/sentry.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
// STARTER: import - do not remove comment
|
// STARTER: import - do not remove comment
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/design_screen.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/edit/design_edit_vm.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/view/design_view_vm.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_middleware.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/ui/credit/credit_screen.dart';
|
import 'package:invoiceninja_flutter/ui/credit/credit_screen.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/credit/edit/credit_edit_vm.dart';
|
import 'package:invoiceninja_flutter/ui/credit/edit/credit_edit_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/credit/view/credit_view_vm.dart';
|
import 'package:invoiceninja_flutter/ui/credit/view/credit_view_vm.dart';
|
||||||
|
|
@ -100,6 +106,7 @@ void main({bool isTesting = false}) async {
|
||||||
..addAll(createStoreSettingsMiddleware())
|
..addAll(createStoreSettingsMiddleware())
|
||||||
..addAll(createStoreReportsMiddleware())
|
..addAll(createStoreReportsMiddleware())
|
||||||
// STARTER: middleware - do not remove comment
|
// STARTER: middleware - do not remove comment
|
||||||
|
..addAll(createStoreDesignsMiddleware())
|
||||||
..addAll(createStoreCreditsMiddleware())
|
..addAll(createStoreCreditsMiddleware())
|
||||||
..addAll(createStoreUsersMiddleware())
|
..addAll(createStoreUsersMiddleware())
|
||||||
..addAll(createStoreTaxRatesMiddleware())
|
..addAll(createStoreTaxRatesMiddleware())
|
||||||
|
|
@ -351,6 +358,9 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
|
||||||
QuoteEditScreen.route: (context) => QuoteEditScreen(),
|
QuoteEditScreen.route: (context) => QuoteEditScreen(),
|
||||||
QuoteEmailScreen.route: (context) => QuoteEmailScreen(),
|
QuoteEmailScreen.route: (context) => QuoteEmailScreen(),
|
||||||
// STARTER: routes - do not remove comment
|
// STARTER: routes - do not remove comment
|
||||||
|
DesignScreen.route: (context) => DesignScreenBuilder(),
|
||||||
|
DesignViewScreen.route: (context) => DesignViewScreen(),
|
||||||
|
DesignEditScreen.route: (context) => DesignEditScreen(),
|
||||||
CreditScreen.route: (context) => CreditScreenBuilder(),
|
CreditScreen.route: (context) => CreditScreenBuilder(),
|
||||||
CreditViewScreen.route: (context) => CreditViewScreen(),
|
CreditViewScreen.route: (context) => CreditViewScreen(),
|
||||||
CreditEditScreen.route: (context) => CreditEditScreen(),
|
CreditEditScreen.route: (context) => CreditEditScreen(),
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ import 'package:invoiceninja_flutter/utils/dialogs.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
|
||||||
// STARTER: import - do not remove comment
|
// STARTER: import - do not remove comment
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_actions.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/credit/credit_actions.dart';
|
import 'package:invoiceninja_flutter/redux/credit/credit_actions.dart';
|
||||||
|
|
||||||
class PersistUI {}
|
class PersistUI {}
|
||||||
|
|
@ -232,6 +234,13 @@ void filterEntitiesByType({
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
// STARTER: filter - do not remove comment
|
// STARTER: filter - do not remove comment
|
||||||
|
case EntityType.design:
|
||||||
|
store.dispatch(FilterDesignsByEntity(
|
||||||
|
entityId: filterEntity.id,
|
||||||
|
entityType: filterEntity.entityType,
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
|
||||||
case EntityType.credit:
|
case EntityType.credit:
|
||||||
store.dispatch(FilterCreditsByEntity(
|
store.dispatch(FilterCreditsByEntity(
|
||||||
entityId: filterEntity.id,
|
entityId: filterEntity.id,
|
||||||
|
|
@ -307,6 +316,10 @@ void viewEntitiesByType({
|
||||||
store.dispatch(ViewGroupList(navigator: navigator));
|
store.dispatch(ViewGroupList(navigator: navigator));
|
||||||
break;
|
break;
|
||||||
// STARTER: view list - do not remove comment
|
// STARTER: view list - do not remove comment
|
||||||
|
case EntityType.design:
|
||||||
|
store.dispatch(ViewDesignList(navigator: navigator));
|
||||||
|
break;
|
||||||
|
|
||||||
case EntityType.credit:
|
case EntityType.credit:
|
||||||
store.dispatch(ViewCreditList(navigator: navigator));
|
store.dispatch(ViewCreditList(navigator: navigator));
|
||||||
break;
|
break;
|
||||||
|
|
@ -434,6 +447,14 @@ void viewEntityById({
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
// STARTER: view - do not remove comment
|
// STARTER: view - do not remove comment
|
||||||
|
case EntityType.design:
|
||||||
|
store.dispatch(ViewDesign(
|
||||||
|
designId: entityId,
|
||||||
|
navigator: navigator,
|
||||||
|
force: force,
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
|
||||||
case EntityType.credit:
|
case EntityType.credit:
|
||||||
store.dispatch(ViewCredit(
|
store.dispatch(ViewCredit(
|
||||||
creditId: entityId,
|
creditId: entityId,
|
||||||
|
|
@ -555,6 +576,14 @@ void createEntityByType(
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
// STARTER: create type - do not remove comment
|
// STARTER: create type - do not remove comment
|
||||||
|
case EntityType.design:
|
||||||
|
store.dispatch(EditDesign(
|
||||||
|
navigator: navigator,
|
||||||
|
force: force,
|
||||||
|
design: DesignEntity(state: state),
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
|
||||||
case EntityType.credit:
|
case EntityType.credit:
|
||||||
store.dispatch(EditCredit(
|
store.dispatch(EditCredit(
|
||||||
navigator: navigator,
|
navigator: navigator,
|
||||||
|
|
@ -696,6 +725,15 @@ void createEntity({
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
// STARTER: create - do not remove comment
|
// STARTER: create - do not remove comment
|
||||||
|
case EntityType.design:
|
||||||
|
store.dispatch(EditDesign(
|
||||||
|
navigator: navigator,
|
||||||
|
design: entity,
|
||||||
|
force: force,
|
||||||
|
completer: completer,
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
|
||||||
case EntityType.credit:
|
case EntityType.credit:
|
||||||
store.dispatch(EditCredit(
|
store.dispatch(EditCredit(
|
||||||
navigator: navigator,
|
navigator: navigator,
|
||||||
|
|
@ -886,6 +924,19 @@ void editEntityById(
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
// STARTER: edit - do not remove comment
|
// STARTER: edit - do not remove comment
|
||||||
|
case EntityType.design:
|
||||||
|
store.dispatch(EditDesign(
|
||||||
|
design: map[entityId],
|
||||||
|
navigator: navigator,
|
||||||
|
completer: completer ??
|
||||||
|
snackBarCompleter<DesignEntity>(
|
||||||
|
context,
|
||||||
|
entity.isNew
|
||||||
|
? localization.createdDesign
|
||||||
|
: localization.updatedDesign),
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
|
||||||
case EntityType.credit:
|
case EntityType.credit:
|
||||||
store.dispatch(EditCredit(
|
store.dispatch(EditCredit(
|
||||||
credit: map[entityId],
|
credit: map[entityId],
|
||||||
|
|
@ -968,6 +1019,10 @@ void handleEntitiesActions(
|
||||||
handleDocumentAction(context, entities, action);
|
handleDocumentAction(context, entities, action);
|
||||||
break;
|
break;
|
||||||
// STARTER: actions - do not remove comment
|
// STARTER: actions - do not remove comment
|
||||||
|
case EntityType.design:
|
||||||
|
handleDesignAction(context, entities, action);
|
||||||
|
break;
|
||||||
|
|
||||||
case EntityType.credit:
|
case EntityType.credit:
|
||||||
handleCreditAction(context, entities, action);
|
handleCreditAction(context, entities, action);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ import 'package:invoiceninja_flutter/redux/auth/auth_reducer.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/company/company_reducer.dart';
|
import 'package:invoiceninja_flutter/redux/company/company_reducer.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/static/static_reducer.dart';
|
import 'package:invoiceninja_flutter/redux/static/static_reducer.dart';
|
||||||
// STARTER: import - do not remove comment
|
// STARTER: import - do not remove comment
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_actions.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/credit/credit_actions.dart';
|
import 'package:invoiceninja_flutter/redux/credit/credit_actions.dart';
|
||||||
|
|
||||||
// We create the State reducer by combining many smaller reducers into one!
|
// We create the State reducer by combining many smaller reducers into one!
|
||||||
|
|
@ -85,6 +87,10 @@ final lastErrorReducer = combineReducers<String>([
|
||||||
return '${action.error}';
|
return '${action.error}';
|
||||||
}),
|
}),
|
||||||
// STARTER: errors - do not remove comment
|
// STARTER: errors - do not remove comment
|
||||||
|
TypedReducer<String, LoadDesignsFailure>((state, action) {
|
||||||
|
return '${action.error}';
|
||||||
|
}),
|
||||||
|
|
||||||
TypedReducer<String, LoadCreditsFailure>((state, action) {
|
TypedReducer<String, LoadCreditsFailure>((state, action) {
|
||||||
return '${action.error}';
|
return '${action.error}';
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,9 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
|
||||||
case EntityType.invoice:
|
case EntityType.invoice:
|
||||||
return invoiceState.map;
|
return invoiceState.map;
|
||||||
// STARTER: states switch map - do not remove comment
|
// STARTER: states switch map - do not remove comment
|
||||||
|
case EntityType.design:
|
||||||
|
return designState.map;
|
||||||
|
|
||||||
case EntityType.credit:
|
case EntityType.credit:
|
||||||
return creditState.map;
|
return creditState.map;
|
||||||
|
|
||||||
|
|
@ -224,6 +227,9 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
|
||||||
case EntityType.invoice:
|
case EntityType.invoice:
|
||||||
return invoiceState.list;
|
return invoiceState.list;
|
||||||
// STARTER: states switch list - do not remove comment
|
// STARTER: states switch list - do not remove comment
|
||||||
|
case EntityType.design:
|
||||||
|
return designState.list;
|
||||||
|
|
||||||
case EntityType.credit:
|
case EntityType.credit:
|
||||||
return creditState.list;
|
return creditState.list;
|
||||||
|
|
||||||
|
|
@ -263,6 +269,9 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
|
||||||
case EntityType.invoice:
|
case EntityType.invoice:
|
||||||
return invoiceUIState;
|
return invoiceUIState;
|
||||||
// STARTER: states switch - do not remove comment
|
// STARTER: states switch - do not remove comment
|
||||||
|
case EntityType.design:
|
||||||
|
return designUIState;
|
||||||
|
|
||||||
case EntityType.credit:
|
case EntityType.credit:
|
||||||
return creditUIState;
|
return creditUIState;
|
||||||
|
|
||||||
|
|
@ -316,6 +325,10 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
|
||||||
ListUIState get invoiceListState => uiState.invoiceUIState.listUIState;
|
ListUIState get invoiceListState => uiState.invoiceUIState.listUIState;
|
||||||
|
|
||||||
// STARTER: state getters - do not remove comment
|
// STARTER: state getters - do not remove comment
|
||||||
|
DesignState get designState => userCompanyState.designState;
|
||||||
|
ListUIState get designListState => uiState.designUIState.listUIState;
|
||||||
|
DesignUIState get designUIState => uiState.designUIState;
|
||||||
|
|
||||||
CreditState get creditState => userCompanyState.creditState;
|
CreditState get creditState => userCompanyState.creditState;
|
||||||
|
|
||||||
ListUIState get creditListState => uiState.creditUIState.listUIState;
|
ListUIState get creditListState => uiState.creditUIState.listUIState;
|
||||||
|
|
@ -423,6 +436,8 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
|
||||||
case CreditEditScreen.route:
|
case CreditEditScreen.route:
|
||||||
return hasCreditChanges(creditUIState.editing, creditState.map);
|
return hasCreditChanges(creditUIState.editing, creditState.map);
|
||||||
// STARTER: has changes - do not remove comment
|
// STARTER: has changes - do not remove comment
|
||||||
|
case DesignEditScreen.route:
|
||||||
|
return hasDesignChanges(designUIState.editing, designState.map);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uiState.currentRoute.startsWith('/settings')) {
|
if (uiState.currentRoute.startsWith('/settings')) {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ import 'package:invoiceninja_flutter/redux/payment/payment_reducer.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/quote/quote_reducer.dart';
|
import 'package:invoiceninja_flutter/redux/quote/quote_reducer.dart';
|
||||||
|
|
||||||
// STARTER: import - do not remove comment
|
// STARTER: import - do not remove comment
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_reducer.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/credit/credit_reducer.dart';
|
import 'package:invoiceninja_flutter/redux/credit/credit_reducer.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/user/user_reducer.dart';
|
import 'package:invoiceninja_flutter/redux/user/user_reducer.dart';
|
||||||
|
|
@ -40,6 +42,7 @@ UserCompanyState companyReducer(UserCompanyState state, dynamic action) {
|
||||||
..vendorState.replace(vendorsReducer(state.vendorState, action))
|
..vendorState.replace(vendorsReducer(state.vendorState, action))
|
||||||
..taskState.replace(tasksReducer(state.taskState, action))
|
..taskState.replace(tasksReducer(state.taskState, action))
|
||||||
// STARTER: reducer - do not remove comment
|
// STARTER: reducer - do not remove comment
|
||||||
|
..designState.replace(designsReducer(state.designState, action))
|
||||||
..creditState.replace(creditsReducer(state.creditState, action))
|
..creditState.replace(creditsReducer(state.creditState, action))
|
||||||
..userState.replace(usersReducer(state.userState, action))
|
..userState.replace(usersReducer(state.userState, action))
|
||||||
..taxRateState.replace(taxRatesReducer(state.taxRateState, action))
|
..taxRateState.replace(taxRatesReducer(state.taxRateState, action))
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
import 'package:built_value/built_value.dart';
|
import 'package:built_value/built_value.dart';
|
||||||
import 'package:built_value/serializer.dart';
|
import 'package:built_value/serializer.dart';
|
||||||
// STARTER: import - do not remove comment
|
// STARTER: import - do not remove comment
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_state.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/credit/credit_state.dart';
|
import 'package:invoiceninja_flutter/redux/credit/credit_state.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/user/user_state.dart';
|
import 'package:invoiceninja_flutter/redux/user/user_state.dart';
|
||||||
|
|
@ -39,6 +41,8 @@ abstract class UserCompanyState
|
||||||
paymentState: PaymentState(),
|
paymentState: PaymentState(),
|
||||||
quoteState: QuoteState(),
|
quoteState: QuoteState(),
|
||||||
// STARTER: constructor - do not remove comment
|
// STARTER: constructor - do not remove comment
|
||||||
|
designState: DesignState(),
|
||||||
|
|
||||||
creditState: CreditState(),
|
creditState: CreditState(),
|
||||||
|
|
||||||
userState: UserState(),
|
userState: UserState(),
|
||||||
|
|
@ -74,6 +78,8 @@ abstract class UserCompanyState
|
||||||
QuoteState get quoteState;
|
QuoteState get quoteState;
|
||||||
|
|
||||||
// STARTER: fields - do not remove comment
|
// STARTER: fields - do not remove comment
|
||||||
|
DesignState get designState;
|
||||||
|
|
||||||
CreditState get creditState;
|
CreditState get creditState;
|
||||||
|
|
||||||
UserState get userState;
|
UserState get userState;
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,9 @@ class _$UserCompanyStateSerializer
|
||||||
'quoteState',
|
'quoteState',
|
||||||
serializers.serialize(object.quoteState,
|
serializers.serialize(object.quoteState,
|
||||||
specifiedType: const FullType(QuoteState)),
|
specifiedType: const FullType(QuoteState)),
|
||||||
|
'designState',
|
||||||
|
serializers.serialize(object.designState,
|
||||||
|
specifiedType: const FullType(DesignState)),
|
||||||
'creditState',
|
'creditState',
|
||||||
serializers.serialize(object.creditState,
|
serializers.serialize(object.creditState,
|
||||||
specifiedType: const FullType(CreditState)),
|
specifiedType: const FullType(CreditState)),
|
||||||
|
|
@ -134,6 +137,10 @@ class _$UserCompanyStateSerializer
|
||||||
result.quoteState.replace(serializers.deserialize(value,
|
result.quoteState.replace(serializers.deserialize(value,
|
||||||
specifiedType: const FullType(QuoteState)) as QuoteState);
|
specifiedType: const FullType(QuoteState)) as QuoteState);
|
||||||
break;
|
break;
|
||||||
|
case 'designState':
|
||||||
|
result.designState.replace(serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(DesignState)) as DesignState);
|
||||||
|
break;
|
||||||
case 'creditState':
|
case 'creditState':
|
||||||
result.creditState.replace(serializers.deserialize(value,
|
result.creditState.replace(serializers.deserialize(value,
|
||||||
specifiedType: const FullType(CreditState)) as CreditState);
|
specifiedType: const FullType(CreditState)) as CreditState);
|
||||||
|
|
@ -321,6 +328,8 @@ class _$UserCompanyState extends UserCompanyState {
|
||||||
@override
|
@override
|
||||||
final QuoteState quoteState;
|
final QuoteState quoteState;
|
||||||
@override
|
@override
|
||||||
|
final DesignState designState;
|
||||||
|
@override
|
||||||
final CreditState creditState;
|
final CreditState creditState;
|
||||||
@override
|
@override
|
||||||
final UserState userState;
|
final UserState userState;
|
||||||
|
|
@ -347,6 +356,7 @@ class _$UserCompanyState extends UserCompanyState {
|
||||||
this.projectState,
|
this.projectState,
|
||||||
this.paymentState,
|
this.paymentState,
|
||||||
this.quoteState,
|
this.quoteState,
|
||||||
|
this.designState,
|
||||||
this.creditState,
|
this.creditState,
|
||||||
this.userState,
|
this.userState,
|
||||||
this.taxRateState,
|
this.taxRateState,
|
||||||
|
|
@ -383,6 +393,9 @@ class _$UserCompanyState extends UserCompanyState {
|
||||||
if (quoteState == null) {
|
if (quoteState == null) {
|
||||||
throw new BuiltValueNullFieldError('UserCompanyState', 'quoteState');
|
throw new BuiltValueNullFieldError('UserCompanyState', 'quoteState');
|
||||||
}
|
}
|
||||||
|
if (designState == null) {
|
||||||
|
throw new BuiltValueNullFieldError('UserCompanyState', 'designState');
|
||||||
|
}
|
||||||
if (creditState == null) {
|
if (creditState == null) {
|
||||||
throw new BuiltValueNullFieldError('UserCompanyState', 'creditState');
|
throw new BuiltValueNullFieldError('UserCompanyState', 'creditState');
|
||||||
}
|
}
|
||||||
|
|
@ -424,6 +437,7 @@ class _$UserCompanyState extends UserCompanyState {
|
||||||
projectState == other.projectState &&
|
projectState == other.projectState &&
|
||||||
paymentState == other.paymentState &&
|
paymentState == other.paymentState &&
|
||||||
quoteState == other.quoteState &&
|
quoteState == other.quoteState &&
|
||||||
|
designState == other.designState &&
|
||||||
creditState == other.creditState &&
|
creditState == other.creditState &&
|
||||||
userState == other.userState &&
|
userState == other.userState &&
|
||||||
taxRateState == other.taxRateState &&
|
taxRateState == other.taxRateState &&
|
||||||
|
|
@ -447,6 +461,7 @@ class _$UserCompanyState extends UserCompanyState {
|
||||||
$jc(
|
$jc(
|
||||||
$jc(
|
$jc(
|
||||||
$jc(
|
$jc(
|
||||||
|
$jc(
|
||||||
$jc(
|
$jc(
|
||||||
$jc(
|
$jc(
|
||||||
0,
|
0,
|
||||||
|
|
@ -456,7 +471,8 @@ class _$UserCompanyState extends UserCompanyState {
|
||||||
.hashCode),
|
.hashCode),
|
||||||
productState
|
productState
|
||||||
.hashCode),
|
.hashCode),
|
||||||
clientState.hashCode),
|
clientState
|
||||||
|
.hashCode),
|
||||||
invoiceState.hashCode),
|
invoiceState.hashCode),
|
||||||
expenseState.hashCode),
|
expenseState.hashCode),
|
||||||
vendorState.hashCode),
|
vendorState.hashCode),
|
||||||
|
|
@ -464,6 +480,7 @@ class _$UserCompanyState extends UserCompanyState {
|
||||||
projectState.hashCode),
|
projectState.hashCode),
|
||||||
paymentState.hashCode),
|
paymentState.hashCode),
|
||||||
quoteState.hashCode),
|
quoteState.hashCode),
|
||||||
|
designState.hashCode),
|
||||||
creditState.hashCode),
|
creditState.hashCode),
|
||||||
userState.hashCode),
|
userState.hashCode),
|
||||||
taxRateState.hashCode),
|
taxRateState.hashCode),
|
||||||
|
|
@ -485,6 +502,7 @@ class _$UserCompanyState extends UserCompanyState {
|
||||||
..add('projectState', projectState)
|
..add('projectState', projectState)
|
||||||
..add('paymentState', paymentState)
|
..add('paymentState', paymentState)
|
||||||
..add('quoteState', quoteState)
|
..add('quoteState', quoteState)
|
||||||
|
..add('designState', designState)
|
||||||
..add('creditState', creditState)
|
..add('creditState', creditState)
|
||||||
..add('userState', userState)
|
..add('userState', userState)
|
||||||
..add('taxRateState', taxRateState)
|
..add('taxRateState', taxRateState)
|
||||||
|
|
@ -563,6 +581,12 @@ class UserCompanyStateBuilder
|
||||||
set quoteState(QuoteStateBuilder quoteState) =>
|
set quoteState(QuoteStateBuilder quoteState) =>
|
||||||
_$this._quoteState = quoteState;
|
_$this._quoteState = quoteState;
|
||||||
|
|
||||||
|
DesignStateBuilder _designState;
|
||||||
|
DesignStateBuilder get designState =>
|
||||||
|
_$this._designState ??= new DesignStateBuilder();
|
||||||
|
set designState(DesignStateBuilder designState) =>
|
||||||
|
_$this._designState = designState;
|
||||||
|
|
||||||
CreditStateBuilder _creditState;
|
CreditStateBuilder _creditState;
|
||||||
CreditStateBuilder get creditState =>
|
CreditStateBuilder get creditState =>
|
||||||
_$this._creditState ??= new CreditStateBuilder();
|
_$this._creditState ??= new CreditStateBuilder();
|
||||||
|
|
@ -607,6 +631,7 @@ class UserCompanyStateBuilder
|
||||||
_projectState = _$v.projectState?.toBuilder();
|
_projectState = _$v.projectState?.toBuilder();
|
||||||
_paymentState = _$v.paymentState?.toBuilder();
|
_paymentState = _$v.paymentState?.toBuilder();
|
||||||
_quoteState = _$v.quoteState?.toBuilder();
|
_quoteState = _$v.quoteState?.toBuilder();
|
||||||
|
_designState = _$v.designState?.toBuilder();
|
||||||
_creditState = _$v.creditState?.toBuilder();
|
_creditState = _$v.creditState?.toBuilder();
|
||||||
_userState = _$v.userState?.toBuilder();
|
_userState = _$v.userState?.toBuilder();
|
||||||
_taxRateState = _$v.taxRateState?.toBuilder();
|
_taxRateState = _$v.taxRateState?.toBuilder();
|
||||||
|
|
@ -647,6 +672,7 @@ class UserCompanyStateBuilder
|
||||||
projectState: projectState.build(),
|
projectState: projectState.build(),
|
||||||
paymentState: paymentState.build(),
|
paymentState: paymentState.build(),
|
||||||
quoteState: quoteState.build(),
|
quoteState: quoteState.build(),
|
||||||
|
designState: designState.build(),
|
||||||
creditState: creditState.build(),
|
creditState: creditState.build(),
|
||||||
userState: userState.build(),
|
userState: userState.build(),
|
||||||
taxRateState: taxRateState.build(),
|
taxRateState: taxRateState.build(),
|
||||||
|
|
@ -677,6 +703,8 @@ class UserCompanyStateBuilder
|
||||||
paymentState.build();
|
paymentState.build();
|
||||||
_$failedField = 'quoteState';
|
_$failedField = 'quoteState';
|
||||||
quoteState.build();
|
quoteState.build();
|
||||||
|
_$failedField = 'designState';
|
||||||
|
designState.build();
|
||||||
_$failedField = 'creditState';
|
_$failedField = 'creditState';
|
||||||
creditState.build();
|
creditState.build();
|
||||||
_$failedField = 'userState';
|
_$failedField = 'userState';
|
||||||
|
|
|
||||||
|
|
@ -292,7 +292,9 @@ Middleware<AppState> _loadCredit(CreditRepository repository) {
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dispatch(LoadCreditRequest());
|
store.dispatch(LoadCreditRequest());
|
||||||
repository.loadItem(store.state.credentials, action.creditId).then((credit) {
|
repository
|
||||||
|
.loadItem(store.state.credentials, action.creditId)
|
||||||
|
.then((credit) {
|
||||||
store.dispatch(LoadCreditSuccess(credit));
|
store.dispatch(LoadCreditSuccess(credit));
|
||||||
|
|
||||||
if (action.completer != null) {
|
if (action.completer != null) {
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,8 @@ Reducer<String> selectedIdReducer = combineReducers([
|
||||||
TypedReducer<String, ViewCredit>((selectedId, action) => action.creditId),
|
TypedReducer<String, ViewCredit>((selectedId, action) => action.creditId),
|
||||||
TypedReducer<String, AddCreditSuccess>(
|
TypedReducer<String, AddCreditSuccess>(
|
||||||
(selectedId, action) => action.credit.id),
|
(selectedId, action) => action.credit.id),
|
||||||
TypedReducer<String, ShowEmailCredit>((selectedId, action) => action.credit.id),
|
TypedReducer<String, ShowEmailCredit>(
|
||||||
|
(selectedId, action) => action.credit.id),
|
||||||
TypedReducer<String, SelectCompany>((selectedId, action) => ''),
|
TypedReducer<String, SelectCompany>((selectedId, action) => ''),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -227,7 +228,8 @@ ListUIState _addToListMultiselect(
|
||||||
|
|
||||||
ListUIState _removeFromListMultiselect(
|
ListUIState _removeFromListMultiselect(
|
||||||
ListUIState creditListState, RemoveFromCreditMultiselect action) {
|
ListUIState creditListState, RemoveFromCreditMultiselect action) {
|
||||||
return creditListState.rebuild((b) => b..selectedIds.remove(action.entity.id));
|
return creditListState
|
||||||
|
.rebuild((b) => b..selectedIds.remove(action.entity.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
ListUIState _clearListMultiselect(
|
ListUIState _clearListMultiselect(
|
||||||
|
|
@ -368,5 +370,6 @@ CreditState _updateCredit(CreditState creditState, dynamic action) {
|
||||||
return creditState.rebuild((b) => b..map[action.credit.id] = action.credit);
|
return creditState.rebuild((b) => b..map[action.credit.id] = action.credit);
|
||||||
}
|
}
|
||||||
|
|
||||||
CreditState _setLoadedCredits(CreditState creditState, LoadCreditsSuccess action) =>
|
CreditState _setLoadedCredits(
|
||||||
|
CreditState creditState, LoadCreditsSuccess action) =>
|
||||||
creditState.loadCredits(action.credits);
|
creditState.loadCredits(action.credits);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@ ClientEntity creditClientSelector(
|
||||||
return clientMap[credit.clientId];
|
return clientMap[credit.clientId];
|
||||||
}
|
}
|
||||||
|
|
||||||
var memoizedFilteredCreditList = memo4((BuiltMap<String, InvoiceEntity> creditMap,
|
var memoizedFilteredCreditList = memo4((BuiltMap<String, InvoiceEntity>
|
||||||
|
creditMap,
|
||||||
BuiltList<String> creditList,
|
BuiltList<String> creditList,
|
||||||
BuiltMap<String, ClientEntity> clientMap,
|
BuiltMap<String, ClientEntity> clientMap,
|
||||||
ListUIState creditListState) =>
|
ListUIState creditListState) =>
|
||||||
|
|
@ -91,7 +92,7 @@ var memoizedCreditStatsForUser = memo2(
|
||||||
EntityStats creditStatsForUser(
|
EntityStats creditStatsForUser(
|
||||||
String userId,
|
String userId,
|
||||||
BuiltMap<String, InvoiceEntity> creditMap,
|
BuiltMap<String, InvoiceEntity> creditMap,
|
||||||
) {
|
) {
|
||||||
int countActive = 0;
|
int countActive = 0;
|
||||||
int countArchived = 0;
|
int countArchived = 0;
|
||||||
creditMap.forEach((creditId, credit) {
|
creditMap.forEach((creditId, credit) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,335 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:built_collection/built_collection.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
|
import 'package:invoiceninja_flutter/constants.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||||
|
|
||||||
|
class ViewDesignList extends AbstractNavigatorAction implements PersistUI {
|
||||||
|
ViewDesignList({
|
||||||
|
@required NavigatorState navigator,
|
||||||
|
this.force = false,
|
||||||
|
}) : super(navigator: navigator);
|
||||||
|
|
||||||
|
final bool force;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewDesign extends AbstractNavigatorAction
|
||||||
|
implements PersistUI, PersistPrefs {
|
||||||
|
ViewDesign({
|
||||||
|
@required NavigatorState navigator,
|
||||||
|
@required this.designId,
|
||||||
|
this.force = false,
|
||||||
|
}) : super(navigator: navigator);
|
||||||
|
|
||||||
|
final String designId;
|
||||||
|
final bool force;
|
||||||
|
}
|
||||||
|
|
||||||
|
class EditDesign extends AbstractNavigatorAction
|
||||||
|
implements PersistUI, PersistPrefs {
|
||||||
|
EditDesign(
|
||||||
|
{@required this.design,
|
||||||
|
@required NavigatorState navigator,
|
||||||
|
this.completer,
|
||||||
|
this.cancelCompleter,
|
||||||
|
this.force = false})
|
||||||
|
: super(navigator: navigator);
|
||||||
|
|
||||||
|
final DesignEntity design;
|
||||||
|
final Completer completer;
|
||||||
|
final Completer cancelCompleter;
|
||||||
|
final bool force;
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateDesign implements PersistUI {
|
||||||
|
UpdateDesign(this.design);
|
||||||
|
|
||||||
|
final DesignEntity design;
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadDesign {
|
||||||
|
LoadDesign({this.completer, this.designId});
|
||||||
|
|
||||||
|
final Completer completer;
|
||||||
|
final String designId;
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadDesignActivity {
|
||||||
|
LoadDesignActivity({this.completer, this.designId});
|
||||||
|
|
||||||
|
final Completer completer;
|
||||||
|
final String designId;
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadDesigns {
|
||||||
|
LoadDesigns({this.completer, this.force = false});
|
||||||
|
|
||||||
|
final Completer completer;
|
||||||
|
final bool force;
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadDesignRequest implements StartLoading {}
|
||||||
|
|
||||||
|
class LoadDesignFailure implements StopLoading {
|
||||||
|
LoadDesignFailure(this.error);
|
||||||
|
|
||||||
|
final dynamic error;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LoadDesignFailure{error: $error}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadDesignSuccess implements StopLoading, PersistData {
|
||||||
|
LoadDesignSuccess(this.design);
|
||||||
|
|
||||||
|
final DesignEntity design;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LoadDesignSuccess{design: $design}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadDesignsRequest implements StartLoading {}
|
||||||
|
|
||||||
|
class LoadDesignsFailure implements StopLoading {
|
||||||
|
LoadDesignsFailure(this.error);
|
||||||
|
|
||||||
|
final dynamic error;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LoadDesignsFailure{error: $error}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadDesignsSuccess implements StopLoading, PersistData {
|
||||||
|
LoadDesignsSuccess(this.designs);
|
||||||
|
|
||||||
|
final BuiltList<DesignEntity> designs;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LoadDesignsSuccess{designs: $designs}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SaveDesignRequest implements StartSaving {
|
||||||
|
SaveDesignRequest({this.completer, this.design});
|
||||||
|
|
||||||
|
final Completer completer;
|
||||||
|
final DesignEntity design;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SaveDesignSuccess implements StopSaving, PersistData, PersistUI {
|
||||||
|
SaveDesignSuccess(this.design);
|
||||||
|
|
||||||
|
final DesignEntity design;
|
||||||
|
}
|
||||||
|
|
||||||
|
class AddDesignSuccess implements StopSaving, PersistData, PersistUI {
|
||||||
|
AddDesignSuccess(this.design);
|
||||||
|
|
||||||
|
final DesignEntity design;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SaveDesignFailure implements StopSaving {
|
||||||
|
SaveDesignFailure(this.error);
|
||||||
|
|
||||||
|
final Object error;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ArchiveDesignsRequest implements StartSaving {
|
||||||
|
ArchiveDesignsRequest(this.completer, this.designIds);
|
||||||
|
|
||||||
|
final Completer completer;
|
||||||
|
final List<String> designIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ArchiveDesignsSuccess implements StopSaving, PersistData {
|
||||||
|
ArchiveDesignsSuccess(this.designs);
|
||||||
|
|
||||||
|
final List<DesignEntity> designs;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ArchiveDesignsFailure implements StopSaving {
|
||||||
|
ArchiveDesignsFailure(this.designs);
|
||||||
|
|
||||||
|
final List<DesignEntity> designs;
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeleteDesignsRequest implements StartSaving {
|
||||||
|
DeleteDesignsRequest(this.completer, this.designIds);
|
||||||
|
|
||||||
|
final Completer completer;
|
||||||
|
final List<String> designIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeleteDesignsSuccess implements StopSaving, PersistData {
|
||||||
|
DeleteDesignsSuccess(this.designs);
|
||||||
|
|
||||||
|
final List<DesignEntity> designs;
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeleteDesignsFailure implements StopSaving {
|
||||||
|
DeleteDesignsFailure(this.designs);
|
||||||
|
|
||||||
|
final List<DesignEntity> designs;
|
||||||
|
}
|
||||||
|
|
||||||
|
class RestoreDesignsRequest implements StartSaving {
|
||||||
|
RestoreDesignsRequest(this.completer, this.designIds);
|
||||||
|
|
||||||
|
final Completer completer;
|
||||||
|
final List<String> designIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
class RestoreDesignsSuccess implements StopSaving, PersistData {
|
||||||
|
RestoreDesignsSuccess(this.design);
|
||||||
|
|
||||||
|
final List<DesignEntity> designs;
|
||||||
|
}
|
||||||
|
|
||||||
|
class RestoreDesignsFailure implements StopSaving {
|
||||||
|
RestoreDesignsFailure(this.design);
|
||||||
|
|
||||||
|
final List<DesignEntity> designs;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FilterDesigns implements PersistUI {
|
||||||
|
FilterDesigns(this.filter);
|
||||||
|
|
||||||
|
final String filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SortDesigns implements PersistUI {
|
||||||
|
SortDesigns(this.field);
|
||||||
|
|
||||||
|
final String field;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FilterDesignsByState implements PersistUI {
|
||||||
|
FilterDesignsByState(this.state);
|
||||||
|
|
||||||
|
final EntityState state;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FilterDesignsByCustom1 implements PersistUI {
|
||||||
|
FilterDesignsByCustom1(this.value);
|
||||||
|
|
||||||
|
final String value;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FilterDesignsByCustom2 implements PersistUI {
|
||||||
|
FilterDesignsByCustom2(this.value);
|
||||||
|
|
||||||
|
final String value;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FilterDesignsByCustom3 implements PersistUI {
|
||||||
|
FilterDesignsByCustom3(this.value);
|
||||||
|
|
||||||
|
final String value;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FilterDesignsByCustom4 implements PersistUI {
|
||||||
|
FilterDesignsByCustom4(this.value);
|
||||||
|
|
||||||
|
final String value;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FilterDesignsByEntity implements PersistUI {
|
||||||
|
FilterDesignsByEntity({this.entityId, this.entityType});
|
||||||
|
|
||||||
|
final String entityId;
|
||||||
|
final EntityType entityType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleDesignAction(
|
||||||
|
BuildContext context, List<BaseEntity> designs, EntityAction action) {
|
||||||
|
if (designs.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final store = StoreProvider.of<AppState>(context);
|
||||||
|
final state = store.state;
|
||||||
|
final CompanyEntity company = state.company;
|
||||||
|
final localization = AppLocalization.of(context);
|
||||||
|
final design = designs.first as DesignEntity;
|
||||||
|
final designIds = designs.map((design) => design.id).toList();
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case EntityAction.edit:
|
||||||
|
editEntity(context: context, entity: design);
|
||||||
|
break;
|
||||||
|
case EntityAction.restore:
|
||||||
|
store.dispatch(RestoreDesignsRequest(
|
||||||
|
snackBarCompleter<Null>(context, localization.restoredDesign),
|
||||||
|
designIds));
|
||||||
|
break;
|
||||||
|
case EntityAction.archive:
|
||||||
|
store.dispatch(ArchiveDesignsRequest(
|
||||||
|
snackBarCompleter<Null>(context, localization.archivedDesign),
|
||||||
|
designIds));
|
||||||
|
break;
|
||||||
|
case EntityAction.delete:
|
||||||
|
store.dispatch(DeleteDesignsRequest(
|
||||||
|
snackBarCompleter<Null>(context, localization.deletedDesign),
|
||||||
|
designIds));
|
||||||
|
break;
|
||||||
|
case EntityAction.toggleMultiselect:
|
||||||
|
if (!store.state.designListState.isInMultiselect()) {
|
||||||
|
store.dispatch(StartDesignMultiselect(context: context));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (designs.isEmpty) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final design in designs) {
|
||||||
|
if (!store.state.designListState.isSelected(design.id)) {
|
||||||
|
store.dispatch(
|
||||||
|
AddToDesignMultiselect(context: context, entity: design));
|
||||||
|
} else {
|
||||||
|
store.dispatch(
|
||||||
|
RemoveFromDesignMultiselect(context: context, entity: design));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StartDesignMultiselect {
|
||||||
|
StartDesignMultiselect({@required this.context});
|
||||||
|
|
||||||
|
final BuildContext context;
|
||||||
|
}
|
||||||
|
|
||||||
|
class AddToDesignMultiselect {
|
||||||
|
AddToDesignMultiselect({@required this.context, @required this.entity});
|
||||||
|
|
||||||
|
final BuildContext context;
|
||||||
|
final BaseEntity entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
class RemoveFromDesignMultiselect {
|
||||||
|
RemoveFromDesignMultiselect({@required this.context, @required this.entity});
|
||||||
|
|
||||||
|
final BuildContext context;
|
||||||
|
final BaseEntity entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClearDesignMultiselect {
|
||||||
|
ClearDesignMultiselect({@required this.context});
|
||||||
|
|
||||||
|
final BuildContext context;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,275 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:redux/redux.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_middleware.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/design_screen.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/edit/design_edit_vm.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/view/design_view_vm.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/repositories/design_repository.dart';
|
||||||
|
|
||||||
|
List<Middleware<AppState>> createStoreDesignsMiddleware([
|
||||||
|
DesignRepository repository = const DesignRepository(),
|
||||||
|
]) {
|
||||||
|
final viewDesignList = _viewDesignList();
|
||||||
|
final viewDesign = _viewDesign();
|
||||||
|
final editDesign = _editDesign();
|
||||||
|
final loadDesigns = _loadDesigns(repository);
|
||||||
|
final loadDesign = _loadDesign(repository);
|
||||||
|
final saveDesign = _saveDesign(repository);
|
||||||
|
final archiveDesign = _archiveDesign(repository);
|
||||||
|
final deleteDesign = _deleteDesign(repository);
|
||||||
|
final restoreDesign = _restoreDesign(repository);
|
||||||
|
|
||||||
|
return [
|
||||||
|
TypedMiddleware<AppState, ViewDesignList>(viewDesignList),
|
||||||
|
TypedMiddleware<AppState, ViewDesign>(viewDesign),
|
||||||
|
TypedMiddleware<AppState, EditDesign>(editDesign),
|
||||||
|
TypedMiddleware<AppState, LoadDesigns>(loadDesigns),
|
||||||
|
TypedMiddleware<AppState, LoadDesign>(loadDesign),
|
||||||
|
TypedMiddleware<AppState, SaveDesignRequest>(saveDesign),
|
||||||
|
TypedMiddleware<AppState, ArchiveDesignRequest>(archiveDesign),
|
||||||
|
TypedMiddleware<AppState, DeleteDesignRequest>(deleteDesign),
|
||||||
|
TypedMiddleware<AppState, RestoreDesignRequest>(restoreDesign),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
Middleware<AppState> _editDesign() {
|
||||||
|
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
|
||||||
|
final action = dynamicAction as EditDesign;
|
||||||
|
|
||||||
|
if (!action.force &&
|
||||||
|
hasChanges(store: store, context: action.context, action: action)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
next(action);
|
||||||
|
|
||||||
|
store.dispatch(UpdateCurrentRoute(DesignEditScreen.route));
|
||||||
|
|
||||||
|
if (isMobile(action.context)) {
|
||||||
|
action.navigator.pushNamed(DesignEditScreen.route);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Middleware<AppState> _viewDesign() {
|
||||||
|
return (Store<AppState> store, dynamic dynamicAction,
|
||||||
|
NextDispatcher next) async {
|
||||||
|
final action = dynamicAction as ViewDesign;
|
||||||
|
|
||||||
|
if (!action.force &&
|
||||||
|
hasChanges(store: store, context: action.context, action: action)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
next(action);
|
||||||
|
|
||||||
|
store.dispatch(UpdateCurrentRoute(DesignViewScreen.route));
|
||||||
|
|
||||||
|
if (isMobile(action.context)) {
|
||||||
|
Navigator.of(action.context).pushNamed(DesignViewScreen.route);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Middleware<AppState> _viewDesignList() {
|
||||||
|
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
|
||||||
|
final action = dynamicAction as ViewDesignList;
|
||||||
|
|
||||||
|
if (!action.force &&
|
||||||
|
hasChanges(store: store, context: action.context, action: action)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
next(action);
|
||||||
|
|
||||||
|
if (store.state.designState.isStale) {
|
||||||
|
store.dispatch(LoadDesigns());
|
||||||
|
}
|
||||||
|
|
||||||
|
store.dispatch(UpdateCurrentRoute(DesignScreen.route));
|
||||||
|
|
||||||
|
if (isMobile(action.context)) {
|
||||||
|
Navigator.of(action.context).pushNamedAndRemoveUntil(
|
||||||
|
DesignScreen.route, (Route<dynamic> route) => false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Middleware<AppState> _archiveDesign(DesignRepository repository) {
|
||||||
|
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
|
||||||
|
final action = dynamicAction as ArchiveDesignsRequest;
|
||||||
|
final prevDesigns =
|
||||||
|
action.designIds.map((id) => store.state.designState.map[id]).toList();
|
||||||
|
repository
|
||||||
|
.bulkAction(
|
||||||
|
store.state.credentials, action.designIds, EntityAction.archive)
|
||||||
|
.then((List<DesignEntity> designs) {
|
||||||
|
store.dispatch(ArchiveDesignsSuccess(designs));
|
||||||
|
if (action.completer != null) {
|
||||||
|
action.completer.complete(null);
|
||||||
|
}
|
||||||
|
}).catchError((Object error) {
|
||||||
|
print(error);
|
||||||
|
store.dispatch(ArchiveDesignsFailure(prevDesigns));
|
||||||
|
if (action.completer != null) {
|
||||||
|
action.completer.completeError(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
next(action);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Middleware<AppState> _deleteDesign(DesignRepository repository) {
|
||||||
|
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
|
||||||
|
final action = dynamicAction as DeleteDesignsRequest;
|
||||||
|
final prevDesigns =
|
||||||
|
action.designIds.map((id) => store.state.designState.map[id]).toList();
|
||||||
|
repository
|
||||||
|
.bulkAction(
|
||||||
|
store.state.credentials, action.designIds, EntityAction.delete)
|
||||||
|
.then((List<DesignEntity> designs) {
|
||||||
|
store.dispatch(DeleteDesignsSuccess(designs));
|
||||||
|
if (action.completer != null) {
|
||||||
|
action.completer.complete(null);
|
||||||
|
}
|
||||||
|
}).catchError((Object error) {
|
||||||
|
print(error);
|
||||||
|
store.dispatch(DeleteDesignsFailure(prevDesigns));
|
||||||
|
if (action.completer != null) {
|
||||||
|
action.completer.completeError(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
next(action);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Middleware<AppState> _restoreDesign(DesignRepository repository) {
|
||||||
|
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
|
||||||
|
final action = dynamicAction as RestoreDesignsRequest;
|
||||||
|
final prevDesigns =
|
||||||
|
action.designIds.map((id) => store.state.designState.map[id]).toList();
|
||||||
|
repository
|
||||||
|
.bulkAction(
|
||||||
|
store.state.credentials, action.designIds, EntityAction.restore)
|
||||||
|
.then((List<DesignEntity> designs) {
|
||||||
|
store.dispatch(RestoreDesignSuccess(designs));
|
||||||
|
if (action.completer != null) {
|
||||||
|
action.completer.complete(null);
|
||||||
|
}
|
||||||
|
}).catchError((Object error) {
|
||||||
|
print(error);
|
||||||
|
store.dispatch(RestoreDesignFailure(prevDesigns));
|
||||||
|
if (action.completer != null) {
|
||||||
|
action.completer.completeError(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
next(action);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Middleware<AppState> _saveDesign(DesignRepository repository) {
|
||||||
|
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
|
||||||
|
final action = dynamicAction as SaveDesignRequest;
|
||||||
|
repository
|
||||||
|
.saveData(store.state.credentials, action.design)
|
||||||
|
.then((DesignEntity design) {
|
||||||
|
if (action.design.isNew) {
|
||||||
|
store.dispatch(AddDesignSuccess(design));
|
||||||
|
} else {
|
||||||
|
store.dispatch(SaveDesignSuccess(design));
|
||||||
|
}
|
||||||
|
|
||||||
|
action.completer.complete(design);
|
||||||
|
|
||||||
|
final designUIState = store.state.designUIState;
|
||||||
|
if (designUIState.saveCompleter != null) {
|
||||||
|
designUIState.saveCompleter.complete(design);
|
||||||
|
}
|
||||||
|
}).catchError((Object error) {
|
||||||
|
print(error);
|
||||||
|
store.dispatch(SaveDesignFailure(error));
|
||||||
|
action.completer.completeError(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
next(action);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Middleware<AppState> _loadDesign(DesignRepository repository) {
|
||||||
|
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
|
||||||
|
final action = dynamicAction as LoadDesign;
|
||||||
|
final AppState state = store.state;
|
||||||
|
|
||||||
|
if (state.isLoading) {
|
||||||
|
next(action);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
store.dispatch(LoadDesignRequest());
|
||||||
|
repository.loadItem(state.credentials, action.designId).then((design) {
|
||||||
|
store.dispatch(LoadDesignSuccess(design));
|
||||||
|
|
||||||
|
if (action.completer != null) {
|
||||||
|
action.completer.complete(null);
|
||||||
|
}
|
||||||
|
}).catchError((Object error) {
|
||||||
|
print(error);
|
||||||
|
store.dispatch(LoadDesignFailure(error));
|
||||||
|
if (action.completer != null) {
|
||||||
|
action.completer.completeError(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
next(action);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Middleware<AppState> _loadDesigns(DesignRepository repository) {
|
||||||
|
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
|
||||||
|
final action = dynamicAction as LoadDesigns;
|
||||||
|
final AppState state = store.state;
|
||||||
|
|
||||||
|
if (!state.designState.isStale && !action.force) {
|
||||||
|
next(action);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.isLoading) {
|
||||||
|
next(action);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int updatedAt = (state.designState.lastUpdated / 1000).round();
|
||||||
|
|
||||||
|
store.dispatch(LoadDesignsRequest());
|
||||||
|
repository.loadList(state.credentials, updatedAt).then((data) {
|
||||||
|
store.dispatch(LoadDesignsSuccess(data));
|
||||||
|
|
||||||
|
if (action.completer != null) {
|
||||||
|
action.completer.complete(null);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if (state.productState.isStale) {
|
||||||
|
store.dispatch(LoadProducts());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}).catchError((Object error) {
|
||||||
|
print(error);
|
||||||
|
store.dispatch(LoadDesignsFailure(error));
|
||||||
|
if (action.completer != null) {
|
||||||
|
action.completer.completeError(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
next(action);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,275 @@
|
||||||
|
import 'package:redux/redux.dart';
|
||||||
|
import 'package:built_collection/built_collection.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/company/company_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/ui/entity_ui_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
||||||
|
|
||||||
|
EntityUIState designUIReducer(DesignUIState state, dynamic action) {
|
||||||
|
return state.rebuild((b) => b
|
||||||
|
..listUIState.replace(designListReducer(state.listUIState, action))
|
||||||
|
..editing.replace(editingReducer(state.editing, action))
|
||||||
|
..selectedId = selectedIdReducer(state.selectedId, action));
|
||||||
|
}
|
||||||
|
|
||||||
|
Reducer<String> selectedIdReducer = combineReducers([
|
||||||
|
TypedReducer<String, ViewDesign>(
|
||||||
|
(String selectedId, dynamic action) => action.designId),
|
||||||
|
TypedReducer<String, AddDesignSuccess>(
|
||||||
|
(String selectedId, dynamic action) => action.design.id),
|
||||||
|
TypedReducer<String, SelectCompany>((selectedId, action) => ''),
|
||||||
|
]);
|
||||||
|
|
||||||
|
final editingReducer = combineReducers<DesignEntity>([
|
||||||
|
TypedReducer<DesignEntity, SaveDesignSuccess>(_updateEditing),
|
||||||
|
TypedReducer<DesignEntity, AddDesignSuccess>(_updateEditing),
|
||||||
|
TypedReducer<DesignEntity, RestoreDesignSuccess>((designs, action) {
|
||||||
|
return action.designs[0];
|
||||||
|
}),
|
||||||
|
TypedReducer<DesignEntity, ArchiveDesignSuccess>((designs, action) {
|
||||||
|
return action.designs[0];
|
||||||
|
}),
|
||||||
|
TypedReducer<DesignEntity, DeleteDesignSuccess>((designs, action) {
|
||||||
|
return action.designs[0];
|
||||||
|
}),
|
||||||
|
TypedReducer<DesignEntity, EditDesign>(_updateEditing),
|
||||||
|
TypedReducer<DesignEntity, UpdateDesign>((design, action) {
|
||||||
|
return action.design.rebuild((b) => b..isChanged = true);
|
||||||
|
}),
|
||||||
|
TypedReducer<DesignEntity, SelectCompany>(_clearEditing),
|
||||||
|
TypedReducer<DesignEntity, DiscardChanges>(_clearEditing),
|
||||||
|
]);
|
||||||
|
|
||||||
|
DesignEntity _clearEditing(DesignEntity design, dynamic action) {
|
||||||
|
return DesignEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignEntity _updateEditing(DesignEntity design, dynamic action) {
|
||||||
|
return action.design;
|
||||||
|
}
|
||||||
|
|
||||||
|
final designListReducer = combineReducers<ListUIState>([
|
||||||
|
TypedReducer<ListUIState, SortDesigns>(_sortDesigns),
|
||||||
|
TypedReducer<ListUIState, FilterDesignsByState>(_filterDesignsByState),
|
||||||
|
TypedReducer<ListUIState, FilterDesigns>(_filterDesigns),
|
||||||
|
TypedReducer<ListUIState, FilterDesignsByCustom1>(_filterDesignsByCustom1),
|
||||||
|
TypedReducer<ListUIState, FilterDesignsByCustom2>(_filterDesignsByCustom2),
|
||||||
|
TypedReducer<ListUIState, FilterDesignsByEntity>(_filterDesignsByClient),
|
||||||
|
TypedReducer<ListUIState, StartDesignMultiselect>(_startListMultiselect),
|
||||||
|
TypedReducer<ListUIState, AddToDesignMultiselect>(_addToListMultiselect),
|
||||||
|
TypedReducer<ListUIState, RemoveFromDesignMultiselect>(
|
||||||
|
_removeFromListMultiselect),
|
||||||
|
TypedReducer<ListUIState, ClearDesignMultiselect>(_clearListMultiselect),
|
||||||
|
]);
|
||||||
|
|
||||||
|
ListUIState _filterDesignsByClient(
|
||||||
|
ListUIState designListState, FilterDesignsByEntity action) {
|
||||||
|
return designListState.rebuild((b) => b
|
||||||
|
..filterEntityId = action.entityId
|
||||||
|
..filterEntityType = action.entityType);
|
||||||
|
}
|
||||||
|
|
||||||
|
ListUIState _filterDesignsByCustom1(
|
||||||
|
ListUIState designListState, FilterDesignsByCustom1 action) {
|
||||||
|
if (designListState.custom1Filters.contains(action.value)) {
|
||||||
|
return designListState
|
||||||
|
.rebuild((b) => b..custom1Filters.remove(action.value));
|
||||||
|
} else {
|
||||||
|
return designListState.rebuild((b) => b..custom1Filters.add(action.value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListUIState _filterDesignsByCustom2(
|
||||||
|
ListUIState designListState, FilterDesignsByCustom2 action) {
|
||||||
|
if (designListState.custom2Filters.contains(action.value)) {
|
||||||
|
return designListState
|
||||||
|
.rebuild((b) => b..custom2Filters.remove(action.value));
|
||||||
|
} else {
|
||||||
|
return designListState.rebuild((b) => b..custom2Filters.add(action.value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListUIState _filterDesignsByState(
|
||||||
|
ListUIState designListState, FilterDesignsByState action) {
|
||||||
|
if (designListState.stateFilters.contains(action.state)) {
|
||||||
|
return designListState.rebuild((b) => b..stateFilters.remove(action.state));
|
||||||
|
} else {
|
||||||
|
return designListState.rebuild((b) => b..stateFilters.add(action.state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListUIState _filterDesigns(ListUIState designListState, FilterDesigns action) {
|
||||||
|
return designListState.rebuild((b) => b
|
||||||
|
..filter = action.filter
|
||||||
|
..filterClearedAt = action.filter == null
|
||||||
|
? DateTime.now().millisecondsSinceEpoch
|
||||||
|
: designListState.filterClearedAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
ListUIState _sortDesigns(ListUIState designListState, SortDesigns action) {
|
||||||
|
return designListState.rebuild((b) => b
|
||||||
|
..sortAscending = b.sortField != action.field || !b.sortAscending
|
||||||
|
..sortField = action.field);
|
||||||
|
}
|
||||||
|
|
||||||
|
ListUIState _startListMultiselect(
|
||||||
|
ListUIState productListState, StartDesignMultiselect action) {
|
||||||
|
return productListState.rebuild((b) => b..selectedIds = ListBuilder());
|
||||||
|
}
|
||||||
|
|
||||||
|
ListUIState _addToListMultiselect(
|
||||||
|
ListUIState productListState, AddToDesignMultiselect action) {
|
||||||
|
return productListState.rebuild((b) => b..selectedIds.add(action.entity.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
ListUIState _removeFromListMultiselect(
|
||||||
|
ListUIState productListState, RemoveFromDesignMultiselect action) {
|
||||||
|
return productListState
|
||||||
|
.rebuild((b) => b..selectedIds.remove(action.entity.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
ListUIState _clearListMultiselect(
|
||||||
|
ListUIState productListState, ClearDesignMultiselect action) {
|
||||||
|
return productListState.rebuild((b) => b..selectedIds = null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final designsReducer = combineReducers<DesignState>([
|
||||||
|
TypedReducer<DesignState, SaveDesignSuccess>(_updateDesign),
|
||||||
|
TypedReducer<DesignState, AddDesignSuccess>(_addDesign),
|
||||||
|
TypedReducer<DesignState, LoadDesignsSuccess>(_setLoadedDesigns),
|
||||||
|
TypedReducer<DesignState, LoadDesignSuccess>(_setLoadedDesign),
|
||||||
|
TypedReducer<DesignState, ArchiveDesignRequest>(_archiveDesignRequest),
|
||||||
|
TypedReducer<DesignState, ArchiveDesignSuccess>(_archiveDesignSuccess),
|
||||||
|
TypedReducer<DesignState, ArchiveDesignFailure>(_archiveDesignFailure),
|
||||||
|
TypedReducer<DesignState, DeleteDesignRequest>(_deleteDesignRequest),
|
||||||
|
TypedReducer<DesignState, DeleteDesignSuccess>(_deleteDesignSuccess),
|
||||||
|
TypedReducer<DesignState, DeleteDesignFailure>(_deleteDesignFailure),
|
||||||
|
TypedReducer<DesignState, RestoreDesignRequest>(_restoreDesignRequest),
|
||||||
|
TypedReducer<DesignState, RestoreDesignSuccess>(_restoreDesignSuccess),
|
||||||
|
TypedReducer<DesignState, RestoreDesignFailure>(_restoreDesignFailure),
|
||||||
|
]);
|
||||||
|
|
||||||
|
DesignState _archiveDesignRequest(
|
||||||
|
DesignState designState, ArchiveDesignsRequest action) {
|
||||||
|
final designs = action.designIds.map((id) => designState.map[id]).toList();
|
||||||
|
|
||||||
|
for (int i = 0; i < designs.length; i++) {
|
||||||
|
designs[i] = designs[i]
|
||||||
|
.rebuild((b) => b..archivedAt = DateTime.now().millisecondsSinceEpoch);
|
||||||
|
}
|
||||||
|
return designState.rebuild((b) {
|
||||||
|
for (final design in designs) {
|
||||||
|
b.map[design.id] = design;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignState _archiveDesignSuccess(
|
||||||
|
DesignState designState, ArchiveDesignsSuccess action) {
|
||||||
|
return designState.rebuild((b) {
|
||||||
|
for (final design in action.designs) {
|
||||||
|
b.map[design.id] = design;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignState _archiveDesignFailure(
|
||||||
|
DesignState designState, ArchiveDesignsFailure action) {
|
||||||
|
return designState.rebuild((b) {
|
||||||
|
for (final design in action.designs) {
|
||||||
|
b.map[design.id] = design;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignState _deleteDesignRequest(
|
||||||
|
DesignState designState, DeleteDesignsRequest action) {
|
||||||
|
final designs = action.designIds.map((id) => designState.map[id]).toList();
|
||||||
|
|
||||||
|
for (int i = 0; i < designs.length; i++) {
|
||||||
|
designs[i] = designs[i].rebuild((b) => b
|
||||||
|
..archivedAt = DateTime.now().millisecondsSinceEpoch
|
||||||
|
..isDeleted = true);
|
||||||
|
}
|
||||||
|
return designState.rebuild((b) {
|
||||||
|
for (final design in designs) {
|
||||||
|
b.map[design.id] = design;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignState _deleteDesignSuccess(
|
||||||
|
DesignState designState, DeleteDesignsSuccess action) {
|
||||||
|
return designState.rebuild((b) {
|
||||||
|
for (final design in action.designs) {
|
||||||
|
b.map[design.id] = design;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignState _deleteDesignFailure(
|
||||||
|
DesignState designState, DeleteDesignsFailure action) {
|
||||||
|
return designState.rebuild((b) {
|
||||||
|
for (final design in action.designs) {
|
||||||
|
b.map[design.id] = design;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignState _restoreDesignRequest(
|
||||||
|
DesignState designState, RestoreDesignsRequest action) {
|
||||||
|
final designs = action.designIds.map((id) => designState.map[id]).toList();
|
||||||
|
|
||||||
|
for (int i = 0; i < designs.length; i++) {
|
||||||
|
designs[i] = designs[i].rebuild((b) => b
|
||||||
|
..archivedAt = null
|
||||||
|
..isDeleted = false);
|
||||||
|
}
|
||||||
|
return designState.rebuild((b) {
|
||||||
|
for (final design in designs) {
|
||||||
|
b.map[design.id] = design;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignState _restoreDesignSuccess(
|
||||||
|
DesignState designState, RestoreDesignsSuccess action) {
|
||||||
|
return designState.rebuild((b) {
|
||||||
|
for (final design in action.designs) {
|
||||||
|
b.map[design.id] = design;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignState _restoreDesignFailure(
|
||||||
|
DesignState designState, RestoreDesignsFailure action) {
|
||||||
|
return designState.rebuild((b) {
|
||||||
|
for (final design in action.designs) {
|
||||||
|
b.map[design.id] = design;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignState _addDesign(DesignState designState, AddDesignSuccess action) {
|
||||||
|
return designState.rebuild((b) => b
|
||||||
|
..map[action.design.id] = action.design
|
||||||
|
..list.add(action.design.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignState _updateDesign(DesignState designState, SaveDesignSuccess action) {
|
||||||
|
return designState.rebuild((b) => b..map[action.design.id] = action.design);
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignState _setLoadedDesign(
|
||||||
|
DesignState designState, LoadDesignSuccess action) {
|
||||||
|
return designState.rebuild((b) => b..map[action.design.id] = action.design);
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignState _setLoadedDesigns(
|
||||||
|
DesignState designState, LoadDesignsSuccess action) =>
|
||||||
|
designState.loadDesigns(action.designs);
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
import 'package:invoiceninja_flutter/data/models/design_model.dart';
|
||||||
|
import 'package:memoize/memoize.dart';
|
||||||
|
import 'package:built_collection/built_collection.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
|
||||||
|
|
||||||
|
var memoizedDropdownDesignList = memo3(
|
||||||
|
(BuiltMap<String, DesignEntity> designMap, BuiltList<String> designList,
|
||||||
|
String clientId) =>
|
||||||
|
dropdownDesignsSelector(designMap, designList, clientId));
|
||||||
|
|
||||||
|
List<String> dropdownDesignsSelector(BuiltMap<String, DesignEntity> designMap,
|
||||||
|
BuiltList<String> designList, String clientId) {
|
||||||
|
final list = designList.where((designId) {
|
||||||
|
final design = designMap[designId];
|
||||||
|
/*
|
||||||
|
if (clientId != null && clientId > 0 && design.clientId != clientId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return design.isActive;
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
list.sort((designAId, designBId) {
|
||||||
|
final designA = designMap[designAId];
|
||||||
|
final designB = designMap[designBId];
|
||||||
|
return designA.compareTo(designB, DesignFields.name, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
var memoizedFilteredDesignList = memo3(
|
||||||
|
(BuiltMap<String, DesignEntity> designMap, BuiltList<String> designList,
|
||||||
|
ListUIState designListState) =>
|
||||||
|
filteredDesignsSelector(designMap, designList, designListState));
|
||||||
|
|
||||||
|
List<String> filteredDesignsSelector(BuiltMap<String, DesignEntity> designMap,
|
||||||
|
BuiltList<String> designList, ListUIState designListState) {
|
||||||
|
final list = designList.where((designId) {
|
||||||
|
final design = designMap[designId];
|
||||||
|
if (designListState.filterEntityId != null &&
|
||||||
|
design.entityId != designListState.filterEntityId) {
|
||||||
|
return false;
|
||||||
|
} else {}
|
||||||
|
|
||||||
|
if (!design.matchesStates(designListState.stateFilters)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return design.matchesFilter(designListState.filter);
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
list.sort((designAId, designBId) {
|
||||||
|
final designA = designMap[designAId];
|
||||||
|
final designB = designMap[designBId];
|
||||||
|
return designA.compareTo(
|
||||||
|
designB, designListState.sortField, designListState.sortAscending);
|
||||||
|
});
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasDesignChanges(
|
||||||
|
DesignEntity design, BuiltMap<String, DesignEntity> designMap) =>
|
||||||
|
design.isNew ? design.isChanged : design != designMap[design.id];
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:built_value/built_value.dart';
|
||||||
|
import 'package:built_value/serializer.dart';
|
||||||
|
import 'package:built_collection/built_collection.dart';
|
||||||
|
import 'package:invoiceninja_flutter/constants.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/design_model.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/ui/entity_ui_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
|
||||||
|
part 'design_state.g.dart';
|
||||||
|
|
||||||
|
abstract class DesignState implements Built<DesignState, DesignStateBuilder> {
|
||||||
|
factory DesignState() {
|
||||||
|
return _$DesignState._(
|
||||||
|
lastUpdated: 0,
|
||||||
|
map: BuiltMap<String, DesignEntity>(),
|
||||||
|
list: BuiltList<String>(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
DesignState._();
|
||||||
|
|
||||||
|
@nullable
|
||||||
|
int get lastUpdated;
|
||||||
|
|
||||||
|
BuiltMap<String, DesignEntity> get map;
|
||||||
|
BuiltList<String> get list;
|
||||||
|
|
||||||
|
bool get isStale {
|
||||||
|
if (!isLoaded) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DateTime.now().millisecondsSinceEpoch - lastUpdated >
|
||||||
|
kMillisecondsToRefreshData;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get isLoaded => lastUpdated != null && lastUpdated > 0;
|
||||||
|
|
||||||
|
DesignState loadDesigns(BuiltList<DesignEntity> clients) {
|
||||||
|
final map = Map<String, DesignEntity>.fromIterable(
|
||||||
|
clients,
|
||||||
|
key: (dynamic item) => item.id,
|
||||||
|
value: (dynamic item) => item,
|
||||||
|
);
|
||||||
|
|
||||||
|
return rebuild((b) => b
|
||||||
|
..lastUpdated = DateTime.now().millisecondsSinceEpoch
|
||||||
|
..map.addAll(map)
|
||||||
|
..list.replace(map.keys));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Serializer<DesignState> get serializer => _$designStateSerializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class DesignUIState extends Object
|
||||||
|
with EntityUIState
|
||||||
|
implements Built<DesignUIState, DesignUIStateBuilder> {
|
||||||
|
factory DesignUIState() {
|
||||||
|
return _$DesignUIState._(
|
||||||
|
listUIState: ListUIState(DesignFields.name),
|
||||||
|
editing: DesignEntity(),
|
||||||
|
selectedId: '',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
DesignUIState._();
|
||||||
|
|
||||||
|
@nullable
|
||||||
|
DesignEntity get editing;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isCreatingNew => editing.isNew;
|
||||||
|
|
||||||
|
static Serializer<DesignUIState> get serializer => _$designUIStateSerializer;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,406 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'design_state.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// BuiltValueGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
Serializer<DesignState> _$designStateSerializer = new _$DesignStateSerializer();
|
||||||
|
Serializer<DesignUIState> _$designUIStateSerializer =
|
||||||
|
new _$DesignUIStateSerializer();
|
||||||
|
|
||||||
|
class _$DesignStateSerializer implements StructuredSerializer<DesignState> {
|
||||||
|
@override
|
||||||
|
final Iterable<Type> types = const [DesignState, _$DesignState];
|
||||||
|
@override
|
||||||
|
final String wireName = 'DesignState';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<Object> serialize(Serializers serializers, DesignState object,
|
||||||
|
{FullType specifiedType = FullType.unspecified}) {
|
||||||
|
final result = <Object>[
|
||||||
|
'map',
|
||||||
|
serializers.serialize(object.map,
|
||||||
|
specifiedType: const FullType(BuiltMap,
|
||||||
|
const [const FullType(String), const FullType(DesignEntity)])),
|
||||||
|
'list',
|
||||||
|
serializers.serialize(object.list,
|
||||||
|
specifiedType:
|
||||||
|
const FullType(BuiltList, const [const FullType(String)])),
|
||||||
|
];
|
||||||
|
if (object.lastUpdated != null) {
|
||||||
|
result
|
||||||
|
..add('lastUpdated')
|
||||||
|
..add(serializers.serialize(object.lastUpdated,
|
||||||
|
specifiedType: const FullType(int)));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DesignState deserialize(Serializers serializers, Iterable<Object> serialized,
|
||||||
|
{FullType specifiedType = FullType.unspecified}) {
|
||||||
|
final result = new DesignStateBuilder();
|
||||||
|
|
||||||
|
final iterator = serialized.iterator;
|
||||||
|
while (iterator.moveNext()) {
|
||||||
|
final key = iterator.current as String;
|
||||||
|
iterator.moveNext();
|
||||||
|
final dynamic value = iterator.current;
|
||||||
|
switch (key) {
|
||||||
|
case 'lastUpdated':
|
||||||
|
result.lastUpdated = serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(int)) as int;
|
||||||
|
break;
|
||||||
|
case 'map':
|
||||||
|
result.map.replace(serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(BuiltMap, const [
|
||||||
|
const FullType(String),
|
||||||
|
const FullType(DesignEntity)
|
||||||
|
])));
|
||||||
|
break;
|
||||||
|
case 'list':
|
||||||
|
result.list.replace(serializers.deserialize(value,
|
||||||
|
specifiedType:
|
||||||
|
const FullType(BuiltList, const [const FullType(String)]))
|
||||||
|
as BuiltList<Object>);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$DesignUIStateSerializer implements StructuredSerializer<DesignUIState> {
|
||||||
|
@override
|
||||||
|
final Iterable<Type> types = const [DesignUIState, _$DesignUIState];
|
||||||
|
@override
|
||||||
|
final String wireName = 'DesignUIState';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<Object> serialize(Serializers serializers, DesignUIState object,
|
||||||
|
{FullType specifiedType = FullType.unspecified}) {
|
||||||
|
final result = <Object>[
|
||||||
|
'listUIState',
|
||||||
|
serializers.serialize(object.listUIState,
|
||||||
|
specifiedType: const FullType(ListUIState)),
|
||||||
|
];
|
||||||
|
if (object.editing != null) {
|
||||||
|
result
|
||||||
|
..add('editing')
|
||||||
|
..add(serializers.serialize(object.editing,
|
||||||
|
specifiedType: const FullType(DesignEntity)));
|
||||||
|
}
|
||||||
|
if (object.selectedId != null) {
|
||||||
|
result
|
||||||
|
..add('selectedId')
|
||||||
|
..add(serializers.serialize(object.selectedId,
|
||||||
|
specifiedType: const FullType(String)));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DesignUIState deserialize(
|
||||||
|
Serializers serializers, Iterable<Object> serialized,
|
||||||
|
{FullType specifiedType = FullType.unspecified}) {
|
||||||
|
final result = new DesignUIStateBuilder();
|
||||||
|
|
||||||
|
final iterator = serialized.iterator;
|
||||||
|
while (iterator.moveNext()) {
|
||||||
|
final key = iterator.current as String;
|
||||||
|
iterator.moveNext();
|
||||||
|
final dynamic value = iterator.current;
|
||||||
|
switch (key) {
|
||||||
|
case 'editing':
|
||||||
|
result.editing.replace(serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(DesignEntity)) as DesignEntity);
|
||||||
|
break;
|
||||||
|
case 'listUIState':
|
||||||
|
result.listUIState.replace(serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(ListUIState)) as ListUIState);
|
||||||
|
break;
|
||||||
|
case 'selectedId':
|
||||||
|
result.selectedId = serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(String)) as String;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$DesignState extends DesignState {
|
||||||
|
@override
|
||||||
|
final int lastUpdated;
|
||||||
|
@override
|
||||||
|
final BuiltMap<String, DesignEntity> map;
|
||||||
|
@override
|
||||||
|
final BuiltList<String> list;
|
||||||
|
|
||||||
|
factory _$DesignState([void Function(DesignStateBuilder) updates]) =>
|
||||||
|
(new DesignStateBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
_$DesignState._({this.lastUpdated, this.map, this.list}) : super._() {
|
||||||
|
if (map == null) {
|
||||||
|
throw new BuiltValueNullFieldError('DesignState', 'map');
|
||||||
|
}
|
||||||
|
if (list == null) {
|
||||||
|
throw new BuiltValueNullFieldError('DesignState', 'list');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DesignState rebuild(void Function(DesignStateBuilder) updates) =>
|
||||||
|
(toBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
@override
|
||||||
|
DesignStateBuilder toBuilder() => new DesignStateBuilder()..replace(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(other, this)) return true;
|
||||||
|
return other is DesignState &&
|
||||||
|
lastUpdated == other.lastUpdated &&
|
||||||
|
map == other.map &&
|
||||||
|
list == other.list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return $jf(
|
||||||
|
$jc($jc($jc(0, lastUpdated.hashCode), map.hashCode), list.hashCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (newBuiltValueToStringHelper('DesignState')
|
||||||
|
..add('lastUpdated', lastUpdated)
|
||||||
|
..add('map', map)
|
||||||
|
..add('list', list))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DesignStateBuilder implements Builder<DesignState, DesignStateBuilder> {
|
||||||
|
_$DesignState _$v;
|
||||||
|
|
||||||
|
int _lastUpdated;
|
||||||
|
int get lastUpdated => _$this._lastUpdated;
|
||||||
|
set lastUpdated(int lastUpdated) => _$this._lastUpdated = lastUpdated;
|
||||||
|
|
||||||
|
MapBuilder<String, DesignEntity> _map;
|
||||||
|
MapBuilder<String, DesignEntity> get map =>
|
||||||
|
_$this._map ??= new MapBuilder<String, DesignEntity>();
|
||||||
|
set map(MapBuilder<String, DesignEntity> map) => _$this._map = map;
|
||||||
|
|
||||||
|
ListBuilder<String> _list;
|
||||||
|
ListBuilder<String> get list => _$this._list ??= new ListBuilder<String>();
|
||||||
|
set list(ListBuilder<String> list) => _$this._list = list;
|
||||||
|
|
||||||
|
DesignStateBuilder();
|
||||||
|
|
||||||
|
DesignStateBuilder get _$this {
|
||||||
|
if (_$v != null) {
|
||||||
|
_lastUpdated = _$v.lastUpdated;
|
||||||
|
_map = _$v.map?.toBuilder();
|
||||||
|
_list = _$v.list?.toBuilder();
|
||||||
|
_$v = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(DesignState other) {
|
||||||
|
if (other == null) {
|
||||||
|
throw new ArgumentError.notNull('other');
|
||||||
|
}
|
||||||
|
_$v = other as _$DesignState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(void Function(DesignStateBuilder) updates) {
|
||||||
|
if (updates != null) updates(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
_$DesignState build() {
|
||||||
|
_$DesignState _$result;
|
||||||
|
try {
|
||||||
|
_$result = _$v ??
|
||||||
|
new _$DesignState._(
|
||||||
|
lastUpdated: lastUpdated, map: map.build(), list: list.build());
|
||||||
|
} catch (_) {
|
||||||
|
String _$failedField;
|
||||||
|
try {
|
||||||
|
_$failedField = 'map';
|
||||||
|
map.build();
|
||||||
|
_$failedField = 'list';
|
||||||
|
list.build();
|
||||||
|
} catch (e) {
|
||||||
|
throw new BuiltValueNestedFieldError(
|
||||||
|
'DesignState', _$failedField, e.toString());
|
||||||
|
}
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
replace(_$result);
|
||||||
|
return _$result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$DesignUIState extends DesignUIState {
|
||||||
|
@override
|
||||||
|
final DesignEntity editing;
|
||||||
|
@override
|
||||||
|
final ListUIState listUIState;
|
||||||
|
@override
|
||||||
|
final String selectedId;
|
||||||
|
@override
|
||||||
|
final Completer<SelectableEntity> saveCompleter;
|
||||||
|
@override
|
||||||
|
final Completer<Null> cancelCompleter;
|
||||||
|
|
||||||
|
factory _$DesignUIState([void Function(DesignUIStateBuilder) updates]) =>
|
||||||
|
(new DesignUIStateBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
_$DesignUIState._(
|
||||||
|
{this.editing,
|
||||||
|
this.listUIState,
|
||||||
|
this.selectedId,
|
||||||
|
this.saveCompleter,
|
||||||
|
this.cancelCompleter})
|
||||||
|
: super._() {
|
||||||
|
if (listUIState == null) {
|
||||||
|
throw new BuiltValueNullFieldError('DesignUIState', 'listUIState');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DesignUIState rebuild(void Function(DesignUIStateBuilder) updates) =>
|
||||||
|
(toBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
@override
|
||||||
|
DesignUIStateBuilder toBuilder() => new DesignUIStateBuilder()..replace(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(other, this)) return true;
|
||||||
|
return other is DesignUIState &&
|
||||||
|
editing == other.editing &&
|
||||||
|
listUIState == other.listUIState &&
|
||||||
|
selectedId == other.selectedId &&
|
||||||
|
saveCompleter == other.saveCompleter &&
|
||||||
|
cancelCompleter == other.cancelCompleter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return $jf($jc(
|
||||||
|
$jc(
|
||||||
|
$jc($jc($jc(0, editing.hashCode), listUIState.hashCode),
|
||||||
|
selectedId.hashCode),
|
||||||
|
saveCompleter.hashCode),
|
||||||
|
cancelCompleter.hashCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (newBuiltValueToStringHelper('DesignUIState')
|
||||||
|
..add('editing', editing)
|
||||||
|
..add('listUIState', listUIState)
|
||||||
|
..add('selectedId', selectedId)
|
||||||
|
..add('saveCompleter', saveCompleter)
|
||||||
|
..add('cancelCompleter', cancelCompleter))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DesignUIStateBuilder
|
||||||
|
implements Builder<DesignUIState, DesignUIStateBuilder> {
|
||||||
|
_$DesignUIState _$v;
|
||||||
|
|
||||||
|
DesignEntityBuilder _editing;
|
||||||
|
DesignEntityBuilder get editing =>
|
||||||
|
_$this._editing ??= new DesignEntityBuilder();
|
||||||
|
set editing(DesignEntityBuilder editing) => _$this._editing = editing;
|
||||||
|
|
||||||
|
ListUIStateBuilder _listUIState;
|
||||||
|
ListUIStateBuilder get listUIState =>
|
||||||
|
_$this._listUIState ??= new ListUIStateBuilder();
|
||||||
|
set listUIState(ListUIStateBuilder listUIState) =>
|
||||||
|
_$this._listUIState = listUIState;
|
||||||
|
|
||||||
|
String _selectedId;
|
||||||
|
String get selectedId => _$this._selectedId;
|
||||||
|
set selectedId(String selectedId) => _$this._selectedId = selectedId;
|
||||||
|
|
||||||
|
Completer<SelectableEntity> _saveCompleter;
|
||||||
|
Completer<SelectableEntity> get saveCompleter => _$this._saveCompleter;
|
||||||
|
set saveCompleter(Completer<SelectableEntity> saveCompleter) =>
|
||||||
|
_$this._saveCompleter = saveCompleter;
|
||||||
|
|
||||||
|
Completer<Null> _cancelCompleter;
|
||||||
|
Completer<Null> get cancelCompleter => _$this._cancelCompleter;
|
||||||
|
set cancelCompleter(Completer<Null> cancelCompleter) =>
|
||||||
|
_$this._cancelCompleter = cancelCompleter;
|
||||||
|
|
||||||
|
DesignUIStateBuilder();
|
||||||
|
|
||||||
|
DesignUIStateBuilder get _$this {
|
||||||
|
if (_$v != null) {
|
||||||
|
_editing = _$v.editing?.toBuilder();
|
||||||
|
_listUIState = _$v.listUIState?.toBuilder();
|
||||||
|
_selectedId = _$v.selectedId;
|
||||||
|
_saveCompleter = _$v.saveCompleter;
|
||||||
|
_cancelCompleter = _$v.cancelCompleter;
|
||||||
|
_$v = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(DesignUIState other) {
|
||||||
|
if (other == null) {
|
||||||
|
throw new ArgumentError.notNull('other');
|
||||||
|
}
|
||||||
|
_$v = other as _$DesignUIState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(void Function(DesignUIStateBuilder) updates) {
|
||||||
|
if (updates != null) updates(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
_$DesignUIState build() {
|
||||||
|
_$DesignUIState _$result;
|
||||||
|
try {
|
||||||
|
_$result = _$v ??
|
||||||
|
new _$DesignUIState._(
|
||||||
|
editing: _editing?.build(),
|
||||||
|
listUIState: listUIState.build(),
|
||||||
|
selectedId: selectedId,
|
||||||
|
saveCompleter: saveCompleter,
|
||||||
|
cancelCompleter: cancelCompleter);
|
||||||
|
} catch (_) {
|
||||||
|
String _$failedField;
|
||||||
|
try {
|
||||||
|
_$failedField = 'editing';
|
||||||
|
_editing?.build();
|
||||||
|
_$failedField = 'listUIState';
|
||||||
|
listUIState.build();
|
||||||
|
} catch (e) {
|
||||||
|
throw new BuiltValueNestedFieldError(
|
||||||
|
'DesignUIState', _$failedField, e.toString());
|
||||||
|
}
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
replace(_$result);
|
||||||
|
return _$result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||||
|
|
@ -23,6 +23,8 @@ import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/user/user_actions.dart';
|
import 'package:invoiceninja_flutter/redux/user/user_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/vendor/vendor_actions.dart';
|
import 'package:invoiceninja_flutter/redux/vendor/vendor_actions.dart';
|
||||||
// STARTER: import - do not remove comment
|
// STARTER: import - do not remove comment
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_actions.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/credit/credit_actions.dart';
|
import 'package:invoiceninja_flutter/redux/credit/credit_actions.dart';
|
||||||
|
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
|
|
@ -397,6 +399,13 @@ Reducer<BuiltList<HistoryRecord>> historyReducer = combineReducers([
|
||||||
_addToHistory(historyList,
|
_addToHistory(historyList,
|
||||||
HistoryRecord(id: action.group.id, entityType: EntityType.group))),
|
HistoryRecord(id: action.group.id, entityType: EntityType.group))),
|
||||||
// STARTER: history - do not remove comment
|
// STARTER: history - do not remove comment
|
||||||
|
TypedReducer<BuiltList<HistoryRecord>, ViewDesign>((historyList, action) =>
|
||||||
|
_addToHistory(historyList,
|
||||||
|
HistoryRecord(id: action.designId, entityType: EntityType.design))),
|
||||||
|
TypedReducer<BuiltList<HistoryRecord>, EditDesign>((historyList, action) =>
|
||||||
|
_addToHistory(historyList,
|
||||||
|
HistoryRecord(id: action.design.id, entityType: EntityType.design))),
|
||||||
|
|
||||||
TypedReducer<BuiltList<HistoryRecord>, ViewCredit>((historyList, action) =>
|
TypedReducer<BuiltList<HistoryRecord>, ViewCredit>((historyList, action) =>
|
||||||
_addToHistory(historyList,
|
_addToHistory(historyList,
|
||||||
HistoryRecord(id: action.creditId, entityType: EntityType.credit))),
|
HistoryRecord(id: action.creditId, entityType: EntityType.credit))),
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ import 'package:invoiceninja_flutter/redux/quote/quote_reducer.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/task/task_reducer.dart';
|
import 'package:invoiceninja_flutter/redux/task/task_reducer.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/vendor/vendor_reducer.dart';
|
import 'package:invoiceninja_flutter/redux/vendor/vendor_reducer.dart';
|
||||||
// STARTER: import - do not remove comment
|
// STARTER: import - do not remove comment
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_reducer.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/credit/credit_reducer.dart';
|
import 'package:invoiceninja_flutter/redux/credit/credit_reducer.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/user/user_reducer.dart';
|
import 'package:invoiceninja_flutter/redux/user/user_reducer.dart';
|
||||||
|
|
@ -49,6 +51,7 @@ UIState uiReducer(UIState state, dynamic action) {
|
||||||
.replace(dashboardUIReducer(state.dashboardUIState, action))
|
.replace(dashboardUIReducer(state.dashboardUIState, action))
|
||||||
..reportsUIState.replace(reportsUIReducer(state.reportsUIState, action))
|
..reportsUIState.replace(reportsUIReducer(state.reportsUIState, action))
|
||||||
// STARTER: reducer - do not remove comment
|
// STARTER: reducer - do not remove comment
|
||||||
|
..designUIState.replace(designUIReducer(state.designUIState, action))
|
||||||
..creditUIState.replace(creditUIReducer(state.creditUIState, action))
|
..creditUIState.replace(creditUIReducer(state.creditUIState, action))
|
||||||
..userUIState.replace(userUIReducer(state.userUIState, action))
|
..userUIState.replace(userUIReducer(state.userUIState, action))
|
||||||
..taxRateUIState.replace(taxRateUIReducer(state.taxRateUIState, action))
|
..taxRateUIState.replace(taxRateUIReducer(state.taxRateUIState, action))
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ import 'package:invoiceninja_flutter/redux/task/task_state.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/vendor/vendor_state.dart';
|
import 'package:invoiceninja_flutter/redux/vendor/vendor_state.dart';
|
||||||
|
|
||||||
// STARTER: import - do not remove comment
|
// STARTER: import - do not remove comment
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_state.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/credit/credit_state.dart';
|
import 'package:invoiceninja_flutter/redux/credit/credit_state.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/user/user_state.dart';
|
import 'package:invoiceninja_flutter/redux/user/user_state.dart';
|
||||||
|
|
@ -37,6 +39,8 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
|
||||||
clientUIState: ClientUIState(),
|
clientUIState: ClientUIState(),
|
||||||
invoiceUIState: InvoiceUIState(),
|
invoiceUIState: InvoiceUIState(),
|
||||||
// STARTER: constructor - do not remove comment
|
// STARTER: constructor - do not remove comment
|
||||||
|
designUIState: DesignUIState(),
|
||||||
|
|
||||||
creditUIState: CreditUIState(),
|
creditUIState: CreditUIState(),
|
||||||
|
|
||||||
userUIState: UserUIState(),
|
userUIState: UserUIState(),
|
||||||
|
|
@ -77,6 +81,8 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
|
||||||
InvoiceUIState get invoiceUIState;
|
InvoiceUIState get invoiceUIState;
|
||||||
|
|
||||||
// STARTER: properties - do not remove comment
|
// STARTER: properties - do not remove comment
|
||||||
|
DesignUIState get designUIState;
|
||||||
|
|
||||||
CreditUIState get creditUIState;
|
CreditUIState get creditUIState;
|
||||||
|
|
||||||
UserUIState get userUIState;
|
UserUIState get userUIState;
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,9 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
|
||||||
'invoiceUIState',
|
'invoiceUIState',
|
||||||
serializers.serialize(object.invoiceUIState,
|
serializers.serialize(object.invoiceUIState,
|
||||||
specifiedType: const FullType(InvoiceUIState)),
|
specifiedType: const FullType(InvoiceUIState)),
|
||||||
|
'designUIState',
|
||||||
|
serializers.serialize(object.designUIState,
|
||||||
|
specifiedType: const FullType(DesignUIState)),
|
||||||
'creditUIState',
|
'creditUIState',
|
||||||
serializers.serialize(object.creditUIState,
|
serializers.serialize(object.creditUIState,
|
||||||
specifiedType: const FullType(CreditUIState)),
|
specifiedType: const FullType(CreditUIState)),
|
||||||
|
|
@ -142,6 +145,10 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
|
||||||
result.invoiceUIState.replace(serializers.deserialize(value,
|
result.invoiceUIState.replace(serializers.deserialize(value,
|
||||||
specifiedType: const FullType(InvoiceUIState)) as InvoiceUIState);
|
specifiedType: const FullType(InvoiceUIState)) as InvoiceUIState);
|
||||||
break;
|
break;
|
||||||
|
case 'designUIState':
|
||||||
|
result.designUIState.replace(serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(DesignUIState)) as DesignUIState);
|
||||||
|
break;
|
||||||
case 'creditUIState':
|
case 'creditUIState':
|
||||||
result.creditUIState.replace(serializers.deserialize(value,
|
result.creditUIState.replace(serializers.deserialize(value,
|
||||||
specifiedType: const FullType(CreditUIState)) as CreditUIState);
|
specifiedType: const FullType(CreditUIState)) as CreditUIState);
|
||||||
|
|
@ -228,6 +235,8 @@ class _$UIState extends UIState {
|
||||||
@override
|
@override
|
||||||
final InvoiceUIState invoiceUIState;
|
final InvoiceUIState invoiceUIState;
|
||||||
@override
|
@override
|
||||||
|
final DesignUIState designUIState;
|
||||||
|
@override
|
||||||
final CreditUIState creditUIState;
|
final CreditUIState creditUIState;
|
||||||
@override
|
@override
|
||||||
final UserUIState userUIState;
|
final UserUIState userUIState;
|
||||||
|
|
@ -269,6 +278,7 @@ class _$UIState extends UIState {
|
||||||
this.productUIState,
|
this.productUIState,
|
||||||
this.clientUIState,
|
this.clientUIState,
|
||||||
this.invoiceUIState,
|
this.invoiceUIState,
|
||||||
|
this.designUIState,
|
||||||
this.creditUIState,
|
this.creditUIState,
|
||||||
this.userUIState,
|
this.userUIState,
|
||||||
this.taxRateUIState,
|
this.taxRateUIState,
|
||||||
|
|
@ -308,6 +318,9 @@ class _$UIState extends UIState {
|
||||||
if (invoiceUIState == null) {
|
if (invoiceUIState == null) {
|
||||||
throw new BuiltValueNullFieldError('UIState', 'invoiceUIState');
|
throw new BuiltValueNullFieldError('UIState', 'invoiceUIState');
|
||||||
}
|
}
|
||||||
|
if (designUIState == null) {
|
||||||
|
throw new BuiltValueNullFieldError('UIState', 'designUIState');
|
||||||
|
}
|
||||||
if (creditUIState == null) {
|
if (creditUIState == null) {
|
||||||
throw new BuiltValueNullFieldError('UIState', 'creditUIState');
|
throw new BuiltValueNullFieldError('UIState', 'creditUIState');
|
||||||
}
|
}
|
||||||
|
|
@ -372,6 +385,7 @@ class _$UIState extends UIState {
|
||||||
productUIState == other.productUIState &&
|
productUIState == other.productUIState &&
|
||||||
clientUIState == other.clientUIState &&
|
clientUIState == other.clientUIState &&
|
||||||
invoiceUIState == other.invoiceUIState &&
|
invoiceUIState == other.invoiceUIState &&
|
||||||
|
designUIState == other.designUIState &&
|
||||||
creditUIState == other.creditUIState &&
|
creditUIState == other.creditUIState &&
|
||||||
userUIState == other.userUIState &&
|
userUIState == other.userUIState &&
|
||||||
taxRateUIState == other.taxRateUIState &&
|
taxRateUIState == other.taxRateUIState &&
|
||||||
|
|
@ -408,12 +422,12 @@ class _$UIState extends UIState {
|
||||||
$jc(
|
$jc(
|
||||||
$jc(
|
$jc(
|
||||||
$jc(
|
$jc(
|
||||||
$jc($jc($jc($jc($jc(0, selectedCompanyIndex.hashCode), currentRoute.hashCode), previousRoute.hashCode), filter.hashCode),
|
$jc($jc($jc($jc($jc($jc(0, selectedCompanyIndex.hashCode), currentRoute.hashCode), previousRoute.hashCode), filter.hashCode), filterClearedAt.hashCode),
|
||||||
filterClearedAt.hashCode),
|
|
||||||
dashboardUIState.hashCode),
|
dashboardUIState.hashCode),
|
||||||
productUIState.hashCode),
|
productUIState.hashCode),
|
||||||
clientUIState.hashCode),
|
clientUIState.hashCode),
|
||||||
invoiceUIState.hashCode),
|
invoiceUIState.hashCode),
|
||||||
|
designUIState.hashCode),
|
||||||
creditUIState.hashCode),
|
creditUIState.hashCode),
|
||||||
userUIState.hashCode),
|
userUIState.hashCode),
|
||||||
taxRateUIState.hashCode),
|
taxRateUIState.hashCode),
|
||||||
|
|
@ -442,6 +456,7 @@ class _$UIState extends UIState {
|
||||||
..add('productUIState', productUIState)
|
..add('productUIState', productUIState)
|
||||||
..add('clientUIState', clientUIState)
|
..add('clientUIState', clientUIState)
|
||||||
..add('invoiceUIState', invoiceUIState)
|
..add('invoiceUIState', invoiceUIState)
|
||||||
|
..add('designUIState', designUIState)
|
||||||
..add('creditUIState', creditUIState)
|
..add('creditUIState', creditUIState)
|
||||||
..add('userUIState', userUIState)
|
..add('userUIState', userUIState)
|
||||||
..add('taxRateUIState', taxRateUIState)
|
..add('taxRateUIState', taxRateUIState)
|
||||||
|
|
@ -510,6 +525,12 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
|
||||||
set invoiceUIState(InvoiceUIStateBuilder invoiceUIState) =>
|
set invoiceUIState(InvoiceUIStateBuilder invoiceUIState) =>
|
||||||
_$this._invoiceUIState = invoiceUIState;
|
_$this._invoiceUIState = invoiceUIState;
|
||||||
|
|
||||||
|
DesignUIStateBuilder _designUIState;
|
||||||
|
DesignUIStateBuilder get designUIState =>
|
||||||
|
_$this._designUIState ??= new DesignUIStateBuilder();
|
||||||
|
set designUIState(DesignUIStateBuilder designUIState) =>
|
||||||
|
_$this._designUIState = designUIState;
|
||||||
|
|
||||||
CreditUIStateBuilder _creditUIState;
|
CreditUIStateBuilder _creditUIState;
|
||||||
CreditUIStateBuilder get creditUIState =>
|
CreditUIStateBuilder get creditUIState =>
|
||||||
_$this._creditUIState ??= new CreditUIStateBuilder();
|
_$this._creditUIState ??= new CreditUIStateBuilder();
|
||||||
|
|
@ -608,6 +629,7 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
|
||||||
_productUIState = _$v.productUIState?.toBuilder();
|
_productUIState = _$v.productUIState?.toBuilder();
|
||||||
_clientUIState = _$v.clientUIState?.toBuilder();
|
_clientUIState = _$v.clientUIState?.toBuilder();
|
||||||
_invoiceUIState = _$v.invoiceUIState?.toBuilder();
|
_invoiceUIState = _$v.invoiceUIState?.toBuilder();
|
||||||
|
_designUIState = _$v.designUIState?.toBuilder();
|
||||||
_creditUIState = _$v.creditUIState?.toBuilder();
|
_creditUIState = _$v.creditUIState?.toBuilder();
|
||||||
_userUIState = _$v.userUIState?.toBuilder();
|
_userUIState = _$v.userUIState?.toBuilder();
|
||||||
_taxRateUIState = _$v.taxRateUIState?.toBuilder();
|
_taxRateUIState = _$v.taxRateUIState?.toBuilder();
|
||||||
|
|
@ -655,6 +677,7 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
|
||||||
productUIState: productUIState.build(),
|
productUIState: productUIState.build(),
|
||||||
clientUIState: clientUIState.build(),
|
clientUIState: clientUIState.build(),
|
||||||
invoiceUIState: invoiceUIState.build(),
|
invoiceUIState: invoiceUIState.build(),
|
||||||
|
designUIState: designUIState.build(),
|
||||||
creditUIState: creditUIState.build(),
|
creditUIState: creditUIState.build(),
|
||||||
userUIState: userUIState.build(),
|
userUIState: userUIState.build(),
|
||||||
taxRateUIState: taxRateUIState.build(),
|
taxRateUIState: taxRateUIState.build(),
|
||||||
|
|
@ -680,6 +703,8 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
|
||||||
clientUIState.build();
|
clientUIState.build();
|
||||||
_$failedField = 'invoiceUIState';
|
_$failedField = 'invoiceUIState';
|
||||||
invoiceUIState.build();
|
invoiceUIState.build();
|
||||||
|
_$failedField = 'designUIState';
|
||||||
|
designUIState.build();
|
||||||
_$failedField = 'creditUIState';
|
_$failedField = 'creditUIState';
|
||||||
creditUIState.build();
|
creditUIState.build();
|
||||||
_$failedField = 'userUIState';
|
_$failedField = 'userUIState';
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@ import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
// STARTER: import - do not remove comment
|
// STARTER: import - do not remove comment
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_actions.dart';
|
||||||
|
|
||||||
|
|
||||||
class MenuDrawer extends StatelessWidget {
|
class MenuDrawer extends StatelessWidget {
|
||||||
const MenuDrawer({
|
const MenuDrawer({
|
||||||
|
|
@ -256,6 +258,14 @@ class MenuDrawer extends StatelessWidget {
|
||||||
title: localization.expenses,
|
title: localization.expenses,
|
||||||
),
|
),
|
||||||
// STARTER: menu - do not remove comment
|
// STARTER: menu - do not remove comment
|
||||||
|
DrawerTile(
|
||||||
|
company: company,
|
||||||
|
entityType: EntityType.design,
|
||||||
|
icon: getEntityIcon(EntityType.design),
|
||||||
|
title: localization.designs,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
DrawerTile(
|
DrawerTile(
|
||||||
company: company,
|
company: company,
|
||||||
icon: getEntityIcon(EntityType.reports),
|
icon: getEntityIcon(EntityType.reports),
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,8 @@ class CreditEditItemsVM extends EntityEditItemsVM {
|
||||||
if (index == credit.lineItems.length) {
|
if (index == credit.lineItems.length) {
|
||||||
store.dispatch(AddCreditItem(creditItem: creditItem));
|
store.dispatch(AddCreditItem(creditItem: creditItem));
|
||||||
} else {
|
} else {
|
||||||
store.dispatch(UpdateCreditItem(creditItem: creditItem, index: index));
|
store.dispatch(
|
||||||
|
UpdateCreditItem(creditItem: creditItem, index: index));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,8 @@ class CreditEditVM extends EntityEditVM {
|
||||||
if (isMobile(context)) {
|
if (isMobile(context)) {
|
||||||
store.dispatch(UpdateCurrentRoute(CreditViewScreen.route));
|
store.dispatch(UpdateCurrentRoute(CreditViewScreen.route));
|
||||||
if (credit.isNew) {
|
if (credit.isNew) {
|
||||||
Navigator.of(context).pushReplacementNamed(CreditViewScreen.route);
|
Navigator.of(context)
|
||||||
|
.pushReplacementNamed(CreditViewScreen.route);
|
||||||
} else {
|
} else {
|
||||||
Navigator.of(context).pop(savedCredit);
|
Navigator.of(context).pop(savedCredit);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,167 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/help_text.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/design_presenter.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/tables/entity_datatable.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/design_list_item.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/design_list_vm.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
|
||||||
|
class DesignList extends StatefulWidget {
|
||||||
|
const DesignList({
|
||||||
|
Key key,
|
||||||
|
@required this.viewModel,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final DesignListVM viewModel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
_DesignListState createState() => _DesignListState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DesignListState extends State<DesignList> {
|
||||||
|
EntityDataTableSource dataTableSource;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
final viewModel = widget.viewModel;
|
||||||
|
|
||||||
|
dataTableSource = EntityDataTableSource(
|
||||||
|
context: context,
|
||||||
|
entityType: EntityType.design,
|
||||||
|
editingId: viewModel.state.designUIState.editing.id,
|
||||||
|
tableColumns: viewModel.tableColumns,
|
||||||
|
entityList: viewModel.designList,
|
||||||
|
entityMap: viewModel.designMap,
|
||||||
|
entityPresenter: DesignPresenter(),
|
||||||
|
onTap: (BaseEntity design) => viewModel.onDesignTap(context, design));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(DesignList oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
|
||||||
|
final viewModel = widget.viewModel;
|
||||||
|
dataTableSource.editingId = viewModel.state.designUIState.editing.id;
|
||||||
|
dataTableSource.entityList = viewModel.designList;
|
||||||
|
dataTableSource.entityMap = viewModel.designMap;
|
||||||
|
|
||||||
|
// ignore: invalid_use_of_visible_for_testing_member, invalid_use_of_protected_member
|
||||||
|
dataTableSource.notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final store = StoreProvider.of<AppState>(context);
|
||||||
|
final viewModel = widget.viewModel;
|
||||||
|
final state = viewModel.state;
|
||||||
|
final listUIState = state.uiState.designUIState.listUIState;
|
||||||
|
final isInMultiselect = listUIState.isInMultiselect();
|
||||||
|
final isList = state.prefState.moduleLayout == ModuleLayout.list;
|
||||||
|
final designList = viewModel.designList;
|
||||||
|
|
||||||
|
if (!viewModel.isLoaded) {
|
||||||
|
return viewModel.isLoading ? LoadingIndicator() : SizedBox();
|
||||||
|
} else if (viewModel.designMap.isEmpty) {
|
||||||
|
return HelpText(AppLocalization.of(context).noRecordsFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.shouldSelectEntity(
|
||||||
|
entityType: EntityType.design, hasRecords: designList.isNotEmpty)) {
|
||||||
|
viewEntityById(
|
||||||
|
context: context,
|
||||||
|
entityType: EntityType.design,
|
||||||
|
entityId: designList.isEmpty ? null : designList.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final listOrTable = () {
|
||||||
|
if (isList) {
|
||||||
|
return ListView.separated(
|
||||||
|
separatorBuilder: (context, index) => ListDivider(),
|
||||||
|
itemCount: viewModel.designList.length,
|
||||||
|
itemBuilder: (BuildContext context, index) {
|
||||||
|
final designId = viewModel.designList[index];
|
||||||
|
final design = viewModel.designMap[designId];
|
||||||
|
|
||||||
|
return DesignListItem(
|
||||||
|
user: viewModel.state.user,
|
||||||
|
filter: viewModel.filter,
|
||||||
|
design: design,
|
||||||
|
onEntityAction: (EntityAction action) {
|
||||||
|
if (action == EntityAction.more) {
|
||||||
|
showEntityActionsDialog(
|
||||||
|
entities: [design],
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
handleDesignAction(context, [design], action);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onTap: () => viewModel.onDesignTap(context, design),
|
||||||
|
onLongPress: () async {
|
||||||
|
final longPressIsSelection =
|
||||||
|
state.prefState.longPressSelectionIsDefault ?? true;
|
||||||
|
if (longPressIsSelection && !isInMultiselect) {
|
||||||
|
handleDesignAction(
|
||||||
|
context, [design], EntityAction.toggleMultiselect);
|
||||||
|
} else {
|
||||||
|
showEntityActionsDialog(
|
||||||
|
entities: [design],
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isChecked: isInMultiselect && listUIState.isSelected(design.id),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
child: PaginatedDataTable(
|
||||||
|
onSelectAll: (value) {
|
||||||
|
final designs = viewModel.designList
|
||||||
|
.map<DesignEntity>(
|
||||||
|
(designId) => viewModel.designMap[designId])
|
||||||
|
.where((design) => value != listUIState.isSelected(design.id))
|
||||||
|
.toList();
|
||||||
|
handleDesignAction(
|
||||||
|
context, designs, EntityAction.toggleMultiselect);
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
if (!listUIState.isInMultiselect()) DataColumn(label: SizedBox()),
|
||||||
|
...viewModel.tableColumns.map((field) => DataColumn(
|
||||||
|
label: Text(AppLocalization.of(context).lookup(field)),
|
||||||
|
numeric: EntityPresenter.isFieldNumeric(field),
|
||||||
|
onSort: (int columnIndex, bool ascending) =>
|
||||||
|
store.dispatch(SortDesigns(field)))),
|
||||||
|
],
|
||||||
|
source: dataTableSource,
|
||||||
|
header: DatatableHeader(
|
||||||
|
entityType: EntityType.design,
|
||||||
|
onClearPressed: viewModel.onClearEntityFilterPressed,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return RefreshIndicator(
|
||||||
|
onRefresh: () => viewModel.onRefreshed(context),
|
||||||
|
child: listOrTable(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/design_model.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/entity_state_label.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/dismissible_entity.dart';
|
||||||
|
|
||||||
|
class DesignListItem extends StatelessWidget {
|
||||||
|
const DesignListItem({
|
||||||
|
@required this.user,
|
||||||
|
@required this.onEntityAction,
|
||||||
|
@required this.onTap,
|
||||||
|
@required this.onLongPress,
|
||||||
|
@required this.design,
|
||||||
|
@required this.filter,
|
||||||
|
this.onCheckboxChanged,
|
||||||
|
this.isChecked = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
final UserEntity user;
|
||||||
|
final Function(EntityAction) onEntityAction;
|
||||||
|
final GestureTapCallback onTap;
|
||||||
|
final GestureTapCallback onLongPress;
|
||||||
|
final DesignEntity design;
|
||||||
|
final String filter;
|
||||||
|
final Function(bool) onCheckboxChanged;
|
||||||
|
final bool isChecked;
|
||||||
|
|
||||||
|
static final designItemKey = (int id) => Key('__design_item_${id}__');
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final store = StoreProvider.of<AppState>(context);
|
||||||
|
final state = store.state;
|
||||||
|
final uiState = state.uiState;
|
||||||
|
final designUIState = uiState.designUIState;
|
||||||
|
final listUIState = designUIState.listUIState;
|
||||||
|
final isInMultiselect = listUIState.isInMultiselect();
|
||||||
|
final showCheckbox = onCheckboxChanged != null || isInMultiselect;
|
||||||
|
|
||||||
|
final filterMatch = filter != null && filter.isNotEmpty
|
||||||
|
? design.matchesFilterValue(filter)
|
||||||
|
: null;
|
||||||
|
final subtitle = filterMatch;
|
||||||
|
|
||||||
|
return DismissibleEntity(
|
||||||
|
userCompany: state.userCompany,
|
||||||
|
entity: design,
|
||||||
|
isSelected: design.id ==
|
||||||
|
(uiState.isEditing
|
||||||
|
? designUIState.editing.id
|
||||||
|
: designUIState.selectedId),
|
||||||
|
onEntityAction: onEntityAction,
|
||||||
|
child: ListTile(
|
||||||
|
onTap: isInMultiselect
|
||||||
|
? () => onEntityAction(EntityAction.toggleMultiselect)
|
||||||
|
: onTap,
|
||||||
|
onLongPress: onLongPress,
|
||||||
|
leading: showCheckbox
|
||||||
|
? IgnorePointer(
|
||||||
|
ignoring: listUIState.isInMultiselect(),
|
||||||
|
child: Checkbox(
|
||||||
|
value: isChecked,
|
||||||
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
onChanged: (value) => onCheckboxChanged(value),
|
||||||
|
activeColor: Theme.of(context).accentColor,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
title: Container(
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
design.name,
|
||||||
|
style: Theme.of(context).textTheme.headline6,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(formatNumber(design.listDisplayAmount, context),
|
||||||
|
style: Theme.of(context).textTheme.headline6),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
subtitle: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
subtitle != null && subtitle.isNotEmpty
|
||||||
|
? Text(
|
||||||
|
subtitle,
|
||||||
|
maxLines: 3,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
)
|
||||||
|
: Container(),
|
||||||
|
EntityStateLabel(design),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/design_model.dart';
|
||||||
|
import 'package:redux/redux.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
|
import 'package:built_collection/built_collection.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_selectors.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/design_list.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_actions.dart';
|
||||||
|
|
||||||
|
class DesignListBuilder extends StatelessWidget {
|
||||||
|
const DesignListBuilder({Key key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return StoreConnector<AppState, DesignListVM>(
|
||||||
|
converter: DesignListVM.fromStore,
|
||||||
|
builder: (context, viewModel) {
|
||||||
|
return DesignList(
|
||||||
|
viewModel: viewModel,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DesignListVM {
|
||||||
|
DesignListVM({
|
||||||
|
@required this.state,
|
||||||
|
@required this.userCompany,
|
||||||
|
@required this.designList,
|
||||||
|
@required this.designMap,
|
||||||
|
@required this.filter,
|
||||||
|
@required this.isLoading,
|
||||||
|
@required this.isLoaded,
|
||||||
|
@required this.onDesignTap,
|
||||||
|
@required this.listState,
|
||||||
|
@required this.onRefreshed,
|
||||||
|
@required this.onEntityAction,
|
||||||
|
@required this.tableColumns,
|
||||||
|
@required this.onClearEntityFilterPressed,
|
||||||
|
@required this.onViewEntityFilterPressed,
|
||||||
|
});
|
||||||
|
|
||||||
|
static DesignListVM fromStore(Store<AppState> store) {
|
||||||
|
Future<Null> _handleRefresh(BuildContext context) {
|
||||||
|
if (store.state.isLoading) {
|
||||||
|
return Future<Null>(null);
|
||||||
|
}
|
||||||
|
final completer = snackBarCompleter<Null>(
|
||||||
|
context, AppLocalization.of(context).refreshComplete);
|
||||||
|
store.dispatch(LoadDesigns(completer: completer, force: true));
|
||||||
|
return completer.future;
|
||||||
|
}
|
||||||
|
|
||||||
|
final state = store.state;
|
||||||
|
|
||||||
|
return DesignListVM(
|
||||||
|
state: state,
|
||||||
|
userCompany: state.userCompany,
|
||||||
|
listState: state.designListState,
|
||||||
|
designList: memoizedFilteredDesignList(
|
||||||
|
state.designState.map, state.designState.list, state.designListState),
|
||||||
|
designMap: state.designState.map,
|
||||||
|
isLoading: state.isLoading,
|
||||||
|
isLoaded: state.designState.isLoaded,
|
||||||
|
filter: state.designUIState.listUIState.filter,
|
||||||
|
onClearEntityFilterPressed: () => store.dispatch(FilterDesignsByEntity()),
|
||||||
|
onViewEntityFilterPressed: (BuildContext context) => viewEntityById(
|
||||||
|
context: context,
|
||||||
|
entityId: state.designListState.filterEntityId,
|
||||||
|
entityType: state.designListState.filterEntityType),
|
||||||
|
onDesignTap: (context, design) {
|
||||||
|
if (store.state.designListState.isInMultiselect()) {
|
||||||
|
handleDesignAction(context, [design], EntityAction.toggleMultiselect);
|
||||||
|
} else {
|
||||||
|
viewEntity(context: context, entity: design);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onEntityAction: (BuildContext context, List<BaseEntity> designs,
|
||||||
|
EntityAction action) =>
|
||||||
|
handleDesignAction(context, designs, action),
|
||||||
|
onRefreshed: (context) => _handleRefresh(context),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final AppState state;
|
||||||
|
final UserCompanyEntity userCompany;
|
||||||
|
final List<String> designList;
|
||||||
|
final BuiltMap<String, DesignEntity> designMap;
|
||||||
|
final ListUIState listState;
|
||||||
|
final String filter;
|
||||||
|
final bool isLoading;
|
||||||
|
final bool isLoaded;
|
||||||
|
final Function(BuildContext, DesignEntity) onDesignTap;
|
||||||
|
final Function(BuildContext) onRefreshed;
|
||||||
|
final Function(BuildContext, List<BaseEntity>, EntityAction) onEntityAction;
|
||||||
|
final Function onClearEntityFilterPressed;
|
||||||
|
final Function(BuildContext) onViewEntityFilterPressed;
|
||||||
|
final List<String> tableColumns;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/design_model.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
||||||
|
|
||||||
|
class DesignPresenter extends EntityPresenter {
|
||||||
|
static List<String> getTableFields(UserCompanyEntity userCompany) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget getField({String field, BuildContext context}) {
|
||||||
|
final state = StoreProvider.of<AppState>(context).state;
|
||||||
|
final design = entity as InvoiceEntity;
|
||||||
|
|
||||||
|
switch (field) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.getField(field: field, context: context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/app_bottom_bar.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/forms/save_cancel_buttons.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/list_scaffold.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/list_filter.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/list_filter_button.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/design_list_vm.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
|
||||||
|
import 'design_screen_vm.dart';
|
||||||
|
|
||||||
|
class DesignScreen extends StatelessWidget {
|
||||||
|
const DesignScreen({
|
||||||
|
Key key,
|
||||||
|
@required this.viewModel,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
static const String route = '/design';
|
||||||
|
|
||||||
|
final DesignScreenVM viewModel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final store = StoreProvider.of<AppState>(context);
|
||||||
|
final state = store.state;
|
||||||
|
final company = state.company;
|
||||||
|
final userCompany = state.userCompany;
|
||||||
|
final localization = AppLocalization.of(context);
|
||||||
|
final listUIState = state.uiState.designUIState.listUIState;
|
||||||
|
final isInMultiselect = listUIState.isInMultiselect();
|
||||||
|
|
||||||
|
return ListScaffold(
|
||||||
|
isChecked: isInMultiselect &&
|
||||||
|
listUIState.selectedIds.length == viewModel.designList.length,
|
||||||
|
showCheckbox: isInMultiselect,
|
||||||
|
onHamburgerLongPress: () => store.dispatch(StartDesignMultiselect()),
|
||||||
|
onCheckboxChanged: (value) {
|
||||||
|
final designs = viewModel.designList
|
||||||
|
.map<DesignEntity>((designId) => viewModel.designMap[designId])
|
||||||
|
.where((design) => value != listUIState.isSelected(design.id))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
handleDesignAction(context, designs, EntityAction.toggleMultiselect);
|
||||||
|
},
|
||||||
|
appBarTitle: ListFilter(
|
||||||
|
title: localization.designs,
|
||||||
|
key: ValueKey(state.designListState.filterClearedAt),
|
||||||
|
filter: state.designListState.filter,
|
||||||
|
onFilterChanged: (value) {
|
||||||
|
store.dispatch(FilterDesigns(value));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
appBarActions: [
|
||||||
|
if (!viewModel.isInMultiselect)
|
||||||
|
ListFilterButton(
|
||||||
|
filter: state.designListState.filter,
|
||||||
|
onFilterPressed: (String value) {
|
||||||
|
store.dispatch(FilterDesigns(value));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (viewModel.isInMultiselect)
|
||||||
|
SaveCancelButtons(
|
||||||
|
saveLabel: localization.done,
|
||||||
|
onSavePressed: listUIState.selectedIds.isEmpty
|
||||||
|
? null
|
||||||
|
: (context) async {
|
||||||
|
final designs = listUIState.selectedIds
|
||||||
|
.map<DesignEntity>(
|
||||||
|
(designId) => viewModel.designMap[designId])
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
await showEntityActionsDialog(
|
||||||
|
entities: designs,
|
||||||
|
context: context,
|
||||||
|
multiselect: true,
|
||||||
|
completer: Completer<Null>()
|
||||||
|
..future.then<dynamic>(
|
||||||
|
(_) => store.dispatch(ClearDesignMultiselect())),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onCancelPressed: (context) =>
|
||||||
|
store.dispatch(ClearDesignMultiselect()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
body: DesignListBuilder(),
|
||||||
|
bottomNavigationBar: AppBottomBar(
|
||||||
|
entityType: EntityType.design,
|
||||||
|
onSelectedSortField: (value) {
|
||||||
|
store.dispatch(SortDesigns(value));
|
||||||
|
},
|
||||||
|
sortFields: [
|
||||||
|
DesignFields.name,
|
||||||
|
DesignFields.balance,
|
||||||
|
DesignFields.updatedAt,
|
||||||
|
],
|
||||||
|
onSelectedState: (EntityState state, value) {
|
||||||
|
store.dispatch(FilterDesignsByState(state));
|
||||||
|
},
|
||||||
|
onCheckboxPressed: () {
|
||||||
|
if (store.state.designListState.isInMultiselect()) {
|
||||||
|
store.dispatch(ClearDesignMultiselect());
|
||||||
|
} else {
|
||||||
|
store.dispatch(StartDesignMultiselect());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
customValues1: company.getCustomFieldValues(CustomFieldType.design1,
|
||||||
|
excludeBlank: true),
|
||||||
|
customValues2: company.getCustomFieldValues(CustomFieldType.design2,
|
||||||
|
excludeBlank: true),
|
||||||
|
customValues3: company.getCustomFieldValues(CustomFieldType.design3,
|
||||||
|
excludeBlank: true),
|
||||||
|
customValues4: company.getCustomFieldValues(CustomFieldType.design4,
|
||||||
|
excludeBlank: true),
|
||||||
|
onSelectedCustom1: (value) =>
|
||||||
|
store.dispatch(FilterDesignsByCustom1(value)),
|
||||||
|
onSelectedCustom2: (value) =>
|
||||||
|
store.dispatch(FilterDesignsByCustom2(value)),
|
||||||
|
onSelectedCustom3: (value) =>
|
||||||
|
store.dispatch(FilterDesignsByCustom3(value)),
|
||||||
|
onSelectedCustom4: (value) =>
|
||||||
|
store.dispatch(FilterDesignsByCustom4(value)),
|
||||||
|
),
|
||||||
|
floatingActionButton: userCompany.canCreate(EntityType.design)
|
||||||
|
? FloatingActionButton(
|
||||||
|
heroTag: 'design_fab',
|
||||||
|
backgroundColor: Theme.of(context).primaryColorDark,
|
||||||
|
onPressed: () {
|
||||||
|
createEntityByType(
|
||||||
|
context: context, entityType: EntityType.design);
|
||||||
|
},
|
||||||
|
child: Icon(
|
||||||
|
Icons.add,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
tooltip: localization.newDesign,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
import 'package:built_collection/built_collection.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_selectors.dart';
|
||||||
|
import 'package:redux/redux.dart';
|
||||||
|
|
||||||
|
import 'design_screen.dart';
|
||||||
|
|
||||||
|
class DesignScreenBuilder extends StatelessWidget {
|
||||||
|
const DesignScreenBuilder({Key key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return StoreConnector<AppState, DesignScreenVM>(
|
||||||
|
converter: DesignScreenVM.fromStore,
|
||||||
|
builder: (context, vm) {
|
||||||
|
return DesignScreen(
|
||||||
|
viewModel: vm,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DesignScreenVM {
|
||||||
|
DesignScreenVM({
|
||||||
|
@required this.isInMultiselect,
|
||||||
|
@required this.designList,
|
||||||
|
@required this.userCompany,
|
||||||
|
@required this.onEntityAction,
|
||||||
|
@required this.designMap,
|
||||||
|
});
|
||||||
|
|
||||||
|
final bool isInMultiselect;
|
||||||
|
final UserCompanyEntity userCompany;
|
||||||
|
final List<String> designList;
|
||||||
|
final Function(BuildContext, List<BaseEntity>, EntityAction) onEntityAction;
|
||||||
|
final BuiltMap<String, DesignEntity> designMap;
|
||||||
|
|
||||||
|
static DesignScreenVM fromStore(Store<AppState> store) {
|
||||||
|
final state = store.state;
|
||||||
|
|
||||||
|
return DesignScreenVM(
|
||||||
|
designMap: state.designState.map,
|
||||||
|
designList: memoizedFilteredDesignList(
|
||||||
|
state.designState.map, state.designState.list, state.designListState),
|
||||||
|
userCompany: state.userCompany,
|
||||||
|
isInMultiselect: state.designListState.isInMultiselect(),
|
||||||
|
onEntityAction: (BuildContext context, List<BaseEntity> designs,
|
||||||
|
EntityAction action) =>
|
||||||
|
handleDesignAction(context, designs, action),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/edit/design_edit_vm.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
|
|
||||||
|
class DesignEdit extends StatefulWidget {
|
||||||
|
const DesignEdit({
|
||||||
|
Key key,
|
||||||
|
@required this.viewModel,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final DesignEditVM viewModel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
_DesignEditState createState() => _DesignEditState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DesignEditState extends State<DesignEdit> {
|
||||||
|
static final GlobalKey<FormState> _formKey =
|
||||||
|
GlobalKey<FormState>(debugLabel: '_designEdit');
|
||||||
|
final _debouncer = Debouncer();
|
||||||
|
|
||||||
|
// STARTER: controllers - do not remove comment
|
||||||
|
|
||||||
|
List<TextEditingController> _controllers = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
_controllers = [
|
||||||
|
// STARTER: array - do not remove comment
|
||||||
|
];
|
||||||
|
|
||||||
|
_controllers.forEach((controller) => controller.removeListener(_onChanged));
|
||||||
|
|
||||||
|
final design = widget.viewModel.design;
|
||||||
|
// STARTER: read value - do not remove comment
|
||||||
|
|
||||||
|
_controllers.forEach((controller) => controller.addListener(_onChanged));
|
||||||
|
|
||||||
|
super.didChangeDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controllers.forEach((controller) {
|
||||||
|
controller.removeListener(_onChanged);
|
||||||
|
controller.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onChanged() {
|
||||||
|
_debouncer.run(() {
|
||||||
|
final design = widget.viewModel.design.rebuild((b) => b
|
||||||
|
// STARTER: set value - do not remove comment
|
||||||
|
);
|
||||||
|
if (design != widget.viewModel.design) {
|
||||||
|
widget.viewModel.onChanged(design);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final viewModel = widget.viewModel;
|
||||||
|
final localization = AppLocalization.of(context);
|
||||||
|
final design = viewModel.design;
|
||||||
|
|
||||||
|
return EditScaffold(
|
||||||
|
onCancelPressed: (context) => viewModel.onCancelPressed(context),
|
||||||
|
onSavePressed: (context) {
|
||||||
|
final bool isValid = _formKey.currentState.validate();
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_autoValidate = !isValid;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isValid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.onSavePressed(context);
|
||||||
|
},
|
||||||
|
body: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Builder(builder: (BuildContext context) {
|
||||||
|
return ListView(
|
||||||
|
children: <Widget>[
|
||||||
|
FormCard(
|
||||||
|
children: <Widget>[
|
||||||
|
// STARTER: widgets - do not remove comment
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/design_screen.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||||
|
import 'package:redux/redux.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/view/design_view_vm.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/design_model.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/edit/design_edit.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
|
|
||||||
|
class DesignEditScreen extends StatelessWidget {
|
||||||
|
const DesignEditScreen({Key key}) : super(key: key);
|
||||||
|
static const String route = '/design/edit';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return StoreConnector<AppState, DesignEditVM>(
|
||||||
|
converter: (Store<AppState> store) {
|
||||||
|
return DesignEditVM.fromStore(store);
|
||||||
|
},
|
||||||
|
builder: (context, viewModel) {
|
||||||
|
return DesignEdit(
|
||||||
|
viewModel: viewModel,
|
||||||
|
key: ValueKey(viewModel.design.id),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DesignEditVM {
|
||||||
|
DesignEditVM({
|
||||||
|
@required this.state,
|
||||||
|
@required this.design,
|
||||||
|
@required this.company,
|
||||||
|
@required this.onChanged,
|
||||||
|
@required this.isSaving,
|
||||||
|
@required this.origDesign,
|
||||||
|
@required this.onSavePressed,
|
||||||
|
@required this.onCancelPressed,
|
||||||
|
@required this.isLoading,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory DesignEditVM.fromStore(Store<AppState> store) {
|
||||||
|
final state = store.state;
|
||||||
|
final design = state.designUIState.editing;
|
||||||
|
|
||||||
|
return DesignEditVM(
|
||||||
|
state: state,
|
||||||
|
isLoading: state.isLoading,
|
||||||
|
isSaving: state.isSaving,
|
||||||
|
origDesign: state.designState.map[design.id],
|
||||||
|
design: design,
|
||||||
|
company: state.selectedCompany,
|
||||||
|
onChanged: (DesignEntity design) {
|
||||||
|
store.dispatch(UpdateDesign(design));
|
||||||
|
},
|
||||||
|
onCancelPressed: (BuildContext context) {
|
||||||
|
store.dispatch(
|
||||||
|
EditDesign(design: DesignEntity(), context: context, force: true));
|
||||||
|
store.dispatch(UpdateCurrentRoute(state.uiState.previousRoute));
|
||||||
|
},
|
||||||
|
onSavePressed: (BuildContext context) {
|
||||||
|
final Completer<DesignEntity> completer = new Completer<DesignEntity>();
|
||||||
|
store.dispatch(SaveDesignRequest(completer: completer, design: design));
|
||||||
|
return completer.future.then((savedDesign) {
|
||||||
|
if (isMobile(context)) {
|
||||||
|
store.dispatch(UpdateCurrentRoute(DesignViewScreen.route));
|
||||||
|
if (design.isNew) {
|
||||||
|
Navigator.of(context)
|
||||||
|
.pushReplacementNamed(DesignViewScreen.route);
|
||||||
|
} else {
|
||||||
|
Navigator.of(context).pop(savedDesign);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
store.dispatch(ViewDesign(
|
||||||
|
context: context, designId: savedDesign.id, force: true));
|
||||||
|
}
|
||||||
|
}).catchError((Object error) {
|
||||||
|
showDialog<ErrorDialog>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return ErrorDialog(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final DesignEntity design;
|
||||||
|
final CompanyEntity company;
|
||||||
|
final Function(DesignEntity) onChanged;
|
||||||
|
final Function(BuildContext) onSavePressed;
|
||||||
|
final Function(BuildContext) onCancelPressed;
|
||||||
|
final bool isLoading;
|
||||||
|
final bool isSaving;
|
||||||
|
final DesignEntity origDesign;
|
||||||
|
final AppState state;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/buttons/edit_icon_button.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/actions_menu_button.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/view/design_view_vm.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/entities/entity_state_title.dart';
|
||||||
|
|
||||||
|
class DesignView extends StatefulWidget {
|
||||||
|
const DesignView({
|
||||||
|
Key key,
|
||||||
|
@required this.viewModel,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final DesignViewVM viewModel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
_DesignViewState createState() => new _DesignViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DesignViewState extends State<DesignView> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final viewModel = widget.viewModel;
|
||||||
|
final userCompany = viewModel.state.userCompany;
|
||||||
|
final design = viewModel.design;
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: EntityStateTitle(entity: design),
|
||||||
|
actions: [
|
||||||
|
userCompany.canEditEntity(design)
|
||||||
|
? EditIconButton(
|
||||||
|
isVisible: !design.isDeleted,
|
||||||
|
onPressed: () => viewModel.onEditPressed(context),
|
||||||
|
)
|
||||||
|
: Container(),
|
||||||
|
ActionMenuButton(
|
||||||
|
entityActions: design.getActions(userCompany: userCompany),
|
||||||
|
isSaving: viewModel.isSaving,
|
||||||
|
entity: design,
|
||||||
|
onSelected: viewModel.onEntityAction,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: FormCard(children: [
|
||||||
|
// STARTER: widgets - do not remove comment
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/design_screen.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
import 'package:redux/redux.dart';
|
||||||
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/design/design_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/design_model.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/design/view/design_view.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
|
|
||||||
|
class DesignViewScreen extends StatelessWidget {
|
||||||
|
const DesignViewScreen({Key key}) : super(key: key);
|
||||||
|
static const String route = '/design/view';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return StoreConnector<AppState, DesignViewVM>(
|
||||||
|
converter: (Store<AppState> store) {
|
||||||
|
return DesignViewVM.fromStore(store);
|
||||||
|
},
|
||||||
|
builder: (context, vm) {
|
||||||
|
return DesignView(
|
||||||
|
viewModel: vm,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DesignViewVM {
|
||||||
|
DesignViewVM({
|
||||||
|
@required this.state,
|
||||||
|
@required this.design,
|
||||||
|
@required this.company,
|
||||||
|
@required this.onEntityAction,
|
||||||
|
@required this.onRefreshed,
|
||||||
|
@required this.isSaving,
|
||||||
|
@required this.isLoading,
|
||||||
|
@required this.isDirty,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory DesignViewVM.fromStore(Store<AppState> store) {
|
||||||
|
final state = store.state;
|
||||||
|
final design = state.designState.map[state.designUIState.selectedId] ??
|
||||||
|
DesignEntity(id: state.designUIState.selectedId);
|
||||||
|
|
||||||
|
Future<Null> _handleRefresh(BuildContext context) {
|
||||||
|
final completer = snackBarCompleter<Null>(
|
||||||
|
context, AppLocalization.of(context).refreshComplete);
|
||||||
|
store.dispatch(LoadDesign(completer: completer, designId: design.id));
|
||||||
|
return completer.future;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DesignViewVM(
|
||||||
|
state: state,
|
||||||
|
company: state.selectedCompany,
|
||||||
|
isSaving: state.isSaving,
|
||||||
|
isLoading: state.isLoading,
|
||||||
|
isDirty: design.isNew,
|
||||||
|
design: design,
|
||||||
|
onRefreshed: (context) => _handleRefresh(context),
|
||||||
|
onEntityAction: (BuildContext context, EntityAction action) =>
|
||||||
|
handleDesignAction(context, design, action),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final AppState state;
|
||||||
|
final DesignEntity design;
|
||||||
|
final CompanyEntity company;
|
||||||
|
final Function(BuildContext, EntityAction) onEntityAction;
|
||||||
|
final Function(BuildContext) onRefreshed;
|
||||||
|
final bool isSaving;
|
||||||
|
final bool isLoading;
|
||||||
|
final bool isDirty;
|
||||||
|
}
|
||||||
|
|
@ -28,7 +28,7 @@ import 'package:memoize/memoize.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/web_stub.dart'
|
import 'package:invoiceninja_flutter/utils/web_stub.dart'
|
||||||
if (dart.library.html) 'package:invoiceninja_flutter/utils/web.dart';
|
if (dart.library.html) 'package:invoiceninja_flutter/utils/web.dart';
|
||||||
|
|
||||||
class ReportsScreenBuilder extends StatelessWidget {
|
class ReportsScreenBuilder extends StatelessWidget {
|
||||||
const ReportsScreenBuilder({Key key}) : super(key: key);
|
const ReportsScreenBuilder({Key key}) : super(key: key);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,17 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
static final Map<String, Map<String, String>> _localizedValues = {
|
static final Map<String, Map<String, String>> _localizedValues = {
|
||||||
'en': {
|
'en': {
|
||||||
// STARTER: lang key - do not remove comment
|
// STARTER: lang key - do not remove comment
|
||||||
|
'design': 'Design',
|
||||||
|
'designs': 'Designs',
|
||||||
|
'new_design': 'New Design',
|
||||||
|
'edit_design': 'Edit Design',
|
||||||
|
'created_design': 'Successfully created design',
|
||||||
|
'updated_design': 'Successfully updated design',
|
||||||
|
'archived_design': 'Successfully archived design',
|
||||||
|
'deleted_design': 'Successfully deleted design',
|
||||||
|
'removed_design': 'Successfully removed design',
|
||||||
|
'restored_design': 'Successfully restored design',
|
||||||
|
|
||||||
'proposals': 'Proposals',
|
'proposals': 'Proposals',
|
||||||
'tickets': 'Tickets',
|
'tickets': 'Tickets',
|
||||||
'recurring_invoices': 'Recurring Invoices',
|
'recurring_invoices': 'Recurring Invoices',
|
||||||
|
|
@ -32780,6 +32791,16 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
String get appUpdated => _localizedValues[localeCode]['app_updated'];
|
String get appUpdated => _localizedValues[localeCode]['app_updated'];
|
||||||
|
|
||||||
// STARTER: lang field - do not remove comment
|
// STARTER: lang field - do not remove comment
|
||||||
|
String get design => _localizedValues[localeCode][' design'];
|
||||||
|
String get designs => _localizedValues[localeCode]['designs'];
|
||||||
|
String get newDesign => _localizedValues[localeCode]['new_design'];
|
||||||
|
String get createdDesign => _localizedValues[localeCode]['created_design'];
|
||||||
|
String get updatedDesign => _localizedValues[localeCode]['updated_design'];
|
||||||
|
String get archivedDesign => _localizedValues[localeCode]['archived_design'];
|
||||||
|
String get deletedDesign => _localizedValues[localeCode]['deleted_design'];
|
||||||
|
String get restoredDesign => _localizedValues[localeCode]['restored_design'];
|
||||||
|
String get editDesign => _localizedValues[localeCode]['edit_design'];
|
||||||
|
|
||||||
String get newCredit => _localizedValues[localeCode]['new_credit'];
|
String get newCredit => _localizedValues[localeCode]['new_credit'];
|
||||||
|
|
||||||
String get createdCredit => _localizedValues[localeCode]['created_credit'];
|
String get createdCredit => _localizedValues[localeCode]['created_credit'];
|
||||||
|
|
|
||||||
|
|
@ -438,6 +438,10 @@ else
|
||||||
code="String get ${module_camel} => _localizedValues[localeCode][' ${module_snake}']; String get ${module_camel}s => _localizedValues[localeCode]['${module_snake}s']; String get new${Module} => _localizedValues[localeCode]['new_${module_snake}']; String get created${Module} => _localizedValues[localeCode]['created_${module_snake}']; String get updated${Module} => _localizedValues[localeCode]['updated_${module_snake}']; String get archived${Module} => _localizedValues[localeCode]['archived_${module_snake}']; String get deleted${Module} => _localizedValues[localeCode]['deleted_${module_snake}']; String get restored${Module} => _localizedValues[localeCode]['restored_${module_snake}']; String get edit${Module} => _localizedValues[localeCode]['edit_${module_snake}'];${lineBreak}"
|
code="String get ${module_camel} => _localizedValues[localeCode][' ${module_snake}']; String get ${module_camel}s => _localizedValues[localeCode]['${module_snake}s']; String get new${Module} => _localizedValues[localeCode]['new_${module_snake}']; String get created${Module} => _localizedValues[localeCode]['created_${module_snake}']; String get updated${Module} => _localizedValues[localeCode]['updated_${module_snake}']; String get archived${Module} => _localizedValues[localeCode]['archived_${module_snake}']; String get deleted${Module} => _localizedValues[localeCode]['deleted_${module_snake}']; String get restored${Module} => _localizedValues[localeCode]['restored_${module_snake}']; String get edit${Module} => _localizedValues[localeCode]['edit_${module_snake}'];${lineBreak}"
|
||||||
sed -i -e "s/$comment/$comment${lineBreak}$code/g" ./lib/utils/i18n.dart
|
sed -i -e "s/$comment/$comment${lineBreak}$code/g" ./lib/utils/i18n.dart
|
||||||
|
|
||||||
|
comment="STARTER: entity type - do not remove comment"
|
||||||
|
code="static const EntityType ${module_camel} = _\$${module_camel}${lineBreak}"
|
||||||
|
sed -i -e "s/$comment/$comment${lineBreak}$code/g" ./lib/data/models/entities.dart
|
||||||
|
|
||||||
echo "Generating built files.."
|
echo "Generating built files.."
|
||||||
flutter packages pub run build_runner clean
|
flutter packages pub run build_runner clean
|
||||||
flutter packages pub run build_runner build --delete-conflicting-outputs
|
flutter packages pub run build_runner build --delete-conflicting-outputs
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ import 'package:built_value/built_value.dart';
|
||||||
import 'package:built_collection/built_collection.dart';
|
import 'package:built_collection/built_collection.dart';
|
||||||
import 'package:built_value/serializer.dart';
|
import 'package:built_value/serializer.dart';
|
||||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
||||||
|
|
||||||
part 'stub_model.g.dart';
|
part 'stub_model.g.dart';
|
||||||
|
|
||||||
|
|
||||||
abstract class StubListResponse
|
abstract class StubListResponse
|
||||||
implements Built<StubListResponse, StubListResponseBuilder> {
|
implements Built<StubListResponse, StubListResponseBuilder> {
|
||||||
factory StubListResponse([void updates(StubListResponseBuilder b)]) =
|
factory StubListResponse([void updates(StubListResponseBuilder b)]) =
|
||||||
|
|
@ -48,6 +48,8 @@ abstract class StubEntity extends Object with BaseEntity implements Built<StubEn
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StubEntity._();
|
||||||
|
|
||||||
String get displayName {
|
String get displayName {
|
||||||
// STARTER: display name - do not remove comment
|
// STARTER: display name - do not remove comment
|
||||||
}
|
}
|
||||||
|
|
@ -80,6 +82,36 @@ abstract class StubEntity extends Object with BaseEntity implements Built<StubEn
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
StubEntity._();
|
@override
|
||||||
|
bool matchesFilter(String filter) {
|
||||||
|
if (filter == null || filter.isEmpty) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter = filter.toLowerCase();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String matchesFilterValue(String filter) {
|
||||||
|
if (filter == null || filter.isEmpty) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter = filter.toLowerCase();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get listDisplayName => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
double get listDisplayAmount => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
FormatNumberType get listDisplayAmountType => null;
|
||||||
|
|
||||||
static Serializer<StubEntity> get serializer => _$stubEntitySerializer;
|
static Serializer<StubEntity> get serializer => _$stubEntitySerializer;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue