Setting up basic API Structure
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import 'package:ac_web/Api/Dtos/AgentTaskDto.dart';
|
||||
import 'package:ac_web/Api/Dtos/EAgentStatus.dart';
|
||||
import 'package:ac_web/Api/Dtos/EAgentType.dart';
|
||||
import 'package:ac_web/Api/JsonReader.dart';
|
||||
|
||||
/// Dart counterpart of the backend `AgentData` returned by `GET /agents`.
|
||||
class AgentDto {
|
||||
const AgentDto({
|
||||
required this.name,
|
||||
required this.type,
|
||||
required this.lastSeen,
|
||||
required this.tasks,
|
||||
required this.status,
|
||||
});
|
||||
|
||||
final String name;
|
||||
final EAgentType type;
|
||||
final DateTime lastSeen;
|
||||
final List<AgentTaskDto> tasks;
|
||||
final EAgentStatus status;
|
||||
|
||||
bool get hasTasks => tasks.isNotEmpty;
|
||||
|
||||
factory AgentDto.fromJson(Map<String, dynamic> json) {
|
||||
return AgentDto(
|
||||
name: JsonReader.requireString(json, 'Name'),
|
||||
type: JsonReader.enumValue(
|
||||
json,
|
||||
'Type',
|
||||
EAgentType.values,
|
||||
(value) => value.name,
|
||||
EAgentType.unknown,
|
||||
),
|
||||
lastSeen: JsonReader.requireDateTime(json, 'LastSeen'),
|
||||
tasks: JsonReader.list(json, 'Tasks', AgentTaskDto.fromJson),
|
||||
status: JsonReader.enumValue(
|
||||
json,
|
||||
'Status',
|
||||
EAgentStatus.values,
|
||||
(value) => value.name,
|
||||
EAgentStatus.unknown,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return <String, dynamic>{
|
||||
'Name': name,
|
||||
'Type': type.name,
|
||||
'LastSeen': lastSeen.toIso8601String(),
|
||||
'Tasks': tasks.map((task) => task.toJson()).toList(growable: false),
|
||||
'Status': status.name,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => 'AgentDto(name: $name, type: ${type.name}, status: ${status.name})';
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import 'package:ac_web/Api/JsonReader.dart';
|
||||
|
||||
/// Dart counterpart of the backend `AgentTaskDto`.
|
||||
///
|
||||
/// The exact shape of the backend dto is not final yet, therefore everything
|
||||
/// except the name is treated as optional. Unknown properties are simply
|
||||
/// ignored, so this dto keeps working while the api grows.
|
||||
class AgentTaskDto {
|
||||
const AgentTaskDto({
|
||||
required this.name,
|
||||
this.id,
|
||||
this.description,
|
||||
this.status,
|
||||
this.progress,
|
||||
this.createdAt,
|
||||
this.finishedAt,
|
||||
});
|
||||
|
||||
final String name;
|
||||
final String? id;
|
||||
final String? description;
|
||||
final String? status;
|
||||
|
||||
/// Completion between 0 and 100 if the api reports it.
|
||||
final int? progress;
|
||||
|
||||
final DateTime? createdAt;
|
||||
final DateTime? finishedAt;
|
||||
|
||||
bool get isFinished => finishedAt != null;
|
||||
|
||||
factory AgentTaskDto.fromJson(Map<String, dynamic> json) {
|
||||
return AgentTaskDto(
|
||||
name: JsonReader.optionalString(json, 'Name') ?? '',
|
||||
id: JsonReader.optionalString(json, 'Id'),
|
||||
description: JsonReader.optionalString(json, 'Description'),
|
||||
status: JsonReader.optionalString(json, 'Status'),
|
||||
progress: JsonReader.optionalInt(json, 'Progress'),
|
||||
createdAt: JsonReader.optionalDateTime(json, 'CreatedAt'),
|
||||
finishedAt: JsonReader.optionalDateTime(json, 'FinishedAt'),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return <String, dynamic>{
|
||||
'Name': name,
|
||||
if (id != null) 'Id': id,
|
||||
if (description != null) 'Description': description,
|
||||
if (status != null) 'Status': status,
|
||||
if (progress != null) 'Progress': progress,
|
||||
if (createdAt != null) 'CreatedAt': createdAt!.toIso8601String(),
|
||||
if (finishedAt != null) 'FinishedAt': finishedAt!.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => 'AgentTaskDto(name: $name, status: $status)';
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/// Mirror of the backend `EAgentStatus` enum.
|
||||
///
|
||||
/// See the note in `EAgentType.dart` about ordering and [unknown].
|
||||
enum EAgentStatus {
|
||||
offline,
|
||||
idle,
|
||||
working,
|
||||
error,
|
||||
unknown;
|
||||
|
||||
bool get isOnline => this == EAgentStatus.idle || this == EAgentStatus.working;
|
||||
|
||||
String get displayName {
|
||||
switch (this) {
|
||||
case EAgentStatus.offline:
|
||||
return 'Offline';
|
||||
case EAgentStatus.idle:
|
||||
return 'Idle';
|
||||
case EAgentStatus.working:
|
||||
return 'Working';
|
||||
case EAgentStatus.error:
|
||||
return 'Error';
|
||||
case EAgentStatus.unknown:
|
||||
return 'Unknown';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/// Mirror of the backend `EAgentType` enum.
|
||||
///
|
||||
/// The order of the values has to match the order in the .Net enum, because
|
||||
/// the api may serialize enums as their numeric value. [unknown] is kept last
|
||||
/// so that it never shadows a real backend value and acts as fallback for
|
||||
/// values this client does not know yet.
|
||||
enum EAgentType {
|
||||
developer,
|
||||
tester,
|
||||
reviewer,
|
||||
manager,
|
||||
unknown;
|
||||
|
||||
/// Human readable label, e.g. for chips or table cells.
|
||||
String get displayName {
|
||||
switch (this) {
|
||||
case EAgentType.developer:
|
||||
return 'Developer';
|
||||
case EAgentType.tester:
|
||||
return 'Tester';
|
||||
case EAgentType.reviewer:
|
||||
return 'Reviewer';
|
||||
case EAgentType.manager:
|
||||
return 'Manager';
|
||||
case EAgentType.unknown:
|
||||
return 'Unknown';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import 'package:ac_web/Api/JsonReader.dart';
|
||||
|
||||
/// Dart counterpart of the backend `ReportDto` returned by `GET /reports`.
|
||||
class ReportDto {
|
||||
const ReportDto({
|
||||
required this.id,
|
||||
required this.author,
|
||||
required this.timestamp,
|
||||
required this.type,
|
||||
required this.text,
|
||||
});
|
||||
|
||||
final String id;
|
||||
final String author;
|
||||
final DateTime timestamp;
|
||||
|
||||
/// Free form report type. The backend sends this as a plain string, so it is
|
||||
/// intentionally not modelled as an enum here.
|
||||
final String type;
|
||||
|
||||
final String text;
|
||||
|
||||
factory ReportDto.fromJson(Map<String, dynamic> json) {
|
||||
return ReportDto(
|
||||
id: JsonReader.requireString(json, 'Id'),
|
||||
author: JsonReader.requireString(json, 'Author'),
|
||||
timestamp: JsonReader.requireDateTime(json, 'Timestamp'),
|
||||
type: JsonReader.optionalString(json, 'Type') ?? '',
|
||||
text: JsonReader.optionalString(json, 'Text') ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return <String, dynamic>{
|
||||
'Id': id,
|
||||
'Author': author,
|
||||
'Timestamp': timestamp.toIso8601String(),
|
||||
'Type': type,
|
||||
'Text': text,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => 'ReportDto(id: $id, author: $author, type: $type)';
|
||||
}
|
||||
Reference in New Issue
Block a user