Statistics
| Branch: | Tag: | Revision:

root / Classes / EditAccountGroupsViewController.m @ c2940e36

History | View | Annotate | Download (15.7 kB)

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 kGroupName 0 
47
#define kGroupUsers 1
48
#define kSave 2
49
#define kRemove 3
50

    
51
@implementation EditAccountGroupsViewController
52

    
53
@synthesize account, groupName, groups, metadata;
54
@synthesize removeGroupEnabled, groupUUIDs, groupNameTextField, groupUsersTextFields, numberOfGroupUsersRows;
55

    
56
#pragma mark - View lifecycle
57

    
58
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
59
    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
60
}
61

    
62
- (void)viewDidLoad {
63
    [super viewDidLoad];
64
    self.groupUUIDs = [groups objectForKey:groupName];
65
    if (!self.groupUUIDs) {
66
        self.groupUUIDs = [NSArray array];
67
        numberOfGroupUsersRows = 2;
68
        self.groupUsersTextFields = [NSMutableDictionary dictionaryWithCapacity:1];
69
    } else {
70
        numberOfGroupUsersRows = groupUUIDs.count + 1;
71
        self.groupUsersTextFields = [NSMutableDictionary dictionaryWithCapacity:groupUUIDs.count];
72
    }
73
}
74

    
75
#pragma mark - Memory management
76

    
77
- (void)dealloc {
78
    [account release];
79
    [groupName release];
80
    [groups release];
81
    [metadata release];
82
    [groupUUIDs release];
83
    [groupNameTextField release];
84
    [groupUsersTextFields release];
85
    [super dealloc];
86
}
87

    
88
#pragma mark - Internal
89

    
90
- (BOOL)groupNameIsValid:(NSString *)input {
91
    if (!input.length) {
92
        [self alert:@"Invalid input" message:@"Group name cannot be empty."];
93
        return NO;
94
    } else if ([input rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"=,;"]].location != NSNotFound) {
95
        [self alert:@"Invalid input" message:@"Group name cannot contain '=', ',' or ';'."];
96
        return NO;
97
    }
98
    return YES;
99
}
100

    
101
- (NSMutableDictionary *)groupsInfoForGroups:(NSMutableDictionary *)groupsDictionary {
102
    NSMutableDictionary *groupsInfo = [NSMutableDictionary dictionaryWithCapacity:groupsDictionary.count];
103
    for (NSString *groupUser in groupsDictionary) {
104
        [groupsInfo setObject:[[groupsDictionary objectForKey:groupUser] componentsJoinedByString:@","]
105
                       forKey:groupUser];
106
    }
107
    return groupsInfo;
108
}
109

    
110
#pragma mark - UITableViewDataSource
111

    
112
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
113
    return (removeGroupEnabled ? 4 : 3);
114
}
115

    
116
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
117
    if (section == kGroupUsers) {
118
        return numberOfGroupUsersRows;
119
    }
120
    return 1;
