Developer Area

root/apps/iphone/my.tel/trunk/Classes/RecordEditController.m @ 424

Revision 424, 15.9 kB (checked in by henri, 5 years ago)

Support for private subdomain links

Line 
1//
2//  RecordEditController.m
3//  VIP.tel
4//
5//  Created by Henri Asseily on 11/21/08.
6//  Copyright 2008 Telnic Ltd.. All rights reserved.
7//
8// TODO: NTN labels
9// (check with engineers first)
10
11#import "RecordEditController.h"
12
13#define kRTransitionDuration    0.3
14
15#define kNTNLabelLength 100             // NTN label length             TODO: verify with engineers
16#define kTLabelLength 20                // Terminal label length
17
18@implementation RecordEditController
19
20@synthesize barHeader;
21@synthesize barButtonSave;
22@synthesize rPicker;
23@synthesize rValue;
24@synthesize rLabel;
25@synthesize rVisibility;
26@synthesize buttonPrivacy;
27@synthesize delegate;
28
29#pragma mark ----- Calling methods
30
31- (void)presentViewForRecord:(NSDictionary *)aRec {
32        [theRecord release];
33        if (!aRec) { // new
34                barHeader.title = @"New Item";
35                rValue.text = @"";
36                rLabel.text = @"";
37                rVisibility.on = TRUE;
38                theRecord = [[NSMutableDictionary dictionaryWithObjectsAndKeys:
39                                         @"0",                                                                                  @"apiId",
40                                         [VIPConnect sharedInstance].selectedDomain,    @"domainName",
41                                         [NSArray arrayWithObject:@"voice"],                    @"serviceKeys",
42                                         @"",                                                                                   @"label",
43                                         [NSArray array],                                                               @"locations",
44                                         [NSArray array],                                                               @"profiles",
45                                         [NSArray array],                                                               @"groups",
46                                          @"1",                                                                                 @"terminal",
47                                         nil] retain];
48        } else { // edit
49                theRecord = [[NSMutableDictionary dictionaryWithDictionary:aRec] retain];
50                barHeader.title = @"Edit Item";
51                [theRecord setObject:[VIPConnect sharedInstance].selectedDomain forKey:@"domainName"];
52                // An NTN may not have the below items
53                if ([[theRecord objectForKey:@"label"] isKindOfClass:[NSNull class]])
54                        [theRecord setObject:@"" forKey:@"label"];
55                if ([[theRecord objectForKey:@"locations"] isKindOfClass:[NSNull class]])
56                        [theRecord setObject:[NSArray array] forKey:@"locations"];
57                if ([[theRecord objectForKey:@"serviceKeys"] isKindOfClass:[NSNull class]]) {
58                        if ([[theRecord objectForKey:@"terminal"] integerValue] == 0) {
59                                [theRecord setObject:[NSArray arrayWithObject:@"ntn"] forKey:@"serviceKeys"];
60                        } else {
61                                [theRecord setObject:[NSArray arrayWithObject:@"voice"] forKey:@"serviceKeys"];
62                        }
63                }
64                if ([[theRecord objectForKey:@"profiles"] isKindOfClass:[NSNull class]])
65                        [theRecord setObject:[NSArray array] forKey:@"profiles"];
66                if ([[theRecord objectForKey:@"groups"] isKindOfClass:[NSNull class]])
67                        [theRecord setObject:[NSArray array] forKey:@"groups"];
68               
69                rValue.text = [theRecord objectForKey:@"value"];
70                rLabel.text = [theRecord objectForKey:@"label"];
71                if ([(NSArray *)[theRecord objectForKey:@"profiles"] containsObject:[VIPConnect sharedInstance].selectedProfileId]) {
72                        rVisibility.on = TRUE;
73                } else {
74                        rVisibility.on = FALSE;
75                }
76        }
77        // We only respect the first LIH and service types.
78        NSString *theService = [(NSArray *)[theRecord objectForKey:@"serviceKeys"] objectAtIndex:0];
79        NSString *theLi;
80        if ([(NSArray *)[theRecord objectForKey:@"locations"] count] == 0) {
81                theLi = @"";
82        } else {
83                theLi = [(NSArray *)[theRecord objectForKey:@"locations"] objectAtIndex:0];
84        }
85       
86        [rPicker selectRow:[sArrKey indexOfObject:theService] inComponent:0 animated:NO];
87        [rPicker selectRow:[liArrKey indexOfObject:theLi] inComponent:1 animated:NO];
88        [self viewWillAppear:YES];
89        [self setStateForTerminal:[[theRecord objectForKey:@"terminal"] boolValue]];
90        // Insert our view at the absolute top
91        [[UIApplication sharedApplication].keyWindow addSubview:self.navigationController.view];
92        // Set up the animation
93    CATransition *animation = [CATransition animation];
94    [animation setDelegate:self];
95   
96        [animation setType:kCATransitionMoveIn];
97        [animation setSubtype:kCATransitionFromRight];
98   
99    // Set the duration and timing function of the transtion -- duration is passed in as a parameter, use ease in/ease out as the timing function
100    [animation setDuration:kRTransitionDuration];
101    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
102   
103    [[[UIApplication sharedApplication].keyWindow layer] addAnimation:animation forKey:@"kEditAnimation"];
104}
105
106- (void)setPickerCol1:(NSDictionary *)pickerData1 col2:(NSDictionary *)pickerData2 {
107        // Sets picker data and sorts the columns
108        NSUInteger i, count;
109
110        // Do first column
111        // First set the keys and related strings
112        [sArrKey setArray:[pickerData1 allKeys]];
113        [sArrVal removeAllObjects];
114        for (NSString *aK in sArrKey) {
115                [sArrVal addObject:[pickerData1 objectForKey:aK]];
116        }
117        // Create a reverse lookup to find the service keys from the strings
118        NSDictionary *pickerDict1 = [NSDictionary dictionaryWithObjects:sArrKey forKeys:sArrVal];
119        // Sort the string arrays as the picker strings
120        [sArrVal sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
121        // Resort the key arrays based on the strings arrays
122        count = [sArrVal count];
123        for (i = 0; i < count; i++) {
124                [sArrKey replaceObjectAtIndex:i
125                                                   withObject:[pickerDict1 objectForKey:[sArrVal objectAtIndex:i]]];
126        }
127        // and finally reload the picker component
128        [rPicker reloadComponent:0];
129       
130        // Same for second column, but also add a "None" entry
131        [liArrKey setArray:[pickerData2 allKeys]];
132        [liArrVal removeAllObjects];
133        for (NSString *aK in liArrKey) {
134                [liArrVal addObject:[pickerData2 objectForKey:aK]];
135        }
136        NSDictionary *pickerDict2 = [NSDictionary dictionaryWithObjects:liArrKey forKeys:liArrVal];
137        [liArrVal sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
138        count = [liArrVal count];
139        for (i = 0; i < count; i++) {
140                [liArrKey replaceObjectAtIndex:i
141                                                        withObject:[pickerDict2 objectForKey:[liArrVal objectAtIndex:i]]];
142        }
143        if ([(NSString *)[liArrKey objectAtIndex:0] length] != 0) {
144                // There isn't an "empty" choice, add it
145                [liArrKey insertObject:@"" atIndex:0];
146                [liArrVal insertObject:@"" atIndex:0];
147        }
148       
149        [rPicker reloadComponent:1];   
150}
151
152#pragma mark ------ Standard View Methods
153- (void)viewDidLoad {
154    [super viewDidLoad];
155        sArrKey = [[NSMutableArray arrayWithCapacity:30] retain];
156        sArrVal = [[NSMutableArray arrayWithCapacity:30] retain];
157        liArrKey = [[NSMutableArray arrayWithCapacity:10] retain];
158        liArrVal = [[NSMutableArray arrayWithCapacity:10] retain];
159        [buttonPrivacy setTitle:@" This item is public"
160                                   forState:UIControlStateDisabled];
161        [buttonPrivacy setTitleColor:[UIColor grayColor] forState:UIControlStateDisabled];
162}
163
164- (void)viewWillAppear:(BOOL)animated {
165        [self setStateForButtonPrivacy];
166}
167
168- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
169    // Return YES for supported orientations
170    return (interfaceOrientation == UIInterfaceOrientationPortrait);
171}
172
173
174- (void)didReceiveMemoryWarning {
175    [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
176    // Release anything that's not essential, such as cached data
177}
178
179
180- (void)dealloc {
181        [sArrKey release];
182        [sArrVal release];
183        [liArrKey release];
184        [liArrVal release];
185        [naptrValuePlaceholders release];
186    [super dealloc];
187}
188
189#pragma mark ------ Actions
190
191- (IBAction)didClickCancel:(id)sender {
192        [self slideViewForEditing:NO];
193        [self.navigationController.view removeFromSuperview];
194}
195
196- (IBAction)didClickSave:(id)sender {
197        // store value, label, profiles.
198        // servicekey and LI are set when the user selects the pickerViews
199        // apiId and domainName are set at the start in presentView
200        [theRecord setObject:rValue.text forKey:@"value"];
201        [theRecord setObject:rLabel.text forKey:@"label"];
202
203        VIPConnect *vipSI = [VIPConnect sharedInstance];
204        NSMutableArray *newProfilesArray = [NSMutableArray arrayWithArray:[theRecord objectForKey:@"profiles"]];
205        [newProfilesArray removeObjectIdenticalTo:vipSI.selectedProfileId];
206        if (rVisibility.on) {
207                [newProfilesArray addObject:vipSI.selectedProfileId];
208        }
209        [theRecord setObject:newProfilesArray forKey:@"profiles"];
210       
211        // Store the record
212        if ([rPicker numberOfRowsInComponent:1] == 0) { // ntn
213                [self storeNTNaptrRecord];
214        } else  {
215                [self storeRecord];
216        }       
217}
218
219- (IBAction)didClickPrivacy:(id)sender {
220        RecordGroupsController *rGC = [RecordGroupsController controllerForRecord:theRecord groups:nil];
221        rGC.delegate = self;
222        [self.navigationController pushViewController:rGC animated:YES];
223}
224
225#pragma mark ------ Data methods
226
227- (void)storeRecord {
228        /*
229         inputRecord = {
230         domainName: "cartman.tel",
231         apiId: 0,
232         serviceKeys: ["voice", "fax"],
233         value: "+34.34343443",
234         label: "my home number",
235         groups: [1, 2, 3],
236         profiles: [12, 23, 47],
237         locations: ["x-home", "x-mobile"]
238         };
239         
240         successResult = {
241         success: "true",
242         actionMessages: ["record stored successfully",
243         "2nd message here",
244         "3dmessage here"],
245         apiId: 17
246         };
247         */     
248        Record *conn = [[[Record alloc] init] autorelease];
249        [conn setTheDelegate:[VIPConnect sharedInstance]];
250        [conn setActionSel:@selector(doNothing:)];
251        [conn setConnectionUrl:[conn urlFromAction:@"storerecord"]];
252        [conn setPayload:theRecord];
253        NSDictionary *parsedJson = [conn performLookup:FALSE];
254       
255        if ([[parsedJson valueForKey:@"success"] integerValue] == 1) {
256                [delegate didStoreRecord:theRecord];
257                [self slideViewForEditing:NO];
258                [self.navigationController.view removeFromSuperview];
259        } else {
260                [JsonConnection throwJsonErrorAlert:parsedJson];
261        }       
262}
263
264- (void)storeNTNaptrRecord {
265        /*
266         inputRecord = {
267         domainName: "cartman.tel",
268         apiId: 0,
269         value: "test",
270         groups: [],
271         profiles: [],
272         globalProfile: true
273         };
274         
275         successResult = {
276         success: true,
277         actionMessages: ["record stored successfully",
278         "2nd message here",
279         "3dmessage here"],
280         apiId: 17
281         };     
282         */
283       
284        NSMutableDictionary *ntnRec = [NSMutableDictionary dictionaryWithDictionary:theRecord];
285        [ntnRec removeObjectForKey:@"locations"];
286        //[ntnRec setObject:[NSArray array] forKey:@"groups"];
287        [ntnRec setObject:[NSArray array] forKey:@"profiles"];
288        [ntnRec setValue:[NSNumber numberWithBool:TRUE] forKey:@"globalProfile"];
289       
290        if ([(NSString *)[ntnRec objectForKey:@"value"] hasSuffix:@".tel"]) {
291                // A fully qualified NTN has to end with a dot (".tel.")
292                [ntnRec setObject:[(NSString *)[ntnRec objectForKey:@"value"] stringByAppendingString:@"."]
293                                   forKey:@"value"];
294        }
295       
296        Record *conn = [[[Record alloc] init] autorelease];
297        [conn setTheDelegate:[VIPConnect sharedInstance]];
298        [conn setActionSel:@selector(doNothing:)];
299        [conn setConnectionUrl:[conn urlFromAction:@"storentnaptrrecord"]];
300        [conn setPayload:ntnRec];
301        NSDictionary *parsedJson = [conn performLookup:FALSE];
302       
303        if ([[parsedJson valueForKey:@"success"] integerValue] == 1) {
304                [delegate didStoreRecord:theRecord];
305                [self slideViewForEditing:NO];
306                [self.navigationController.view removeFromSuperview];
307        } else {
308                [JsonConnection throwJsonErrorAlert:parsedJson];
309        }       
310}
311
312#pragma mark ------ Utility methods
313
314- (void)setStateForTerminal:(BOOL)isTerminal {
315        // Disable label for now on ntn.
316        // TODO: re-enable when labels allowed for ntn
317        if (isTerminal) {
318                rLabel.placeholder = @"Short description";
319                rLabel.enabled = YES;
320                rVisibility.enabled = YES;
321                buttonPrivacy.enabled = YES;
322                [self setStateForButtonPrivacy];
323        } else {
324                rLabel.text = @"";
325                rLabel.enabled = NO;
326                rLabel.placeholder = @" -- disabled --";
327                rVisibility.on = YES;
328                rVisibility.enabled = NO;
329                buttonPrivacy.enabled = YES;    // TODO: See if privacy works for NTN
330                [self setStateForButtonPrivacy];
331        }
332        [self.view setNeedsLayout];
333        [self.view setNeedsDisplay];
334}
335
336- (void)setStateForButtonPrivacy {
337        NSUInteger numGroups = [(NSArray *)[theRecord objectForKey:@"groups"] count];
338        if (numGroups == 0) {
339                [buttonPrivacy setTitle:@" This item is public"
340                                           forState:(UIControlStateNormal & UIControlStateHighlighted)];
341        } else {
342                if (numGroups == 1)
343                        [buttonPrivacy setTitle:@" Member of 1 privacy group"
344                                                   forState:(UIControlStateNormal & UIControlStateHighlighted)];
345                else
346                        [buttonPrivacy setTitle:[NSString stringWithFormat:@" Member of %d privacy groups", numGroups]
347                                                   forState:(UIControlStateNormal & UIControlStateHighlighted)];
348        }
349}
350
351- (void)slideViewForEditing:(BOOL)isEditing {
352        if (isEditing) {
353                if (self.view.frame.origin.y >=0) {
354                        CGRect newFrame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y -220,
355                                                                                 self.view.frame.size.width, self.view.frame.size.height + 220);
356                        self.view.frame = newFrame;
357                }
358        } else {
359                if (self.view.frame.origin.y <0) {
360                        CGRect newFrame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y + 220,
361                                                                                 self.view.frame.size.width, self.view.frame.size.height - 220);
362                       
363                        self.view.frame = newFrame;
364                }
365        }
366}
367
368#pragma mark ------ RecordGroupsDelegate methods
369- (void)replaceGroupsForRecord:(NSDictionary *)aRecord withGroups:(NSArray *)groupsIdList {
370        [theRecord setObject:groupsIdList forKey:@"groups"];
371}
372
373#pragma mark ------ TextField delegate methods
374- (void)textFieldDidBeginEditing:(UITextField *)textField {
375        [self slideViewForEditing:YES];
376        return;
377}
378- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
379        return YES;
380}
381- (BOOL)textFieldShouldReturn:(UITextField *)textField {
382        [textField resignFirstResponder];
383        [self slideViewForEditing:NO];
384        return YES;
385}
386- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
387                                                                                        replacementString:(NSString *)string {
388        // Check length of fields. Terminal labels should be very short
389        if (textField == rLabel) {
390                if ([rPicker numberOfRowsInComponent:1] == 0) { // ntn
391                        if ((range.location + range.length) >= kNTNLabelLength)
392                                return NO;
393                } else {
394                        if ((range.location + range.length) >= kTLabelLength)
395                                return NO;
396                }
397        }
398        return YES;
399}
400
401#pragma mark ------ Picker data source methods
402
403- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
404        return 2;
405}
406
407- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
408        if (component == 0) {
409                return [sArrVal count];
410        }
411        if (component == 1) {
412                if (!self.navigationController.view.superview) {        // View hasn't been loaded yet, check for ntn directly from record
413                        if ([[theRecord objectForKey:@"terminal"] integerValue] == 0)
414                                return 0;
415                } else {
416                        if ([[sArrKey objectAtIndex:[rPicker selectedRowInComponent:0]] isEqualToString:@"ntn"] )       // ntn: disable locations
417                                return 0;
418                }
419                return [liArrVal count];
420        }
421        return 0;
422}
423
424#pragma mark ------ Picker delegate methods
425
426- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
427        if (component == 0) {
428                [theRecord setObject:[NSArray arrayWithObject:[sArrKey objectAtIndex:row]]
429                                          forKey:@"serviceKeys"];
430                // Set the placeholder text in the value field to a nice example
431                if (!naptrValuePlaceholders) {
432                        naptrValuePlaceholders = [NSDictionary dictionaryWithContentsOfFile:
433                                                                           [[NSBundle mainBundle] pathForResource:@"NaptrValuePlaceholders" ofType:@"plist"]];
434                }
435                rValue.placeholder = [naptrValuePlaceholders objectForKey:[sArrKey objectAtIndex:row]];
436                rValue.text = @"";
437                //  Synchronize the locations component for NTNs in service component
438                if ([[sArrKey objectAtIndex:row] isEqualToString:@"ntn"]) {
439                        if ([pickerView numberOfRowsInComponent:1] > 0) {
440                                [pickerView reloadComponent:1];
441                                [self setStateForTerminal:NO];
442                        }
443                } else {
444                        if ([pickerView numberOfRowsInComponent:1] == 0) {
445                                [pickerView reloadComponent:1];
446                                [self setStateForTerminal:YES];
447                        }
448                }
449        }
450        if (component == 1) {
451                if (row > -1) { // Not an ntn
452                        [theRecord setObject:[NSArray arrayWithObject:[liArrKey objectAtIndex:row]]
453                                                  forKey:@"locations"];
454                } else {
455                        // this shouldn't happen
456                        [theRecord removeObjectForKey:@"locations"];
457                }
458        }
459}
460
461/*
462- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component {
463}
464 */
465
466- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
467        if (component == 0) {
468                return 200;
469        }
470        if (component == 1) {
471                return 100;
472        }
473        return 0;
474}
475
476
477- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
478        if (component == 0) {
479                return [sArrVal objectAtIndex:row];
480        }
481        if (component == 1) {
482                return [liArrVal objectAtIndex:row];
483        }
484        return @"";
485}
486
487/*
488- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row
489                  forComponent:(NSInteger)component reusingView:(UIView *)view {
490}
491 */
492                               
493@end
Note: See TracBrowser for help on using the browser.
Telnic
Search This Site
Partners
Neustar
ICANN
Main site | WHOIS | Sell .tel | FAQ | Archived Site | About Telnic | Contact Us