From ef51f27e91c501f02c1efa68bfb1b38c30514d09 Mon Sep 17 00:00:00 2001 From: Inex Code Date: Tue, 23 Jul 2024 02:47:53 +0300 Subject: [PATCH] feat(services): Service settings --- assets/translations/en.json | 11 +- .../graphql_maps/schema/schema.graphql | 76 + .../graphql_maps/schema/schema.graphql.dart | 137 + .../graphql_maps/schema/services.graphql | 44 + .../graphql_maps/schema/services.graphql.dart | 2922 +++++++++++++++++ .../graphql_maps/server_api/services_api.dart | 34 + .../cubit/client_jobs/client_jobs_state.dart | 6 +- .../get_it/api_connection_repository.dart | 13 + lib/logic/models/job.dart | 45 + lib/logic/models/service.dart | 157 + .../basic_bool_config_item.dart | 36 + .../basic_enum_config_item.dart | 46 + .../basic_string_config_item.dart | 105 + .../domain_string_config_item.dart | 114 + lib/ui/pages/services/service_page.dart | 43 +- .../pages/services/service_settings_page.dart | 238 ++ lib/ui/router/router.dart | 4 + lib/ui/router/router.gr.dart | 48 + 18 files changed, 4061 insertions(+), 18 deletions(-) create mode 100644 lib/ui/pages/services/config_item_fields/basic_bool_config_item.dart create mode 100644 lib/ui/pages/services/config_item_fields/basic_enum_config_item.dart create mode 100644 lib/ui/pages/services/config_item_fields/basic_string_config_item.dart create mode 100644 lib/ui/pages/services/config_item_fields/domain_string_config_item.dart create mode 100644 lib/ui/pages/services/service_settings_page.dart diff --git a/assets/translations/en.json b/assets/translations/en.json index 66f21bf7..48dc65a0 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -349,7 +349,13 @@ "activating": "Activating", "deactivating": "Deactivating", "reloading": "Restarting" - } + }, + "settings": "Service settings", + "modified": "Modified", + "invalid_input": "Invalid input", + "create_job": "Create job", + "update_job": "Update job", + "wait_for_jobs": "Server is busy with other jobs. Please wait until they are finished." }, "mail": { "login_info": "Use username and password from users tab. IMAP port is 143 with STARTTLS, SMTP port is 587 with STARTTLS." @@ -602,7 +608,8 @@ "change_ssh_settings": "Change SSH settings", "update_dns_records": "Update DNS records", "dns_records_did_not_change": "No changes needed", - "dns_records_changed": "DNS records updated" + "dns_records_changed": "DNS records updated", + "change_service_settings": "Change service settings for {}" }, "validations": { "required": "Required", diff --git a/lib/logic/api_maps/graphql_maps/schema/schema.graphql b/lib/logic/api_maps/graphql_maps/schema/schema.graphql index 21968b8b..67f47eca 100644 --- a/lib/logic/api_maps/graphql_maps/schema/schema.graphql +++ b/lib/logic/api_maps/graphql_maps/schema/schema.graphql @@ -130,6 +130,22 @@ enum BackupReason { PRE_RESTORE } +type BoolConfigItem implements ConfigItem { + id: String! + description: String! + widget: String! + type: String! + value: Boolean! + defaultValue: Boolean! +} + +interface ConfigItem { + id: String! + description: String! + widget: String! + type: String! +} + """Date with time (isoformat)""" scalar DateTime @@ -155,6 +171,16 @@ type DnsRecord { displayName: String! } +type EnumConfigItem implements ConfigItem { + id: String! + description: String! + widget: String! + type: String! + value: String! + defaultValue: String! + options: [String!]! +} + type GenericBackupConfigReturn implements MutationReturnInterface { success: Boolean! message: String! @@ -183,6 +209,11 @@ input InitializeRepositoryInput { password: String! } +""" +The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). +""" +scalar JSON @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf") + type Job { getJobs: [ApiJob!]! getJob(jobId: String!): ApiJob @@ -192,6 +223,24 @@ type JobMutations { removeJob(jobId: String!): GenericMutationReturn! } +type LogEntry { + message: String! + timestamp: DateTime! + priority: Int + systemdUnit: String + systemdSlice: String + cursor: String! +} + +type Logs { + paginated(limit: Int! = 20, upCursor: String = null, downCursor: String = null): PaginatedEntries! +} + +type LogsPageMeta { + upCursor: String + downCursor: String +} + input MigrateToBindsInput { emailBlockDevice: String! bitwardenBlockDevice: String! @@ -252,9 +301,18 @@ interface MutationReturnInterface { code: Int! } +type PaginatedEntries { + """Metadata to aid in pagination.""" + pageMeta: LogsPageMeta! + + """The list of log entries.""" + entries: [LogEntry!]! +} + type Query { api: Api! system: System! + logs: Logs! users: Users! storage: Storage! jobs: Job! @@ -305,6 +363,7 @@ type Service { url: String dnsRecords: [DnsRecord!] storageUsage: ServiceStorageUsage! + configuration: [ConfigItem!] backupSnapshots: [SnapshotInfo!] } @@ -350,9 +409,15 @@ type ServicesMutations { stopService(serviceId: String!): ServiceMutationReturn! startService(serviceId: String!): ServiceMutationReturn! restartService(serviceId: String!): ServiceMutationReturn! + setServiceConfiguration(input: SetServiceConfigurationInput!): ServiceMutationReturn! moveService(input: MoveServiceInput!): ServiceJobMutationReturn! } +input SetServiceConfigurationInput { + serviceId: String! + configuration: JSON! +} + enum Severity { INFO WARNING @@ -408,9 +473,20 @@ type StorageVolume { usages: [StorageUsageInterface!]! } +type StringConfigItem implements ConfigItem { + id: String! + description: String! + widget: String! + type: String! + value: String! + defaultValue: String! + regex: String +} + type Subscription { jobUpdates: [ApiJob!]! count: Int! + logEntries: LogEntry! } type System { diff --git a/lib/logic/api_maps/graphql_maps/schema/schema.graphql.dart b/lib/logic/api_maps/graphql_maps/schema/schema.graphql.dart index 039a87a7..71feddeb 100644 --- a/lib/logic/api_maps/graphql_maps/schema/schema.graphql.dart +++ b/lib/logic/api_maps/graphql_maps/schema/schema.graphql.dart @@ -1111,6 +1111,138 @@ class _CopyWithStubImpl$Input$SSHSettingsInput _res; } +class Input$SetServiceConfigurationInput { + factory Input$SetServiceConfigurationInput({ + required String serviceId, + required Map configuration, + }) => + Input$SetServiceConfigurationInput._({ + r'serviceId': serviceId, + r'configuration': configuration, + }); + + Input$SetServiceConfigurationInput._(this._$data); + + factory Input$SetServiceConfigurationInput.fromJson( + Map data) { + final result$data = {}; + final l$serviceId = data['serviceId']; + result$data['serviceId'] = (l$serviceId as String); + final l$configuration = data['configuration']; + result$data['configuration'] = (l$configuration as Map); + return Input$SetServiceConfigurationInput._(result$data); + } + + Map _$data; + + String get serviceId => (_$data['serviceId'] as String); + + Map get configuration => + (_$data['configuration'] as Map); + + Map toJson() { + final result$data = {}; + final l$serviceId = serviceId; + result$data['serviceId'] = l$serviceId; + final l$configuration = configuration; + result$data['configuration'] = l$configuration; + return result$data; + } + + CopyWith$Input$SetServiceConfigurationInput< + Input$SetServiceConfigurationInput> + get copyWith => CopyWith$Input$SetServiceConfigurationInput( + this, + (i) => i, + ); + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (!(other is Input$SetServiceConfigurationInput) || + runtimeType != other.runtimeType) { + return false; + } + final l$serviceId = serviceId; + final lOther$serviceId = other.serviceId; + if (l$serviceId != lOther$serviceId) { + return false; + } + final l$configuration = configuration; + final lOther$configuration = other.configuration; + if (l$configuration != lOther$configuration) { + return false; + } + return true; + } + + @override + int get hashCode { + final l$serviceId = serviceId; + final l$configuration = configuration; + return Object.hashAll([ + l$serviceId, + l$configuration, + ]); + } +} + +abstract class CopyWith$Input$SetServiceConfigurationInput { + factory CopyWith$Input$SetServiceConfigurationInput( + Input$SetServiceConfigurationInput instance, + TRes Function(Input$SetServiceConfigurationInput) then, + ) = _CopyWithImpl$Input$SetServiceConfigurationInput; + + factory CopyWith$Input$SetServiceConfigurationInput.stub(TRes res) = + _CopyWithStubImpl$Input$SetServiceConfigurationInput; + + TRes call({ + String? serviceId, + Map? configuration, + }); +} + +class _CopyWithImpl$Input$SetServiceConfigurationInput + implements CopyWith$Input$SetServiceConfigurationInput { + _CopyWithImpl$Input$SetServiceConfigurationInput( + this._instance, + this._then, + ); + + final Input$SetServiceConfigurationInput _instance; + + final TRes Function(Input$SetServiceConfigurationInput) _then; + + static const _undefined = {}; + + TRes call({ + Object? serviceId = _undefined, + Object? configuration = _undefined, + }) => + _then(Input$SetServiceConfigurationInput._({ + ..._instance._$data, + if (serviceId != _undefined && serviceId != null) + 'serviceId': (serviceId as String), + if (configuration != _undefined && configuration != null) + 'configuration': (configuration as Map), + })); +} + +class _CopyWithStubImpl$Input$SetServiceConfigurationInput + implements CopyWith$Input$SetServiceConfigurationInput { + _CopyWithStubImpl$Input$SetServiceConfigurationInput(this._res); + + TRes _res; + + call({ + String? serviceId, + Map? configuration, + }) => + _res; +} + class Input$SshMutationInput { factory Input$SshMutationInput({ required String username, @@ -2152,5 +2284,10 @@ const possibleTypesMap = >{ 'TimezoneMutationReturn', 'UserMutationReturn', }, + 'ConfigItem': { + 'BoolConfigItem', + 'EnumConfigItem', + 'StringConfigItem', + }, 'StorageUsageInterface': {'ServiceStorageUsage'}, }; diff --git a/lib/logic/api_maps/graphql_maps/schema/services.graphql b/lib/logic/api_maps/graphql_maps/schema/services.graphql index 30421a06..b0588d63 100644 --- a/lib/logic/api_maps/graphql_maps/schema/services.graphql +++ b/lib/logic/api_maps/graphql_maps/schema/services.graphql @@ -1,3 +1,32 @@ +fragment BoolConfigItem on BoolConfigItem { + id + description + type + boolValue: value + defaultBoolValue: defaultValue + widget +} + +fragment EnumConfigItem on EnumConfigItem { + id + description + type + stringValue: value + defaultStringValue: defaultValue + options + widget +} + +fragment StringConfigItem on StringConfigItem { + id + description + type + stringValue: value + defaultStringValue: defaultValue + regex + widget +} + query AllServices { services { allServices { @@ -22,6 +51,14 @@ query AllServices { } svgIcon url + configuration { + id + description + type + ... BoolConfigItem + ... EnumConfigItem + ... StringConfigItem + } } } } @@ -77,3 +114,10 @@ mutation MoveService($input: MoveServiceInput!) { } } +mutation SetServiceConfiguration($input: SetServiceConfigurationInput!) { + services { + setServiceConfiguration(input: $input) { + ...basicMutationReturnFields + } + } +} diff --git a/lib/logic/api_maps/graphql_maps/schema/services.graphql.dart b/lib/logic/api_maps/graphql_maps/schema/services.graphql.dart index 446906df..7d0859c5 100644 --- a/lib/logic/api_maps/graphql_maps/schema/services.graphql.dart +++ b/lib/logic/api_maps/graphql_maps/schema/services.graphql.dart @@ -5,6 +5,1032 @@ import 'schema.graphql.dart'; import 'server_api.graphql.dart'; import 'server_settings.graphql.dart'; +class Fragment$BoolConfigItem { + Fragment$BoolConfigItem({ + required this.id, + required this.description, + required this.type, + required this.boolValue, + required this.defaultBoolValue, + required this.widget, + this.$__typename = 'BoolConfigItem', + }); + + factory Fragment$BoolConfigItem.fromJson(Map json) { + final l$id = json['id']; + final l$description = json['description']; + final l$type = json['type']; + final l$boolValue = json['boolValue']; + final l$defaultBoolValue = json['defaultBoolValue']; + final l$widget = json['widget']; + final l$$__typename = json['__typename']; + return Fragment$BoolConfigItem( + id: (l$id as String), + description: (l$description as String), + type: (l$type as String), + boolValue: (l$boolValue as bool), + defaultBoolValue: (l$defaultBoolValue as bool), + widget: (l$widget as String), + $__typename: (l$$__typename as String), + ); + } + + final String id; + + final String description; + + final String type; + + final bool boolValue; + + final bool defaultBoolValue; + + final String widget; + + final String $__typename; + + Map toJson() { + final _resultData = {}; + final l$id = id; + _resultData['id'] = l$id; + final l$description = description; + _resultData['description'] = l$description; + final l$type = type; + _resultData['type'] = l$type; + final l$boolValue = boolValue; + _resultData['boolValue'] = l$boolValue; + final l$defaultBoolValue = defaultBoolValue; + _resultData['defaultBoolValue'] = l$defaultBoolValue; + final l$widget = widget; + _resultData['widget'] = l$widget; + final l$$__typename = $__typename; + _resultData['__typename'] = l$$__typename; + return _resultData; + } + + @override + int get hashCode { + final l$id = id; + final l$description = description; + final l$type = type; + final l$boolValue = boolValue; + final l$defaultBoolValue = defaultBoolValue; + final l$widget = widget; + final l$$__typename = $__typename; + return Object.hashAll([ + l$id, + l$description, + l$type, + l$boolValue, + l$defaultBoolValue, + l$widget, + l$$__typename, + ]); + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (!(other is Fragment$BoolConfigItem) || + runtimeType != other.runtimeType) { + return false; + } + final l$id = id; + final lOther$id = other.id; + if (l$id != lOther$id) { + return false; + } + final l$description = description; + final lOther$description = other.description; + if (l$description != lOther$description) { + return false; + } + final l$type = type; + final lOther$type = other.type; + if (l$type != lOther$type) { + return false; + } + final l$boolValue = boolValue; + final lOther$boolValue = other.boolValue; + if (l$boolValue != lOther$boolValue) { + return false; + } + final l$defaultBoolValue = defaultBoolValue; + final lOther$defaultBoolValue = other.defaultBoolValue; + if (l$defaultBoolValue != lOther$defaultBoolValue) { + return false; + } + final l$widget = widget; + final lOther$widget = other.widget; + if (l$widget != lOther$widget) { + return false; + } + final l$$__typename = $__typename; + final lOther$$__typename = other.$__typename; + if (l$$__typename != lOther$$__typename) { + return false; + } + return true; + } +} + +extension UtilityExtension$Fragment$BoolConfigItem on Fragment$BoolConfigItem { + CopyWith$Fragment$BoolConfigItem get copyWith => + CopyWith$Fragment$BoolConfigItem( + this, + (i) => i, + ); +} + +abstract class CopyWith$Fragment$BoolConfigItem { + factory CopyWith$Fragment$BoolConfigItem( + Fragment$BoolConfigItem instance, + TRes Function(Fragment$BoolConfigItem) then, + ) = _CopyWithImpl$Fragment$BoolConfigItem; + + factory CopyWith$Fragment$BoolConfigItem.stub(TRes res) = + _CopyWithStubImpl$Fragment$BoolConfigItem; + + TRes call({ + String? id, + String? description, + String? type, + bool? boolValue, + bool? defaultBoolValue, + String? widget, + String? $__typename, + }); +} + +class _CopyWithImpl$Fragment$BoolConfigItem + implements CopyWith$Fragment$BoolConfigItem { + _CopyWithImpl$Fragment$BoolConfigItem( + this._instance, + this._then, + ); + + final Fragment$BoolConfigItem _instance; + + final TRes Function(Fragment$BoolConfigItem) _then; + + static const _undefined = {}; + + TRes call({ + Object? id = _undefined, + Object? description = _undefined, + Object? type = _undefined, + Object? boolValue = _undefined, + Object? defaultBoolValue = _undefined, + Object? widget = _undefined, + Object? $__typename = _undefined, + }) => + _then(Fragment$BoolConfigItem( + id: id == _undefined || id == null ? _instance.id : (id as String), + description: description == _undefined || description == null + ? _instance.description + : (description as String), + type: type == _undefined || type == null + ? _instance.type + : (type as String), + boolValue: boolValue == _undefined || boolValue == null + ? _instance.boolValue + : (boolValue as bool), + defaultBoolValue: + defaultBoolValue == _undefined || defaultBoolValue == null + ? _instance.defaultBoolValue + : (defaultBoolValue as bool), + widget: widget == _undefined || widget == null + ? _instance.widget + : (widget as String), + $__typename: $__typename == _undefined || $__typename == null + ? _instance.$__typename + : ($__typename as String), + )); +} + +class _CopyWithStubImpl$Fragment$BoolConfigItem + implements CopyWith$Fragment$BoolConfigItem { + _CopyWithStubImpl$Fragment$BoolConfigItem(this._res); + + TRes _res; + + call({ + String? id, + String? description, + String? type, + bool? boolValue, + bool? defaultBoolValue, + String? widget, + String? $__typename, + }) => + _res; +} + +const fragmentDefinitionBoolConfigItem = FragmentDefinitionNode( + name: NameNode(value: 'BoolConfigItem'), + typeCondition: TypeConditionNode( + on: NamedTypeNode( + name: NameNode(value: 'BoolConfigItem'), + isNonNull: false, + )), + directives: [], + selectionSet: SelectionSetNode(selections: [ + FieldNode( + name: NameNode(value: 'id'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'description'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'type'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'value'), + alias: NameNode(value: 'boolValue'), + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'defaultValue'), + alias: NameNode(value: 'defaultBoolValue'), + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'widget'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: '__typename'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + ]), +); +const documentNodeFragmentBoolConfigItem = DocumentNode(definitions: [ + fragmentDefinitionBoolConfigItem, +]); + +extension ClientExtension$Fragment$BoolConfigItem on graphql.GraphQLClient { + void writeFragment$BoolConfigItem({ + required Fragment$BoolConfigItem data, + required Map idFields, + bool broadcast = true, + }) => + this.writeFragment( + graphql.FragmentRequest( + idFields: idFields, + fragment: const graphql.Fragment( + fragmentName: 'BoolConfigItem', + document: documentNodeFragmentBoolConfigItem, + ), + ), + data: data.toJson(), + broadcast: broadcast, + ); + Fragment$BoolConfigItem? readFragment$BoolConfigItem({ + required Map idFields, + bool optimistic = true, + }) { + final result = this.readFragment( + graphql.FragmentRequest( + idFields: idFields, + fragment: const graphql.Fragment( + fragmentName: 'BoolConfigItem', + document: documentNodeFragmentBoolConfigItem, + ), + ), + optimistic: optimistic, + ); + return result == null ? null : Fragment$BoolConfigItem.fromJson(result); + } +} + +class Fragment$EnumConfigItem { + Fragment$EnumConfigItem({ + required this.id, + required this.description, + required this.type, + required this.stringValue, + required this.defaultStringValue, + required this.options, + required this.widget, + this.$__typename = 'EnumConfigItem', + }); + + factory Fragment$EnumConfigItem.fromJson(Map json) { + final l$id = json['id']; + final l$description = json['description']; + final l$type = json['type']; + final l$stringValue = json['stringValue']; + final l$defaultStringValue = json['defaultStringValue']; + final l$options = json['options']; + final l$widget = json['widget']; + final l$$__typename = json['__typename']; + return Fragment$EnumConfigItem( + id: (l$id as String), + description: (l$description as String), + type: (l$type as String), + stringValue: (l$stringValue as String), + defaultStringValue: (l$defaultStringValue as String), + options: (l$options as List).map((e) => (e as String)).toList(), + widget: (l$widget as String), + $__typename: (l$$__typename as String), + ); + } + + final String id; + + final String description; + + final String type; + + final String stringValue; + + final String defaultStringValue; + + final List options; + + final String widget; + + final String $__typename; + + Map toJson() { + final _resultData = {}; + final l$id = id; + _resultData['id'] = l$id; + final l$description = description; + _resultData['description'] = l$description; + final l$type = type; + _resultData['type'] = l$type; + final l$stringValue = stringValue; + _resultData['stringValue'] = l$stringValue; + final l$defaultStringValue = defaultStringValue; + _resultData['defaultStringValue'] = l$defaultStringValue; + final l$options = options; + _resultData['options'] = l$options.map((e) => e).toList(); + final l$widget = widget; + _resultData['widget'] = l$widget; + final l$$__typename = $__typename; + _resultData['__typename'] = l$$__typename; + return _resultData; + } + + @override + int get hashCode { + final l$id = id; + final l$description = description; + final l$type = type; + final l$stringValue = stringValue; + final l$defaultStringValue = defaultStringValue; + final l$options = options; + final l$widget = widget; + final l$$__typename = $__typename; + return Object.hashAll([ + l$id, + l$description, + l$type, + l$stringValue, + l$defaultStringValue, + Object.hashAll(l$options.map((v) => v)), + l$widget, + l$$__typename, + ]); + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (!(other is Fragment$EnumConfigItem) || + runtimeType != other.runtimeType) { + return false; + } + final l$id = id; + final lOther$id = other.id; + if (l$id != lOther$id) { + return false; + } + final l$description = description; + final lOther$description = other.description; + if (l$description != lOther$description) { + return false; + } + final l$type = type; + final lOther$type = other.type; + if (l$type != lOther$type) { + return false; + } + final l$stringValue = stringValue; + final lOther$stringValue = other.stringValue; + if (l$stringValue != lOther$stringValue) { + return false; + } + final l$defaultStringValue = defaultStringValue; + final lOther$defaultStringValue = other.defaultStringValue; + if (l$defaultStringValue != lOther$defaultStringValue) { + return false; + } + final l$options = options; + final lOther$options = other.options; + if (l$options.length != lOther$options.length) { + return false; + } + for (int i = 0; i < l$options.length; i++) { + final l$options$entry = l$options[i]; + final lOther$options$entry = lOther$options[i]; + if (l$options$entry != lOther$options$entry) { + return false; + } + } + final l$widget = widget; + final lOther$widget = other.widget; + if (l$widget != lOther$widget) { + return false; + } + final l$$__typename = $__typename; + final lOther$$__typename = other.$__typename; + if (l$$__typename != lOther$$__typename) { + return false; + } + return true; + } +} + +extension UtilityExtension$Fragment$EnumConfigItem on Fragment$EnumConfigItem { + CopyWith$Fragment$EnumConfigItem get copyWith => + CopyWith$Fragment$EnumConfigItem( + this, + (i) => i, + ); +} + +abstract class CopyWith$Fragment$EnumConfigItem { + factory CopyWith$Fragment$EnumConfigItem( + Fragment$EnumConfigItem instance, + TRes Function(Fragment$EnumConfigItem) then, + ) = _CopyWithImpl$Fragment$EnumConfigItem; + + factory CopyWith$Fragment$EnumConfigItem.stub(TRes res) = + _CopyWithStubImpl$Fragment$EnumConfigItem; + + TRes call({ + String? id, + String? description, + String? type, + String? stringValue, + String? defaultStringValue, + List? options, + String? widget, + String? $__typename, + }); +} + +class _CopyWithImpl$Fragment$EnumConfigItem + implements CopyWith$Fragment$EnumConfigItem { + _CopyWithImpl$Fragment$EnumConfigItem( + this._instance, + this._then, + ); + + final Fragment$EnumConfigItem _instance; + + final TRes Function(Fragment$EnumConfigItem) _then; + + static const _undefined = {}; + + TRes call({ + Object? id = _undefined, + Object? description = _undefined, + Object? type = _undefined, + Object? stringValue = _undefined, + Object? defaultStringValue = _undefined, + Object? options = _undefined, + Object? widget = _undefined, + Object? $__typename = _undefined, + }) => + _then(Fragment$EnumConfigItem( + id: id == _undefined || id == null ? _instance.id : (id as String), + description: description == _undefined || description == null + ? _instance.description + : (description as String), + type: type == _undefined || type == null + ? _instance.type + : (type as String), + stringValue: stringValue == _undefined || stringValue == null + ? _instance.stringValue + : (stringValue as String), + defaultStringValue: + defaultStringValue == _undefined || defaultStringValue == null + ? _instance.defaultStringValue + : (defaultStringValue as String), + options: options == _undefined || options == null + ? _instance.options + : (options as List), + widget: widget == _undefined || widget == null + ? _instance.widget + : (widget as String), + $__typename: $__typename == _undefined || $__typename == null + ? _instance.$__typename + : ($__typename as String), + )); +} + +class _CopyWithStubImpl$Fragment$EnumConfigItem + implements CopyWith$Fragment$EnumConfigItem { + _CopyWithStubImpl$Fragment$EnumConfigItem(this._res); + + TRes _res; + + call({ + String? id, + String? description, + String? type, + String? stringValue, + String? defaultStringValue, + List? options, + String? widget, + String? $__typename, + }) => + _res; +} + +const fragmentDefinitionEnumConfigItem = FragmentDefinitionNode( + name: NameNode(value: 'EnumConfigItem'), + typeCondition: TypeConditionNode( + on: NamedTypeNode( + name: NameNode(value: 'EnumConfigItem'), + isNonNull: false, + )), + directives: [], + selectionSet: SelectionSetNode(selections: [ + FieldNode( + name: NameNode(value: 'id'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'description'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'type'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'value'), + alias: NameNode(value: 'stringValue'), + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'defaultValue'), + alias: NameNode(value: 'defaultStringValue'), + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'options'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'widget'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: '__typename'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + ]), +); +const documentNodeFragmentEnumConfigItem = DocumentNode(definitions: [ + fragmentDefinitionEnumConfigItem, +]); + +extension ClientExtension$Fragment$EnumConfigItem on graphql.GraphQLClient { + void writeFragment$EnumConfigItem({ + required Fragment$EnumConfigItem data, + required Map idFields, + bool broadcast = true, + }) => + this.writeFragment( + graphql.FragmentRequest( + idFields: idFields, + fragment: const graphql.Fragment( + fragmentName: 'EnumConfigItem', + document: documentNodeFragmentEnumConfigItem, + ), + ), + data: data.toJson(), + broadcast: broadcast, + ); + Fragment$EnumConfigItem? readFragment$EnumConfigItem({ + required Map idFields, + bool optimistic = true, + }) { + final result = this.readFragment( + graphql.FragmentRequest( + idFields: idFields, + fragment: const graphql.Fragment( + fragmentName: 'EnumConfigItem', + document: documentNodeFragmentEnumConfigItem, + ), + ), + optimistic: optimistic, + ); + return result == null ? null : Fragment$EnumConfigItem.fromJson(result); + } +} + +class Fragment$StringConfigItem { + Fragment$StringConfigItem({ + required this.id, + required this.description, + required this.type, + required this.stringValue, + required this.defaultStringValue, + this.regex, + required this.widget, + this.$__typename = 'StringConfigItem', + }); + + factory Fragment$StringConfigItem.fromJson(Map json) { + final l$id = json['id']; + final l$description = json['description']; + final l$type = json['type']; + final l$stringValue = json['stringValue']; + final l$defaultStringValue = json['defaultStringValue']; + final l$regex = json['regex']; + final l$widget = json['widget']; + final l$$__typename = json['__typename']; + return Fragment$StringConfigItem( + id: (l$id as String), + description: (l$description as String), + type: (l$type as String), + stringValue: (l$stringValue as String), + defaultStringValue: (l$defaultStringValue as String), + regex: (l$regex as String?), + widget: (l$widget as String), + $__typename: (l$$__typename as String), + ); + } + + final String id; + + final String description; + + final String type; + + final String stringValue; + + final String defaultStringValue; + + final String? regex; + + final String widget; + + final String $__typename; + + Map toJson() { + final _resultData = {}; + final l$id = id; + _resultData['id'] = l$id; + final l$description = description; + _resultData['description'] = l$description; + final l$type = type; + _resultData['type'] = l$type; + final l$stringValue = stringValue; + _resultData['stringValue'] = l$stringValue; + final l$defaultStringValue = defaultStringValue; + _resultData['defaultStringValue'] = l$defaultStringValue; + final l$regex = regex; + _resultData['regex'] = l$regex; + final l$widget = widget; + _resultData['widget'] = l$widget; + final l$$__typename = $__typename; + _resultData['__typename'] = l$$__typename; + return _resultData; + } + + @override + int get hashCode { + final l$id = id; + final l$description = description; + final l$type = type; + final l$stringValue = stringValue; + final l$defaultStringValue = defaultStringValue; + final l$regex = regex; + final l$widget = widget; + final l$$__typename = $__typename; + return Object.hashAll([ + l$id, + l$description, + l$type, + l$stringValue, + l$defaultStringValue, + l$regex, + l$widget, + l$$__typename, + ]); + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (!(other is Fragment$StringConfigItem) || + runtimeType != other.runtimeType) { + return false; + } + final l$id = id; + final lOther$id = other.id; + if (l$id != lOther$id) { + return false; + } + final l$description = description; + final lOther$description = other.description; + if (l$description != lOther$description) { + return false; + } + final l$type = type; + final lOther$type = other.type; + if (l$type != lOther$type) { + return false; + } + final l$stringValue = stringValue; + final lOther$stringValue = other.stringValue; + if (l$stringValue != lOther$stringValue) { + return false; + } + final l$defaultStringValue = defaultStringValue; + final lOther$defaultStringValue = other.defaultStringValue; + if (l$defaultStringValue != lOther$defaultStringValue) { + return false; + } + final l$regex = regex; + final lOther$regex = other.regex; + if (l$regex != lOther$regex) { + return false; + } + final l$widget = widget; + final lOther$widget = other.widget; + if (l$widget != lOther$widget) { + return false; + } + final l$$__typename = $__typename; + final lOther$$__typename = other.$__typename; + if (l$$__typename != lOther$$__typename) { + return false; + } + return true; + } +} + +extension UtilityExtension$Fragment$StringConfigItem + on Fragment$StringConfigItem { + CopyWith$Fragment$StringConfigItem get copyWith => + CopyWith$Fragment$StringConfigItem( + this, + (i) => i, + ); +} + +abstract class CopyWith$Fragment$StringConfigItem { + factory CopyWith$Fragment$StringConfigItem( + Fragment$StringConfigItem instance, + TRes Function(Fragment$StringConfigItem) then, + ) = _CopyWithImpl$Fragment$StringConfigItem; + + factory CopyWith$Fragment$StringConfigItem.stub(TRes res) = + _CopyWithStubImpl$Fragment$StringConfigItem; + + TRes call({ + String? id, + String? description, + String? type, + String? stringValue, + String? defaultStringValue, + String? regex, + String? widget, + String? $__typename, + }); +} + +class _CopyWithImpl$Fragment$StringConfigItem + implements CopyWith$Fragment$StringConfigItem { + _CopyWithImpl$Fragment$StringConfigItem( + this._instance, + this._then, + ); + + final Fragment$StringConfigItem _instance; + + final TRes Function(Fragment$StringConfigItem) _then; + + static const _undefined = {}; + + TRes call({ + Object? id = _undefined, + Object? description = _undefined, + Object? type = _undefined, + Object? stringValue = _undefined, + Object? defaultStringValue = _undefined, + Object? regex = _undefined, + Object? widget = _undefined, + Object? $__typename = _undefined, + }) => + _then(Fragment$StringConfigItem( + id: id == _undefined || id == null ? _instance.id : (id as String), + description: description == _undefined || description == null + ? _instance.description + : (description as String), + type: type == _undefined || type == null + ? _instance.type + : (type as String), + stringValue: stringValue == _undefined || stringValue == null + ? _instance.stringValue + : (stringValue as String), + defaultStringValue: + defaultStringValue == _undefined || defaultStringValue == null + ? _instance.defaultStringValue + : (defaultStringValue as String), + regex: regex == _undefined ? _instance.regex : (regex as String?), + widget: widget == _undefined || widget == null + ? _instance.widget + : (widget as String), + $__typename: $__typename == _undefined || $__typename == null + ? _instance.$__typename + : ($__typename as String), + )); +} + +class _CopyWithStubImpl$Fragment$StringConfigItem + implements CopyWith$Fragment$StringConfigItem { + _CopyWithStubImpl$Fragment$StringConfigItem(this._res); + + TRes _res; + + call({ + String? id, + String? description, + String? type, + String? stringValue, + String? defaultStringValue, + String? regex, + String? widget, + String? $__typename, + }) => + _res; +} + +const fragmentDefinitionStringConfigItem = FragmentDefinitionNode( + name: NameNode(value: 'StringConfigItem'), + typeCondition: TypeConditionNode( + on: NamedTypeNode( + name: NameNode(value: 'StringConfigItem'), + isNonNull: false, + )), + directives: [], + selectionSet: SelectionSetNode(selections: [ + FieldNode( + name: NameNode(value: 'id'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'description'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'type'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'value'), + alias: NameNode(value: 'stringValue'), + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'defaultValue'), + alias: NameNode(value: 'defaultStringValue'), + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'regex'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'widget'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: '__typename'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + ]), +); +const documentNodeFragmentStringConfigItem = DocumentNode(definitions: [ + fragmentDefinitionStringConfigItem, +]); + +extension ClientExtension$Fragment$StringConfigItem on graphql.GraphQLClient { + void writeFragment$StringConfigItem({ + required Fragment$StringConfigItem data, + required Map idFields, + bool broadcast = true, + }) => + this.writeFragment( + graphql.FragmentRequest( + idFields: idFields, + fragment: const graphql.Fragment( + fragmentName: 'StringConfigItem', + document: documentNodeFragmentStringConfigItem, + ), + ), + data: data.toJson(), + broadcast: broadcast, + ); + Fragment$StringConfigItem? readFragment$StringConfigItem({ + required Map idFields, + bool optimistic = true, + }) { + final result = this.readFragment( + graphql.FragmentRequest( + idFields: idFields, + fragment: const graphql.Fragment( + fragmentName: 'StringConfigItem', + document: documentNodeFragmentStringConfigItem, + ), + ), + optimistic: optimistic, + ); + return result == null ? null : Fragment$StringConfigItem.fromJson(result); + } +} + class Query$AllServices { Query$AllServices({ required this.services, @@ -305,6 +1331,54 @@ const documentNodeQueryAllServices = DocumentNode(definitions: [ directives: [], selectionSet: null, ), + FieldNode( + name: NameNode(value: 'configuration'), + alias: null, + arguments: [], + directives: [], + selectionSet: SelectionSetNode(selections: [ + FieldNode( + name: NameNode(value: 'id'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'description'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FieldNode( + name: NameNode(value: 'type'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + FragmentSpreadNode( + name: NameNode(value: 'BoolConfigItem'), + directives: [], + ), + FragmentSpreadNode( + name: NameNode(value: 'EnumConfigItem'), + directives: [], + ), + FragmentSpreadNode( + name: NameNode(value: 'StringConfigItem'), + directives: [], + ), + FieldNode( + name: NameNode(value: '__typename'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + ]), + ), FieldNode( name: NameNode(value: '__typename'), alias: null, @@ -333,6 +1407,9 @@ const documentNodeQueryAllServices = DocumentNode(definitions: [ ]), ), fragmentDefinitionfragmentDnsRecords, + fragmentDefinitionBoolConfigItem, + fragmentDefinitionEnumConfigItem, + fragmentDefinitionStringConfigItem, ]); Query$AllServices _parserFn$Query$AllServices(Map data) => Query$AllServices.fromJson(data); @@ -622,6 +1699,7 @@ class Query$AllServices$services$allServices { required this.storageUsage, required this.svgIcon, this.url, + this.configuration, this.$__typename = 'Service', }); @@ -640,6 +1718,7 @@ class Query$AllServices$services$allServices { final l$storageUsage = json['storageUsage']; final l$svgIcon = json['svgIcon']; final l$url = json['url']; + final l$configuration = json['configuration']; final l$$__typename = json['__typename']; return Query$AllServices$services$allServices( description: (l$description as String), @@ -660,6 +1739,11 @@ class Query$AllServices$services$allServices { (l$storageUsage as Map)), svgIcon: (l$svgIcon as String), url: (l$url as String?), + configuration: (l$configuration as List?) + ?.map((e) => + Query$AllServices$services$allServices$configuration.fromJson( + (e as Map))) + .toList(), $__typename: (l$$__typename as String), ); } @@ -690,6 +1774,9 @@ class Query$AllServices$services$allServices { final String? url; + final List? + configuration; + final String $__typename; Map toJson() { @@ -720,6 +1807,9 @@ class Query$AllServices$services$allServices { _resultData['svgIcon'] = l$svgIcon; final l$url = url; _resultData['url'] = l$url; + final l$configuration = configuration; + _resultData['configuration'] = + l$configuration?.map((e) => e.toJson()).toList(); final l$$__typename = $__typename; _resultData['__typename'] = l$$__typename; return _resultData; @@ -740,6 +1830,7 @@ class Query$AllServices$services$allServices { final l$storageUsage = storageUsage; final l$svgIcon = svgIcon; final l$url = url; + final l$configuration = configuration; final l$$__typename = $__typename; return Object.hashAll([ l$description, @@ -755,6 +1846,9 @@ class Query$AllServices$services$allServices { l$storageUsage, l$svgIcon, l$url, + l$configuration == null + ? null + : Object.hashAll(l$configuration.map((v) => v)), l$$__typename, ]); } @@ -844,6 +1938,22 @@ class Query$AllServices$services$allServices { if (l$url != lOther$url) { return false; } + final l$configuration = configuration; + final lOther$configuration = other.configuration; + if (l$configuration != null && lOther$configuration != null) { + if (l$configuration.length != lOther$configuration.length) { + return false; + } + for (int i = 0; i < l$configuration.length; i++) { + final l$configuration$entry = l$configuration[i]; + final lOther$configuration$entry = lOther$configuration[i]; + if (l$configuration$entry != lOther$configuration$entry) { + return false; + } + } + } else if (l$configuration != lOther$configuration) { + return false; + } final l$$__typename = $__typename; final lOther$$__typename = other.$__typename; if (l$$__typename != lOther$$__typename) { @@ -886,6 +1996,7 @@ abstract class CopyWith$Query$AllServices$services$allServices { Query$AllServices$services$allServices$storageUsage? storageUsage, String? svgIcon, String? url, + List? configuration, String? $__typename, }); TRes dnsRecords( @@ -896,6 +2007,12 @@ abstract class CopyWith$Query$AllServices$services$allServices { _fn); CopyWith$Query$AllServices$services$allServices$storageUsage get storageUsage; + TRes configuration( + Iterable? Function( + Iterable< + CopyWith$Query$AllServices$services$allServices$configuration< + Query$AllServices$services$allServices$configuration>>?) + _fn); } class _CopyWithImpl$Query$AllServices$services$allServices @@ -925,6 +2042,7 @@ class _CopyWithImpl$Query$AllServices$services$allServices Object? storageUsage = _undefined, Object? svgIcon = _undefined, Object? url = _undefined, + Object? configuration = _undefined, Object? $__typename = _undefined, }) => _then(Query$AllServices$services$allServices( @@ -965,6 +2083,10 @@ class _CopyWithImpl$Query$AllServices$services$allServices ? _instance.svgIcon : (svgIcon as String), url: url == _undefined ? _instance.url : (url as String?), + configuration: configuration == _undefined + ? _instance.configuration + : (configuration + as List?), $__typename: $__typename == _undefined || $__typename == null ? _instance.$__typename : ($__typename as String), @@ -989,6 +2111,19 @@ class _CopyWithImpl$Query$AllServices$services$allServices return CopyWith$Query$AllServices$services$allServices$storageUsage( local$storageUsage, (e) => call(storageUsage: e)); } + + TRes configuration( + Iterable? Function( + Iterable< + CopyWith$Query$AllServices$services$allServices$configuration< + Query$AllServices$services$allServices$configuration>>?) + _fn) => + call( + configuration: _fn(_instance.configuration?.map((e) => + CopyWith$Query$AllServices$services$allServices$configuration( + e, + (i) => i, + )))?.toList()); } class _CopyWithStubImpl$Query$AllServices$services$allServices @@ -1011,6 +2146,7 @@ class _CopyWithStubImpl$Query$AllServices$services$allServices Query$AllServices$services$allServices$storageUsage? storageUsage, String? svgIcon, String? url, + List? configuration, String? $__typename, }) => _res; @@ -1021,6 +2157,8 @@ class _CopyWithStubImpl$Query$AllServices$services$allServices get storageUsage => CopyWith$Query$AllServices$services$allServices$storageUsage.stub( _res); + + configuration(_fn) => _res; } class Query$AllServices$services$allServices$storageUsage { @@ -1359,6 +2497,1051 @@ class _CopyWithStubImpl$Query$AllServices$services$allServices$storageUsage$volu _res; } +class Query$AllServices$services$allServices$configuration { + Query$AllServices$services$allServices$configuration({ + required this.id, + required this.description, + required this.type, + required this.$__typename, + }); + + factory Query$AllServices$services$allServices$configuration.fromJson( + Map json) { + switch (json["__typename"] as String) { + case "BoolConfigItem": + return Query$AllServices$services$allServices$configuration$$BoolConfigItem + .fromJson(json); + + case "EnumConfigItem": + return Query$AllServices$services$allServices$configuration$$EnumConfigItem + .fromJson(json); + + case "StringConfigItem": + return Query$AllServices$services$allServices$configuration$$StringConfigItem + .fromJson(json); + + default: + final l$id = json['id']; + final l$description = json['description']; + final l$type = json['type']; + final l$$__typename = json['__typename']; + return Query$AllServices$services$allServices$configuration( + id: (l$id as String), + description: (l$description as String), + type: (l$type as String), + $__typename: (l$$__typename as String), + ); + } + } + + final String id; + + final String description; + + final String type; + + final String $__typename; + + Map toJson() { + final _resultData = {}; + final l$id = id; + _resultData['id'] = l$id; + final l$description = description; + _resultData['description'] = l$description; + final l$type = type; + _resultData['type'] = l$type; + final l$$__typename = $__typename; + _resultData['__typename'] = l$$__typename; + return _resultData; + } + + @override + int get hashCode { + final l$id = id; + final l$description = description; + final l$type = type; + final l$$__typename = $__typename; + return Object.hashAll([ + l$id, + l$description, + l$type, + l$$__typename, + ]); + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (!(other is Query$AllServices$services$allServices$configuration) || + runtimeType != other.runtimeType) { + return false; + } + final l$id = id; + final lOther$id = other.id; + if (l$id != lOther$id) { + return false; + } + final l$description = description; + final lOther$description = other.description; + if (l$description != lOther$description) { + return false; + } + final l$type = type; + final lOther$type = other.type; + if (l$type != lOther$type) { + return false; + } + final l$$__typename = $__typename; + final lOther$$__typename = other.$__typename; + if (l$$__typename != lOther$$__typename) { + return false; + } + return true; + } +} + +extension UtilityExtension$Query$AllServices$services$allServices$configuration + on Query$AllServices$services$allServices$configuration { + CopyWith$Query$AllServices$services$allServices$configuration< + Query$AllServices$services$allServices$configuration> + get copyWith => + CopyWith$Query$AllServices$services$allServices$configuration( + this, + (i) => i, + ); + _T when<_T>({ + required _T Function( + Query$AllServices$services$allServices$configuration$$BoolConfigItem) + boolConfigItem, + required _T Function( + Query$AllServices$services$allServices$configuration$$EnumConfigItem) + enumConfigItem, + required _T Function( + Query$AllServices$services$allServices$configuration$$StringConfigItem) + stringConfigItem, + required _T Function() orElse, + }) { + switch ($__typename) { + case "BoolConfigItem": + return boolConfigItem(this + as Query$AllServices$services$allServices$configuration$$BoolConfigItem); + + case "EnumConfigItem": + return enumConfigItem(this + as Query$AllServices$services$allServices$configuration$$EnumConfigItem); + + case "StringConfigItem": + return stringConfigItem(this + as Query$AllServices$services$allServices$configuration$$StringConfigItem); + + default: + return orElse(); + } + } + + _T maybeWhen<_T>({ + _T Function( + Query$AllServices$services$allServices$configuration$$BoolConfigItem)? + boolConfigItem, + _T Function( + Query$AllServices$services$allServices$configuration$$EnumConfigItem)? + enumConfigItem, + _T Function( + Query$AllServices$services$allServices$configuration$$StringConfigItem)? + stringConfigItem, + required _T Function() orElse, + }) { + switch ($__typename) { + case "BoolConfigItem": + if (boolConfigItem != null) { + return boolConfigItem(this + as Query$AllServices$services$allServices$configuration$$BoolConfigItem); + } else { + return orElse(); + } + + case "EnumConfigItem": + if (enumConfigItem != null) { + return enumConfigItem(this + as Query$AllServices$services$allServices$configuration$$EnumConfigItem); + } else { + return orElse(); + } + + case "StringConfigItem": + if (stringConfigItem != null) { + return stringConfigItem(this + as Query$AllServices$services$allServices$configuration$$StringConfigItem); + } else { + return orElse(); + } + + default: + return orElse(); + } + } +} + +abstract class CopyWith$Query$AllServices$services$allServices$configuration< + TRes> { + factory CopyWith$Query$AllServices$services$allServices$configuration( + Query$AllServices$services$allServices$configuration instance, + TRes Function(Query$AllServices$services$allServices$configuration) then, + ) = _CopyWithImpl$Query$AllServices$services$allServices$configuration; + + factory CopyWith$Query$AllServices$services$allServices$configuration.stub( + TRes res) = + _CopyWithStubImpl$Query$AllServices$services$allServices$configuration; + + TRes call({ + String? id, + String? description, + String? type, + String? $__typename, + }); +} + +class _CopyWithImpl$Query$AllServices$services$allServices$configuration + implements + CopyWith$Query$AllServices$services$allServices$configuration { + _CopyWithImpl$Query$AllServices$services$allServices$configuration( + this._instance, + this._then, + ); + + final Query$AllServices$services$allServices$configuration _instance; + + final TRes Function(Query$AllServices$services$allServices$configuration) + _then; + + static const _undefined = {}; + + TRes call({ + Object? id = _undefined, + Object? description = _undefined, + Object? type = _undefined, + Object? $__typename = _undefined, + }) => + _then(Query$AllServices$services$allServices$configuration( + id: id == _undefined || id == null ? _instance.id : (id as String), + description: description == _undefined || description == null + ? _instance.description + : (description as String), + type: type == _undefined || type == null + ? _instance.type + : (type as String), + $__typename: $__typename == _undefined || $__typename == null + ? _instance.$__typename + : ($__typename as String), + )); +} + +class _CopyWithStubImpl$Query$AllServices$services$allServices$configuration< + TRes> + implements + CopyWith$Query$AllServices$services$allServices$configuration { + _CopyWithStubImpl$Query$AllServices$services$allServices$configuration( + this._res); + + TRes _res; + + call({ + String? id, + String? description, + String? type, + String? $__typename, + }) => + _res; +} + +class Query$AllServices$services$allServices$configuration$$BoolConfigItem + implements + Fragment$BoolConfigItem, + Query$AllServices$services$allServices$configuration { + Query$AllServices$services$allServices$configuration$$BoolConfigItem({ + required this.id, + required this.description, + required this.type, + required this.boolValue, + required this.defaultBoolValue, + required this.widget, + this.$__typename = 'BoolConfigItem', + }); + + factory Query$AllServices$services$allServices$configuration$$BoolConfigItem.fromJson( + Map json) { + final l$id = json['id']; + final l$description = json['description']; + final l$type = json['type']; + final l$boolValue = json['boolValue']; + final l$defaultBoolValue = json['defaultBoolValue']; + final l$widget = json['widget']; + final l$$__typename = json['__typename']; + return Query$AllServices$services$allServices$configuration$$BoolConfigItem( + id: (l$id as String), + description: (l$description as String), + type: (l$type as String), + boolValue: (l$boolValue as bool), + defaultBoolValue: (l$defaultBoolValue as bool), + widget: (l$widget as String), + $__typename: (l$$__typename as String), + ); + } + + final String id; + + final String description; + + final String type; + + final bool boolValue; + + final bool defaultBoolValue; + + final String widget; + + final String $__typename; + + Map toJson() { + final _resultData = {}; + final l$id = id; + _resultData['id'] = l$id; + final l$description = description; + _resultData['description'] = l$description; + final l$type = type; + _resultData['type'] = l$type; + final l$boolValue = boolValue; + _resultData['boolValue'] = l$boolValue; + final l$defaultBoolValue = defaultBoolValue; + _resultData['defaultBoolValue'] = l$defaultBoolValue; + final l$widget = widget; + _resultData['widget'] = l$widget; + final l$$__typename = $__typename; + _resultData['__typename'] = l$$__typename; + return _resultData; + } + + @override + int get hashCode { + final l$id = id; + final l$description = description; + final l$type = type; + final l$boolValue = boolValue; + final l$defaultBoolValue = defaultBoolValue; + final l$widget = widget; + final l$$__typename = $__typename; + return Object.hashAll([ + l$id, + l$description, + l$type, + l$boolValue, + l$defaultBoolValue, + l$widget, + l$$__typename, + ]); + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (!(other + is Query$AllServices$services$allServices$configuration$$BoolConfigItem) || + runtimeType != other.runtimeType) { + return false; + } + final l$id = id; + final lOther$id = other.id; + if (l$id != lOther$id) { + return false; + } + final l$description = description; + final lOther$description = other.description; + if (l$description != lOther$description) { + return false; + } + final l$type = type; + final lOther$type = other.type; + if (l$type != lOther$type) { + return false; + } + final l$boolValue = boolValue; + final lOther$boolValue = other.boolValue; + if (l$boolValue != lOther$boolValue) { + return false; + } + final l$defaultBoolValue = defaultBoolValue; + final lOther$defaultBoolValue = other.defaultBoolValue; + if (l$defaultBoolValue != lOther$defaultBoolValue) { + return false; + } + final l$widget = widget; + final lOther$widget = other.widget; + if (l$widget != lOther$widget) { + return false; + } + final l$$__typename = $__typename; + final lOther$$__typename = other.$__typename; + if (l$$__typename != lOther$$__typename) { + return false; + } + return true; + } +} + +extension UtilityExtension$Query$AllServices$services$allServices$configuration$$BoolConfigItem + on Query$AllServices$services$allServices$configuration$$BoolConfigItem { + CopyWith$Query$AllServices$services$allServices$configuration$$BoolConfigItem< + Query$AllServices$services$allServices$configuration$$BoolConfigItem> + get copyWith => + CopyWith$Query$AllServices$services$allServices$configuration$$BoolConfigItem( + this, + (i) => i, + ); +} + +abstract class CopyWith$Query$AllServices$services$allServices$configuration$$BoolConfigItem< + TRes> { + factory CopyWith$Query$AllServices$services$allServices$configuration$$BoolConfigItem( + Query$AllServices$services$allServices$configuration$$BoolConfigItem + instance, + TRes Function( + Query$AllServices$services$allServices$configuration$$BoolConfigItem) + then, + ) = _CopyWithImpl$Query$AllServices$services$allServices$configuration$$BoolConfigItem; + + factory CopyWith$Query$AllServices$services$allServices$configuration$$BoolConfigItem.stub( + TRes res) = + _CopyWithStubImpl$Query$AllServices$services$allServices$configuration$$BoolConfigItem; + + TRes call({ + String? id, + String? description, + String? type, + bool? boolValue, + bool? defaultBoolValue, + String? widget, + String? $__typename, + }); +} + +class _CopyWithImpl$Query$AllServices$services$allServices$configuration$$BoolConfigItem< + TRes> + implements + CopyWith$Query$AllServices$services$allServices$configuration$$BoolConfigItem< + TRes> { + _CopyWithImpl$Query$AllServices$services$allServices$configuration$$BoolConfigItem( + this._instance, + this._then, + ); + + final Query$AllServices$services$allServices$configuration$$BoolConfigItem + _instance; + + final TRes Function( + Query$AllServices$services$allServices$configuration$$BoolConfigItem) + _then; + + static const _undefined = {}; + + TRes call({ + Object? id = _undefined, + Object? description = _undefined, + Object? type = _undefined, + Object? boolValue = _undefined, + Object? defaultBoolValue = _undefined, + Object? widget = _undefined, + Object? $__typename = _undefined, + }) => + _then( + Query$AllServices$services$allServices$configuration$$BoolConfigItem( + id: id == _undefined || id == null ? _instance.id : (id as String), + description: description == _undefined || description == null + ? _instance.description + : (description as String), + type: type == _undefined || type == null + ? _instance.type + : (type as String), + boolValue: boolValue == _undefined || boolValue == null + ? _instance.boolValue + : (boolValue as bool), + defaultBoolValue: + defaultBoolValue == _undefined || defaultBoolValue == null + ? _instance.defaultBoolValue + : (defaultBoolValue as bool), + widget: widget == _undefined || widget == null + ? _instance.widget + : (widget as String), + $__typename: $__typename == _undefined || $__typename == null + ? _instance.$__typename + : ($__typename as String), + )); +} + +class _CopyWithStubImpl$Query$AllServices$services$allServices$configuration$$BoolConfigItem< + TRes> + implements + CopyWith$Query$AllServices$services$allServices$configuration$$BoolConfigItem< + TRes> { + _CopyWithStubImpl$Query$AllServices$services$allServices$configuration$$BoolConfigItem( + this._res); + + TRes _res; + + call({ + String? id, + String? description, + String? type, + bool? boolValue, + bool? defaultBoolValue, + String? widget, + String? $__typename, + }) => + _res; +} + +class Query$AllServices$services$allServices$configuration$$EnumConfigItem + implements + Fragment$EnumConfigItem, + Query$AllServices$services$allServices$configuration { + Query$AllServices$services$allServices$configuration$$EnumConfigItem({ + required this.id, + required this.description, + required this.type, + required this.stringValue, + required this.defaultStringValue, + required this.options, + required this.widget, + this.$__typename = 'EnumConfigItem', + }); + + factory Query$AllServices$services$allServices$configuration$$EnumConfigItem.fromJson( + Map json) { + final l$id = json['id']; + final l$description = json['description']; + final l$type = json['type']; + final l$stringValue = json['stringValue']; + final l$defaultStringValue = json['defaultStringValue']; + final l$options = json['options']; + final l$widget = json['widget']; + final l$$__typename = json['__typename']; + return Query$AllServices$services$allServices$configuration$$EnumConfigItem( + id: (l$id as String), + description: (l$description as String), + type: (l$type as String), + stringValue: (l$stringValue as String), + defaultStringValue: (l$defaultStringValue as String), + options: (l$options as List).map((e) => (e as String)).toList(), + widget: (l$widget as String), + $__typename: (l$$__typename as String), + ); + } + + final String id; + + final String description; + + final String type; + + final String stringValue; + + final String defaultStringValue; + + final List options; + + final String widget; + + final String $__typename; + + Map toJson() { + final _resultData = {}; + final l$id = id; + _resultData['id'] = l$id; + final l$description = description; + _resultData['description'] = l$description; + final l$type = type; + _resultData['type'] = l$type; + final l$stringValue = stringValue; + _resultData['stringValue'] = l$stringValue; + final l$defaultStringValue = defaultStringValue; + _resultData['defaultStringValue'] = l$defaultStringValue; + final l$options = options; + _resultData['options'] = l$options.map((e) => e).toList(); + final l$widget = widget; + _resultData['widget'] = l$widget; + final l$$__typename = $__typename; + _resultData['__typename'] = l$$__typename; + return _resultData; + } + + @override + int get hashCode { + final l$id = id; + final l$description = description; + final l$type = type; + final l$stringValue = stringValue; + final l$defaultStringValue = defaultStringValue; + final l$options = options; + final l$widget = widget; + final l$$__typename = $__typename; + return Object.hashAll([ + l$id, + l$description, + l$type, + l$stringValue, + l$defaultStringValue, + Object.hashAll(l$options.map((v) => v)), + l$widget, + l$$__typename, + ]); + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (!(other + is Query$AllServices$services$allServices$configuration$$EnumConfigItem) || + runtimeType != other.runtimeType) { + return false; + } + final l$id = id; + final lOther$id = other.id; + if (l$id != lOther$id) { + return false; + } + final l$description = description; + final lOther$description = other.description; + if (l$description != lOther$description) { + return false; + } + final l$type = type; + final lOther$type = other.type; + if (l$type != lOther$type) { + return false; + } + final l$stringValue = stringValue; + final lOther$stringValue = other.stringValue; + if (l$stringValue != lOther$stringValue) { + return false; + } + final l$defaultStringValue = defaultStringValue; + final lOther$defaultStringValue = other.defaultStringValue; + if (l$defaultStringValue != lOther$defaultStringValue) { + return false; + } + final l$options = options; + final lOther$options = other.options; + if (l$options.length != lOther$options.length) { + return false; + } + for (int i = 0; i < l$options.length; i++) { + final l$options$entry = l$options[i]; + final lOther$options$entry = lOther$options[i]; + if (l$options$entry != lOther$options$entry) { + return false; + } + } + final l$widget = widget; + final lOther$widget = other.widget; + if (l$widget != lOther$widget) { + return false; + } + final l$$__typename = $__typename; + final lOther$$__typename = other.$__typename; + if (l$$__typename != lOther$$__typename) { + return false; + } + return true; + } +} + +extension UtilityExtension$Query$AllServices$services$allServices$configuration$$EnumConfigItem + on Query$AllServices$services$allServices$configuration$$EnumConfigItem { + CopyWith$Query$AllServices$services$allServices$configuration$$EnumConfigItem< + Query$AllServices$services$allServices$configuration$$EnumConfigItem> + get copyWith => + CopyWith$Query$AllServices$services$allServices$configuration$$EnumConfigItem( + this, + (i) => i, + ); +} + +abstract class CopyWith$Query$AllServices$services$allServices$configuration$$EnumConfigItem< + TRes> { + factory CopyWith$Query$AllServices$services$allServices$configuration$$EnumConfigItem( + Query$AllServices$services$allServices$configuration$$EnumConfigItem + instance, + TRes Function( + Query$AllServices$services$allServices$configuration$$EnumConfigItem) + then, + ) = _CopyWithImpl$Query$AllServices$services$allServices$configuration$$EnumConfigItem; + + factory CopyWith$Query$AllServices$services$allServices$configuration$$EnumConfigItem.stub( + TRes res) = + _CopyWithStubImpl$Query$AllServices$services$allServices$configuration$$EnumConfigItem; + + TRes call({ + String? id, + String? description, + String? type, + String? stringValue, + String? defaultStringValue, + List? options, + String? widget, + String? $__typename, + }); +} + +class _CopyWithImpl$Query$AllServices$services$allServices$configuration$$EnumConfigItem< + TRes> + implements + CopyWith$Query$AllServices$services$allServices$configuration$$EnumConfigItem< + TRes> { + _CopyWithImpl$Query$AllServices$services$allServices$configuration$$EnumConfigItem( + this._instance, + this._then, + ); + + final Query$AllServices$services$allServices$configuration$$EnumConfigItem + _instance; + + final TRes Function( + Query$AllServices$services$allServices$configuration$$EnumConfigItem) + _then; + + static const _undefined = {}; + + TRes call({ + Object? id = _undefined, + Object? description = _undefined, + Object? type = _undefined, + Object? stringValue = _undefined, + Object? defaultStringValue = _undefined, + Object? options = _undefined, + Object? widget = _undefined, + Object? $__typename = _undefined, + }) => + _then( + Query$AllServices$services$allServices$configuration$$EnumConfigItem( + id: id == _undefined || id == null ? _instance.id : (id as String), + description: description == _undefined || description == null + ? _instance.description + : (description as String), + type: type == _undefined || type == null + ? _instance.type + : (type as String), + stringValue: stringValue == _undefined || stringValue == null + ? _instance.stringValue + : (stringValue as String), + defaultStringValue: + defaultStringValue == _undefined || defaultStringValue == null + ? _instance.defaultStringValue + : (defaultStringValue as String), + options: options == _undefined || options == null + ? _instance.options + : (options as List), + widget: widget == _undefined || widget == null + ? _instance.widget + : (widget as String), + $__typename: $__typename == _undefined || $__typename == null + ? _instance.$__typename + : ($__typename as String), + )); +} + +class _CopyWithStubImpl$Query$AllServices$services$allServices$configuration$$EnumConfigItem< + TRes> + implements + CopyWith$Query$AllServices$services$allServices$configuration$$EnumConfigItem< + TRes> { + _CopyWithStubImpl$Query$AllServices$services$allServices$configuration$$EnumConfigItem( + this._res); + + TRes _res; + + call({ + String? id, + String? description, + String? type, + String? stringValue, + String? defaultStringValue, + List? options, + String? widget, + String? $__typename, + }) => + _res; +} + +class Query$AllServices$services$allServices$configuration$$StringConfigItem + implements + Fragment$StringConfigItem, + Query$AllServices$services$allServices$configuration { + Query$AllServices$services$allServices$configuration$$StringConfigItem({ + required this.id, + required this.description, + required this.type, + required this.stringValue, + required this.defaultStringValue, + this.regex, + required this.widget, + this.$__typename = 'StringConfigItem', + }); + + factory Query$AllServices$services$allServices$configuration$$StringConfigItem.fromJson( + Map json) { + final l$id = json['id']; + final l$description = json['description']; + final l$type = json['type']; + final l$stringValue = json['stringValue']; + final l$defaultStringValue = json['defaultStringValue']; + final l$regex = json['regex']; + final l$widget = json['widget']; + final l$$__typename = json['__typename']; + return Query$AllServices$services$allServices$configuration$$StringConfigItem( + id: (l$id as String), + description: (l$description as String), + type: (l$type as String), + stringValue: (l$stringValue as String), + defaultStringValue: (l$defaultStringValue as String), + regex: (l$regex as String?), + widget: (l$widget as String), + $__typename: (l$$__typename as String), + ); + } + + final String id; + + final String description; + + final String type; + + final String stringValue; + + final String defaultStringValue; + + final String? regex; + + final String widget; + + final String $__typename; + + Map toJson() { + final _resultData = {}; + final l$id = id; + _resultData['id'] = l$id; + final l$description = description; + _resultData['description'] = l$description; + final l$type = type; + _resultData['type'] = l$type; + final l$stringValue = stringValue; + _resultData['stringValue'] = l$stringValue; + final l$defaultStringValue = defaultStringValue; + _resultData['defaultStringValue'] = l$defaultStringValue; + final l$regex = regex; + _resultData['regex'] = l$regex; + final l$widget = widget; + _resultData['widget'] = l$widget; + final l$$__typename = $__typename; + _resultData['__typename'] = l$$__typename; + return _resultData; + } + + @override + int get hashCode { + final l$id = id; + final l$description = description; + final l$type = type; + final l$stringValue = stringValue; + final l$defaultStringValue = defaultStringValue; + final l$regex = regex; + final l$widget = widget; + final l$$__typename = $__typename; + return Object.hashAll([ + l$id, + l$description, + l$type, + l$stringValue, + l$defaultStringValue, + l$regex, + l$widget, + l$$__typename, + ]); + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (!(other + is Query$AllServices$services$allServices$configuration$$StringConfigItem) || + runtimeType != other.runtimeType) { + return false; + } + final l$id = id; + final lOther$id = other.id; + if (l$id != lOther$id) { + return false; + } + final l$description = description; + final lOther$description = other.description; + if (l$description != lOther$description) { + return false; + } + final l$type = type; + final lOther$type = other.type; + if (l$type != lOther$type) { + return false; + } + final l$stringValue = stringValue; + final lOther$stringValue = other.stringValue; + if (l$stringValue != lOther$stringValue) { + return false; + } + final l$defaultStringValue = defaultStringValue; + final lOther$defaultStringValue = other.defaultStringValue; + if (l$defaultStringValue != lOther$defaultStringValue) { + return false; + } + final l$regex = regex; + final lOther$regex = other.regex; + if (l$regex != lOther$regex) { + return false; + } + final l$widget = widget; + final lOther$widget = other.widget; + if (l$widget != lOther$widget) { + return false; + } + final l$$__typename = $__typename; + final lOther$$__typename = other.$__typename; + if (l$$__typename != lOther$$__typename) { + return false; + } + return true; + } +} + +extension UtilityExtension$Query$AllServices$services$allServices$configuration$$StringConfigItem + on Query$AllServices$services$allServices$configuration$$StringConfigItem { + CopyWith$Query$AllServices$services$allServices$configuration$$StringConfigItem< + Query$AllServices$services$allServices$configuration$$StringConfigItem> + get copyWith => + CopyWith$Query$AllServices$services$allServices$configuration$$StringConfigItem( + this, + (i) => i, + ); +} + +abstract class CopyWith$Query$AllServices$services$allServices$configuration$$StringConfigItem< + TRes> { + factory CopyWith$Query$AllServices$services$allServices$configuration$$StringConfigItem( + Query$AllServices$services$allServices$configuration$$StringConfigItem + instance, + TRes Function( + Query$AllServices$services$allServices$configuration$$StringConfigItem) + then, + ) = _CopyWithImpl$Query$AllServices$services$allServices$configuration$$StringConfigItem; + + factory CopyWith$Query$AllServices$services$allServices$configuration$$StringConfigItem.stub( + TRes res) = + _CopyWithStubImpl$Query$AllServices$services$allServices$configuration$$StringConfigItem; + + TRes call({ + String? id, + String? description, + String? type, + String? stringValue, + String? defaultStringValue, + String? regex, + String? widget, + String? $__typename, + }); +} + +class _CopyWithImpl$Query$AllServices$services$allServices$configuration$$StringConfigItem< + TRes> + implements + CopyWith$Query$AllServices$services$allServices$configuration$$StringConfigItem< + TRes> { + _CopyWithImpl$Query$AllServices$services$allServices$configuration$$StringConfigItem( + this._instance, + this._then, + ); + + final Query$AllServices$services$allServices$configuration$$StringConfigItem + _instance; + + final TRes Function( + Query$AllServices$services$allServices$configuration$$StringConfigItem) + _then; + + static const _undefined = {}; + + TRes call({ + Object? id = _undefined, + Object? description = _undefined, + Object? type = _undefined, + Object? stringValue = _undefined, + Object? defaultStringValue = _undefined, + Object? regex = _undefined, + Object? widget = _undefined, + Object? $__typename = _undefined, + }) => + _then( + Query$AllServices$services$allServices$configuration$$StringConfigItem( + id: id == _undefined || id == null ? _instance.id : (id as String), + description: description == _undefined || description == null + ? _instance.description + : (description as String), + type: type == _undefined || type == null + ? _instance.type + : (type as String), + stringValue: stringValue == _undefined || stringValue == null + ? _instance.stringValue + : (stringValue as String), + defaultStringValue: + defaultStringValue == _undefined || defaultStringValue == null + ? _instance.defaultStringValue + : (defaultStringValue as String), + regex: regex == _undefined ? _instance.regex : (regex as String?), + widget: widget == _undefined || widget == null + ? _instance.widget + : (widget as String), + $__typename: $__typename == _undefined || $__typename == null + ? _instance.$__typename + : ($__typename as String), + )); +} + +class _CopyWithStubImpl$Query$AllServices$services$allServices$configuration$$StringConfigItem< + TRes> + implements + CopyWith$Query$AllServices$services$allServices$configuration$$StringConfigItem< + TRes> { + _CopyWithStubImpl$Query$AllServices$services$allServices$configuration$$StringConfigItem( + this._res); + + TRes _res; + + call({ + String? id, + String? description, + String? type, + String? stringValue, + String? defaultStringValue, + String? regex, + String? widget, + String? $__typename, + }) => + _res; +} + class Variables$Mutation$EnableService { factory Variables$Mutation$EnableService({required String serviceId}) => Variables$Mutation$EnableService._({ @@ -5622,3 +7805,742 @@ class _CopyWithStubImpl$Mutation$MoveService$services$moveService CopyWith$Fragment$basicApiJobsFields get job => CopyWith$Fragment$basicApiJobsFields.stub(_res); } + +class Variables$Mutation$SetServiceConfiguration { + factory Variables$Mutation$SetServiceConfiguration( + {required Input$SetServiceConfigurationInput input}) => + Variables$Mutation$SetServiceConfiguration._({ + r'input': input, + }); + + Variables$Mutation$SetServiceConfiguration._(this._$data); + + factory Variables$Mutation$SetServiceConfiguration.fromJson( + Map data) { + final result$data = {}; + final l$input = data['input']; + result$data['input'] = Input$SetServiceConfigurationInput.fromJson( + (l$input as Map)); + return Variables$Mutation$SetServiceConfiguration._(result$data); + } + + Map _$data; + + Input$SetServiceConfigurationInput get input => + (_$data['input'] as Input$SetServiceConfigurationInput); + + Map toJson() { + final result$data = {}; + final l$input = input; + result$data['input'] = l$input.toJson(); + return result$data; + } + + CopyWith$Variables$Mutation$SetServiceConfiguration< + Variables$Mutation$SetServiceConfiguration> + get copyWith => CopyWith$Variables$Mutation$SetServiceConfiguration( + this, + (i) => i, + ); + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (!(other is Variables$Mutation$SetServiceConfiguration) || + runtimeType != other.runtimeType) { + return false; + } + final l$input = input; + final lOther$input = other.input; + if (l$input != lOther$input) { + return false; + } + return true; + } + + @override + int get hashCode { + final l$input = input; + return Object.hashAll([l$input]); + } +} + +abstract class CopyWith$Variables$Mutation$SetServiceConfiguration { + factory CopyWith$Variables$Mutation$SetServiceConfiguration( + Variables$Mutation$SetServiceConfiguration instance, + TRes Function(Variables$Mutation$SetServiceConfiguration) then, + ) = _CopyWithImpl$Variables$Mutation$SetServiceConfiguration; + + factory CopyWith$Variables$Mutation$SetServiceConfiguration.stub(TRes res) = + _CopyWithStubImpl$Variables$Mutation$SetServiceConfiguration; + + TRes call({Input$SetServiceConfigurationInput? input}); +} + +class _CopyWithImpl$Variables$Mutation$SetServiceConfiguration + implements CopyWith$Variables$Mutation$SetServiceConfiguration { + _CopyWithImpl$Variables$Mutation$SetServiceConfiguration( + this._instance, + this._then, + ); + + final Variables$Mutation$SetServiceConfiguration _instance; + + final TRes Function(Variables$Mutation$SetServiceConfiguration) _then; + + static const _undefined = {}; + + TRes call({Object? input = _undefined}) => + _then(Variables$Mutation$SetServiceConfiguration._({ + ..._instance._$data, + if (input != _undefined && input != null) + 'input': (input as Input$SetServiceConfigurationInput), + })); +} + +class _CopyWithStubImpl$Variables$Mutation$SetServiceConfiguration + implements CopyWith$Variables$Mutation$SetServiceConfiguration { + _CopyWithStubImpl$Variables$Mutation$SetServiceConfiguration(this._res); + + TRes _res; + + call({Input$SetServiceConfigurationInput? input}) => _res; +} + +class Mutation$SetServiceConfiguration { + Mutation$SetServiceConfiguration({ + required this.services, + this.$__typename = 'Mutation', + }); + + factory Mutation$SetServiceConfiguration.fromJson(Map json) { + final l$services = json['services']; + final l$$__typename = json['__typename']; + return Mutation$SetServiceConfiguration( + services: Mutation$SetServiceConfiguration$services.fromJson( + (l$services as Map)), + $__typename: (l$$__typename as String), + ); + } + + final Mutation$SetServiceConfiguration$services services; + + final String $__typename; + + Map toJson() { + final _resultData = {}; + final l$services = services; + _resultData['services'] = l$services.toJson(); + final l$$__typename = $__typename; + _resultData['__typename'] = l$$__typename; + return _resultData; + } + + @override + int get hashCode { + final l$services = services; + final l$$__typename = $__typename; + return Object.hashAll([ + l$services, + l$$__typename, + ]); + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (!(other is Mutation$SetServiceConfiguration) || + runtimeType != other.runtimeType) { + return false; + } + final l$services = services; + final lOther$services = other.services; + if (l$services != lOther$services) { + return false; + } + final l$$__typename = $__typename; + final lOther$$__typename = other.$__typename; + if (l$$__typename != lOther$$__typename) { + return false; + } + return true; + } +} + +extension UtilityExtension$Mutation$SetServiceConfiguration + on Mutation$SetServiceConfiguration { + CopyWith$Mutation$SetServiceConfiguration + get copyWith => CopyWith$Mutation$SetServiceConfiguration( + this, + (i) => i, + ); +} + +abstract class CopyWith$Mutation$SetServiceConfiguration { + factory CopyWith$Mutation$SetServiceConfiguration( + Mutation$SetServiceConfiguration instance, + TRes Function(Mutation$SetServiceConfiguration) then, + ) = _CopyWithImpl$Mutation$SetServiceConfiguration; + + factory CopyWith$Mutation$SetServiceConfiguration.stub(TRes res) = + _CopyWithStubImpl$Mutation$SetServiceConfiguration; + + TRes call({ + Mutation$SetServiceConfiguration$services? services, + String? $__typename, + }); + CopyWith$Mutation$SetServiceConfiguration$services get services; +} + +class _CopyWithImpl$Mutation$SetServiceConfiguration + implements CopyWith$Mutation$SetServiceConfiguration { + _CopyWithImpl$Mutation$SetServiceConfiguration( + this._instance, + this._then, + ); + + final Mutation$SetServiceConfiguration _instance; + + final TRes Function(Mutation$SetServiceConfiguration) _then; + + static const _undefined = {}; + + TRes call({ + Object? services = _undefined, + Object? $__typename = _undefined, + }) => + _then(Mutation$SetServiceConfiguration( + services: services == _undefined || services == null + ? _instance.services + : (services as Mutation$SetServiceConfiguration$services), + $__typename: $__typename == _undefined || $__typename == null + ? _instance.$__typename + : ($__typename as String), + )); + + CopyWith$Mutation$SetServiceConfiguration$services get services { + final local$services = _instance.services; + return CopyWith$Mutation$SetServiceConfiguration$services( + local$services, (e) => call(services: e)); + } +} + +class _CopyWithStubImpl$Mutation$SetServiceConfiguration + implements CopyWith$Mutation$SetServiceConfiguration { + _CopyWithStubImpl$Mutation$SetServiceConfiguration(this._res); + + TRes _res; + + call({ + Mutation$SetServiceConfiguration$services? services, + String? $__typename, + }) => + _res; + + CopyWith$Mutation$SetServiceConfiguration$services get services => + CopyWith$Mutation$SetServiceConfiguration$services.stub(_res); +} + +const documentNodeMutationSetServiceConfiguration = DocumentNode(definitions: [ + OperationDefinitionNode( + type: OperationType.mutation, + name: NameNode(value: 'SetServiceConfiguration'), + variableDefinitions: [ + VariableDefinitionNode( + variable: VariableNode(name: NameNode(value: 'input')), + type: NamedTypeNode( + name: NameNode(value: 'SetServiceConfigurationInput'), + isNonNull: true, + ), + defaultValue: DefaultValueNode(value: null), + directives: [], + ) + ], + directives: [], + selectionSet: SelectionSetNode(selections: [ + FieldNode( + name: NameNode(value: 'services'), + alias: null, + arguments: [], + directives: [], + selectionSet: SelectionSetNode(selections: [ + FieldNode( + name: NameNode(value: 'setServiceConfiguration'), + alias: null, + arguments: [ + ArgumentNode( + name: NameNode(value: 'input'), + value: VariableNode(name: NameNode(value: 'input')), + ) + ], + directives: [], + selectionSet: SelectionSetNode(selections: [ + FragmentSpreadNode( + name: NameNode(value: 'basicMutationReturnFields'), + directives: [], + ), + FieldNode( + name: NameNode(value: '__typename'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + ]), + ), + FieldNode( + name: NameNode(value: '__typename'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + ]), + ), + FieldNode( + name: NameNode(value: '__typename'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), + ]), + ), + fragmentDefinitionbasicMutationReturnFields, +]); +Mutation$SetServiceConfiguration _parserFn$Mutation$SetServiceConfiguration( + Map data) => + Mutation$SetServiceConfiguration.fromJson(data); +typedef OnMutationCompleted$Mutation$SetServiceConfiguration = FutureOr + Function( + Map?, + Mutation$SetServiceConfiguration?, +); + +class Options$Mutation$SetServiceConfiguration + extends graphql.MutationOptions { + Options$Mutation$SetServiceConfiguration({ + String? operationName, + required Variables$Mutation$SetServiceConfiguration variables, + graphql.FetchPolicy? fetchPolicy, + graphql.ErrorPolicy? errorPolicy, + graphql.CacheRereadPolicy? cacheRereadPolicy, + Object? optimisticResult, + Mutation$SetServiceConfiguration? typedOptimisticResult, + graphql.Context? context, + OnMutationCompleted$Mutation$SetServiceConfiguration? onCompleted, + graphql.OnMutationUpdate? update, + graphql.OnError? onError, + }) : onCompletedWithParsed = onCompleted, + super( + variables: variables.toJson(), + operationName: operationName, + fetchPolicy: fetchPolicy, + errorPolicy: errorPolicy, + cacheRereadPolicy: cacheRereadPolicy, + optimisticResult: optimisticResult ?? typedOptimisticResult?.toJson(), + context: context, + onCompleted: onCompleted == null + ? null + : (data) => onCompleted( + data, + data == null + ? null + : _parserFn$Mutation$SetServiceConfiguration(data), + ), + update: update, + onError: onError, + document: documentNodeMutationSetServiceConfiguration, + parserFn: _parserFn$Mutation$SetServiceConfiguration, + ); + + final OnMutationCompleted$Mutation$SetServiceConfiguration? + onCompletedWithParsed; + + @override + List get properties => [ + ...super.onCompleted == null + ? super.properties + : super.properties.where((property) => property != onCompleted), + onCompletedWithParsed, + ]; +} + +class WatchOptions$Mutation$SetServiceConfiguration + extends graphql.WatchQueryOptions { + WatchOptions$Mutation$SetServiceConfiguration({ + String? operationName, + required Variables$Mutation$SetServiceConfiguration variables, + graphql.FetchPolicy? fetchPolicy, + graphql.ErrorPolicy? errorPolicy, + graphql.CacheRereadPolicy? cacheRereadPolicy, + Object? optimisticResult, + Mutation$SetServiceConfiguration? typedOptimisticResult, + graphql.Context? context, + Duration? pollInterval, + bool? eagerlyFetchResults, + bool carryForwardDataOnException = true, + bool fetchResults = false, + }) : super( + variables: variables.toJson(), + operationName: operationName, + fetchPolicy: fetchPolicy, + errorPolicy: errorPolicy, + cacheRereadPolicy: cacheRereadPolicy, + optimisticResult: optimisticResult ?? typedOptimisticResult?.toJson(), + context: context, + document: documentNodeMutationSetServiceConfiguration, + pollInterval: pollInterval, + eagerlyFetchResults: eagerlyFetchResults, + carryForwardDataOnException: carryForwardDataOnException, + fetchResults: fetchResults, + parserFn: _parserFn$Mutation$SetServiceConfiguration, + ); +} + +extension ClientExtension$Mutation$SetServiceConfiguration + on graphql.GraphQLClient { + Future> + mutate$SetServiceConfiguration( + Options$Mutation$SetServiceConfiguration options) async => + await this.mutate(options); + graphql.ObservableQuery + watchMutation$SetServiceConfiguration( + WatchOptions$Mutation$SetServiceConfiguration options) => + this.watchMutation(options); +} + +class Mutation$SetServiceConfiguration$services { + Mutation$SetServiceConfiguration$services({ + required this.setServiceConfiguration, + this.$__typename = 'ServicesMutations', + }); + + factory Mutation$SetServiceConfiguration$services.fromJson( + Map json) { + final l$setServiceConfiguration = json['setServiceConfiguration']; + final l$$__typename = json['__typename']; + return Mutation$SetServiceConfiguration$services( + setServiceConfiguration: + Mutation$SetServiceConfiguration$services$setServiceConfiguration + .fromJson((l$setServiceConfiguration as Map)), + $__typename: (l$$__typename as String), + ); + } + + final Mutation$SetServiceConfiguration$services$setServiceConfiguration + setServiceConfiguration; + + final String $__typename; + + Map toJson() { + final _resultData = {}; + final l$setServiceConfiguration = setServiceConfiguration; + _resultData['setServiceConfiguration'] = l$setServiceConfiguration.toJson(); + final l$$__typename = $__typename; + _resultData['__typename'] = l$$__typename; + return _resultData; + } + + @override + int get hashCode { + final l$setServiceConfiguration = setServiceConfiguration; + final l$$__typename = $__typename; + return Object.hashAll([ + l$setServiceConfiguration, + l$$__typename, + ]); + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (!(other is Mutation$SetServiceConfiguration$services) || + runtimeType != other.runtimeType) { + return false; + } + final l$setServiceConfiguration = setServiceConfiguration; + final lOther$setServiceConfiguration = other.setServiceConfiguration; + if (l$setServiceConfiguration != lOther$setServiceConfiguration) { + return false; + } + final l$$__typename = $__typename; + final lOther$$__typename = other.$__typename; + if (l$$__typename != lOther$$__typename) { + return false; + } + return true; + } +} + +extension UtilityExtension$Mutation$SetServiceConfiguration$services + on Mutation$SetServiceConfiguration$services { + CopyWith$Mutation$SetServiceConfiguration$services< + Mutation$SetServiceConfiguration$services> + get copyWith => CopyWith$Mutation$SetServiceConfiguration$services( + this, + (i) => i, + ); +} + +abstract class CopyWith$Mutation$SetServiceConfiguration$services { + factory CopyWith$Mutation$SetServiceConfiguration$services( + Mutation$SetServiceConfiguration$services instance, + TRes Function(Mutation$SetServiceConfiguration$services) then, + ) = _CopyWithImpl$Mutation$SetServiceConfiguration$services; + + factory CopyWith$Mutation$SetServiceConfiguration$services.stub(TRes res) = + _CopyWithStubImpl$Mutation$SetServiceConfiguration$services; + + TRes call({ + Mutation$SetServiceConfiguration$services$setServiceConfiguration? + setServiceConfiguration, + String? $__typename, + }); + CopyWith$Mutation$SetServiceConfiguration$services$setServiceConfiguration< + TRes> get setServiceConfiguration; +} + +class _CopyWithImpl$Mutation$SetServiceConfiguration$services + implements CopyWith$Mutation$SetServiceConfiguration$services { + _CopyWithImpl$Mutation$SetServiceConfiguration$services( + this._instance, + this._then, + ); + + final Mutation$SetServiceConfiguration$services _instance; + + final TRes Function(Mutation$SetServiceConfiguration$services) _then; + + static const _undefined = {}; + + TRes call({ + Object? setServiceConfiguration = _undefined, + Object? $__typename = _undefined, + }) => + _then(Mutation$SetServiceConfiguration$services( + setServiceConfiguration: setServiceConfiguration == _undefined || + setServiceConfiguration == null + ? _instance.setServiceConfiguration + : (setServiceConfiguration + as Mutation$SetServiceConfiguration$services$setServiceConfiguration), + $__typename: $__typename == _undefined || $__typename == null + ? _instance.$__typename + : ($__typename as String), + )); + + CopyWith$Mutation$SetServiceConfiguration$services$setServiceConfiguration< + TRes> get setServiceConfiguration { + final local$setServiceConfiguration = _instance.setServiceConfiguration; + return CopyWith$Mutation$SetServiceConfiguration$services$setServiceConfiguration( + local$setServiceConfiguration, (e) => call(setServiceConfiguration: e)); + } +} + +class _CopyWithStubImpl$Mutation$SetServiceConfiguration$services + implements CopyWith$Mutation$SetServiceConfiguration$services { + _CopyWithStubImpl$Mutation$SetServiceConfiguration$services(this._res); + + TRes _res; + + call({ + Mutation$SetServiceConfiguration$services$setServiceConfiguration? + setServiceConfiguration, + String? $__typename, + }) => + _res; + + CopyWith$Mutation$SetServiceConfiguration$services$setServiceConfiguration< + TRes> + get setServiceConfiguration => + CopyWith$Mutation$SetServiceConfiguration$services$setServiceConfiguration + .stub(_res); +} + +class Mutation$SetServiceConfiguration$services$setServiceConfiguration + implements Fragment$basicMutationReturnFields$$ServiceMutationReturn { + Mutation$SetServiceConfiguration$services$setServiceConfiguration({ + required this.code, + required this.message, + required this.success, + this.$__typename = 'ServiceMutationReturn', + }); + + factory Mutation$SetServiceConfiguration$services$setServiceConfiguration.fromJson( + Map json) { + final l$code = json['code']; + final l$message = json['message']; + final l$success = json['success']; + final l$$__typename = json['__typename']; + return Mutation$SetServiceConfiguration$services$setServiceConfiguration( + code: (l$code as int), + message: (l$message as String), + success: (l$success as bool), + $__typename: (l$$__typename as String), + ); + } + + final int code; + + final String message; + + final bool success; + + final String $__typename; + + Map toJson() { + final _resultData = {}; + final l$code = code; + _resultData['code'] = l$code; + final l$message = message; + _resultData['message'] = l$message; + final l$success = success; + _resultData['success'] = l$success; + final l$$__typename = $__typename; + _resultData['__typename'] = l$$__typename; + return _resultData; + } + + @override + int get hashCode { + final l$code = code; + final l$message = message; + final l$success = success; + final l$$__typename = $__typename; + return Object.hashAll([ + l$code, + l$message, + l$success, + l$$__typename, + ]); + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (!(other + is Mutation$SetServiceConfiguration$services$setServiceConfiguration) || + runtimeType != other.runtimeType) { + return false; + } + final l$code = code; + final lOther$code = other.code; + if (l$code != lOther$code) { + return false; + } + final l$message = message; + final lOther$message = other.message; + if (l$message != lOther$message) { + return false; + } + final l$success = success; + final lOther$success = other.success; + if (l$success != lOther$success) { + return false; + } + final l$$__typename = $__typename; + final lOther$$__typename = other.$__typename; + if (l$$__typename != lOther$$__typename) { + return false; + } + return true; + } +} + +extension UtilityExtension$Mutation$SetServiceConfiguration$services$setServiceConfiguration + on Mutation$SetServiceConfiguration$services$setServiceConfiguration { + CopyWith$Mutation$SetServiceConfiguration$services$setServiceConfiguration< + Mutation$SetServiceConfiguration$services$setServiceConfiguration> + get copyWith => + CopyWith$Mutation$SetServiceConfiguration$services$setServiceConfiguration( + this, + (i) => i, + ); +} + +abstract class CopyWith$Mutation$SetServiceConfiguration$services$setServiceConfiguration< + TRes> { + factory CopyWith$Mutation$SetServiceConfiguration$services$setServiceConfiguration( + Mutation$SetServiceConfiguration$services$setServiceConfiguration instance, + TRes Function( + Mutation$SetServiceConfiguration$services$setServiceConfiguration) + then, + ) = _CopyWithImpl$Mutation$SetServiceConfiguration$services$setServiceConfiguration; + + factory CopyWith$Mutation$SetServiceConfiguration$services$setServiceConfiguration.stub( + TRes res) = + _CopyWithStubImpl$Mutation$SetServiceConfiguration$services$setServiceConfiguration; + + TRes call({ + int? code, + String? message, + bool? success, + String? $__typename, + }); +} + +class _CopyWithImpl$Mutation$SetServiceConfiguration$services$setServiceConfiguration< + TRes> + implements + CopyWith$Mutation$SetServiceConfiguration$services$setServiceConfiguration< + TRes> { + _CopyWithImpl$Mutation$SetServiceConfiguration$services$setServiceConfiguration( + this._instance, + this._then, + ); + + final Mutation$SetServiceConfiguration$services$setServiceConfiguration + _instance; + + final TRes Function( + Mutation$SetServiceConfiguration$services$setServiceConfiguration) _then; + + static const _undefined = {}; + + TRes call({ + Object? code = _undefined, + Object? message = _undefined, + Object? success = _undefined, + Object? $__typename = _undefined, + }) => + _then(Mutation$SetServiceConfiguration$services$setServiceConfiguration( + code: + code == _undefined || code == null ? _instance.code : (code as int), + message: message == _undefined || message == null + ? _instance.message + : (message as String), + success: success == _undefined || success == null + ? _instance.success + : (success as bool), + $__typename: $__typename == _undefined || $__typename == null + ? _instance.$__typename + : ($__typename as String), + )); +} + +class _CopyWithStubImpl$Mutation$SetServiceConfiguration$services$setServiceConfiguration< + TRes> + implements + CopyWith$Mutation$SetServiceConfiguration$services$setServiceConfiguration< + TRes> { + _CopyWithStubImpl$Mutation$SetServiceConfiguration$services$setServiceConfiguration( + this._res); + + TRes _res; + + call({ + int? code, + String? message, + bool? success, + String? $__typename, + }) => + _res; +} diff --git a/lib/logic/api_maps/graphql_maps/server_api/services_api.dart b/lib/logic/api_maps/graphql_maps/server_api/services_api.dart index d2926b56..3a575121 100644 --- a/lib/logic/api_maps/graphql_maps/server_api/services_api.dart +++ b/lib/logic/api_maps/graphql_maps/server_api/services_api.dart @@ -174,4 +174,38 @@ mixin ServicesApi on GraphQLApiMap { ); } } + + Future setServiceConfiguration( + final String serviceId, + final Map settings, + ) async { + try { + final GraphQLClient client = await getClient(); + final variables = Variables$Mutation$SetServiceConfiguration( + input: Input$SetServiceConfigurationInput( + serviceId: serviceId, + configuration: settings, + ), + ); + final mutation = + Options$Mutation$SetServiceConfiguration(variables: variables); + final response = await client.mutate$SetServiceConfiguration(mutation); + return GenericResult( + data: null, + success: + response.parsedData?.services.setServiceConfiguration.success ?? + false, + code: response.parsedData?.services.setServiceConfiguration.code ?? 0, + message: response.parsedData?.services.setServiceConfiguration.message, + ); + } catch (e) { + print(e); + return GenericResult( + data: null, + success: false, + code: 0, + message: e.toString(), + ); + } + } } diff --git a/lib/logic/cubit/client_jobs/client_jobs_state.dart b/lib/logic/cubit/client_jobs/client_jobs_state.dart index 757885f3..8eccc0a8 100644 --- a/lib/logic/cubit/client_jobs/client_jobs_state.dart +++ b/lib/logic/cubit/client_jobs/client_jobs_state.dart @@ -46,7 +46,11 @@ class JobsStateWithJobs extends JobsState { JobsState addJob(final ClientJob job) { if (job is ReplaceableJob) { final List newJobsList = clientJobList - .where((final element) => element.runtimeType != job.runtimeType) + .where( + (final element) => job.shouldReplaceOnlyIfSameId + ? element.runtimeType != job.runtimeType || element.id != job.id + : element.runtimeType != job.runtimeType, + ) .toList(); if (job.shouldRemoveInsteadOfAdd(clientJobList)) { getIt().showSnackBar('jobs.job_removed'.tr()); diff --git a/lib/logic/get_it/api_connection_repository.dart b/lib/logic/get_it/api_connection_repository.dart index f67b54ea..22edb7d9 100644 --- a/lib/logic/get_it/api_connection_repository.dart +++ b/lib/logic/get_it/api_connection_repository.dart @@ -242,6 +242,19 @@ class ApiConnectionRepository { } } + Future<(bool, String)> setServiceConfiguration( + final String serviceId, + final Map settings, + ) async { + final GenericResult result = + await api.setServiceConfiguration(serviceId, settings); + if (result.success) { + return (true, result.message ?? 'basis.done'.tr()); + } else { + return (false, result.message ?? 'jobs.generic_error'.tr()); + } + } + void dispose() { _dataStream.close(); _connectionStatusStream.close(); diff --git a/lib/logic/models/job.dart b/lib/logic/models/job.dart index 41226e7e..e09eeb54 100644 --- a/lib/logic/models/job.dart +++ b/lib/logic/models/job.dart @@ -367,9 +367,12 @@ abstract class ReplaceableJob extends ClientJob { super.id, super.status, super.message, + super.requiresRebuild, + super.requiresDnsUpdate, }); bool shouldRemoveInsteadOfAdd(final List jobs) => false; + bool get shouldReplaceOnlyIfSameId => false; } class ChangeAutoUpgradeSettingsJob extends ReplaceableJob { @@ -502,3 +505,45 @@ class ChangeSshSettingsJob extends ReplaceableJob { id: id, ); } + +class ChangeServiceConfiguration extends ReplaceableJob { + ChangeServiceConfiguration({ + required this.serviceId, + required this.serviceDisplayName, + required this.settings, + super.status, + super.message, + }) : super( + title: 'jobs.change_service_settings'.tr(args: [serviceDisplayName]), + id: 'change_settings_$serviceId', + requiresDnsUpdate: true, + requiresRebuild: true, + ); + + final String serviceId; + final String serviceDisplayName; + final Map settings; + + @override + bool get shouldReplaceOnlyIfSameId => true; + + @override + Future<(bool, String)> execute() async => getIt() + .setServiceConfiguration(serviceId, settings); + + @override + List get props => [...super.props, serviceId, settings]; + + @override + ChangeServiceConfiguration copyWithNewStatus({ + required final JobStatusEnum status, + final String? message, + }) => + ChangeServiceConfiguration( + serviceId: serviceId, + serviceDisplayName: serviceDisplayName, + settings: settings, + status: status, + message: message, + ); +} diff --git a/lib/logic/models/service.dart b/lib/logic/models/service.dart index d5b4e0af..0de4dbcd 100644 --- a/lib/logic/models/service.dart +++ b/lib/logic/models/service.dart @@ -36,6 +36,16 @@ class Service extends Equatable { .toList() ?? [], url: service.url, + configuration: service.configuration + ?.map( + ( + final Query$AllServices$services$allServices$configuration + configItem, + ) => + ServiceConfigItem.fromGraphQL(configItem), + ) + .toList() ?? + [], ); const Service({ required this.id, @@ -50,6 +60,7 @@ class Service extends Equatable { required this.storageUsage, required this.svgIcon, required this.dnsRecords, + required this.configuration, this.url, }); @@ -89,6 +100,7 @@ class Service extends Equatable { svgIcon: '', dnsRecords: [], url: '', + configuration: [], ); final String id; @@ -104,6 +116,7 @@ class Service extends Equatable { final String svgIcon; final String? url; final List dnsRecords; + final List configuration; @override List get props => [ @@ -120,6 +133,7 @@ class Service extends Equatable { svgIcon, dnsRecords, url, + configuration, ]; } @@ -166,3 +180,146 @@ enum ServiceStatus { } } } + +sealed class ServiceConfigItem extends Equatable { + const ServiceConfigItem({ + required this.id, + required this.description, + required this.widget, + required this.type, + }); + + factory ServiceConfigItem.fromGraphQL( + final Query$AllServices$services$allServices$configuration configItem, + ) => + configItem.when( + boolConfigItem: (final boolConfigItem) => BoolServiceConfigItem( + id: boolConfigItem.id, + description: boolConfigItem.description, + widget: boolConfigItem.widget, + type: boolConfigItem.type, + value: boolConfigItem.boolValue, + defaultValue: boolConfigItem.defaultBoolValue, + ), + enumConfigItem: (final enumConfigItem) => EnumServiceConfigItem( + id: enumConfigItem.id, + description: enumConfigItem.description, + widget: enumConfigItem.widget, + type: enumConfigItem.type, + value: enumConfigItem.stringValue, + defaultValue: enumConfigItem.defaultStringValue, + options: enumConfigItem.options, + ), + stringConfigItem: (final stringConfigItem) => StringServiceConfigItem( + id: stringConfigItem.id, + description: stringConfigItem.description, + widget: stringConfigItem.widget, + type: stringConfigItem.type, + value: stringConfigItem.stringValue, + defaultValue: stringConfigItem.defaultStringValue, + regex: stringConfigItem.regex, + ), + orElse: () => FallbackServiceConfigItem( + id: configItem.id, + description: configItem.description, + type: configItem.type, + ), + ); + + final String id; + final String description; + final String widget; + final String type; +} + +class StringServiceConfigItem extends ServiceConfigItem { + const StringServiceConfigItem({ + required super.id, + required super.description, + required super.widget, + required super.type, + required this.value, + required this.defaultValue, + this.regex, + }); + + final String value; + final String defaultValue; + final String? regex; + + @override + List get props => + [id, description, widget, type, value, defaultValue, regex]; +} + +class BoolServiceConfigItem extends ServiceConfigItem { + const BoolServiceConfigItem({ + required super.id, + required super.description, + required super.widget, + required super.type, + required this.value, + required this.defaultValue, + }); + + final bool value; + final bool defaultValue; + + @override + List get props => + [id, description, widget, type, value, defaultValue]; +} + +class EnumServiceConfigItem extends ServiceConfigItem { + const EnumServiceConfigItem({ + required super.id, + required super.description, + required super.widget, + required super.type, + required this.value, + required this.defaultValue, + required this.options, + }); + + final String value; + final String defaultValue; + final List options; + + @override + List get props => + [id, description, widget, type, value, defaultValue, options]; +} + +class FallbackServiceConfigItem extends ServiceConfigItem { + const FallbackServiceConfigItem({ + required super.id, + required super.description, + required super.type, + }) : super(widget: 'fallback'); + + @override + List get props => [id, description, widget, type]; +} + +// TODO: Not used yet by the API +class IntServiceConfigItem extends ServiceConfigItem { + const IntServiceConfigItem({ + required super.id, + required super.description, + required super.widget, + required super.type, + required this.value, + required this.defaultValue, + required this.min, + required this.max, + }); + + final int value; + final int defaultValue; + final int min; + final int max; + + @override + List get props => + [id, description, widget, type, value, defaultValue, min, max]; +} diff --git a/lib/ui/pages/services/config_item_fields/basic_bool_config_item.dart b/lib/ui/pages/services/config_item_fields/basic_bool_config_item.dart new file mode 100644 index 00000000..e3515fd2 --- /dev/null +++ b/lib/ui/pages/services/config_item_fields/basic_bool_config_item.dart @@ -0,0 +1,36 @@ +part of '../service_settings_page.dart'; + +class BasicBoolConfigItem extends StatefulWidget { + const BasicBoolConfigItem({ + required this.configItem, + required this.onChanged, + this.newValue, + super.key, + }); + + final BoolServiceConfigItem configItem; + final Function(bool) onChanged; + final bool? newValue; + + @override + State createState() => _BasicBoolConfigItemState(); +} + +class _BasicBoolConfigItemState extends State { + @override + Widget build(final BuildContext context) => Column( + children: [ + SwitchListTile.adaptive( + title: Text(widget.configItem.description), + subtitle: (widget.newValue != null && + widget.newValue != widget.configItem.value) + ? Text('service_page.modified'.tr()) + : null, + value: widget.newValue ?? widget.configItem.value, + onChanged: (final bool value) { + widget.onChanged(value); + }, + ), + ], + ); +} diff --git a/lib/ui/pages/services/config_item_fields/basic_enum_config_item.dart b/lib/ui/pages/services/config_item_fields/basic_enum_config_item.dart new file mode 100644 index 00000000..4417db92 --- /dev/null +++ b/lib/ui/pages/services/config_item_fields/basic_enum_config_item.dart @@ -0,0 +1,46 @@ +part of '../service_settings_page.dart'; + +class BasicEnumConfigItem extends StatefulWidget { + const BasicEnumConfigItem({ + required this.configItem, + required this.onChanged, + this.newValue, + super.key, + }); + + final EnumServiceConfigItem configItem; + final Function(String) onChanged; + final String? newValue; + + @override + State createState() => _BasicEnumConfigItemState(); +} + +class _BasicEnumConfigItemState extends State { + @override + Widget build(final BuildContext context) => Column( + children: [ + ListTile( + title: Text(widget.configItem.description), + subtitle: (widget.newValue != null && + widget.newValue != widget.configItem.value) + ? Text('service_page.modified'.tr()) + : null, + trailing: DropdownButton( + value: widget.newValue ?? widget.configItem.value, + items: widget.configItem.options + .map>( + (final String option) => DropdownMenuItem( + value: option, + child: Text(option), + ), + ) + .toList(), + onChanged: (final String? value) { + widget.onChanged(value!); + }, + ), + ), + ], + ); +} diff --git a/lib/ui/pages/services/config_item_fields/basic_string_config_item.dart b/lib/ui/pages/services/config_item_fields/basic_string_config_item.dart new file mode 100644 index 00000000..a14e059c --- /dev/null +++ b/lib/ui/pages/services/config_item_fields/basic_string_config_item.dart @@ -0,0 +1,105 @@ +part of '../service_settings_page.dart'; + +class BasicStringConfigItem extends StatefulWidget { + const BasicStringConfigItem({ + required this.configItem, + required this.onChanged, + this.newValue, + super.key, + }); + + final StringServiceConfigItem configItem; + final Function(String, bool) onChanged; + final String? newValue; + + @override + State createState() => _BasicStringConfigItemState(); +} + +class _BasicStringConfigItemState extends State { + final TextEditingController _controller = TextEditingController(); + bool _isValid = true; + + @override + void initState() { + super.initState(); + _controller.text = widget.newValue ?? widget.configItem.value; + _controller.addListener(() { + final String value = _controller.text; + final bool isValid = _validateInput(value); + if (isValid) { + widget.onChanged(value, isValid); + } else { + setState(() { + widget.onChanged(widget.newValue ?? widget.configItem.value, isValid); + _isValid = isValid; + }); + } + }); + } + + bool _validateInput(final String value) { + if (value == '') { + return false; + } + final regexPattern = widget.configItem.regex; + if (regexPattern == null) { + return true; + } + final regex = RegExp(regexPattern); + return regex.hasMatch(value); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(final BuildContext context) => Column( + children: [ + TextField( + controller: _controller, + decoration: InputDecoration( + labelText: widget.configItem.description, + hintText: widget.configItem.value, + counter: _controller.text != widget.configItem.value + ? InkWell( + onTap: () { + _controller.text = widget.configItem.value; + }, + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + 'service_page.modified'.tr(), + style: Theme.of(context) + .textTheme + .labelSmall + ?.copyWith( + color: Theme.of(context).colorScheme.primary, + ), + ), + const Gap(8.0), + Icon( + Icons.undo_outlined, + size: 16.0, + color: Theme.of(context).colorScheme.primary, + ), + ], + ), + ) + : Text( + ' ', + style: Theme.of(context).textTheme.labelSmall, + ), + border: const OutlineInputBorder(), + errorText: _isValid ? null : 'service_page.invalid_input'.tr(), + ), + ), + ], + ); +} diff --git a/lib/ui/pages/services/config_item_fields/domain_string_config_item.dart b/lib/ui/pages/services/config_item_fields/domain_string_config_item.dart new file mode 100644 index 00000000..b1cfc241 --- /dev/null +++ b/lib/ui/pages/services/config_item_fields/domain_string_config_item.dart @@ -0,0 +1,114 @@ +part of '../service_settings_page.dart'; + +class DomainStringConfigItem extends StatefulWidget { + const DomainStringConfigItem({ + required this.configItem, + required this.onChanged, + this.newValue, + super.key, + }); + + final StringServiceConfigItem configItem; + final Function(String, bool) onChanged; + final String? newValue; + + @override + State createState() => _DomainStringConfigItemState(); +} + +class _DomainStringConfigItemState extends State { + final TextEditingController _controller = TextEditingController(); + bool _isValid = true; + + @override + void initState() { + super.initState(); + _controller.text = widget.newValue ?? widget.configItem.value; + _controller.addListener(() { + final String value = _controller.text; + final bool isValid = _validateInput(value); + if (isValid) { + setState(() { + widget.onChanged(value, isValid); + _isValid = isValid; + }); + } else { + setState(() { + widget.onChanged(widget.newValue ?? widget.configItem.value, isValid); + _isValid = isValid; + }); + } + }); + } + + bool _validateInput(final String value) { + if (value == '') { + return false; + } + final regexPattern = widget.configItem.regex; + if (regexPattern == null) { + return true; + } + final regex = RegExp(regexPattern); + return regex.hasMatch(value); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(final BuildContext context) { + final String domain = + getIt().serverDomain?.domainName ?? ''; + + return Column( + children: [ + TextField( + controller: _controller, + decoration: InputDecoration( + labelText: widget.configItem.description, + hintText: widget.configItem.value, + suffixText: '.$domain', + counter: _controller.text != widget.configItem.value + ? InkWell( + onTap: () { + _controller.text = widget.configItem.value; + }, + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + 'service_page.modified'.tr(), + style: Theme.of(context) + .textTheme + .labelSmall + ?.copyWith( + color: Theme.of(context).colorScheme.primary, + ), + ), + const Gap(8.0), + Icon( + Icons.undo_outlined, + size: 16.0, + color: Theme.of(context).colorScheme.primary, + ), + ], + ), + ) + : Text( + ' ', + style: Theme.of(context).textTheme.labelSmall, + ), + border: const OutlineInputBorder(), + errorText: _isValid ? null : 'service_page.invalid_input'.tr(), + ), + ), + ], + ); + } +} diff --git a/lib/ui/pages/services/service_page.dart b/lib/ui/pages/services/service_page.dart index 42f75fe1..8cfe905f 100644 --- a/lib/ui/pages/services/service_page.dart +++ b/lib/ui/pages/services/service_page.dart @@ -96,23 +96,36 @@ class _ServicePageState extends State { ), enabled: !serviceDisabled && !serviceLocked, ), - ListTile( - iconColor: Theme.of(context).colorScheme.onBackground, - onTap: () => context.read().addJob( - ServiceToggleJob( - service: service, - needToTurnOn: serviceDisabled, + if (!service.isRequired) + ListTile( + iconColor: Theme.of(context).colorScheme.onBackground, + onTap: () => context.read().addJob( + ServiceToggleJob( + service: service, + needToTurnOn: serviceDisabled, + ), ), - ), - leading: const Icon(Icons.power_settings_new), - title: Text( - serviceDisabled - ? 'service_page.enable'.tr() - : 'service_page.disable'.tr(), - style: Theme.of(context).textTheme.titleMedium, + leading: const Icon(Icons.power_settings_new), + title: Text( + serviceDisabled + ? 'service_page.enable'.tr() + : 'service_page.disable'.tr(), + style: Theme.of(context).textTheme.titleMedium, + ), + enabled: !serviceLocked, + ), + if (service.configuration.isNotEmpty) + ListTile( + iconColor: Theme.of(context).colorScheme.onBackground, + onTap: () => context.pushRoute( + ServiceSettingsRoute(serviceId: service.id), + ), + leading: const Icon(Icons.settings_outlined), + title: Text( + 'service_page.settings'.tr(), + style: Theme.of(context).textTheme.titleMedium, + ), ), - enabled: !serviceLocked, - ), if (service.isMovable) ListTile( iconColor: Theme.of(context).colorScheme.onBackground, diff --git a/lib/ui/pages/services/service_settings_page.dart b/lib/ui/pages/services/service_settings_page.dart new file mode 100644 index 00000000..400cc9ce --- /dev/null +++ b/lib/ui/pages/services/service_settings_page.dart @@ -0,0 +1,238 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:collection/collection.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:gap/gap.dart'; +import 'package:selfprivacy/config/get_it_config.dart'; +import 'package:selfprivacy/logic/bloc/services/services_bloc.dart'; +import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart'; +import 'package:selfprivacy/logic/get_it/resources_model.dart'; +import 'package:selfprivacy/logic/models/job.dart'; +import 'package:selfprivacy/logic/models/service.dart'; +import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart'; + +part 'config_item_fields/basic_string_config_item.dart'; +part 'config_item_fields/basic_bool_config_item.dart'; +part 'config_item_fields/basic_enum_config_item.dart'; +part 'config_item_fields/domain_string_config_item.dart'; + +@RoutePage() +class ServiceSettingsPage extends StatefulWidget { + const ServiceSettingsPage({required this.serviceId, super.key}); + + final String serviceId; + + @override + State createState() => _ServiceSettingsPageState(); +} + +class _ServiceSettingsPageState extends State { + Map settings = {}; + bool isFormValid = true; + bool isJobAlreadyExists = false; + + Widget configurationItemToWidget( + final BuildContext context, + final ServiceConfigItem configItem, + final Map settings, + ) { + switch (configItem) { + case StringServiceConfigItem(): + void onChanged(final String value, final bool isFieldValid) { + if (isFieldValid) { + setState(() { + if (value == configItem.value) { + settings.remove(configItem.id); + } else { + settings[configItem.id] = value; + } + isFormValid = true; + }); + } else { + setState(() { + isFormValid = false; + }); + } + } + if (configItem.widget == 'subdomain') { + return DomainStringConfigItem( + configItem: configItem, + newValue: settings[configItem.id], + onChanged: onChanged, + ); + } + return BasicStringConfigItem( + configItem: configItem, + newValue: settings[configItem.id], + onChanged: onChanged, + ); + case BoolServiceConfigItem(): + void onChanged(final bool value) { + setState(() { + if (value == configItem.value) { + settings.remove(configItem.id); + } else { + settings[configItem.id] = value; + } + }); + } + return BasicBoolConfigItem( + configItem: configItem, + newValue: settings[configItem.id], + onChanged: onChanged, + ); + + case EnumServiceConfigItem(): + void onChanged(final String value) { + setState(() { + if (value == configItem.value) { + settings.remove(configItem.id); + } else { + settings[configItem.id] = value; + } + }); + } + return BasicEnumConfigItem( + configItem: configItem, + newValue: settings[configItem.id], + onChanged: onChanged, + ); + case FallbackServiceConfigItem(): + return ListTile( + title: Text(configItem.description), + subtitle: Text(configItem.id), + trailing: Text(configItem.type), + leading: const Icon(Icons.error), + ); + case IntServiceConfigItem(): + return ListTile( + title: Text(configItem.description), + subtitle: Text(configItem.id), + trailing: Text(configItem.value.toString()), + leading: const Icon(Icons.error), + ); + } + } + + @override + void initState() { + super.initState(); + + final JobsState state = context.read().state; + + if (state is JobsStateWithJobs) { + final ChangeServiceConfiguration? existingJob = + state.clientJobList.firstWhereOrNull( + (final ClientJob job) => + job is ChangeServiceConfiguration && + job.serviceId == widget.serviceId, + ) as ChangeServiceConfiguration?; + if (existingJob != null) { + setState(() { + settings = existingJob.settings; + isJobAlreadyExists = true; + }); + } + } + } + + @override + Widget build(final BuildContext context) { + final Service? service = + context.watch().state.getServiceById(widget.serviceId); + + if (service == null) { + return const BrandHeroScreen( + hasBackButton: true, + children: [ + Center( + child: CircularProgressIndicator.adaptive(), + ), + ], + ); + } + + final JobsState state = context.watch().state; + + if (state is JobsStateLoading) { + return BrandHeroScreen( + hasBackButton: true, + hasFlashButton: true, + heroIconWidget: SvgPicture.string( + service.svgIcon, + width: 48.0, + height: 48.0, + colorFilter: ColorFilter.mode( + Theme.of(context).colorScheme.onBackground, + BlendMode.srcIn, + ), + ), + heroTitle: service.displayName, + heroSubtitle: 'service_page.settings'.tr(), + children: [ + Center( + child: Column( + children: [ + Text( + 'service_page.wait_for_jobs'.tr(), + textAlign: TextAlign.center, + ), + const Gap(16.0), + const CircularProgressIndicator.adaptive(), + ], + ), + ), + ], + ); + } + + final bool isModified = settings.isNotEmpty; + + return BrandHeroScreen( + hasBackButton: true, + hasFlashButton: true, + heroIconWidget: SvgPicture.string( + service.svgIcon, + width: 48.0, + height: 48.0, + colorFilter: ColorFilter.mode( + Theme.of(context).colorScheme.onBackground, + BlendMode.srcIn, + ), + ), + heroTitle: service.displayName, + heroSubtitle: 'service_page.settings'.tr(), + children: [ + ...service.configuration.map( + (final ServiceConfigItem configItem) => Padding( + padding: const EdgeInsets.only(bottom: 16.0), + child: configurationItemToWidget(context, configItem, settings), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: FilledButton( + onPressed: (isModified && isFormValid) + ? () { + context.read().addJob( + ChangeServiceConfiguration( + serviceId: service.id, + serviceDisplayName: service.displayName, + settings: settings, + ), + ); + context.router.maybePop(); + } + : null, + child: Text( + isJobAlreadyExists + ? 'service_page.update_job'.tr() + : 'service_page.create_job'.tr(), + ), + ), + ), + ], + ); + } +} diff --git a/lib/ui/router/router.dart b/lib/ui/router/router.dart index 44bcd3de..96eec87f 100644 --- a/lib/ui/router/router.dart +++ b/lib/ui/router/router.dart @@ -22,6 +22,7 @@ import 'package:selfprivacy/ui/pages/server_storage/binds_migration/services_mig import 'package:selfprivacy/ui/pages/server_storage/extending_volume.dart'; import 'package:selfprivacy/ui/pages/server_storage/server_storage.dart'; import 'package:selfprivacy/ui/pages/services/service_page.dart'; +import 'package:selfprivacy/ui/pages/services/service_settings_page.dart'; import 'package:selfprivacy/ui/pages/services/services.dart'; import 'package:selfprivacy/ui/pages/setup/initializing/initializing.dart'; import 'package:selfprivacy/ui/pages/setup/recovering/recovery_routing.dart'; @@ -96,6 +97,7 @@ class RootRouter extends _$RootRouter { AutoRoute(page: AboutApplicationRoute.page), AutoRoute(page: DeveloperSettingsRoute.page), AutoRoute(page: ServiceRoute.page), + AutoRoute(page: ServiceSettingsRoute.page), AutoRoute(page: ServerDetailsRoute.page), AutoRoute(page: DnsDetailsRoute.page), AutoRoute(page: BackupDetailsRoute.page), @@ -120,6 +122,8 @@ String getRouteTitle(final String routeName) { case 'ServicesRoute': case 'ServiceRoute': return 'basis.services'; + case 'ServiceSettingsRoute': + return 'service_page.settings'; case 'UsersRoute': return 'basis.users'; case 'MoreRoute': diff --git a/lib/ui/router/router.gr.dart b/lib/ui/router/router.gr.dart index 2428f7df..d45ecec8 100644 --- a/lib/ui/router/router.gr.dart +++ b/lib/ui/router/router.gr.dart @@ -158,6 +158,16 @@ abstract class _$RootRouter extends RootStackRouter { ), ); }, + ServiceSettingsRoute.name: (routeData) { + final args = routeData.argsAs(); + return AutoRoutePage( + routeData: routeData, + child: ServiceSettingsPage( + serviceId: args.serviceId, + key: args.key, + ), + ); + }, ServicesMigrationRoute.name: (routeData) { final args = routeData.argsAs(); return AutoRoutePage( @@ -590,6 +600,44 @@ class ServiceRouteArgs { } } +/// generated route for +/// [ServiceSettingsPage] +class ServiceSettingsRoute extends PageRouteInfo { + ServiceSettingsRoute({ + required String serviceId, + Key? key, + List? children, + }) : super( + ServiceSettingsRoute.name, + args: ServiceSettingsRouteArgs( + serviceId: serviceId, + key: key, + ), + initialChildren: children, + ); + + static const String name = 'ServiceSettingsRoute'; + + static const PageInfo page = + PageInfo(name); +} + +class ServiceSettingsRouteArgs { + const ServiceSettingsRouteArgs({ + required this.serviceId, + this.key, + }); + + final String serviceId; + + final Key? key; + + @override + String toString() { + return 'ServiceSettingsRouteArgs{serviceId: $serviceId, key: $key}'; + } +} + /// generated route for /// [ServicesMigrationPage] class ServicesMigrationRoute extends PageRouteInfo {