121
}
122

    
123
- (UITextField *)textFieldForCell:(UITableViewCell *)cell {
124
    CGRect rect = CGRectInset(cell.contentView.bounds, 10.0, 10.0);
125
    UITextField *textField = [[[UITextField alloc] initWithFrame:rect] autorelease];
126
    textField.frame = rect;
127
    textField.clearButtonMode = UITextFieldViewModeWhileEditing;
128
    textField.backgroundColor = [UIColor clearColor];
129
    textField.opaque = YES;
130
    textField.autocorrectionType = UITextAutocorrectionTypeNo;
131
    textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
132
    textField.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
133
    return textField;
134
}
135

    
136
- (UITextField *)textFieldForCell:(UITableViewCell *)cell withIndexPath:(NSIndexPath *)indexPath {
137
    if (indexPath.section == kGroupName) {
138
        if (!groupNameTextField) {
139
            self.groupNameTextField = [self textFieldForCell:cell];
140
            groupNameTextField.placeholder = @"Group name";
141
            groupNameTextField.text = groupName;
142
            groupNameTextField.delegate = self;
143
        }
144
        return groupNameTextField;
145
    } else if (indexPath.section == kGroupUsers) {
146
        UITextField *groupUserTextField = [groupUsersTextFields objectForKey:indexPath];
147
        if (!groupUserTextField) {
148
            groupUserTextField = [self textFieldForCell:cell];
149
            groupUserTextField.placeholder = @"User";
150
            NSString *groupUser = (indexPath.row < groupUUIDs.count) ? [self.account displaynameForUUID:[groupUUIDs objectAtIndex:indexPath.row] safe:YES] : nil;
151
            groupUserTextField.text = (groupUser && groupUser.length) ? groupUser : nil;
152
            groupUserTextField.tag = indexPath.row;
153
            [groupUsersTextFields setObject:groupUserTextField forKey:indexPath];
154
            groupUserTextField.delegate = self;
155
        }
156
        return groupUserTextField;
157
    }
158
    return nil;
159
}
160

    
161
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
162
    if ((indexPath.section == kGroupName) || ((indexPath.section == kGroupUsers) && (indexPath.row < numberOfGroupUsersRows - 1))) {
163
        static NSString *CellIdentifier = @"TextFieldCell";
164
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
165
        if (cell == nil) {
166
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
167
        }
168
        cell.textLabel.text = nil;
169
        cell.accessoryType = UITableViewCellAccessoryNone;
170
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
171
        for (UIView *view in cell.contentView.subviews) {
172
            [view removeFromSuperview];
173
        }
174
        UITextField *textField = [self textFieldForCell:cell withIndexPath:indexPath];
175
        textField.returnKeyType = (((indexPath.section == kGroupUsers) && (indexPath.row == numberOfGroupUsersRows - 2)) ?
176
                                   UIReturnKeyDefault : UIReturnKeyNext);
177
        [cell.contentView addSubview:textField];
178
        return cell;
179
    }
180
    
181
    static NSString *CellIdentifier = @"Cell";
182
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
183
    if (cell == nil) {
184
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
185
    }
186
    cell.accessoryType = UITableViewCellAccessoryNone;
187

    
188
    if ((indexPath.section == kGroupUsers) && (indexPath.row == numberOfGroupUsersRows - 1)) {
189
        cell.textLabel.text = @"Add User";
190
        cell.selectionStyle = UITableViewCellSelectionStyleBlue;
191
    } else if (indexPath.section == kSave) {
192
        cell.textLabel.text = @"Save Group";
193
        cell.selectionStyle = UITableViewCellSelectionStyleBlue;
194
    } else if (indexPath.section == kRemove) {
195
        cell.textLabel.text = @"Remove Group";
196
        cell.selectionStyle = UITableViewCellSelectionStyleBlue;
197
    }
198
    
199
    return cell;
200
}
201

    
202
#pragma mark - UITableViewDelegate
203

    
204
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
205
    if (((indexPath.section == kGroupUsers) && (indexPath.row == numberOfGroupUsersRows - 1)) ||
206
        (indexPath.section == kSave) || (indexPath.section == kRemove))
207
        [self.view endEditing:YES];
