Merge branch 'master' of https://code.grnet.gr/git/pithos-ios
[pithos-ios] / Classes / EditAccountGroupsViewController.m
1 //
2 //  EditAccountGroupsViewController.m
3 //  pithos-ios
4 //
5 // Copyright 2011 GRNET S.A. All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or
8 // without modification, are permitted provided that the following
9 // conditions are met:
10 // 
11 //   1. Redistributions of source code must retain the above
12 //      copyright notice, this list of conditions and the following
13 //      disclaimer.
14 // 
15 //   2. Redistributions in binary form must reproduce the above
16 //      copyright notice, this list of conditions and the following
17 //      disclaimer in the documentation and/or other materials
18 //      provided with the distribution.
19 // 
20 // THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
21 // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
24 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 // 
33 // The views and conclusions contained in the software and
34 // documentation are those of the authors and should not be
35 // interpreted as representing official policies, either expressed
36 // or implied, of GRNET S.A.
37
38 #import "EditAccountGroupsViewController.h"
39 #import "OpenStackAccount.h"
40 #import "ActivityIndicatorView.h"
41 #import "UIViewController+Conveniences.h"
42 #import "AccountManager.h"
43 #import "OpenStackRequest.h"
44 #import "APICallback.h"
45
46 #define kGroupDetails 0 
47 #define kSave 1
48 #define kRemove 2
49
50 @implementation EditAccountGroupsViewController
51
52 @synthesize account;
53 @synthesize groupName, groupUsers, removeGroupEnabled;
54 @synthesize groups,metadata;
55
56 #pragma mark - View lifecycle
57
58 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
59     return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
60 }
61
62 #pragma mark - Memory management
63
64 - (void)dealloc {
65     [groupName release];
66     [groupUsers release];
67     [account release];
68     [metadata release];
69     [groups release];
70     [super dealloc];
71 }
72
73 #pragma mark - Internal
74
75 - (BOOL)userInputIsValid:(NSString *)input fieldName:(NSString *)fieldName {
76     if (![input length] || ![[input stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length]) {
77         [self alert:@"Invalid input" message:[NSString stringWithFormat:@"%@ field cannot be empty", fieldName]];
78         return NO;
79     }
80     NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@"= "];
81     if ([input rangeOfCharacterFromSet:set].location != NSNotFound) {
82         [self alert:@"Invalid input" message:[NSString stringWithFormat:@"%@ field cannot contain '=' or whitespace characters", fieldName]];
83         return NO;
84     }
85     return YES;
86 }
87
88 #pragma mark - UITableViewDataSource
89
90 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
91     if (removeGroupEnabled)
92         return 3;
93     else
94         return 2;
95 }
96
97 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
98     if (section == kGroupDetails)
99         return 2;
100     else
101         return 1;
102 }
103
104 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
105     static NSString *CellIdentifier = @"Cell";
106     
107     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
108     if (cell == nil) {
109         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
110     }
111     
112     cell.textLabel.text = @"";
113     cell.accessoryType = UITableViewCellAccessoryNone;
114     if (indexPath.section == kGroupDetails) {
115         UITextField *textField = nil;
116         for (id subView in cell.contentView.subviews) {
117             if ([subView isKindOfClass:[UITextField class]]) {
118                 textField = (UITextField *)subView;
119             }
120         }
121         
122         if (textField == nil) {
123             CGRect bounds = [cell.contentView bounds];
124             CGRect rect = CGRectInset(bounds, 10.0, 10.0);                        
125             textField = [[UITextField alloc] initWithFrame:rect];
126             [textField setFrame:rect];
127         }
128         
129         [textField setClearButtonMode:UITextFieldViewModeWhileEditing];
130         [textField setBackgroundColor:[UIColor clearColor]];
131         [textField setOpaque:YES];
132         [textField setAutocorrectionType:UITextAutocorrectionTypeNo];
133         [textField setAutocapitalizationType:UITextAutocapitalizationTypeNone];
134         [textField setDelegate:self];
135         textField.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
136
137         if (indexPath.row == 0) {
138             textField.returnKeyType = UIReturnKeyNext;
139             textField.placeholder = @"Group name";
140             textField.text = self.groupName;
141             textField.tag = 0;
142         } else if (indexPath.row == 1) {
143             textField.returnKeyType = UIReturnKeyDefault;
144             textField.placeholder = @"Group users";
145             textField.text = self.groupUsers;
146             textField.tag = 1;
147         }
148         cell.selectionStyle = UITableViewCellSelectionStyleNone;
149         [cell.contentView addSubview:textField];
150     } else if (indexPath.section == kSave) {
151         cell.textLabel.text = @"Save";
152     } else if (indexPath.section == kRemove) {
153         cell.textLabel.text = @"Remove";
154     }
155     
156     return cell;
157 }
158
159 #pragma mark - UITableViewDelegate
160
161 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
162     NSIndexPath *keyCellIndexPath;
163     NSIndexPath *valueCellIndexPath;
164     UITableViewCell *cell;
165
166     if (indexPath.section != kGroupDetails)
167         [self.view endEditing:YES];
168     
169     if (indexPath.section == kSave) {
170         keyCellIndexPath = [NSIndexPath indexPathForRow:0 inSection:kGroupDetails];
171         cell = [self.tableView cellForRowAtIndexPath:keyCellIndexPath];
172         UITextField *textField = [[cell.contentView subviews] objectAtIndex:0];
173         NSString *newGroupName = textField.text;
174         
175         if (![self userInputIsValid:newGroupName fieldName:@"Group name"]) {
176             [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
177             return;
178         }
179
180         valueCellIndexPath = [NSIndexPath indexPathForRow:1 inSection:kGroupDetails];
181         cell = [self.tableView cellForRowAtIndexPath:valueCellIndexPath];
182         textField = [[cell.contentView subviews] objectAtIndex:0];
183         NSString *newGroupUsers = textField.text;
184         
185         if (![self userInputIsValid:newGroupUsers fieldName:@"Group users"]) {
186             [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
187             return;
188         }
189
190         [groups removeObjectForKey:groupName];
191         [groups setObject:newGroupUsers forKey:newGroupName];
192         NSDictionary *accountInfo = [NSDictionary dictionaryWithObjectsAndKeys:groups, @"groups",
193                                         metadata, @"metadata",
194                                         nil
195                                         ];
196         __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Saving group..."
197                                                                                                        andAddToView:self.view];
198         [[self.account.manager writeAccountMetadata:accountInfo]
199          success:^(OpenStackRequest *request) {
200              [activityIndicatorView removeFromSuperview];
201              self.groupName = newGroupName;
202              self.groupUsers = newGroupUsers;
203              self.removeGroupEnabled = YES;
204              self.navigationItem.title = @"Edit Group";
205              [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
206              [self.tableView reloadData]; 
207          }
208          failure:^(OpenStackRequest *request) {
209              [activityIndicatorView removeFromSuperview];
210              [groups removeObjectForKey:newGroupName];
211              [groups setObject:self.groupUsers forKey:self.groupName];
212              [self.tableView reloadData];
213              [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
214              [self alert:@"There was a problem saving the group information." request:request];
215          }];
216     } else if (indexPath.section == kRemove) {
217         [groups removeObjectForKey:groupName];
218         NSDictionary *accountInfo = [NSDictionary dictionaryWithObjectsAndKeys:groups, @"groups",
219                                         metadata, @"metadata",
220                                         nil
221                                         ];
222         __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Removing group..."
223                                                                                                        andAddToView:self.view];
224         [[self.account.manager writeAccountMetadata:accountInfo]
225          success:^(OpenStackRequest *request) {
226              [activityIndicatorView removeFromSuperview];
227              self.groupName = @"";
228              self.groupUsers = @"";
229              self.removeGroupEnabled = NO;
230              [self.tableView reloadData];
231              [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
232          }
233          failure:^(OpenStackRequest *request) {
234              [activityIndicatorView removeFromSuperview];
235              [groups setObject:groupUsers forKey:groupName];
236              [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
237              [self alert:@"There was a problem removing the group information." request:request];
238          }];
239     }
240 }
241
242 #pragma mark - UITextFieldDelegate
243
244 - (BOOL)textFieldShouldReturn:(UITextField *)textField {
245     if ([textField returnKeyType] == UIReturnKeyNext) {
246         [self userInputIsValid:textField.text fieldName:@"Group name"];
247
248         NSInteger nextTag = [textField tag] + 1;
249         UIView *nextTextField = [self.tableView viewWithTag:nextTag];
250         [nextTextField becomeFirstResponder];
251     } else {
252         [self userInputIsValid:textField.text fieldName:@"Group users"];
253         [textField resignFirstResponder];
254     }
255     
256     return YES;
257 }
258
259 @end