diff --git a/lib/main.dart b/lib/main.dart index 9d2849e..c3020f0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,6 +10,7 @@ import 'package:git_touch/screens/commits.dart'; import 'package:git_touch/screens/gitlab_blob.dart'; import 'package:git_touch/screens/gitlab_commits.dart'; import 'package:git_touch/screens/gitlab_issue.dart'; +import 'package:git_touch/screens/gitlab_issues.dart'; import 'package:git_touch/screens/gitlab_project.dart'; import 'package:git_touch/screens/gitlab_tree.dart'; import 'package:git_touch/screens/gitlab_user.dart'; @@ -69,6 +70,7 @@ void main() async { gitlabTreeRouter, gitlabProjectRouter, gitlabIssueRouter, + gitlabIssuesRouter, gitlabCommitsRouter, loginRouter, settingsRouter, diff --git a/lib/models/gitlab.dart b/lib/models/gitlab.dart index 0430534..c8cefda 100644 --- a/lib/models/gitlab.dart +++ b/lib/models/gitlab.dart @@ -47,7 +47,7 @@ class GitlabTodo { GitlabTodoProject project; String actionName; String targetType; - GitlabIssue target; + GitlabTodoTarget target; GitlabTodo(); @@ -56,7 +56,7 @@ class GitlabTodo { } @JsonSerializable(fieldRename: FieldRename.snake) -class GitlabIssue { +class GitlabTodoTarget { int iid; int projectId; String title; @@ -64,10 +64,10 @@ class GitlabIssue { String description; String createdAt; - GitlabIssue(); + GitlabTodoTarget(); - factory GitlabIssue.fromJson(Map json) => - _$GitlabIssueFromJson(json); + factory GitlabTodoTarget.fromJson(Map json) => + _$GitlabTodoTargetFromJson(json); } @JsonSerializable(fieldRename: FieldRename.snake) @@ -188,3 +188,17 @@ class GitlabCommit { factory GitlabCommit.fromJson(Map json) => _$GitlabCommitFromJson(json); } + +@JsonSerializable(fieldRename: FieldRename.snake) +class GitlabIssue { + String title; + int iid; + int projectId; + GitlabUser author; + int userNotesCount; + DateTime updatedAt; + List labels; + GitlabIssue(); + factory GitlabIssue.fromJson(Map json) => + _$GitlabIssueFromJson(json); +} diff --git a/lib/models/gitlab.g.dart b/lib/models/gitlab.g.dart index 868352f..0447d0b 100644 --- a/lib/models/gitlab.g.dart +++ b/lib/models/gitlab.g.dart @@ -68,7 +68,7 @@ GitlabTodo _$GitlabTodoFromJson(Map json) { ..targetType = json['target_type'] as String ..target = json['target'] == null ? null - : GitlabIssue.fromJson(json['target'] as Map); + : GitlabTodoTarget.fromJson(json['target'] as Map); } Map _$GitlabTodoToJson(GitlabTodo instance) => @@ -80,8 +80,8 @@ Map _$GitlabTodoToJson(GitlabTodo instance) => 'target': instance.target, }; -GitlabIssue _$GitlabIssueFromJson(Map json) { - return GitlabIssue() +GitlabTodoTarget _$GitlabTodoTargetFromJson(Map json) { + return GitlabTodoTarget() ..iid = json['iid'] as int ..projectId = json['project_id'] as int ..title = json['title'] as String @@ -92,7 +92,7 @@ GitlabIssue _$GitlabIssueFromJson(Map json) { ..createdAt = json['created_at'] as String; } -Map _$GitlabIssueToJson(GitlabIssue instance) => +Map _$GitlabTodoTargetToJson(GitlabTodoTarget instance) => { 'iid': instance.iid, 'project_id': instance.projectId, @@ -274,3 +274,29 @@ Map _$GitlabCommitToJson(GitlabCommit instance) => 'author_name': instance.authorName, 'message': instance.message, }; + +GitlabIssue _$GitlabIssueFromJson(Map json) { + return GitlabIssue() + ..title = json['title'] as String + ..iid = json['iid'] as int + ..projectId = json['project_id'] as int + ..author = json['author'] == null + ? null + : GitlabUser.fromJson(json['author'] as Map) + ..userNotesCount = json['user_notes_count'] as int + ..updatedAt = json['updated_at'] == null + ? null + : DateTime.parse(json['updated_at'] as String) + ..labels = (json['labels'] as List)?.map((e) => e as String)?.toList(); +} + +Map _$GitlabIssueToJson(GitlabIssue instance) => + { + 'title': instance.title, + 'iid': instance.iid, + 'project_id': instance.projectId, + 'author': instance.author, + 'user_notes_count': instance.userNotesCount, + 'updated_at': instance.updatedAt?.toIso8601String(), + 'labels': instance.labels, + }; diff --git a/lib/screens/gitlab_issue.dart b/lib/screens/gitlab_issue.dart index 46181b3..d69afe4 100644 --- a/lib/screens/gitlab_issue.dart +++ b/lib/screens/gitlab_issue.dart @@ -24,7 +24,7 @@ class GitlabIssueScreen extends StatelessWidget { @override Widget build(BuildContext context) { return RefreshStatefulScaffold< - Tuple3, List>>( + Tuple3, List>>( title: Text('Issue #$iid'), fetchData: () async { final type = isMr ? 'merge_requests' : 'issues'; @@ -37,7 +37,7 @@ class GitlabIssueScreen extends StatelessWidget { .fetchGitlab('/projects/$projectId/$type/$iid/award_emoji'), ]); return Tuple3( - GitlabIssue.fromJson(items[0]), + GitlabTodoTarget.fromJson(items[0]), (items[1] as List).map((v) => GitlabIssueNote.fromJson(v)), items[2] as List, ); diff --git a/lib/screens/gitlab_issues.dart b/lib/screens/gitlab_issues.dart new file mode 100644 index 0000000..924be17 --- /dev/null +++ b/lib/screens/gitlab_issues.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:git_touch/models/auth.dart'; +import 'package:git_touch/models/gitlab.dart'; +import 'package:git_touch/scaffolds/list_stateful.dart'; +import 'package:git_touch/utils/utils.dart'; +import 'package:git_touch/widgets/app_bar_title.dart'; +import 'package:git_touch/widgets/issue_item.dart'; +import 'package:git_touch/widgets/label.dart'; +import 'package:provider/provider.dart'; + +final gitlabIssuesRouter = RouterScreen('/gitlab/projects/:id/issues', + (context, params) => GitlabIssuesScreen(params['id'].first)); + +class GitlabIssuesScreen extends StatelessWidget { + final String id; + + GitlabIssuesScreen(this.id); + + Future> _query(BuildContext context, + [int page = 1]) async { + final res = await Provider.of(context) + .fetchGitlab('/projects/$id/issues?page=$page'); + return ListPayload( + cursor: page + 1, + hasMore: true, // TODO: + items: (res as List).map((v) => GitlabIssue.fromJson(v)).toList(), + ); + } + + @override + Widget build(BuildContext context) { + return ListStatefulScaffold( + title: AppBarTitle('Issues'), + // TODO: create issue + onRefresh: () => _query(context), + onLoadMore: (cursor) => _query(context, cursor), + itemBuilder: (p) => IssueItem( + author: p.author.username, + avatarUrl: p.author.avatarUrl, + commentCount: p.userNotesCount, + number: p.iid, + title: p.title, + updatedAt: p.updatedAt, + labels: p.labels.isEmpty + ? null + : Wrap(spacing: 4, runSpacing: 4, children: [ + for (var label in p.labels) + MyLabel(name: label, cssColor: '#428BCA') + ]), + url: '/gitlab/projects/${p.projectId}/issues/${p.iid}', + ), + ); + } +}