Permalink
Browse files

Add assignee and milestone management

Closes #288
  • Loading branch information...
1 parent 2522454 commit f1d8f250659e5deaa4434ff29039c6aff393325e @dennisreimann committed Jun 18, 2013
View
@@ -18,9 +18,9 @@
@property(nonatomic,strong)NSDate *closedAt;
@property(nonatomic,strong)NSURL *htmlURL;
@property(nonatomic,assign)NSInteger number;
-@property(nonatomic,readonly)NSString *repoIdWithIssueNumber;
@property(nonatomic,readonly)BOOL isNew;
@property(nonatomic,readonly)BOOL isOpen;
+@property(nonatomic,readonly)NSString *repoIdWithIssueNumber;
@property(nonatomic,readonly)NSMutableAttributedString *attributedBody;
- (id)initWithRepository:(GHRepository *)repo;
View
@@ -72,6 +72,13 @@ - (GHIssueComments *)comments {
return _comments;
}
+- (GHLabels *)labels {
+ if (!_labels) {
+ _labels = [[GHLabels alloc] initWithRepository:self.repository];
+ }
+ return _labels;
+}
+
#pragma mark Loading
- (void)setValues:(id)dict {
@@ -97,12 +104,16 @@ - (void)setValues:(id)dict {
}
// labels
NSArray *labels = [dict safeArrayForKey:@"labels"];
- self.labels = [[GHLabels alloc] initWithRepository:self.repository];
- [self.labels setValues:labels];
+ if (labels) {
+ self.labels = [[GHLabels alloc] initWithRepository:self.repository];
+ [self.labels setValues:labels];
+ }
// milestone
NSDictionary *milestoneDict = [dict safeDictForKey:@"milestone"];
- self.milestone = [[GHMilestone alloc] initWithRepository:self.repository];
- [self.milestone setValues:milestoneDict];
+ if (milestoneDict) {
+ self.milestone = [[GHMilestone alloc] initWithRepository:self.repository];
+ [self.milestone setValues:milestoneDict];
+ }
}
@end
View
@@ -10,10 +10,11 @@
@property(nonatomic,strong)NSString *body;
@property(nonatomic,strong)NSString *state;
@property(nonatomic,strong)NSDate *createdAt;
-@property(nonatomic,strong)NSDate *dueAt;
+@property(nonatomic,strong)NSDate *dueOn;
@property(nonatomic,assign)NSInteger number;
@property(nonatomic,assign)NSInteger openIssueCount;
@property(nonatomic,assign)NSInteger closedIssueCount;
+@property(nonatomic,readonly)NSInteger percentDone;
@property(nonatomic,readonly)BOOL isNew;
- (id)initWithRepository:(GHRepository *)repo;
View
@@ -31,17 +31,26 @@ - (NSString *)resourcePath {
}
}
+- (NSInteger)percentDone {
+ NSInteger issuesTotal = self.openIssueCount + self.closedIssueCount;
+ float percentPerIssue = 100.0f / issuesTotal;
+ NSInteger percentDone = lroundf(self.closedIssueCount * percentPerIssue);
+ return percentDone;
+}
+
#pragma mark Loading
- (void)setValues:(id)dict {
NSString *login = [dict safeStringForKeyPath:@"creator.login"];
self.creator = [iOctocat.sharedInstance userWithLogin:login];
- self.createdAt = [dict safeDateForKey:@"created_at"];
- self.dueAt = [dict safeDateForKey:@"due_at"];
+ self.number = [dict safeIntegerForKey:@"number"];
self.title = [dict safeStringForKey:@"title"];
- self.body = [dict safeStringForKey:@"description"];
self.state = [dict safeStringForKey:@"state"];
- self.number = [dict safeIntegerForKey:@"number"];
+ self.body = [dict safeStringForKey:@"description"];
+ self.dueOn = [dict safeDateForKey:@"due_on"];
+ self.createdAt = [dict safeDateForKey:@"created_at"];
+ self.openIssueCount = [dict safeIntegerForKey:@"open_issues"];
+ self.closedIssueCount = [dict safeIntegerForKey:@"closed_issues"];
}
@end
View
@@ -20,7 +20,7 @@ - (id)initWithResourcePath:(NSString *)path {
}
- (id)initWithRepository:(GHRepository *)repo {
- NSString *path = [NSString stringWithFormat:kLabelsFormat, repo.owner, repo.name];
+ NSString *path = [NSString stringWithFormat:kMilestonesFormat, repo.owner, repo.name];
self = [self initWithResourcePath:path];
if (self) {
self.repository = repo;
View
@@ -1,7 +1,7 @@
#import "GHResource.h"
-@class GHIssues, GHPullRequests, GHForks, GHTags, GHBranches, GHMilestones, GHMilestone, GHLabels, GHUser, GHReadme, GHEvents, GHUsers;
+@class GHIssues, GHPullRequests, GHForks, GHTags, GHBranches, GHMilestones, GHLabels, GHUser, GHReadme, GHEvents, GHUsers;
@interface GHRepository : GHResource
@property(nonatomic,readonly)NSString *repoId;
@@ -19,7 +19,6 @@
@property(nonatomic,strong)GHPullRequests *openPullRequests;
@property(nonatomic,strong)GHPullRequests *closedPullRequests;
@property(nonatomic,strong)GHMilestones *milestones;
-@property(nonatomic,strong)GHMilestone *milestone;
@property(nonatomic,strong)GHLabels *labels;
@property(nonatomic,strong)GHForks *forks;
@property(nonatomic,strong)GHTags *tags;
@@ -29,7 +28,6 @@
@property(nonatomic,strong)GHUsers *contributors;
@property(nonatomic,strong)GHUsers *stargazers;
@property(nonatomic,strong)GHUsers *assignees;
-@property(nonatomic,strong)GHUser *assignee;
@property(nonatomic,readonly)GHUser *user;
@property(nonatomic,readonly)GHRepository *parent;
@property(nonatomic,readwrite)NSInteger forkCount;
View
@@ -8,7 +8,9 @@
#import "GHUsers.h"
#import "GHEvents.h"
#import "GHReadme.h"
+#import "GHLabels.h"
#import "GHBranches.h"
+#import "GHMilestones.h"
#import "GHFMarkdown.h"
#import "NSURL+Extensions.h"
#import "NSDictionary+Extensions.h"
@@ -92,6 +94,20 @@ - (GHForks *)forks {
return _forks;
}
+- (GHMilestones *)milestones {
+ if (!_milestones) {
+ _milestones = [[GHMilestones alloc] initWithRepository:self];
+ }
+ return _milestones;
+}
+
+- (GHLabels *)labels {
+ if (!_labels) {
+ _labels = [[GHLabels alloc] initWithRepository:self];
+ }
+ return _labels;
+}
+
- (GHReadme *)readme {
if (!_readme) {
_readme = [[GHReadme alloc] initWithRepository:self];
@@ -0,0 +1,10 @@
+#import "IOCCollectionController.h"
+#import "IOCIssueManagementDelegate.h"
+
+@class GHIssue;
+
+@interface IOCAssigneesController : IOCCollectionController
+@property(nonatomic,weak)id<IOCIssueManagementDelegate> delegate;
+
+- (id)initWithIssue:(GHIssue *)issue;
+@end
@@ -0,0 +1,104 @@
+#import "IOCAssigneesController.h"
+#import "IOCUserObjectCell.h"
+#import "GHRepository.h"
+#import "GHIssue.h"
+#import "GHUsers.h"
+#import "GHUser.h"
+#import "SVProgressHUD.h"
+
+
+@interface IOCAssigneesController ()
+@property(nonatomic,weak)GHIssue *issue;
+@property(nonatomic,strong)NSIndexPath *selectedIndexPath;
+@end
+
+
+@implementation IOCAssigneesController
+
+- (id)initWithIssue:(GHIssue *)issue {
+ self = [super initWithCollection:issue.repository.assignees];
+ if (self) {
+ _issue = issue;
+ }
+ return self;
+}
+
+- (NSString *)collectionName {
+ return NSLocalizedString(@"Assignees", nil);
+}
+
+- (NSString *)collectionCellIdentifier {
+ return kUserObjectCellIdentifier;
+}
+
+- (BOOL)canReload {
+ return NO;
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ if (self.issue.assignee) {
+ [self.collection whenLoaded:^(GHResource *instance, id data) {
+ NSInteger row = [self.collection indexOfObject:self.issue.assignee];
+ self.selectedIndexPath = [NSIndexPath indexPathForRow:row inSection:0];
+ [self.tableView reloadData];
+ }];
+ } else {
+ self.selectedIndexPath = nil;
+ }
+}
+
+- (void)viewWillDisappear:(BOOL)animated {
+ [super viewWillDisappear:animated];
+ if (!self.collection.isLoaded) return;
+ GHUser *oldAssignee = self.issue.assignee;
+ GHUser *newAssignee = self.selectedIndexPath ? self.collection[self.selectedIndexPath.row] : nil;
+ if (newAssignee != oldAssignee) {
+ NSDictionary *params = @{@"assignee": newAssignee ? newAssignee.login : @""};
+ [self.issue saveWithParams:params start:^(GHResource *instance) {
+ [SVProgressHUD showWithStatus:@"Saving assignee" maskType:SVProgressHUDMaskTypeGradient];
+ } success:^(GHResource *instance, id data) {
+ [SVProgressHUD showSuccessWithStatus:@"Saved assignee"];
+ self.issue.assignee = newAssignee;
+ [self.issue markAsChanged];
+ [self.delegate performSelector:@selector(savedIssueObject:) withObject:self.issue];
+ [self.navigationController popViewControllerAnimated:YES];
+ } failure:^(GHResource *instance, NSError *error) {
+ [SVProgressHUD showErrorWithStatus:@"Saving assignee failed"];
+ }];
+ }
+}
+
+#pragma mark TableView
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+ if (self.collection.isEmpty) return [super tableView:tableView cellForRowAtIndexPath:indexPath];
+ NSInteger row = indexPath.row;
+ IOCUserObjectCell *cell = (IOCUserObjectCell *)[tableView dequeueReusableCellWithIdentifier:self.collectionCellIdentifier];
+ if (!cell) {
+ cell = [IOCUserObjectCell cellWithReuseIdentifier:self.collectionCellIdentifier];
+ cell.selectionStyle = UITableViewCellSelectionStyleNone;
+ }
+ GHUser *user = self.collection[row];
+ cell.userObject = user;
+ cell.accessoryType = self.selectedIndexPath && self.selectedIndexPath.row == row? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
+ return cell;
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+ if (self.collection.isEmpty) return;
+ UITableViewCell *cell = nil;
+ if (self.selectedIndexPath) {
+ cell = [tableView cellForRowAtIndexPath:self.selectedIndexPath];
+ cell.accessoryType = UITableViewCellAccessoryNone;
+ }
+ if ([self.selectedIndexPath isEqual:indexPath]) {
+ self.selectedIndexPath = nil;
+ } else {
+ cell = [tableView cellForRowAtIndexPath:indexPath];
+ cell.accessoryType = UITableViewCellAccessoryCheckmark;
+ self.selectedIndexPath = indexPath;
+ }
+}
+
+@end
Oops, something went wrong.

0 comments on commit f1d8f25

Please sign in to comment.