Skip to content

Commit

Permalink
Expanded artefact view (#33)
Browse files Browse the repository at this point in the history
* Create empty artefact dialog

* Return required fields from backend

* Fetch artefact builds from backend in frontend

* Progress through artefact dialog UI

* Fix backend tests

* fix dart analyze

* fix backend tests

* Add c3 and jenkins links

* Add count of test execution statuses

* Use interspersed

* bug fix

* Add some spacing

* Show all statuses on dashboard header

* Small changes

* Show stage on expanded artefact

* Add other stage names in expanded artefact

* Make text selectable in expanded view of artefact

* Fix analyzer

* Better match figma design

* Capitalize stage titles

* Better match figma design with stages

* Small UI changes

* Remove unused imports

* Small UI improvement

* Small UI improvement

* Remove default switch case when not necessary

* Remove unnecessary .toList calls

* Add more specific error messages
  • Loading branch information
omar-selo authored Jul 6, 2023
1 parent a913988 commit 9b6d77c
Show file tree
Hide file tree
Showing 17 changed files with 628 additions and 84 deletions.
4 changes: 4 additions & 0 deletions backend/test_observer/controllers/artefacts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
# Nadzeya Hutsko <[email protected]>
from pydantic import BaseModel

from test_observer.data_access.models_enums import TestExecutionStatus


class EnvironmentDTO(BaseModel):
id: int
Expand All @@ -34,13 +36,15 @@ class TestExecutionDTO(BaseModel):
jenkins_link: str | None
c3_link: str | None
environment: EnvironmentDTO
status: TestExecutionStatus

class Config:
orm_mode = True


class ArtefactBuildDTO(BaseModel):
id: int
architecture: str
revision: int | None
test_executions: list[TestExecutionDTO]

Expand Down
3 changes: 3 additions & 0 deletions backend/tests/controllers/artefacts/test_artefacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@ def test_get_artefact_builds(db_session: Session, test_client: TestClient):
{
"id": artefact_build.id,
"revision": artefact_build.revision,
"architecture": artefact_build.architecture,
"test_executions": [
{
"id": test_execution.id,
"jenkins_link": test_execution.jenkins_link,
"c3_link": test_execution.c3_link,
"status": test_execution.status.value,
"environment": {
"id": environment.id,
"name": environment.name,
Expand Down Expand Up @@ -77,6 +79,7 @@ def test_get_artefact_builds_only_latest(db_session: Session, test_client: TestC
{
"id": artefact_build2.id,
"revision": artefact_build2.revision,
"architecture": artefact_build2.architecture,
"test_executions": [],
}
]
6 changes: 5 additions & 1 deletion frontend/analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ include: package:flutter_lints/flutter.yaml
analyzer:
plugins:
- custom_lint
exclude: ["lib/models/*.g.dart", "lib/models/*.freezed.dart"]
exclude:
- "**/*.g.dart"
- "**/*.freezed.dart"
errors:
invalid_annotation_target: ignore

linter:
rules:
Expand Down
1 change: 1 addition & 0 deletions frontend/lib/models/artefact.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ part 'artefact.g.dart';
@freezed
class Artefact with _$Artefact {
const factory Artefact({
required int id,
required String name,
required String version,
required Map<String, dynamic> source,
Expand Down
33 changes: 33 additions & 0 deletions frontend/lib/models/artefact_build.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:freezed_annotation/freezed_annotation.dart';

import 'test_execution.dart';

part 'artefact_build.freezed.dart';
part 'artefact_build.g.dart';

@freezed
class ArtefactBuild with _$ArtefactBuild {
const ArtefactBuild._();

const factory ArtefactBuild({
required int id,
required String architecture,
required int? revision,
@JsonKey(name: 'test_executions')
required List<TestExecution> testExecutions,
}) = _ArtefactBuild;

factory ArtefactBuild.fromJson(Map<String, Object?> json) =>
_$ArtefactBuildFromJson(json);

Map<TestExecutionStatus, int> get testExecutionStatusCounts {
final counts = {for (final status in TestExecutionStatus.values) status: 0};

for (final testExecution in testExecutions) {
final status = testExecution.status;
counts[status] = (counts[status] ?? 0) + 1;
}

return counts;
}
}
16 changes: 16 additions & 0 deletions frontend/lib/models/environment.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:freezed_annotation/freezed_annotation.dart';

part 'environment.freezed.dart';
part 'environment.g.dart';

@freezed
class Environment with _$Environment {
const factory Environment({
required int id,
required String name,
required String architecture,
}) = _Environment;

factory Environment.fromJson(Map<String, Object?> json) =>
_$EnvironmentFromJson(json);
}
67 changes: 67 additions & 0 deletions frontend/lib/models/test_execution.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import 'package:flutter/material.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:yaru/yaru.dart';
import 'package:yaru_icons/yaru_icons.dart';

import 'environment.dart';

part 'test_execution.freezed.dart';
part 'test_execution.g.dart';

@freezed
class TestExecution with _$TestExecution {
const factory TestExecution({
required int id,
@JsonKey(name: 'jenkins_link') required String? jenkinsLink,
@JsonKey(name: 'c3_link') required String? c3Link,
required TestExecutionStatus status,
required Environment environment,
}) = _TestExecution;

factory TestExecution.fromJson(Map<String, Object?> json) =>
_$TestExecutionFromJson(json);
}

enum TestExecutionStatus {
@JsonValue('FAILED')
failed,
@JsonValue('NOT_STARTED')
notStarted,
@JsonValue('NOT_TESTED')
notTested,
@JsonValue('IN_PROGRESS')
inProgress,
@JsonValue('PASSED')
passed;

String get name {
switch (this) {
case notStarted:
return 'Not Started';
case inProgress:
return 'In Progress';
case passed:
return 'Passed';
case failed:
return 'Failed';
case notTested:
return 'Not Tested';
}
}

Icon get icon {
const size = 20.0;
switch (this) {
case notStarted:
return const Icon(YaruIcons.media_play, size: size);
case inProgress:
return const Icon(YaruIcons.refresh, size: size);
case passed:
return const Icon(YaruIcons.ok, color: YaruColors.success, size: size);
case failed:
return const Icon(YaruIcons.error, color: YaruColors.red, size: size);
case notTested:
return const Icon(YaruIcons.information, size: size);
}
}
}
20 changes: 20 additions & 0 deletions frontend/lib/providers/artefact_builds.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:riverpod_annotation/riverpod_annotation.dart';

import '../models/artefact_build.dart';
import 'dio.dart';

part 'artefact_builds.g.dart';

@riverpod
Future<List<ArtefactBuild>> artefactBuilds(
ArtefactBuildsRef ref,
int artefactId,
) async {
final dio = ref.watch(dioProvider);

final response = await dio.get('/v1/artefacts/$artefactId/builds');
final List artefactBuildsJson = response.data;
final artefactBuilds =
artefactBuildsJson.map((json) => ArtefactBuild.fromJson(json)).toList();
return artefactBuilds;
}
10 changes: 10 additions & 0 deletions frontend/lib/providers/name_of_selected_stage.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'name_of_selected_stage.g.dart';

@riverpod
String nameOfSelectedStage(NameOfSelectedStageRef ref) {
throw Exception(
'Name of selected stage not set yet, need to override provider',
);
}
8 changes: 8 additions & 0 deletions frontend/lib/providers/names_of_stages.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'names_of_stages.g.dart';

@riverpod
List<String> namesOfStages(NamesOfStagesRef ref) {
throw Exception('Names of stages not set yet, need to override provider');
}
Loading

0 comments on commit 9b6d77c

Please sign in to comment.