208

    
209
    if ((indexPath.section == kGroupUsers) && (indexPath.row == numberOfGroupUsersRows - 1)) {
210
        numberOfGroupUsersRows++;
211
        [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
212
        [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:kGroupUsers] withRowAnimation:UITableViewRowAnimationNone];
213
    } else if (indexPath.section == kSave) {
214
        if (![self groupNameIsValid:groupNameTextField.text]) {
215
            [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
216
        } else {
217
            NSMutableArray *newGroupUsers = [NSMutableArray arrayWithCapacity:groupUsersTextFields.count];
218
            for (UITextField *groupUserTextField in [groupUsersTextFields allValues]) {
219
                if (groupUserTextField.text && groupUserTextField.text.length)
220
                    [newGroupUsers addObject:groupUserTextField.text];
221
            }
222
            if (!newGroupUsers.count) {
223
                [self alert:@"Cannot save group" message:@"Please input at least one user."];
224
                [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
225
            } else {
226
                __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Checking users..."
227
                                                                                                               andAddToView:self.view];
228
                [[self.account.manager userCatalogForDisplaynames:newGroupUsers UUIDs:nil]
229
                 success:^(OpenStackRequest *request) {
230
                     NSDictionary *displaynameCatalog = [request displaynameCatalog];
231
                     NSMutableArray *newGroupUUIDs = [NSMutableArray arrayWithCapacity:newGroupUsers.count];
232
                     for (NSString *groupUser in newGroupUsers) {
233
                         NSString *UUID = [displaynameCatalog objectForKey:groupUser];
234
                         if (!UUID) {
235
                             [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
236
                             [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
237
                             [self alert:@"Invalid user" message:[NSString stringWithFormat:@"User '%@' doesn't exist.", groupUser]];
238
                             return;
239
                         }
240
                         [newGroupUUIDs addObject:UUID];
241
                     }
242
                     // Apply changes.
243
                     [groups removeObjectForKey:groupName];
244
                     [groups setObject:newGroupUUIDs forKey:groupNameTextField.text];
245
                     [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
246
                    __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Saving group..."
247
                                                                                                                   andAddToView:self.view];
248
                     [[self.account.manager writeAccountMetadata:[NSDictionary dictionaryWithObjectsAndKeys:
249
                                                                  [self groupsInfoForGroups:groups], @"groups",
250
                                                                  metadata, @"metadata",
251
                                                                  nil]]
252
                      success:^(OpenStackRequest *request) {
253
                          self.groupName = groupNameTextField.text;
254
                          self.groupUUIDs = newGroupUUIDs;
255
                          numberOfGroupUsersRows = groupUUIDs.count + 1;
256
                          self.groupUsersTextFields = [NSMutableDictionary dictionaryWithCapacity:groupUUIDs.count];
257
                          removeGroupEnabled = YES;
258
                          self.navigationItem.title = @"Edit Group";
259
                          [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
260
                          [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
261
                          [self.tableView reloadData];
262
                     }
263
                     failure:^(OpenStackRequest *request) {
264
                         [groups removeObjectForKey:groupNameTextField.text];
265
                         if (groupUUIDs.count) {
266
                             [groups setObject:groupUUIDs forKey:groupName];
267
                         }
268
                         [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
269
                         [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
270
                         [self alert:@"There was a problem saving the group." request:request];
271
                     }];
272
                 }
273
                 failure:^(OpenStackRequest *request) {
274
                     [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
275
                     [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
276
                     [self alert:@"There was a problem checking the users." request:request];
277
                 }];
278
            }
279
        }
280
    } else if (indexPath.section == kRemove) {
281
        [groups removeObjectForKey:groupName];
282
        __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Removing group..."
283
                                                                                                       andAddToView:self.view];
284
        [[self.account.manager writeAccountMetadata:[NSDictionary dictionaryWithObjectsAndKeys:
285
                                                     [self groupsInfoForGroups:groups], @"groups",
286
                                                     metadata, @"metadata",
287
                                                     nil]]
288
         success:^(OpenStackRequest *request) {
289
             self.groupName = @"";
290
             self.groupUUIDs = [NSArray array];
291
             numberOfGroupUsersRows = 2;
292
             self.groupUsersTextFields = [NSMutableDictionary dictionaryWithCapacity:1];
293
             removeGroupEnabled = NO;
294
             self.navigationItem.title = @"Add Group";
295
             [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
296
             [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
297
             [self.tableView reloadData];
298
         }
299
         failure:^(OpenStackRequest *request) {
300
             if (groupUUIDs.count) {
301
                 [groups setObject:groupUUIDs forKey:groupName];
302
             }
303
             [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
304
             [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
305
             [self alert:@"There was a problem removing the group." request:request];
306
         }];
307
    }
308
}
309

    
310
#pragma mark - UITextFieldDelegate
311

    
312
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
313
    if (textField == groupNameTextField) {
314
        if (![self groupNameIsValid:textField.text]) {
315
            return NO;
316
        }
317
        [[groupUsersTextFields objectForKey:[NSIndexPath indexPathForRow:0 inSection:kGroupUsers]] becomeFirstResponder];
318
    } else if (textField.tag == numberOfGroupUsersRows - 2) {
319
        [textField resignFirstResponder];
320
    } else {
321
        [[groupUsersTextFields objectForKey:[NSIndexPath indexPathForRow:(textField.tag + 1) inSection:kGroupUsers]] becomeFirstResponder];
322
    }    
323
    return YES;
324
}
325

    
326
@end