RulesAddViewController.m 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129
  1. //
  2. // RulesAddViewController.m
  3. // kneet2
  4. //
  5. // Created by Jason Lee on 11/20/15.
  6. // Copyright © 2015 ntels. All rights reserved.
  7. //
  8. #import "JDObject.h"
  9. #import "RequestHandler.h"
  10. #import "ItemModel.h"
  11. #import "RuleModel.h"
  12. #import "DeviceModel.h"
  13. #import "CustomLabel.h"
  14. #import "CustomButton.h"
  15. #import "CustomImageView.h"
  16. #import "CustomTableView.h"
  17. #import "CustomCheckBox.h"
  18. #import "CustomTextView.h"
  19. #import "CustomTextField.h"
  20. #import "UIImageView+WebCache.h"
  21. #import "ValidateUtil.h"
  22. #import "DeviceSelectPopupView.h"
  23. #import "DeviceNodePopupView.h"
  24. #import "TriggerSelectPopupView.h"
  25. #import "RulesConditionViewController.h"
  26. #import "RulesAddViewController.h"
  27. #import "RulesAddCompleteViewController.h"
  28. #import "RulesDetailViewController.h"
  29. #import "RulesViewController.h"
  30. @implementation RulesAddTitleTableViewCell
  31. @end
  32. @implementation RulesAddHeaderTableViewCell
  33. @end
  34. @implementation RulesAddTableViewCell
  35. @end
  36. @implementation RulesAddPushTableViewCell
  37. @end
  38. @implementation RulesAddConditionHeaderTableViewCell
  39. @end
  40. @implementation RulesAddConditionTableViewCell
  41. @end
  42. @implementation RulesAddFooterTableViewCell
  43. @end
  44. @interface RulesAddViewController () <CustomTextViewDelegate> {
  45. NSMutableArray<ItemModel> *_triggerDevices, *_actionDevices, *_conditionDevices;
  46. BOOL _isNotFirstLoading, _hasCondition;
  47. NSMutableArray *_arrayForHeader, *_arrayForFooter;
  48. CustomTextField *_txtRuleTitle;
  49. CustomTextView *_txvMessage;
  50. CustomButton *_btnTriggerAdd, *_btnPushAdd;
  51. CustomCheckBox *_chkConditions;
  52. RulesConditionViewController *_rcv;
  53. }
  54. @property (strong, nonatomic) NSMutableArray<ItemModel> *triggers;
  55. @property (strong, nonatomic) NSMutableArray<ItemModel> *actions;
  56. @property (strong, nonatomic) NSMutableArray<ItemModel> *conditions;
  57. @end
  58. #pragma mark - Class Definition
  59. @implementation RulesAddViewController
  60. - (void)viewDidLoad {
  61. [super viewDidLoad];
  62. [self initProperties];
  63. [self initUI];
  64. [self prepareViewDidLoad];
  65. }
  66. - (void)cloneSubItemsForItemSubType:(NSArray<ItemModel> *)items {
  67. for (ItemModel *item in items) {
  68. if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeDevice]) {//디바이스일 경우,
  69. //기존 아이템을 그대로 사용함.
  70. for (ItemSubModel *subItem in item.subItems) {
  71. [[JDFacade facade] setRadioButtonStatus:@YES object:subItem];
  72. [[JDFacade facade] setCheckBoxStatus:@YES object:subItem];
  73. }
  74. } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeAppPush]) {//푸시일 경우,
  75. item.pushes = (NSMutableArray<ItemSubModel> *)[[NSMutableArray alloc] initWithArray:item.subItems copyItems:YES];
  76. item.subItems = nil;
  77. } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeTimer]) {//타이머일 경우,
  78. item.timers = (NSMutableArray<ItemSubModel> *)[[NSMutableArray alloc] initWithArray:item.subItems copyItems:YES];
  79. item.subItems = nil;
  80. } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeDaylight]) {//해뜰때/질때 경우,
  81. item.daylights = (NSMutableArray<ItemSubModel> *)[[NSMutableArray alloc] initWithArray:item.subItems copyItems:YES];
  82. item.subItems = nil;
  83. } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeHeat]) {//더울때/추울때 경우,
  84. item.heats = (NSMutableArray<ItemSubModel> *)[[NSMutableArray alloc] initWithArray:item.subItems copyItems:YES];
  85. item.subItems = nil;
  86. } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeMode]) {//더울때/추울때 경우,
  87. //기존 아이템을 그대로 사용함.
  88. }
  89. }
  90. }
  91. - (void)setRefRuleDetail:(RuleDetailModel *)refRuleDetail {
  92. _refRuleDetail = refRuleDetail;
  93. _triggers = (NSMutableArray<ItemModel> *)[[NSMutableArray alloc] initWithArray:_refRuleDetail.triggers copyItems:YES];
  94. _actions = (NSMutableArray<ItemModel> *)[[NSMutableArray alloc] initWithArray:_refRuleDetail.actions copyItems:YES];
  95. _conditions = (NSMutableArray<ItemModel> *)[[NSMutableArray alloc] initWithArray:_refRuleDetail.conditions copyItems:YES];
  96. [self cloneSubItemsForItemSubType:_triggers];
  97. [self cloneSubItemsForItemSubType:_actions];
  98. [self cloneSubItemsForItemSubType:_conditions];
  99. _hasCondition = [_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksConditionSubTypeCodeHomeMode];
  100. _hasCondition = [_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksConditionSubTypeCodeDueDate] ? YES : _hasCondition;
  101. _hasCondition = [_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice] ? YES : _hasCondition;
  102. }
  103. - (void)initProperties {
  104. _arrayForHeader = [[NSMutableArray alloc] init];
  105. _arrayForFooter = [[NSMutableArray alloc] init];
  106. if (!_triggers) {
  107. _triggers = (NSMutableArray<ItemModel> *)[[NSMutableArray alloc] init];
  108. }
  109. if (!_actions) {
  110. _actions = (NSMutableArray<ItemModel> *)[[NSMutableArray alloc] init];
  111. }
  112. if (!_conditions) {
  113. _conditions = (NSMutableArray<ItemModel> *)[[NSMutableArray alloc] init];
  114. }
  115. }
  116. - (void)initUI {
  117. [self initTableViewAsDefaultStyle:_tableView];
  118. }
  119. - (void)prepareViewDidLoad {
  120. [self requestDeviceListForHome];
  121. }
  122. #pragma mark - Main Logic
  123. - (void)requestDeviceListForHome {
  124. //parameters
  125. NSDictionary *parameter = @{@"item_type_code": ksItemTypeCodeAction};
  126. NSString *path = [NSString stringWithFormat:API_GET_ITEM_DEVICES, ksItemTypeCodeAction];
  127. [[RequestHandler handler] sendAsyncGetRequestAPIPath:path parameters:parameter modelClass:[ItemListModel class] completion:^(id responseObject) {
  128. if (!responseObject) {//응답결과가 잘못되었거나 없을 경우,
  129. return;
  130. }
  131. ItemListModel *fetchedItemList = (ItemListModel *)responseObject;
  132. if (fetchedItemList && fetchedItemList.list && fetchedItemList.list.count) {//API 성공 ,
  133. _triggerDevices = fetchedItemList.list;
  134. _actionDevices = [(NSMutableArray<ItemModel> *)[NSMutableArray alloc] initWithArray:_triggerDevices copyItems:YES];
  135. _conditionDevices = [(NSMutableArray<ItemModel> *)[NSMutableArray alloc] initWithArray:_triggerDevices copyItems:YES];
  136. if (_refRuleDetail) {//편집일 경우,
  137. ItemModel *triggerDevice = [_triggers objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice];
  138. ItemModel *actionDevice = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice];
  139. ItemModel *conditionDevice = [_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice];
  140. [self matchValueOfDevices:triggerDevice devices:_triggerDevices];
  141. [self matchValueOfDevices:actionDevice devices:_actionDevices];
  142. [self matchValueOfDevices:conditionDevice devices:_conditionDevices];
  143. }
  144. }
  145. } failure:^(id errorObject) {
  146. JDErrorModel *error = (JDErrorModel *)errorObject;
  147. [[JDFacade facade] alert:error.errorMessage];
  148. }];
  149. }
  150. - (void)matchValueOfDevices:(ItemModel *)deviceItem devices:(NSMutableArray<ItemModel> *)devices {
  151. for (ItemSubModel *subItem in deviceItem.subItems) {
  152. NSArray *matchedArray = [devices matchedArrayInSubArrays:@"subItems" predicateFormat:@"sourceId == %@ && sourceSubId == %@", subItem.sourceId, subItem.sourceSubId];
  153. if (matchedArray.count) {
  154. ItemSubModel *matchedSubItem = matchedArray.firstObject;
  155. [[JDFacade facade] setRadioButtonStatus:@YES object:matchedSubItem];
  156. CmdClsValueModel *pCmdClsValue = [matchedSubItem.cmdclsValueList objectKey:@"cmdclsValue" eqaulToString:subItem.cmdclsValue];
  157. [[JDFacade facade] setRadioButtonStatus:@YES object:pCmdClsValue];
  158. }
  159. }
  160. }
  161. - (void)requestRegisterRule {
  162. NSArray *triggers = [self items:_triggers];
  163. NSArray *actions = [self items:_actions];
  164. NSArray *conditions = [self conditions:_conditions];
  165. //validate
  166. if (!triggers || !triggers.count) {
  167. [[JDFacade facade] alert:NSLocalizedString(@"실행할 때를 선택하세요", @"실행할 때를 선택하세요")];
  168. return;
  169. }
  170. if (!actions || !actions.count) {
  171. [[JDFacade facade] alert:NSLocalizedString(@"실행할 장치를 선택하세요", @"실행할 장치를 선택하세요")];
  172. return;
  173. }
  174. //parameters
  175. NSDictionary *parameter = @{@"rule_name" : _txtRuleTitle.text,
  176. @"use_yn" : ksYES,
  177. @"triggers": triggers ? triggers : [NSNull null],
  178. @"actions": actions ? actions : [NSNull null],
  179. @"conditions": conditions ? conditions : [NSNull null]};
  180. NSString *path = [NSString stringWithFormat:API_POST_RULE];
  181. [[RequestHandler handler] sendAsyncPostRequestAPIPath:path parameters:parameter modelClass:[RuleModel class] completion:^(id responseObject) {
  182. if (!responseObject) {//응답결과가 잘못되었거나 없을 경우,
  183. return;
  184. }
  185. RuleModel *result = (RuleModel *) responseObject;
  186. if (result) {//API 성공 ,
  187. RulesAddCompleteViewController *vc = [CommonUtil instantiateViewControllerWithIdentifier:@"RulesAddCompleteViewController" storyboardName:@"Rules"];
  188. vc.providesPresentationContextTransitionStyle = YES;
  189. vc.definesPresentationContext = YES;
  190. [vc setModalPresentationStyle:UIModalPresentationOverCurrentContext];
  191. [self presentViewController:vc animated:YES completion:nil];
  192. }
  193. } failure:^(id errorObject) {
  194. JDErrorModel *error = (JDErrorModel *)errorObject;
  195. [[JDFacade facade] alert:error.errorMessage];
  196. }];
  197. }
  198. - (void)requestModifyRule {
  199. NSArray *triggers = [self items:_triggers];
  200. NSArray *actions = [self items:_actions];
  201. NSArray *conditions = [self conditions:_conditions];
  202. //validate
  203. if (!triggers || !triggers.count) {
  204. [[JDFacade facade] alert:NSLocalizedString(@"실행할 때를 선택하세요", @"실행할 때를 선택하세요")];
  205. return;
  206. }
  207. if (!actions || !actions.count) {
  208. [[JDFacade facade] alert:NSLocalizedString(@"실행할 장치를 선택하세요", @"실행할 장치를 선택하세요")];
  209. return;
  210. }
  211. //parameters
  212. NSDictionary *parameter = @{@"rule_name" : _txtRuleTitle.text,
  213. @"use_yn" : ksYES,
  214. @"triggers": triggers ? triggers : [NSNull null],
  215. @"actions": actions ? actions : [NSNull null],
  216. @"conditions": conditions ? conditions : [NSNull null]};
  217. NSString *path = [NSString stringWithFormat:API_POST_RULE_MODIFY, _refRuleDetail.homegrpRuleId];
  218. [[RequestHandler handler] sendAsyncPostRequestAPIPath:path parameters:parameter modelClass:[RuleModel class] completion:^(id responseObject) {
  219. if (!responseObject) {//응답결과가 잘못되었거나 없을 경우,
  220. return;
  221. }
  222. RuleModel *rule = (RuleModel *) responseObject;
  223. if (rule) {//API 성공
  224. RulesDetailViewController *vc = [[JDFacade facade] viewControllerOnPresentingViewController:self viewControllerClass:[RulesDetailViewController class]];
  225. if (vc) {
  226. [vc requestRuleDetail];
  227. } else {
  228. RulesViewController *rvc = [[JDFacade facade] viewControllerOnPresentingViewController:self viewControllerClass:[RulesViewController class]];
  229. [rvc prepareViewDidLoad];
  230. }
  231. [[JDFacade facade] dismissModalStack:YES completion:^{
  232. [[JDFacade facade] toast:@"편집을 완료합니다"];
  233. }];
  234. }
  235. } failure:^(id errorObject) {
  236. JDErrorModel *error = (JDErrorModel *)errorObject;
  237. [[JDFacade facade] alert:error.errorMessage];
  238. }];
  239. }
  240. //아이템 배열을 리턴함.
  241. - (NSArray *)items:(NSArray<ItemModel> *)items {
  242. //triggers, actions, conditions
  243. NSMutableArray *rItems = [[NSMutableArray alloc] init];
  244. for (ItemModel *item in items) {
  245. NSDictionary *dic = nil;
  246. NSMutableArray *subItems = [[NSMutableArray alloc] init];
  247. NSArray *pdevices = [self subItemsForType:item.subItems itemSubType:ksItemSubTypeCodeDevice];
  248. NSArray *pushes = [self subItemsForType:item.pushes itemSubType:ksItemSubTypeCodeAppPush];
  249. NSArray *timers = [self subItemsForType:item.timers itemSubType:ksItemSubTypeCodeTimer];
  250. NSArray *daylights = [self subItemsForType:item.daylights itemSubType:ksItemSubTypeCodeDaylight];
  251. NSArray *heats = [self subItemsForType:item.heats itemSubType:ksItemSubTypeCodeHeat];
  252. if (pdevices && pdevices.count) {//device
  253. [subItems addObjectsFromArray:pdevices];
  254. }
  255. if (pushes && pushes.count) {//push
  256. [subItems addObjectsFromArray:pushes];
  257. }
  258. if (timers && timers.count) {//timer
  259. [subItems addObjectsFromArray:timers];
  260. }
  261. if (daylights && daylights.count) {//해뜰때/질때
  262. [subItems addObjectsFromArray:daylights];
  263. }
  264. if (heats && heats.count) {//더울떄 / 추울때
  265. [subItems addObjectsFromArray:heats];
  266. }
  267. if (subItems.count) {
  268. dic = @{@"item_name": item.itemName,
  269. @"item_sub_type_code": item.itemSubTypeCode,
  270. @"item_sub": subItems};
  271. [rItems addObject:dic];
  272. }
  273. }
  274. return rItems;
  275. }
  276. //서브아이템 배열을 리턴함.
  277. - (NSArray *)subItemsForType:(NSArray *)subItems itemSubType:(NSString *)itemSubTypeCode {
  278. NSMutableArray *rSubItems = [[NSMutableArray alloc] init];
  279. if ([itemSubTypeCode isEqualToString:ksItemSubTypeCodeDevice]) {//디바이스일 경우,
  280. for (ItemSubModel *pdevice in subItems) {
  281. NSDictionary *rSubItem = @{@"source_id": pdevice.sourceId,
  282. @"source_sub_id": pdevice.sourceSubId,
  283. @"cmdcls_value": pdevice.cmdclsValue,
  284. @"data_type_code": pdevice.dataTypeCode};
  285. [rSubItems addObject:rSubItem];
  286. }
  287. } else if ([itemSubTypeCode isEqualToString:ksItemSubTypeCodeAppPush]) {//푸시일 경우,
  288. //at once.
  289. for (ItemSubModel *subItem in subItems) {
  290. NSDictionary *rSubItem = @{@"condition_type_code": subItem.conditionTypeCode,
  291. @"cmdcls_value": subItem.cmdclsValue};
  292. [rSubItems addObject:rSubItem];
  293. }
  294. } else if ([itemSubTypeCode isEqualToString:ksItemSubTypeCodeTimer]) {//타이머일 경우,
  295. for (ItemSubModel *subItem in subItems) {
  296. NSDictionary *rSubItem = @{@"hour": subItem.hour,
  297. @"minute": subItem.minute};
  298. [rSubItems addObject:rSubItem];
  299. }
  300. } else if ([itemSubTypeCode isEqualToString:ksItemSubTypeCodeDaylight]) {//해뜰때/질때 일 경우,
  301. for (ItemSubModel *subItem in subItems) {
  302. NSDictionary *rSubItem = @{@"source_id": subItem.sourceId,
  303. @"source_sub_id": subItem.sourceSubId};
  304. [rSubItems addObject:rSubItem];
  305. }
  306. } else if ([itemSubTypeCode isEqualToString:ksItemSubTypeCodeHeat]) {//해뜰때/질때 일 경우,
  307. for (ItemSubModel *subItem in subItems) {
  308. NSDictionary *rSubItem = @{@"source_id": subItem.sourceId,
  309. @"condtion_type_code": subItem.conditionTypeCode,
  310. @"cmdcls_value": subItem.cmdclsValue};
  311. [rSubItems addObject:rSubItem];
  312. }
  313. }
  314. return rSubItems;
  315. }
  316. - (NSArray *)conditions:(NSArray<ItemModel> *)items {//trigger만 해당됨.
  317. //conditions
  318. NSMutableArray *rConditions = [[NSMutableArray alloc] init];
  319. for (ItemModel *condition in items) {//item = condition
  320. NSMutableArray *rSubItems = [[NSMutableArray alloc] init];
  321. if ([condition.itemSubTypeCode isEqualToString:ksConditionSubTypeCodeHomeMode]) {
  322. for (ItemSubModel *mode in condition.subItems) {
  323. NSDictionary *rSubItem = @{@"source_id": mode.sourceId,
  324. @"cmdcls_value": mode.cmdclsValue,
  325. @"condition_type_code": mode.conditionTypeCode};
  326. [rSubItems addObject:rSubItem];
  327. }
  328. } else if ([condition.itemSubTypeCode isEqualToString:ksConditionSubTypeCodeDueDate]) {
  329. } else if ([condition.itemSubTypeCode isEqualToString:ksItemSubTypeCodeDevice]) {
  330. for (ItemSubModel *pdevice in condition.subItems) {
  331. NSDictionary *rSubItem = @{@"source_id": pdevice.sourceId,
  332. @"source_sub_id": pdevice.sourceSubId,
  333. @"cmdcls_value": pdevice.cmdclsValue,
  334. @"data_type_code": pdevice.dataTypeCode,
  335. @"condition_type_code": pdevice.conditionTypeCode};
  336. [rSubItems addObject:rSubItem];
  337. }
  338. } else if ([condition.itemSubTypeCode isEqualToString:ksConditionSubTypeCodeDaysOfWeek]) {
  339. for (ItemSubModel *subItem in condition.subItems) {
  340. NSDictionary *rSubItem = @{@"cmdcls_value": subItem.cmdclsValue,
  341. @"condition_type_code": subItem.conditionTypeCode};
  342. [rSubItems addObject:rSubItem];
  343. }
  344. }
  345. if (rSubItems.count) {
  346. NSDictionary *dic = @{@"item_name": condition.itemName,
  347. @"item_sub_type_code": condition.itemSubTypeCode,
  348. @"item_sub": rSubItems};
  349. [rConditions addObject:dic];
  350. }
  351. }
  352. return rConditions;
  353. }
  354. #pragma mark - UITableView DataSource & Delegate
  355. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  356. return 5;
  357. }
  358. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  359. NSInteger count = 0;
  360. if (section == 0) {//title
  361. count = 1;
  362. } else if (section == 1) {//triggers
  363. count = _triggers && _triggers.count ? _triggers.count : 0;
  364. } else if (section == 2) {//actions
  365. ItemModel *deviceItem = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice];
  366. count = deviceItem.subItems && deviceItem.subItems.count ? deviceItem.subItems.count : 0;
  367. } else if (section == 3) {//push-message
  368. ItemModel *pushItem = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeAppPush];
  369. count = pushItem.pushes && pushItem.pushes.count ? pushItem.pushes.count : 0;
  370. } else if (section == 4) {//conditions
  371. count = _chkConditions.checked || _hasCondition ? 1 : 0;
  372. }
  373. return count;
  374. }
  375. - (NSString *)headerTitleForSection:(NSInteger)section {
  376. NSString *title = nil;
  377. if (section == 1) {//trigger
  378. title = @"이 때가 되면";
  379. if (_triggers && _triggers.count) {
  380. ItemModel *item = _triggers[0];
  381. if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeDevice]) {
  382. title = @"장치 상태가 바뀔 때";
  383. } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeTimer]) {
  384. title = @"이 시간마다";
  385. } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeHeat]) {
  386. title = @"더울때 / 추울때";
  387. } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeDaylight]) {
  388. title = @"해뜰때 / 질때";
  389. }
  390. }
  391. } else if (section == 2) {//action
  392. title = @"이 장치를 실행";
  393. // title = _actions && _actions.count ? @"선택됨" : title;
  394. } else if (section == 3) {//pushes
  395. title = @"알림 메시지";
  396. // title = _pushes && _pushes.count ? @"선택됨" : title;
  397. }
  398. // else if (section == 3) {//conditions
  399. // title = @"추가 조건";
  400. // title = _triggers && triggers.count ? @"선택됨" : title;
  401. // }
  402. return title;
  403. }
  404. - (void)addTargetToHeaderAddButton:(CustomButton *)btnAdd section:(NSInteger)section {
  405. if (section == 1) {
  406. _btnTriggerAdd = btnAdd;
  407. [btnAdd addTarget:self action:@selector(btnAddTriggerTouched:) forControlEvents:UIControlEventTouchUpInside];
  408. } else if (section == 2) {
  409. [btnAdd addTarget:self action:@selector(btnAddActionTouched:) forControlEvents:UIControlEventTouchUpInside];
  410. } else if (section == 3) {
  411. _btnPushAdd = btnAdd;
  412. [btnAdd addTarget:self action:@selector(btnAddPushMessageTouched:) forControlEvents:UIControlEventTouchUpInside];
  413. }
  414. }
  415. - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
  416. UIView *view = _arrayForHeader.count > section ? _arrayForHeader[section] : nil;
  417. if (!view) {
  418. if (section == 0) {//title
  419. view = [[UIView alloc] init];
  420. } else if (section == 1 || section == 2 || section == 3) {//TODO : hide add button or not;
  421. RulesAddHeaderTableViewCell *hcell = (RulesAddHeaderTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"HeaderCellIdentifier"];
  422. view = [[UIView alloc] initWithFrame:hcell.contentView.frame];
  423. [view addSubview:hcell];
  424. hcell.lblTitle.text = [self headerTitleForSection:section];
  425. if (![hcell.btnAdd actionsForTarget:self forControlEvent:UIControlEventTouchUpInside]) {
  426. [self addTargetToHeaderAddButton:hcell.btnAdd section:section];
  427. }
  428. } else if (section == 4) {//conditions
  429. RulesAddConditionHeaderTableViewCell *hcell = (RulesAddConditionHeaderTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"ConditionHeaderCellIdentifier"];
  430. view = [[UIView alloc] initWithFrame:hcell.contentView.frame];
  431. [view addSubview:hcell];
  432. _chkConditions = hcell.chkConditions;
  433. if (!_isNotFirstLoading) {
  434. _chkConditions.checked = _hasCondition;
  435. _isNotFirstLoading = YES;
  436. }
  437. if (![_chkConditions actionsForTarget:self forControlEvent:UIControlEventTouchUpInside]) {
  438. [_chkConditions addTarget:self action:@selector(chkConditionsTouched:) forControlEvents:UIControlEventTouchUpInside];
  439. }
  440. }
  441. if (_arrayForHeader.count == section) {
  442. [_arrayForHeader insertObject:view atIndex:section];
  443. }
  444. } else {
  445. if (section == 1 || section == 2 || section == 3) {
  446. RulesAddHeaderTableViewCell *hcell = (RulesAddHeaderTableViewCell *)view.subviews[0];
  447. hcell.lblTitle.text = hcell.lblTitle.text = [self headerTitleForSection:section];
  448. } else if (section == 4) {
  449. // RulesAddConditionHeaderTableViewCell *hcell = (RulesAddConditionHeaderTableViewCell *)view.subviews[0];
  450. }
  451. }
  452. return view;
  453. }
  454. - (void)chkConditionsTouched:(id)sender {
  455. [_tableView reloadData];
  456. }
  457. - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
  458. if (section == 0) {
  459. return 0.01f;
  460. }
  461. return 90.0f;
  462. }
  463. - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
  464. UIView *view = _arrayForFooter.count > section ? _arrayForFooter[section] : nil;
  465. if (!view) {
  466. RulesAddFooterTableViewCell *hcell = (RulesAddFooterTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"FooterCellIdentifier"];
  467. view = [[UIView alloc] initWithFrame:hcell.contentView.frame];
  468. [view addSubview:hcell];
  469. if (_arrayForHeader.count == section) {
  470. [_arrayForHeader insertObject:view atIndex:section];
  471. }
  472. }
  473. return view;
  474. }
  475. - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
  476. if (section == 0) {
  477. return 0.01f;
  478. }
  479. return 15.0f;
  480. }
  481. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  482. CGFloat height = 0.0f;
  483. NSInteger section = indexPath.section;
  484. if (section == 0) {//title
  485. height = 50;
  486. } else if (section == 1) {//triggers
  487. height = 95;
  488. } else if (section == 2) {//actions
  489. height = 95;
  490. } else if (section == 3) {//push-message
  491. height = 115;
  492. } else if (section == 4) {//conditions
  493. if (!_rcv) {
  494. _rcv = [CommonUtil instantiateViewControllerWithIdentifier:@"RulesConditionViewController" storyboardName:@"Rules"];
  495. [self addChildViewController:_rcv];
  496. [_rcv didMoveToParentViewController:self];
  497. }
  498. height = _rcv.tableHeight;
  499. }
  500. return height;
  501. }
  502. + (BOOL)hasDeleteNode:(ItemModel *)deviceItem {
  503. NSArray *matchedArray = [deviceItem.subItems filteredArrayUsingPredicateFormat:@"deleteYn == %@", ksYES];
  504. return matchedArray.count;
  505. }
  506. - (void)configureTriggerCell:(RulesAddTableViewCell *)cell item:(ItemModel *)item {
  507. ItemSubModel *subItem = nil;
  508. if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeDevice]) {//장치일 경우
  509. subItem = [item.subItems matchedObjectName:ksCustomRadioButtonStatus condition:YES];
  510. cell.lblItem.text = subItem.sourceName;
  511. if ([subItem.deleteYn boolValue]) {
  512. [cell.lblItem setStrikethrough:cell.lblItem.text];
  513. }
  514. cell.lblSubItem.text = subItem.sourceSubName;
  515. //노드의 액션 값을 세팅함.
  516. if (subItem.cmdclsValueList && subItem.cmdclsValueList.count) {//커맨드클래스 밸루 리스트가 있을 경우,
  517. CmdClsValueModel *cmdclsValue = [subItem.cmdclsValueList matchedObjectName:ksCustomRadioButtonStatus condition:YES];
  518. cell.lblCondition.text = [DeviceModel contentValueMsgByCmdClsCode:subItem.cmdclsCode cmdclsTypeId:(NSString *)subItem.cmdclsTypeId contentValue:cmdclsValue.cmdclsValue];
  519. } else {
  520. cell.lblCondition.text = subItem.cmdclsValueMsg;
  521. }
  522. cell.lblCondition.hidden = NO;
  523. } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeTimer]) {
  524. subItem = item.timers && item.timers.count ? item.timers[0] : nil;
  525. if (subItem) {
  526. NSInteger phour = [subItem.hour integerValue];
  527. NSString *period = phour < 12 ? @"AM" : @"PM";//NSLocalizedString(@"오전", @"오전") : NSLocalizedString(@"오후", @"오후");
  528. if ([period isEqualToString:NSLocalizedString(@"오후", @"오후")]) {
  529. if (phour > 12) {
  530. phour -= 12;
  531. }
  532. }
  533. NSString *title = [NSString stringWithFormat:@"%@ %zd:%@", period, phour, subItem.minute];
  534. // NSDictionary *titleColor = @{NSForegroundColorAttributeName : kUITextColor02};
  535. cell.lblItem.text = title;
  536. cell.lblSubItem.text = [self daysOfWeekAtSubItem];
  537. cell.lblCondition.hidden = YES;
  538. }
  539. } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeDaylight]) {
  540. subItem = item.daylights && item.daylights.count ? item.daylights[0] : nil;
  541. if (subItem) {
  542. NSString *title = [subItem.sourceId isEqualToString:@"sunriseUtcTime"] ? @"해뜰때" : @"해질때";
  543. cell.lblItem.text = title;
  544. cell.lblSubItem.text = [NSString stringWithFormat:@"%@ / %@", subItem.sourceName, [self daysOfWeekAtSubItem]];
  545. cell.lblCondition.hidden = YES;
  546. }
  547. } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeHeat]) {
  548. subItem = item.heats && item.heats.count ? item.heats[0] : nil;
  549. if (subItem) {
  550. NSString *title = [subItem.conditionTypeCode isEqualToString:ksConditionTypeCodeGreatOrEqual] ? @"더울때" : @"추울때";
  551. cell.lblItem.text = title;
  552. cell.lblSubItem.text = [NSString stringWithFormat:@"%@ / %@℃ / %@", subItem.sourceName, subItem.cmdclsValue, [self daysOfWeekAtSubItem]];
  553. cell.lblCondition.hidden = YES;
  554. }
  555. }
  556. [cell.imgvIcon sd_setImageWithURL:[NSURL URLWithString:subItem.imageFileName] placeholderImage:nil options:SDWebImageRefreshCached];
  557. }
  558. - (NSString *)daysOfWeekAtSubItem {
  559. NSString *daysOfWeek = ksEmptyString;
  560. ItemModel *daysCondition = [_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksConditionSubTypeCodeDaysOfWeek];
  561. if (daysCondition) {
  562. ItemSubModel *subCondition = daysCondition.subItems[0];
  563. daysOfWeek = subCondition.daysOfWeek;
  564. }
  565. return daysOfWeek;
  566. }
  567. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  568. NSInteger section = indexPath.section;
  569. UITableViewCell *cell = nil;
  570. if (section == 0) {//title
  571. RulesAddTitleTableViewCell *tcell = (RulesAddTitleTableViewCell *)[_tableView dequeueReusableCellWithIdentifier:@"TitleCellIdentifier"];
  572. tcell.txtRuleTitle.text = [tcell.txtRuleTitle.text isEmptyString] && _refRuleDetail ? _refRuleDetail.ruleName : tcell.txtRuleTitle.text;
  573. if (!_txtRuleTitle) {
  574. _txtRuleTitle = tcell.txtRuleTitle;
  575. }
  576. cell = tcell;
  577. } else if (section == 1) {//triggers
  578. ItemModel *item = _triggers[indexPath.row];
  579. RulesAddTableViewCell *tcell = (RulesAddTableViewCell *)[_tableView dequeueReusableCellWithIdentifier:@"RulesCellIdentifier"];
  580. [self configureTriggerCell:tcell item:item];
  581. tcell.btnDelete.value = item;
  582. if (![tcell.btnDelete actionsForTarget:self forControlEvent:UIControlEventTouchUpInside]) {
  583. [tcell.btnDelete addTarget:self action:@selector(btnDeleteTriggerTouched:) forControlEvents:UIControlEventTouchUpInside];
  584. }
  585. cell = tcell;
  586. } else if (section == 2) {//actions
  587. ItemModel *deviceItem = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice];
  588. ItemSubModel *subItem = deviceItem.subItems[indexPath.row];
  589. RulesAddTableViewCell *tcell = (RulesAddTableViewCell *)[_tableView dequeueReusableCellWithIdentifier:@"RulesCellIdentifier"];
  590. tcell.lblItem.text = subItem.sourceName;
  591. if ([subItem.deleteYn boolValue]) {
  592. [tcell.lblItem setStrikethrough:tcell.lblItem.text];
  593. }
  594. tcell.lblSubItem.text = subItem.sourceSubName;
  595. [tcell.imgvIcon sd_setImageWithURL:[NSURL URLWithString:subItem.imageFileName] placeholderImage:nil options:SDWebImageRefreshCached];
  596. //노드의 액션 값을 세팅함.
  597. if (subItem.cmdclsValueList && subItem.cmdclsValueList.count) {//커맨드클래스 밸루 리스트가 있을 경우,
  598. CmdClsValueModel *cmdclsValue = [subItem.cmdclsValueList matchedObjectName:ksCustomRadioButtonStatus condition:YES];
  599. tcell.lblCondition.text = cmdclsValue.cmdclsValueMsg;
  600. } else {
  601. tcell.lblCondition.text = subItem.cmdclsValueMsg;
  602. }
  603. tcell.btnDelete.value = subItem;
  604. if (![tcell.btnDelete actionsForTarget:self forControlEvent:UIControlEventTouchUpInside]) {
  605. [tcell.btnDelete addTarget:self action:@selector(btnDeleteDeviceActionTouched:) forControlEvents:UIControlEventTouchUpInside];
  606. }
  607. cell = tcell;
  608. } else if (section == 3) {//push-message
  609. ItemModel *pushItem = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeAppPush];
  610. ItemSubModel *subItem = pushItem.pushes[indexPath.row];
  611. RulesAddPushTableViewCell *tcell = (RulesAddPushTableViewCell *)[_tableView dequeueReusableCellWithIdentifier:@"PushCellIdentifier"];
  612. tcell.txvMessage.delegate = self;
  613. tcell.txvMessage.text = [tcell.txvMessage.text isEmptyString] && _refRuleDetail ? subItem.cmdclsValue : tcell.txvMessage.text;
  614. if (!_txvMessage) {
  615. _txvMessage = tcell.txvMessage;
  616. }
  617. tcell.btnDelete.value = subItem;
  618. if (![tcell.btnDelete actionsForTarget:self forControlEvent:UIControlEventTouchUpInside]) {
  619. [tcell.btnDelete addTarget:self action:@selector(btnDeletePushActionTouched:) forControlEvents:UIControlEventTouchUpInside];
  620. }
  621. cell = tcell;
  622. } else if (section == 4) {//conditions
  623. RulesAddConditionTableViewCell *tcell = (RulesAddConditionTableViewCell *)[_tableView dequeueReusableCellWithIdentifier:@"ConditionCellIdentifier"];
  624. if (_chkConditions.checked) {
  625. if (!tcell.container.subviews.count) {
  626. if ([self isViewLoaded]) {
  627. [_rcv beginAppearanceTransition:YES animated:NO];
  628. [tcell.container addSubview:_rcv.view];
  629. [_rcv endAppearanceTransition];
  630. }
  631. }
  632. tcell.constraintContainerHeight.constant = _rcv.tableHeight;
  633. _rcv.conditions = _conditions;
  634. _rcv.refDevices = _conditionDevices;
  635. }
  636. cell = tcell;
  637. }
  638. return cell;
  639. }
  640. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  641. [tableView deselectRowAtIndexPath:indexPath animated:YES];
  642. if (indexPath.section == 1) {//triggers
  643. ItemModel *deviceItem = [_triggers objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice];
  644. if (deviceItem) {
  645. ItemSubModel *subItem = deviceItem.subItems[indexPath.row];
  646. [RulesAddViewController modifyAction:subItem refDevices:_triggerDevices tableView:_tableView];
  647. }
  648. } else if (indexPath.section == 2) {//actions
  649. ItemModel *deviceItem = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice];
  650. if (deviceItem) {
  651. ItemSubModel *subItem = deviceItem.subItems[indexPath.row];
  652. [RulesAddViewController modifyAction:subItem refDevices:_actionDevices tableView:_tableView];
  653. }
  654. }
  655. }
  656. + (void)modifyAction:(ItemSubModel *)subItem refDevices:(NSMutableArray<ItemModel> *)refDevices tableView:(CustomTableView *)tableView {
  657. if ([subItem.deleteYn boolValue]) {
  658. [[JDFacade facade] toast:@"삭제된 장치입니다\r목록에서 제거하세요"];
  659. return;
  660. }
  661. ItemModel *item = [refDevices objectKey:@"sourceId" eqaulToString:subItem.sourceId];
  662. ItemSubModel *matchedSubItem = [item.subItems objectKey:@"sourceSubId" eqaulToString:subItem.sourceSubId];
  663. //노드 선택 팝럽.
  664. DeviceNodePopupView *npopup = [[DeviceNodePopupView alloc] initFromNib];
  665. npopup.refDevice = item;
  666. npopup.typeCode = ksItemTypeCodeTrigger;
  667. npopup.isModifyMode = YES;
  668. [npopup showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
  669. if (buttonIndex == 0) {//OK
  670. subItem.cmdclsCode = matchedSubItem.cmdclsCode;
  671. subItem.cmdclsTypeId = matchedSubItem.cmdclsTypeId;
  672. subItem.cmdclsValueList = matchedSubItem.cmdclsValueList;
  673. CmdClsValueModel *pCmdClsValue = [subItem.cmdclsValueList matchedObjectName:ksCustomRadioButtonStatus condition:YES];
  674. subItem.cmdclsValue = pCmdClsValue.cmdclsValue; //CommandClassControlNodeView - 에서 선택됨.
  675. if (tableView) {
  676. [tableView reloadData];
  677. }
  678. }
  679. }];
  680. }
  681. #pragma mark - TableView UI Events
  682. - (void)btnAddTriggerTouched:(id)sender {
  683. TriggerSelectPopupView *tpopup = [[TriggerSelectPopupView alloc] initFromNib];
  684. tpopup.refTriggers = _triggers;
  685. tpopup.refDevices = _triggerDevices;
  686. tpopup.refConditions = _conditions;
  687. [tpopup showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
  688. if (buttonIndex == 0) {
  689. _btnTriggerAdd.hidden = YES;
  690. [_tableView reloadData];
  691. }
  692. }];
  693. }
  694. - (void)btnAddActionTouched:(id)sender {
  695. DeviceSelectPopupView *dpopup = [[DeviceSelectPopupView alloc] initFromNib];
  696. dpopup.refDevices = _actionDevices;
  697. dpopup.typeCode = ksItemTypeCodeTrigger;
  698. [dpopup showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
  699. if (buttonIndex == 0) {//ok
  700. DeviceNodePopupView *npopup = [[DeviceNodePopupView alloc] initFromNib];
  701. npopup.refDevice = dpopup.selectedDevices[0];
  702. npopup.typeCode = ksItemTypeCodeTrigger;
  703. [npopup showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
  704. //action add
  705. if (buttonIndex == 0) {//OK
  706. ItemModel *deviceItem = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice];
  707. if (!deviceItem) {//디바이스 아이템이 없을 경우,
  708. deviceItem = [[ItemModel alloc] init];
  709. deviceItem.itemName = @"이 장치를 실행";
  710. deviceItem.itemSubTypeCode = ksItemSubTypeCodeDevice;
  711. deviceItem.subItems = [(NSMutableArray<ItemSubModel> *)[NSMutableArray alloc] init];
  712. [_actions addObject:deviceItem];
  713. }
  714. ItemSubModel *snode = npopup.selectedNode;
  715. //존재 여부 확인
  716. if (![deviceItem.subItems objectByUsingPredicateFormat:@"sourceId == %@ && sourceSubId == %@", snode.sourceId, snode.sourceSubId]) {
  717. [deviceItem.subItems addObject: snode];
  718. }
  719. [_tableView reloadData];
  720. }
  721. }];
  722. }
  723. }];
  724. }
  725. - (void)btnAddPushMessageTouched:(id)sender {
  726. ItemModel *pushItem = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeAppPush];
  727. if (!pushItem) {//디바이스 아이템이 없을 경우,
  728. pushItem = [[ItemModel alloc] init];
  729. pushItem.itemName = [JDFacade facade].loginUser.memberId;
  730. pushItem.itemSubTypeCode = ksItemSubTypeCodeAppPush;
  731. pushItem.pushes = [(NSMutableArray<ItemSubModel> *)[NSMutableArray alloc] init];
  732. ItemSubModel *push = [[ItemSubModel alloc] init];
  733. push.conditionTypeCode = @"02";
  734. [pushItem.pushes addObject:push];
  735. [_actions addObject:pushItem];
  736. }
  737. _btnPushAdd.hidden = YES;
  738. [_tableView reloadData];
  739. }
  740. - (void)btnDeleteTriggerTouched:(id)sender {
  741. if (_triggers && _triggers.count) {
  742. [_triggers removeAllObjects];
  743. }
  744. _btnTriggerAdd.hidden = NO;
  745. [_tableView reloadData];
  746. }
  747. - (void)btnDeleteDeviceActionTouched:(id)sender {
  748. CustomButton *btnDelete = (CustomButton *)sender;
  749. ItemSubModel *subItem = (ItemSubModel *)btnDelete.value;
  750. //선택 설정을 초기화
  751. [[JDFacade facade] setRadioButtonStatus:@NO object:subItem];
  752. for (CmdClsValueModel *cmdclsValue in subItem.cmdclsValueList) {
  753. cmdclsValue.isSelected = NO;
  754. }
  755. ItemModel *deviceItem = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice];
  756. [deviceItem.subItems removeObject:subItem];
  757. [_tableView reloadData];
  758. }
  759. - (void)btnDeletePushActionTouched:(id)sender {
  760. CustomButton *btnDelete = (CustomButton *)sender;
  761. ItemSubModel *push = (ItemSubModel *)btnDelete.value;
  762. ItemModel *pushItem = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeAppPush];
  763. [pushItem.pushes removeObject:push];
  764. _btnPushAdd.hidden = NO;
  765. [_tableView reloadData];
  766. }
  767. #pragma mark - CustomTextView Delegate
  768. - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
  769. NSLog(@"%s\n %zd", __PRETTY_FUNCTION__, textView.text.length);
  770. return textView.text.length < 120;
  771. }
  772. #pragma mark - UI Events
  773. - (IBAction)btnConfirmTouched:(id)sender {
  774. [self.view endEditing:YES];
  775. //1.Validate Title
  776. RulesAddTitleTableViewCell *tcell = (RulesAddTitleTableViewCell *)[_tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; //첫번째 섹션
  777. if (tcell && ![ValidateUtil validateTextfiled:tcell.txtRuleTitle type:ValidateTypeNull title:NSLocalizedString(@"규칙 이름", @"규칙 이름")]) {
  778. return;
  779. }
  780. ItemModel *pushItem = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeAppPush];
  781. if (pushItem) {
  782. if (_txvMessage && [_txvMessage.text isEmptyString]) {//푸시메시지 여부 확인
  783. [_actions removeObject:pushItem];
  784. } else if (_txvMessage) {
  785. ItemSubModel *subItem = pushItem.pushes[0];
  786. subItem.cmdclsValue = _txvMessage.text;
  787. }
  788. }
  789. if (!_refRuleDetail) {//생성
  790. [self requestRegisterRule];
  791. } else {//수정
  792. BOOL hasDeleteNode = NO;
  793. ItemModel *triggerDevice = [_triggers objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice];
  794. ItemModel *actionDevice = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice];
  795. ItemModel *conditionDevice = [_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice];
  796. hasDeleteNode = [RulesAddViewController hasDeleteNode:triggerDevice];
  797. hasDeleteNode = [RulesAddViewController hasDeleteNode:actionDevice] ? YES : hasDeleteNode;
  798. hasDeleteNode = [RulesAddViewController hasDeleteNode:conditionDevice] ? YES : hasDeleteNode;
  799. if (hasDeleteNode) {
  800. [[JDFacade facade] confirm:@"삭제된 장치를 제외 후 저장합니다" completion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
  801. if (buttonIndex == 0) {//OK
  802. [self getRidOfDeleteDevices:triggerDevice];
  803. [self getRidOfDeleteDevices:actionDevice];
  804. [self getRidOfDeleteDevices:conditionDevice];
  805. [_tableView reloadData];
  806. [self requestModifyRule];
  807. }
  808. }];
  809. } else {
  810. [self requestModifyRule];
  811. }
  812. }
  813. }
  814. //삭제된 장치를 제거함.
  815. - (void)getRidOfDeleteDevices:(ItemModel *)deviceItem {
  816. [deviceItem.subItems enumerateObjectsUsingBlock:^(ItemSubModel *subItem, NSUInteger idx, BOOL * _Nonnull stop) {
  817. if (subItem.deleteYn) {
  818. if ([_triggers containsObject:deviceItem]) {
  819. [_triggers removeObject:deviceItem];
  820. return;
  821. }
  822. [deviceItem.subItems removeObject:subItem];
  823. }
  824. }];
  825. }
  826. - (IBAction)btnCancelTouched:(id)sender {
  827. [[JDFacade facade] dismissModalStack:YES completion:nil];
  828. }
  829. #pragma mark - MemoryWarning
  830. - (void)didReceiveMemoryWarning
  831. {
  832. [super didReceiveMemoryWarning];
  833. // Dispose of any resources that can be recreated.
  834. }
  835. @end