Revision 3e581f16
b/Classes/AccountGroupsViewController.h | ||
---|---|---|
45 | 45 |
|
46 | 46 |
@property (nonatomic, retain) OpenStackAccount *account; |
47 | 47 |
@property (nonatomic, retain) NSMutableDictionary *groups; |
48 |
@property (nonatomic, retain) NSMutableDictionary *metadata; |
|
48 | 49 |
|
49 | 50 |
@end |
b/Classes/AccountGroupsViewController.m | ||
---|---|---|
47 | 47 |
|
48 | 48 |
@implementation AccountGroupsViewController |
49 | 49 |
|
50 |
@synthesize account, groups; |
|
50 |
@synthesize account, groups, metadata;
|
|
51 | 51 |
|
52 | 52 |
#pragma mark - View lifecycle |
53 | 53 |
|
... | ... | |
58 | 58 |
- (void)viewWillAppear:(BOOL)animated { |
59 | 59 |
[super viewWillAppear:animated]; |
60 | 60 |
self.navigationItem.title = @"Groups"; |
61 |
groups = [[NSMutableDictionary alloc] init]; |
|
62 |
metadata = [[NSMutableDictionary alloc] init]; |
|
61 |
} |
|
63 | 62 |
|
64 |
__block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Loading..." |
|
63 |
- (void)viewDidAppear:(BOOL)animated { |
|
64 |
[super viewDidAppear:animated]; |
|
65 |
__block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Loading groups..." |
|
65 | 66 |
andAddToView:self.view]; |
66 | 67 |
[[self.account.manager getStorageAccountInfo] |
67 | 68 |
success:^(OpenStackRequest *request) { |
68 |
[activityIndicatorView removeFromSuperview]; |
|
69 |
for (NSString *key in request.responseHeaders) { |
|
70 |
if ([key hasPrefix:@"X-Account-Group-"]) { |
|
71 |
NSString *groupUsers = [NSString decodeFromPercentEscape:[request.responseHeaders objectForKey:key]]; |
|
72 |
NSString *groupName = [NSString decodeFromPercentEscape:[key substringFromIndex:16]]; |
|
73 |
[groups setObject:groupUsers forKey:groupName]; |
|
69 |
self.groups = [NSMutableDictionary dictionary]; |
|
70 |
self.metadata = [NSMutableDictionary dictionary]; |
|
71 |
|
|
72 |
for (NSString *headerName in request.responseHeaders) { |
|
73 |
if ([headerName hasPrefix:@"X-Account-Group-"]) { |
|
74 |
[groups setObject:[[NSString decodeFromPercentEscape:[request.responseHeaders objectForKey:headerName]] componentsSeparatedByString:@","] |
|
75 |
forKey:[NSString decodeFromPercentEscape:[headerName substringFromIndex:16]]]; |
|
76 |
} else if ([headerName hasPrefix:@"X-Account-Meta-"]) { |
|
77 |
[metadata setObject:[NSString decodeFromPercentEscape:[request.responseHeaders objectForKey:headerName]] |
|
78 |
forKey:[NSString decodeFromPercentEscape:[headerName substringFromIndex:15]]]; |
|
74 | 79 |
} |
75 | 80 |
} |
76 | 81 |
|
77 |
for (NSString *header in request.responseHeaders) { |
|
78 |
if ([header hasPrefix:@"X-Account-Meta-"]) { |
|
79 |
NSString *metadataKey = [NSString decodeFromPercentEscape:[header substringFromIndex:15]]; |
|
80 |
NSString *metadataValue = [NSString decodeFromPercentEscape:[request.responseHeaders objectForKey:header]]; |
|
81 |
[metadata setObject:metadataValue forKey:metadataKey]; |
|
82 |
} |
|
82 |
NSMutableArray *UUIDs = [NSMutableArray array]; |
|
83 |
for (NSString *groupName in groups) { |
|
84 |
[UUIDs addObjectsFromArray:[groups objectForKey:groupName]]; |
|
85 |
} |
|
86 |
if (UUIDs.count) { |
|
87 |
[[self.account.manager userCatalogForDisplaynames:nil UUIDs:UUIDs] |
|
88 |
success:^(OpenStackRequest *request) { |
|
89 |
[activityIndicatorView removeFromSuperview]; |
|
90 |
[self.tableView reloadData]; |
|
91 |
} |
|
92 |
failure:^(OpenStackRequest *request) { |
|
93 |
[activityIndicatorView removeFromSuperview]; |
|
94 |
[self.tableView reloadData]; |
|
95 |
[self alert:@"Failed to translate group UUIDs." request:request]; |
|
96 |
}]; |
|
97 |
} else { |
|
98 |
[activityIndicatorView removeFromSuperview]; |
|
99 |
[self.tableView reloadData]; |
|
83 | 100 |
} |
84 |
|
|
85 |
[self.tableView reloadData]; |
|
86 | 101 |
} |
87 | 102 |
failure:^(OpenStackRequest *request) { |
88 | 103 |
[activityIndicatorView removeFromSuperview]; |
89 |
[self alert:@"Error" message:@"Failed to get account information"];
|
|
104 |
[self alert:@"Failed to get account information." request:request];
|
|
90 | 105 |
}]; |
91 | 106 |
} |
92 | 107 |
|
108 |
#pragma mark - Internal |
|
109 |
|
|
110 |
- (NSMutableArray *)groupUsersForGroupName:(NSString *)groupName { |
|
111 |
NSArray *groupUUIDs = [groups objectForKey:groupName]; |
|
112 |
NSMutableArray *groupUsers = [NSMutableArray arrayWithCapacity:groupUUIDs.count]; |
|
113 |
for (NSString *UUID in groupUUIDs) { |
|
114 |
[groupUsers addObject:[self.account displaynameForUUID:UUID safe:YES]]; |
|
115 |
} |
|
116 |
return groupUsers; |
|
117 |
} |
|
118 |
|
|
119 |
- (NSMutableString *)groupUsersStringForGroupName:(NSString *)groupName { |
|
120 |
NSMutableArray *groupUsers = [self groupUsersForGroupName:groupName]; |
|
121 |
NSMutableString *groupUsersString = [NSMutableString string]; |
|
122 |
for (NSUInteger index = 0; index < groupUsers.count; index++) { |
|
123 |
if (index) { |
|
124 |
[groupUsersString appendString:@","]; |
|
125 |
} |
|
126 |
[groupUsersString appendString:[groupUsers objectAtIndex:index]]; |
|
127 |
} |
|
128 |
return groupUsersString; |
|
129 |
} |
|
130 |
|
|
93 | 131 |
#pragma mark - Memory management |
94 | 132 |
|
95 | 133 |
- (void)dealloc { |
... | ... | |
102 | 140 |
#pragma mark - UITableViewDataSource |
103 | 141 |
|
104 | 142 |
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { |
105 |
return [groups count] + 1;
|
|
143 |
return (groups.count + 1);
|
|
106 | 144 |
} |
107 | 145 |
|
108 | 146 |
- (CGFloat)tableView:(UITableView *)aTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { |
109 | 147 |
CGFloat result; |
110 |
if ([groups count] > 0 && indexPath.row < [groups count]) { |
|
111 |
NSString *groupName = [[groups allKeys] objectAtIndex:indexPath.row]; |
|
112 |
NSString *groupUsers = [groups objectForKey:groupName]; |
|
113 |
result = 22.0 + [[NSString stringWithFormat:@"%@", groupUsers] sizeWithFont:[UIFont systemFontOfSize:18.0] |
|
148 |
if (indexPath.row < groups.count) { |
|
149 |
NSString *groupName = [[[groups allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] objectAtIndex:indexPath.row]; |
|
150 |
result = 22.0 + [[self groupUsersStringForGroupName:groupName] sizeWithFont:[UIFont systemFontOfSize:18.0] |
|
114 | 151 |
constrainedToSize:(([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) ? |
115 | 152 |
CGSizeMake(596.0, 9000.0) : |
116 | 153 |
CGSizeMake(280.0, 9000.0)) |
... | ... | |
123 | 160 |
|
124 | 161 |
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { |
125 | 162 |
static NSString *CellIdentifier = @"Cell"; |
126 |
|
|
127 | 163 |
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; |
128 | 164 |
if (cell == nil) { |
129 | 165 |
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease]; |
130 | 166 |
} |
131 | 167 |
|
132 | 168 |
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; |
133 |
if (indexPath.row < [groups count]) {
|
|
134 |
NSString *groupName = [[groups allKeys] objectAtIndex:indexPath.row];
|
|
169 |
if (indexPath.row < groups.count) {
|
|
170 |
NSString *groupName = [[[groups allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] objectAtIndex:indexPath.row];
|
|
135 | 171 |
cell.textLabel.text = groupName; |
136 |
cell.detailTextLabel.text = [groups objectForKey:groupName];
|
|
172 |
cell.detailTextLabel.text = [self groupUsersStringForGroupName:groupName];
|
|
137 | 173 |
cell.detailTextLabel.numberOfLines = 0; |
138 | 174 |
cell.detailTextLabel.lineBreakMode = UILineBreakModeCharacterWrap; |
139 | 175 |
} else { |
... | ... | |
152 | 188 |
vc.account = self.account; |
153 | 189 |
vc.metadata = metadata; |
154 | 190 |
vc.groups = groups; |
155 |
if (indexPath.row < [groups count]) { |
|
156 |
NSString *groupName = [[groups allKeys] objectAtIndex:indexPath.row]; |
|
157 |
NSString *groupUsers = [groups objectForKey:groupName]; |
|
158 |
|
|
191 |
if (indexPath.row < groups.count) { |
|
192 |
NSString *groupName = [[[groups allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] objectAtIndex:indexPath.row]; |
|
159 | 193 |
vc.removeGroupEnabled = YES; |
160 | 194 |
vc.groupName = groupName; |
161 |
vc.groupUsers = groupUsers; |
|
162 | 195 |
vc.navigationItem.title = @"Edit Group"; |
163 | 196 |
} else { |
164 | 197 |
vc.removeGroupEnabled = NO; |
165 | 198 |
vc.groupName = @""; |
166 |
vc.groupUsers = @""; |
|
167 | 199 |
vc.navigationItem.title = @"Add Group"; |
168 | 200 |
} |
169 | 201 |
|
b/Classes/EditAccountGroupsViewController.h | ||
---|---|---|
40 | 40 |
@interface EditAccountGroupsViewController : UITableViewController <UITextFieldDelegate> { |
41 | 41 |
OpenStackAccount *account; |
42 | 42 |
NSString *groupName; |
43 |
NSString *groupUsers; |
|
44 | 43 |
NSMutableDictionary *groups; |
45 | 44 |
NSMutableDictionary *metadata; |
46 | 45 |
|
47 | 46 |
BOOL removeGroupEnabled; |
47 |
NSArray *groupUUIDs; |
|
48 |
UITextField *groupNameTextField; |
|
49 |
NSMutableDictionary *groupUsersTextFields; |
|
50 |
NSInteger numberOfGroupUsersRows; |
|
48 | 51 |
} |
49 | 52 |
|
50 | 53 |
@property (nonatomic, retain) OpenStackAccount *account; |
51 | 54 |
@property (nonatomic, retain) NSString *groupName; |
52 |
@property (nonatomic, retain) NSString *groupUsers; |
|
53 | 55 |
@property (nonatomic, retain) NSMutableDictionary *groups; |
54 | 56 |
@property (nonatomic, retain) NSMutableDictionary *metadata; |
55 |
@property (nonatomic) BOOL removeGroupEnabled; |
|
57 |
|
|
58 |
@property (nonatomic, assign) BOOL removeGroupEnabled; |
|
59 |
@property (nonatomic, retain) NSArray *groupUUIDs; |
|
60 |
@property (nonatomic, retain) UITextField *groupNameTextField; |
|
61 |
@property (nonatomic, retain) NSMutableDictionary *groupUsersTextFields; |
|
62 |
@property (nonatomic, assign) NSInteger numberOfGroupUsersRows; |
|
56 | 63 |
|
57 | 64 |
@end |
b/Classes/EditAccountGroupsViewController.m | ||
---|---|---|
43 | 43 |
#import "OpenStackRequest.h" |
44 | 44 |
#import "APICallback.h" |
45 | 45 |
|
46 |
#define kGroupDetails 0 |
|
47 |
#define kSave 1 |
|
48 |
#define kRemove 2 |
|
46 |
#define kGroupName 0 |
|
47 |
#define kGroupUsers 1 |
|
48 |
#define kSave 2 |
|
49 |
#define kRemove 3 |
|
49 | 50 |
|
50 | 51 |
@implementation EditAccountGroupsViewController |
51 | 52 |
|
52 |
@synthesize account; |
|
53 |
@synthesize groupName, groupUsers, removeGroupEnabled; |
|
54 |
@synthesize groups,metadata; |
|
53 |
@synthesize account, groupName, groups, metadata; |
|
54 |
@synthesize removeGroupEnabled, groupUUIDs, groupNameTextField, groupUsersTextFields, numberOfGroupUsersRows; |
|
55 | 55 |
|
56 | 56 |
#pragma mark - View lifecycle |
57 | 57 |
|
... | ... | |
59 | 59 |
return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait); |
60 | 60 |
} |
61 | 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 |
|
|
62 | 75 |
#pragma mark - Memory management |
63 | 76 |
|
64 | 77 |
- (void)dealloc { |
65 |
[groupName release]; |
|
66 |
[groupUsers release]; |
|
67 | 78 |
[account release]; |
68 |
[metadata release];
|
|
79 |
[groupName release];
|
|
69 | 80 |
[groups release]; |
81 |
[metadata release]; |
|
82 |
[groupUUIDs release]; |
|
83 |
[groupNameTextField release]; |
|
84 |
[groupUsersTextFields release]; |
|
70 | 85 |
[super dealloc]; |
71 | 86 |
} |
72 | 87 |
|
73 | 88 |
#pragma mark - Internal |
74 | 89 |
|
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]];
|
|
90 |
- (BOOL)groupNameIsValid:(NSString *)input {
|
|
91 |
if (!input.length) {
|
|
92 |
[self alert:@"Invalid input" message:@"Group name cannot be empty."];
|
|
78 | 93 |
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]]; |
|
94 |
} else if ([input rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"=,;"]].location != NSNotFound) { |
|
95 |
[self alert:@"Invalid input" message:@"Group name cannot contain '=', ',' or ';'."]; |
|
83 | 96 |
return NO; |
84 | 97 |
} |
85 | 98 |
return YES; |
86 | 99 |
} |
87 | 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 |
|
|
88 | 110 |
#pragma mark - UITableViewDataSource |
89 | 111 |
|
90 | 112 |
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { |
91 |
if (removeGroupEnabled) |
|
92 |
return 3; |
|
93 |
else |
|
94 |
return 2; |
|
113 |
return (removeGroupEnabled ? 4 : 3); |
|
95 | 114 |
} |
96 | 115 |
|
97 | 116 |
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { |
98 |
if (section == kGroupDetails) |
|
99 |
return 2; |
|
100 |
else |
|
101 |
return 1; |
|
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; |
|
102 | 159 |
} |
103 | 160 |
|
104 | 161 |
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { |
105 |
static NSString *CellIdentifier = @"Cell"; |
|
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 |
} |
|
106 | 180 |
|
181 |
static NSString *CellIdentifier = @"Cell"; |
|
107 | 182 |
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; |
108 | 183 |
if (cell == nil) { |
109 | 184 |
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; |
110 | 185 |
} |
111 |
|
|
112 |
cell.textLabel.text = @""; |
|
113 | 186 |
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 | 187 |
|
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]; |
|
188 |
if ((indexPath.section == kGroupUsers) && (indexPath.row == numberOfGroupUsersRows - 1)) { |
|
189 |
cell.textLabel.text = @"Add User"; |
|
190 |
cell.selectionStyle = UITableViewCellSelectionStyleBlue; |
|
150 | 191 |
} else if (indexPath.section == kSave) { |
151 |
cell.textLabel.text = @"Save"; |
|
192 |
cell.textLabel.text = @"Save Group"; |
|
193 |
cell.selectionStyle = UITableViewCellSelectionStyleBlue; |
|
152 | 194 |
} else if (indexPath.section == kRemove) { |
153 |
cell.textLabel.text = @"Remove"; |
|
195 |
cell.textLabel.text = @"Remove Group"; |
|
196 |
cell.selectionStyle = UITableViewCellSelectionStyleBlue; |
|
154 | 197 |
} |
155 | 198 |
|
156 | 199 |
return cell; |
... | ... | |
159 | 202 |
#pragma mark - UITableViewDelegate |
160 | 203 |
|
161 | 204 |
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { |
162 |
NSIndexPath *keyCellIndexPath; |
|
163 |
NSIndexPath *valueCellIndexPath; |
|
164 |
UITableViewCell *cell; |
|
165 |
|
|
166 |
if (indexPath.section != kGroupDetails) |
|
205 |
if (((indexPath.section == kGroupUsers) && (indexPath.row == numberOfGroupUsersRows - 1)) || |
|
206 |
(indexPath.section == kSave) || (indexPath.section == kRemove)) |
|
167 | 207 |
[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 | 208 |
|
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"]) {
|
|
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]) {
|
|
186 | 215 |
[self.tableView deselectRowAtIndexPath:indexPath animated:YES]; |
187 |
return; |
|
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 removeFromSuperview]; |
|
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 removeFromSuperview]; |
|
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 removeFromSuperview]; |
|
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 removeFromSuperview]; |
|
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 removeFromSuperview]; |
|
275 |
[self.tableView deselectRowAtIndexPath:indexPath animated:YES]; |
|
276 |
[self alert:@"There was a problem checking the users." request:request]; |
|
277 |
}]; |
|
278 |
} |
|
188 | 279 |
} |
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 | 280 |
} else if (indexPath.section == kRemove) { |
217 | 281 |
[groups removeObjectForKey:groupName]; |
218 |
NSDictionary *accountInfo = [NSDictionary dictionaryWithObjectsAndKeys:groups, @"groups", |
|
219 |
metadata, @"metadata", |
|
220 |
nil |
|
221 |
]; |
|
222 | 282 |
__block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Removing group..." |
223 | 283 |
andAddToView:self.view]; |
224 |
[[self.account.manager writeAccountMetadata:accountInfo] |
|
284 |
[[self.account.manager writeAccountMetadata:[NSDictionary dictionaryWithObjectsAndKeys: |
|
285 |
[self groupsInfoForGroups:groups], @"groups", |
|
286 |
metadata, @"metadata", |
|
287 |
nil]] |
|
225 | 288 |
success:^(OpenStackRequest *request) { |
226 |
[activityIndicatorView removeFromSuperview]; |
|
227 | 289 |
self.groupName = @""; |
228 |
self.groupUsers = @""; |
|
229 |
self.removeGroupEnabled = NO; |
|
230 |
[self.tableView reloadData]; |
|
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 removeFromSuperview]; |
|
231 | 296 |
[self.tableView deselectRowAtIndexPath:indexPath animated:YES]; |
297 |
[self.tableView reloadData]; |
|
232 | 298 |
} |
233 | 299 |
failure:^(OpenStackRequest *request) { |
300 |
if (groupUUIDs.count) { |
|
301 |
[groups setObject:groupUUIDs forKey:groupName]; |
|
302 |
} |
|
234 | 303 |
[activityIndicatorView removeFromSuperview]; |
235 |
[groups setObject:groupUsers forKey:groupName]; |
|
236 | 304 |
[self.tableView deselectRowAtIndexPath:indexPath animated:YES]; |
237 |
[self alert:@"There was a problem removing the group information." request:request];
|
|
305 |
[self alert:@"There was a problem removing the group." request:request]; |
|
238 | 306 |
}]; |
239 | 307 |
} |
240 | 308 |
} |
... | ... | |
242 | 310 |
#pragma mark - UITextFieldDelegate |
243 | 311 |
|
244 | 312 |
- (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"]; |
|
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) { |
|
253 | 319 |
[textField resignFirstResponder]; |
254 |
} |
|
255 |
|
|
320 |
} else { |
|
321 |
[[groupUsersTextFields objectForKey:[NSIndexPath indexPathForRow:(textField.tag + 1) inSection:kGroupUsers]] becomeFirstResponder]; |
|
322 |
} |
|
256 | 323 |
return YES; |
257 | 324 |
} |
258 | 325 |
|
b/Classes/EditPermissionsViewController.h | ||
---|---|---|
35 | 35 |
// interpreted as representing official policies, either expressed |
36 | 36 |
// or implied, of GRNET S.A. |
37 | 37 |
|
38 |
@class FolderViewController, OpenStackRequest, OpenStackAccount, Container, StorageObject;
|
|
38 |
@class FolderViewController, OpenStackAccount, Container, StorageObject; |
|
39 | 39 |
|
40 | 40 |
@interface EditPermissionsViewController : UITableViewController <UITextFieldDelegate, UIAlertViewDelegate> { |
41 | 41 |
OpenStackAccount *account; |
b/Classes/EditPermissionsViewController.m | ||
---|---|---|
102 | 102 |
} |
103 | 103 |
|
104 | 104 |
- (void)applyPermissions { |
105 |
[self.permissions removeObjectForKey:permissionUser];
|
|
105 |
[permissions removeObjectForKey:permissionUser]; |
|
106 | 106 |
NSString *newPermissionUser = ((groupTextField.text && groupTextField.text.length) ? |
107 | 107 |
[NSString stringWithFormat:@"%@:%@", currentUUID, groupTextField.text] : |
108 | 108 |
currentUUID); |
109 | 109 |
[permissions setObject:(writePermissionSelected ? @"write" : @"read") forKey:newPermissionUser]; |
110 | 110 |
self.oldSharing = object.sharing; |
111 | 111 |
[object setPermissions:permissions]; |
112 |
__block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Applying permissions..."
|
|
113 |
andAddToView:self.view];
|
|
114 |
[[self.account.manager writeObjectMetadata:container object:object]
|
|
115 |
success:^(OpenStackRequest *request) {
|
|
116 |
self.permissionUser = newPermissionUser;
|
|
112 |
__block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Applying permissions..." |
|
113 |
andAddToView:self.view]; |
|
114 |
[[self.account.manager writeObjectMetadata:container object:object] |
|
115 |
success:^(OpenStackRequest *request) { |
|
116 |
self.permissionUser = newPermissionUser; |
|
117 | 117 |
|
118 |
[activityIndicatorView removeFromSuperview];
|
|
119 |
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
|
|
120 |
if (!removePermissionsEnabled) {
|
|
121 |
removePermissionsEnabled = YES;
|
|
122 |
[self.tableView reloadData];
|
|
123 |
}
|
|
124 |
|
|
125 |
if (objectIsFolder || (account.shared && ![oldSharing isEqualToString:object.sharing])) { |
|
126 |
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
|
|
127 |
[self.folderViewController refreshButtonPressed:nil];
|
|
128 |
} else {
|
|
129 |
self.folderViewController.needsRefreshing = YES;
|
|
130 |
self.folderViewController.refreshWhenAppeared = YES;
|
|
131 |
}
|
|
118 |
[activityIndicatorView removeFromSuperview]; |
|
119 |
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES]; |
|
120 |
if (!removePermissionsEnabled) { |
|
121 |
removePermissionsEnabled = YES; |
|
122 |
self.navigationItem.title = @"Edit Permission";
|
|
123 |
[self.tableView reloadData];
|
|
124 |
} |
|
125 |
|
|
126 |
if (objectIsFolder || (account.shared && ![oldSharing isEqualToString:object.sharing])) {
|
|
127 |
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
|
|
128 |
[self.folderViewController refreshButtonPressed:nil];
|
|
129 |
} else {
|
|
130 |
self.folderViewController.needsRefreshing = YES;
|
|
131 |
self.folderViewController.refreshWhenAppeared = YES;
|
|
132 | 132 |
} |
133 | 133 |
} |
134 |
failure:^(OpenStackRequest *request) {
|
|
135 |
object.sharing = self.oldSharing;
|
|
136 |
self.permissions = object.permissions;
|
|
137 |
[activityIndicatorView removeFromSuperview];
|
|
138 |
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
|
|
139 |
[self alert:@"There was a problem applying the permissions." request:request];
|
|
140 |
}];
|
|
141 |
|
|
134 |
}
|
|
135 |
failure:^(OpenStackRequest *request) {
|
|
136 |
object.sharing = self.oldSharing;
|
|
137 |
self.permissions = object.permissions;
|
|
138 |
[activityIndicatorView removeFromSuperview];
|
|
139 |
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
|
|
140 |
[self alert:@"There was a problem applying the permissions." request:request];
|
|
141 |
}]; |
|
142 | 142 |
} |
143 | 143 |
|
144 | 144 |
- (void)createNewFolder { |
... | ... | |
201 | 201 |
if (indexPath.row == 0) { |
202 | 202 |
if (!userTextField) { |
203 | 203 |
self.userTextField = [self textFieldForCell:cell]; |
204 |
userTextField.returnKeyType = UIReturnKeyNext; |
|
204 | 205 |
userTextField.placeholder = @"User"; |
205 | 206 |
NSRange rangeOfColumn = [permissionUser rangeOfString:@":"]; |
206 | 207 |
userTextField.text = [self.account displaynameForUUID:((rangeOfColumn.location == NSNotFound) ? permissionUser : [permissionUser substringToIndex:rangeOfColumn.location]) |
... | ... | |
211 | 212 |
} else if (indexPath.row == 1) { |
212 | 213 |
if (!groupTextField) { |
213 | 214 |
self.groupTextField = [self textFieldForCell:cell]; |
215 |
groupTextField.returnKeyType = UIReturnKeyDefault; |
|
214 | 216 |
groupTextField.placeholder = @"Group (optional)"; |
215 | 217 |
NSRange rangeOfColumn = [permissionUser rangeOfString:@":"]; |
216 | 218 |
groupTextField.text = ((rangeOfColumn.location == NSNotFound) || (rangeOfColumn.location == permissionUser.length - 1)) ? nil : [permissionUser substringFromIndex:(rangeOfColumn.location + 1)]; |
... | ... | |
222 | 224 |
} |
223 | 225 |
|
224 | 226 |
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ |
227 |
if (indexPath.section == kUser) { |
|
228 |
static NSString *CellIdentifier = @"TextFieldCell"; |
|
229 |
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; |
|
230 |
if (cell == nil) { |
|
231 |
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; |
|
232 |
} |
|
233 |
cell.textLabel.text = nil; |
|
234 |
cell.accessoryType = UITableViewCellAccessoryNone; |
|
235 |
cell.selectionStyle = UITableViewCellSelectionStyleNone; |
|
236 |
for (UIView *view in cell.contentView.subviews) { |
|
237 |
[view removeFromSuperview]; |
|
238 |
} |
|
239 |
[cell.contentView addSubview:[self textFieldForCell:cell withIndexPath:indexPath]]; |
|
240 |
return cell; |
|
241 |
} |
|
242 |
|
|
225 | 243 |
static NSString *CellIdentifier = @"Cell"; |
226 | 244 |
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; |
227 | 245 |
if (cell == nil) { |
228 | 246 |
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; |
229 | 247 |
} |
230 | 248 |
|
231 |
if (indexPath.section == kUser) { |
|
232 |
[cell.contentView addSubview:[self textFieldForCell:cell withIndexPath:indexPath]]; |
|
233 |
cell.selectionStyle = UITableViewCellSelectionStyleNone; |
|
234 |
} else if (indexPath.section == kPermissions) { |
|
249 |
if (indexPath.section == kPermissions) { |
|
235 | 250 |
if (indexPath.row == 0) { |
236 | 251 |
cell.textLabel.text = @"Read Only"; |
237 | 252 |
cell.accessoryType = (readPermissionSelected ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone); |
... | ... | |
261 | 276 |
if (indexPath.section != kUser) |
262 | 277 |
[self.view endEditing:YES]; |
263 | 278 |
|
264 |
if (![self userIsValid:userTextField.text] || ![self groupIsValid:groupTextField.text]) { |
|
265 |
[self.tableView deselectRowAtIndexPath:indexPath animated:YES]; |
|
266 |
} else if (indexPath.section == kPermissions) { |
|
279 |
if (indexPath.section == kPermissions) { |
|
267 | 280 |
if ((indexPath.row == 0) && !readPermissionSelected) { |
268 | 281 |
readPermissionSelected = YES; |
269 | 282 |
if (writePermissionSelected) { |
... | ... | |
280 | 293 |
writePermissionsCell.accessoryType = UITableViewCellAccessoryCheckmark; |
281 | 294 |
} |
282 | 295 |
} else if (indexPath.section == kSavePermissions) { |
283 |
if (!readPermissionSelected && !writePermissionSelected) { |
|
296 |
if (![self userIsValid:userTextField.text] || ![self groupIsValid:groupTextField.text]) { |
|
297 |
[self.tableView deselectRowAtIndexPath:indexPath animated:YES]; |
|
298 |
} else if (!readPermissionSelected && !writePermissionSelected) { |
|
284 | 299 |
[self alert:@"Cannot save permissions" message:@"Please select a permission type."]; |
285 | 300 |
[self.tableView deselectRowAtIndexPath:indexPath animated:YES]; |
286 | 301 |
} else { |
... | ... | |
333 | 348 |
self.readPermissionSelected = FALSE; |
334 | 349 |
self.writePermissionSelected = FALSE; |
335 | 350 |
removePermissionsEnabled = NO; |
351 |
self.navigationItem.title = @"Add Permission"; |
|
336 | 352 |
[self.tableView reloadData]; |
337 | 353 |
|
338 | 354 |
if (objectIsFolder || (account.shared && ![oldSharing isEqualToString:object.sharing])) { |
... | ... | |
358 | 374 |
|
359 | 375 |
- (BOOL)textFieldShouldReturn:(UITextField *)textField { |
360 | 376 |
if (textField == userTextField) { |
361 |
[self userIsValid:textField.text]; |
|
377 |
if (![self userIsValid:textField.text]) { |
|
378 |
return NO; |
|
379 |
} |
|
380 |
[groupTextField becomeFirstResponder]; |
|
362 | 381 |
} else if (textField == groupTextField) { |
363 |
[self groupIsValid:textField.text]; |
|
382 |
if (![self groupIsValid:textField.text]) { |
|
383 |
return NO; |
|
384 |
} |
|
385 |
[groupTextField resignFirstResponder]; |
|
364 | 386 |
} |
365 |
[textField resignFirstResponder]; |
|
366 | 387 |
return YES; |
367 | 388 |
} |
368 | 389 |
|
b/Classes/FolderDetailViewController.m | ||
---|---|---|
348 | 348 |
if (indexPath.row == permissions.count) { |
349 | 349 |
user = @""; |
350 | 350 |
vc.removePermissionsEnabled = NO; |
351 |
vc.navigationItem.title = @"Share";
|
|
351 |
vc.navigationItem.title = @"Add Permission";
|
|
352 | 352 |
} else { |
353 | 353 |
user = [[[permissions allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] objectAtIndex:indexPath.row]; |
354 | 354 |
NSString *userPermissions = [permissions objectForKey:user]; |
... | ... | |
363 | 363 |
vc.writePermissionSelected = NO; |
364 | 364 |
} |
365 | 365 |
vc.removePermissionsEnabled = YES; |
366 |
vc.navigationItem.title = @"Edit Sharing";
|
|
366 |
vc.navigationItem.title = @"Edit Permission";
|
|
367 | 367 |
} |
368 | 368 |
|
369 | 369 |
vc.permissionUser = user; |
b/Classes/OpenStackRequest.m | ||
---|---|---|
56 | 56 |
NSMutableString *dataString = [NSMutableString stringWithString:@"{\"displaynames\":["]; |
57 | 57 |
if (displaynames) { |
58 | 58 |
for (NSUInteger index = 0 ; index < displaynames.count ; index++) { |
59 |
[dataString appendFormat:@"\"%@\"%@", [displaynames objectAtIndex:index], ((index == displaynames.count - 1) ? @"" : @",")]; |
|
59 |
[dataString appendFormat:@"\"%@\"%@", |
|
60 |
[[[displaynames objectAtIndex:index] stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"] |
|
61 |
stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""], |
|
62 |
((index == displaynames.count - 1) ? @"" : @",")]; |
|
60 | 63 |
} |
61 | 64 |
} |
62 | 65 |
[dataString appendFormat:@"],\"uuids\":["]; |
... | ... | |
133 | 136 |
OpenStackRequest *request = [self filesRequest:account method:@"POST" path:@""]; |
134 | 137 |
|
135 | 138 |
NSMutableDictionary *groups = [accountInfo objectForKey:@"groups"]; |
136 |
for (NSString *groupName in groups) {
|
|
137 |
NSString *group = [NSString encodeToPercentEscape:[groups objectForKey:groupName]];
|
|
138 |
groupName = [NSString encodeToPercentEscape:groupName];
|
|
139 |
[request.requestHeaders setObject:group forKey:[NSString stringWithFormat:@"X-Account-Group-%@", groupName]];
|
|
140 |
} |
|
141 |
if ([groups count] == 0)
|
|
139 |
if (groups.count) {
|
|
140 |
for (NSString *groupName in groups) {
|
|
141 |
[request.requestHeaders setObject:[NSString encodeToPercentEscape:[groups objectForKey:groupName]]
|
|
142 |
forKey:[NSString stringWithFormat:@"X-Account-Group-%@", [NSString encodeToPercentEscape:groupName]]];
|
|
143 |
}
|
|
144 |
} else {
|
|
142 | 145 |
[request.requestHeaders setObject:@"" forKey:@"X-Account-Group-group"]; |
146 |
} |
|
143 | 147 |
|
144 |
NSMutableDictionary *accountMetadata = [accountInfo objectForKey:@"metadata"]; |
|
145 |
for (NSString *metadataKey in accountMetadata) { |
|
146 |
NSString *metadataValue = [NSString encodeToPercentEscape:[accountMetadata objectForKey:metadataKey]]; |
|
147 |
metadataKey = [NSString encodeToPercentEscape:[accountMetadata objectForKey:metadataKey]]; |
|
148 |
[request.requestHeaders setObject:metadataValue forKey:[NSString stringWithFormat:@"X-Account-Meta-%@",metadataKey]]; |
|
148 |
NSMutableDictionary *metadata = [accountInfo objectForKey:@"metadata"]; |
|
149 |
for (NSString *key in metadata) { |
|
150 |
[request.requestHeaders setObject:[NSString encodeToPercentEscape:[metadata objectForKey:key]] |
|
151 |
forKey:[NSString stringWithFormat:@"X-Account-Meta-%@", [NSString encodeToPercentEscape:key]]]; |
|
149 | 152 |
} |
150 | 153 |
|
151 | 154 |
return request; |
b/Classes/StorageObject.m | ||
---|---|---|
163 | 163 |
} |
164 | 164 |
} |
165 | 165 |
} |
166 |
if (readSharingList && writeSharingList) { |
|
167 |
self.sharing = [NSString stringWithFormat:@"%@;%@", readSharingList, writeSharingList]; |
|
168 |
} else if (readSharingList) { |
|
169 |
self.sharing = readSharingList; |
|
166 |
if (readSharingList) { |
|
167 |
if (writeSharingList) { |
|
168 |
self.sharing = [NSString stringWithFormat:@"%@;%@", readSharingList, writeSharingList]; |
|
169 |
} else { |
|
170 |
self.sharing = readSharingList; |
|
171 |
} |
|
170 | 172 |
} else if (writeSharingList) { |
171 | 173 |
self.sharing = writeSharingList; |
174 |
} else { |
|
175 |
self.sharing = @""; |
|
172 | 176 |
} |
173 | 177 |
} |
174 | 178 |
|
b/Classes/StorageObjectViewController.m | ||
---|---|---|
155 | 155 |
} |
156 | 156 |
|
157 | 157 |
- (void)viewDidAppear:(BOOL)animated { |
158 |
if (object.metadata == nil) { |
|
158 |
[super viewDidAppear:animated]; |
|
159 |
if (!object.metadata) { |
|
159 | 160 |
[self reloadMetadataSection]; |
160 | 161 |
} else { |
161 | 162 |
[self updatePermissionsUserCatalog]; |
... | ... | |
289 | 290 |
|
290 | 291 |
- (void)updatePermissionsUserCatalog { |
291 | 292 |
NSMutableArray *UUIDs = [NSMutableArray arrayWithCapacity:permissions.count]; |
292 |
for (NSString *user in [permissions allKeys]) {
|
|
293 |
for (NSString *user in permissions) {
|
|
293 | 294 |
NSRange rangeOfColumn = [user rangeOfString:@":"]; |
294 | 295 |
NSString *UUID = (rangeOfColumn.location == NSNotFound) ? user : [user substringToIndex:rangeOfColumn.location]; |
295 | 296 |
if (![UUID isEqualToString:@"*"]) { |
... | ... | |
306 | 307 |
} |
307 | 308 |
failure:^(OpenStackRequest *request) { |
308 | 309 |
[activityIndicatorView removeFromSuperview]; |
310 |
[self alert:@"Failed to translate sharing UUIDs." request:request]; |
|
309 | 311 |
}]; |
310 | 312 |
} |
311 | 313 |
} |
... | ... | |
674 | 676 |
if (indexPath.row == permissions.count) { |
675 | 677 |
user = @""; |
676 | 678 |
vc.removePermissionsEnabled = NO; |
677 |
vc.navigationItem.title = @"Share";
|
|
679 |
vc.navigationItem.title = @"Add Permission";
|
|
678 | 680 |
} else { |
679 | 681 |
user = [[[permissions allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] objectAtIndex:indexPath.row]; |
680 | 682 |
NSString *userPermissions = [permissions objectForKey:user]; |
... | ... | |
689 | 691 |
vc.writePermissionSelected = NO; |
690 | 692 |
} |
691 | 693 |
vc.removePermissionsEnabled = YES; |
692 |
vc.navigationItem.title = @"Edit Sharing";
|
|
694 |
vc.navigationItem.title = @"Edit Permission";
|
|
693 | 695 |
} |
694 | 696 |
|
695 | 697 |
vc.permissionUser = user; |
b/OpenStack-Info.plist | ||
---|---|---|
41 | 41 |
<key>CFBundlePackageType</key> |
42 | 42 |
<string>APPL</string> |
43 | 43 |
<key>CFBundleShortVersionString</key> |
44 |
<string>1.5.1</string>
|
|
44 |
<string>1.6</string>
|
|
45 | 45 |
<key>CFBundleSignature</key> |
46 | 46 |
<string>????</string> |
47 | 47 |
<key>CFBundleURLTypes</key> |
... | ... | |
56 | 56 |
</dict> |
57 | 57 |
</array> |
58 | 58 |
<key>CFBundleVersion</key> |
59 |
<string>20130122.0</string>
|
|
59 |
<string>20130203.2</string>
|
|
60 | 60 |
<key>LSRequiresIPhoneOS</key> |
61 | 61 |
<true/> |
62 | 62 |
<key>NSMainNibFile</key> |
Also available in: Unified diff