1const MEMBER_MANAGE = (function () { 2 let $form 3 let $member_agree_wrap 4 let header_ctl 5 let $fileupload_profile_img, $profile_img, $photo_tmp_idx 6 let member_code 7 let passwd_html_show_click = false 8 let $admin_group_list_wrap 9 let afterSavePhotoCallback; 10 const tw_address = {} 11 12 const init = function (type, code) { 13 member_code = code 14 $form = $('#dof') 15 $member_agree_wrap = $('#member_agree_wrap') 16 $fileupload_profile_img = $('#fileupload_profile_img') 17 $profile_img = $('#profile_img') 18 $photo_tmp_idx = $('#photo_tmp_idx') 19 20 header_ctl = new HEADER_CONTROL() 21 header_ctl.init() 22 if (type == 'add') { 23 header_ctl.addBtn('cancel', function () { 24 history.go(-1) 25 }) 26 header_ctl.addBtn('add', function () { 27 submit('add') 28 }) 29 } else { 30 header_ctl.addBtn('delete', function () { 31 adminMember.openDeleteMember(JSON.stringify([{ member_code, delete_old_auth_log: false }])) 32 }) 33 header_ctl.addBtn('save', function () { 34 submit('save') 35 }) 36 } 37 createEvent() 38 setUpload() 39 40 $admin_group_list_wrap = $('._admin_group_list_wrap') 41 if ($admin_group_list_wrap.find('input[type=checkbox]:checked').length > 0) { 42 $('._manager_info_wrap').show() 43 } else { 44 $('._manager_info_wrap').hide() 45 } 46 $admin_group_list_wrap.find('input[type=checkbox]').off('click').on('click', function () { 47 if ($admin_group_list_wrap.find('input[type=checkbox]:checked').length > 0) { 48 $('._manager_info_wrap').show() 49 } else { 50 $('._manager_info_wrap').hide() 51 } 52 header_ctl.change() 53 }) 54 } 55 56 const setAfterSavePhotoCallback = function (callback) { 57 afterSavePhotoCallback = callback; 58 } 59 60 const changeCountry = function (country, code) { 61 $form.find('._addr_form_wrap').hide() 62 if (country.trim() === '') { 63 return false 64 } 65 $.ajax({ 66 url: '/admin/ajax/member/get_site_address_format.cm', 67 data: { country_code: country, unit_code: code }, 68 type: 'POST', 69 dataType: 'json', 70 success: function (res) { 71 const format = res.format 72 switch (format) { 73 case 'KR': 74 $form.find('#kr_addr_form_wrap').show() 75 break 76 case 'TW': 77 $form.find('#tw_addr_form_wrap').show() 78 break 79 case 'VN': 80 $form.find('#vn_addr_form_wrap').show() 81 break 82 case 'HK': 83 $form.find('#hk_addr_form_wrap').show() 84 break 85 case '3': 86 $form.find('#jp_addr_form_wrap').show() 87 break 88 case '5': 89 $form.find('#en_addr_form_wrap').show() 90 break 91 } 92 } 93 }) 94 } 95 96 const checkSubscribePeriodChange = function () { 97 let subscribe_check = false 98 $form.find('._subscribe_left_date').each(function () { 99 if ($(this).prop('disabled')) return false 100 if ($(this).val() != $(this).attr('placeholder')) { 101 subscribe_check = true 102 return false 103 } 104 }) 105 return (!subscribe_check || confirm(getLocalizeString('ì¤ëª _íì그룹ì´ì©ê¶ê¸°ê°ë³ê²½ìë´', '', 'íì그룹 ì´ì©ê¶ 기ê°ì ë³ê²½ë ë°ì´í°ê° ììµëë¤.\nì ì¥íìê² ìµëê¹?'))) 106 } 107 108 var submit = function (type) { 109 const data = $form.serializeObject() 110 data.member_agree_info = $member_agree_wrap.serializeObject() 111 if (!checkSubscribePeriodChange()) return false 112 $.ajax({ 113 type: 'POST', 114 data, 115 url: ('/admin/ajax/member/add.cm'), 116 dataType: 'json', 117 async: false, 118 cache: false, 119 success: function (res) { 120 if (res.msg == 'SUCCESS') { 121 header_ctl.save() 122 if (res.admin_group_fail === 'Y') { 123 alert(getLocalizeString('ì¤ëª _ì´ìì§ì¤ì ê¶íì´ìì´ì´ìì§ê·¸ë£¹ìì¤ì ëì§ìììµëë¤', '', 'ì´ìì§ ì¤ì ê¶íì´ ìì´ ì´ìì§ ê·¸ë£¹ì ì¤ì ëì§ ìììµëë¤.')) 124 } 125 mixpanel.track('complete_bo_member_list_add',{'site_code': SITE_CODE}
125) 126 if (type == 'add') history.go(-1) 127 else location.reload() 128 } else { alert(res.msg) } 129 } 130 }) 131 } 132 133 var createEvent = function () { 134 $form.find('input, textarea, select').off('change, keyup').on('change, keyup, blur', function () { 135 header_ctl.change() 136 }) 137 $form.find('input[type=checkbox],input[type=radio],input[type=file],._file_remove').off('click').on('click', function () { 138 if ($(this).attr('name') == 'default_group[]' && $(this).data('subscribe') == 'Y') { 139 const group_idx = $(this).val() 140 const is_checked = $(this).prop('checked') 141 if (!is_checked && !confirm(getLocalizeString('ì¤ëª _íì그룹ì´ì©ê¶êµ¬ë§¤ë¡ì§ì ë그룹ì ê±°ììë´', '', 'ì´ ê·¸ë£¹ì íì그룹 ì´ì©ê¶ êµ¬ë§¤ë¡ ìë ì§ì ë 그룹ì ëë¤. \n그룹ì§ì ì í´ì íê³ ëì¤ì ë¤ì 그룹ì ì§ì íëë¼ë ìë 그룹 í´ì ì¼ì ìë í´ì ê° ëì§ ìê² ë©ëë¤.\n\n그룹 ì§ì ì í´ì íìê² ìµëê¹?'))) { 142 return false 143 } 144 145 // ì´ì©ê¶ í´ì ìì ì´ë¯ë¡ ê¸°ê° ìì 못íê² disabled ì²ë¦¬ 146 $form.find('._subscribe_left_date').each(function () { 147 if (group_idx == $(this).data('group_idx')) { 148 $(this).prop('disabled', !is_checked) 149 } 150 }) 151 } 152 header_ctl.change() 153 }) 154 $form.find('select').change(function () { 155 header_ctl.change() 156 }) 157 158 $form.find('._subscribe_left_date').on('keypress', function (e) { 159 $(this).val($(this).val().replace(/[^0-9]/g, '')) 160 return (e.keyCode >= 48 && e.keyCode <= 57) 161 }) 162 $form.find('._subscribe_left_date').on('keyup', function (e) { 163 $(this).val($(this).val().replace(/[^0-9]/g, '')) 164 return (e.keyCode >= 48 && e.keyCode <= 57) 165 }) 166 167 $member_agree_wrap.find('input[type=checkbox]').off('click').on('click', function () { 168 header_ctl.change() 169 }) 170 171 const $admin_memo_chars_title = $('#admin_memo_chars_title') 172 const $admin_memo = $('#admin_memo') 173 const $btn_admin_memo = $('#btn_admin_memo') 174 if ($admin_memo.length > 0) { 175 autosize($admin_memo) 176 var pre_admin_memo = $admin_memo.val() 177 $admin_memo_chars_title.html(getByteLength(pre_admin_memo) + '/500') 178 $admin_memo.keyup(function (e) { 179 const content = $(this).val() 180 $admin_memo_chars_title.html(getByteLength(content) + '/500') 181 }) 182 } 183 $btn_admin_memo.click(function () { 184 const memo = $admin_memo.val() 185 if (pre_admin_memo !== memo) { 186 pre_admin_memo = memo 187 const code = $form.find("input[name='code']").val() 188 if (code !== '') { 189 adminMember.updateAdminMemo(code, memo, function (res) { 190 if (res.msg !== 'SUCCESS') alert(res.msg) 191 else location.reload() 192 }) 193 } 194 } 195 }) 196 197 $('#create_recommend_code_btn').click(function () { 198 let is_create_recommend_code = false 199 if (!is_create_recommend_code) { 200 const member_code = $(this).data('member-code') 201 202 $.ajax({ 203 type: 'POST', 204 data: { member_code }, 205 url: ('/admin/ajax/member/create_recommend_code.cm'), 206 dataType: 'json', 207 async: true, 208 cache: false, 209 success: function (res) { 210 is_create_recommend_code = true 211 if (res.msg === 'SUCCESS') { 212 $('._recommend_code_wrap').text(res.recommend_code || '') 213 $('._recommend_tmp_input').val(res.recommend_code) 214 $('._recommend_create_set').addClass('hide') 215 $('._recommend_set').removeClass('hide') 216 } else { 217 alert(res.msg) 218 } 219 } 220 }) 221 } 222 }) 223 } 224 225 var setUpload = function () { 226 $fileupload_profile_img.setUploadImage({ 227 url: '/admin/ajax/upload_image.cm', 228 formData: { temp: 'Y', target: 'member' } 229 }, function (res, data) { 230 $.each(data, function (e, tmp) { 231 if (tmp.tmp_idx > 0) { 232 header_ctl.change(); 233 } 234 if (tmp.url != '') { 235 $profile_img.attr('src', CDN_UPLOAD_URL + tmp.url); 236 $photo_tmp_idx.val(tmp.tmp_idx); 237 238 if (afterSavePhotoCallback) { 239 afterSavePhotoCallback(); 240 } 241 } else { 242 alert(tmp.error); 243 } 244 }) 245 }) 246 } 247 248 const changeJoinTypeForm = function () { 249 const join_type_code = $form.find('select[name=join_type_select]').val() 250 $form.find('input[name=join_type_code]').val(join_type_code) 251 $.ajax({ 252 type: 'POST', 253 data: { join_type_code }, 254 url: ('/admin/ajax/member/change_join_type_form.cm'), 255 dataType: 'json', 256 async: true, 257 cache: false, 258 success: function (res) { 259 if (res.msg === 'SUCCESS') { 260 $form.find('._type_form_wrap').html(res.html) 261 setDaumZipcode() 262 changeCountry('', UNIT_CODE) 263 } else { 264 alert(res.msg) 265 } 266 } 267 }) 268 } 269 270 var setDaumZipcode = function () { 271 const join_addr = new ZIPCODE_DAUM() 272 let address = '' 273 let splitAddress = '' 274 let building = '' 275 let street = ''
276 let city = '' 277 let state = '' 278 279 join_addr.init({ 280 addr_container: $('#join_addr_container'), 281 addr_pop: $('#join_addr_container ._add_list'), 282 post_code: $('#join_addr_postcode'), 283 addr: $('#join_addr'), 284 onShow: function () { 285 $('#join_addr_container').css({ top: -50 + 'px' }) 286 $('#join_addr_detail').parent().css({ top: -50 + 'px' }) 287 }, 288 onComplete: function (data) { 289 $('#join_addr_detail').focus() 290 address = data.addressEnglish 291 if (address == 'undefined') address = data.jibunAddressEnglish 292 splitAddress = address.split(',') 293 if (splitAddress.length > 5) { 294 building = splitAddress[0] 295 street = splitAddress[1] 296 city = splitAddress[2] 297 state = splitAddress[3] + ' ' + splitAddress[4] 298 } else { 299 building = splitAddress[0] 300 street = splitAddress[1] 301 city = splitAddress[2] 302 state = splitAddress[3] 303 } 304 $("input[name='addr_building']").val(building) 305 $("input[name='addr_street']").val(street) 306 $("input[name='addr_city']").val(city) 307 $("input[name='addr_state']").val(state) 308 $("input[name='addr_zipcode']").val(data.zonecode) 309 }, 310 onClose: function () { 311 $('#join_addr_detail').parent().css({ top: 0 + 'px' }) 312 }, 313 height: '470' 314 }) 315 } 316 317 const openChangePasswordMyModal = function (idx) { 318 $.ajax({ 319 type: 'GET', 320 url: '/admin/ajax/change_password_my_modal.cm', 321 dataType: 'json', 322 data: { idx }, 323 async: true, 324 cache: false, 325 success: function (data) { 326 if (data.msg === 'SUCCESS') { 327 const $html = $(data.html) 328 $.cocoaDialog.open({ 329 type: 'site_change_password', 330 custom_popup: $html 331 }) 332 } else { 333 alert(data.msg) 334 } 335 } 336 }) 337 } 338 339 return { 340 init: function (type, code) { 341 init(type, code) 342 }, 343 changeCountry: function (country, code) { 344 changeCountry(country, code) 345 }, 346 showPasswdHtml: function () { 347 if (!passwd_html_show_click) { 348 passwd_html_show_click = true 349 let placeholder_text = getLocalizeString('ì¤ëª _ë¹ë°ë²í¸', '', 'ë¹ë°ë²í¸'); 350 if (member_code !== '') { 351 placeholder_text = getLocalizeString('ì¤ëª _ë¹ë°ë²í¸ë³ê²½ììë§ì ë ¥', '', 'ë¹ë°ë²í¸ ë³ê²½ììë§ ì ë ¥í´ì£¼ì¸ì'); 352 } 353 const passwd_html = "<input type='password' autocomplete='off' name='passwd' id='user_password' class='form-control' placeholder='" + placeholder_text + "'>"; 354 $('#password_wrap .col-md-9').append(passwd_html); 355 356 $form.find('input[name="passwd"]').off('change, keyup').on('change, keyup, blur', function () { 357 header_ctl.change(); 358 }) 359 } 360 }, 361 changeJoinTypeForm: function () { 362 changeJoinTypeForm(); 363 }, 364 setDaumZipcode: function () { 365 setDaumZipcode(); 366 }, 367 openChangePasswordMyModal: function (idx) { 368 openChangePasswordMyModal(idx); 369 }, 370 setAfterSavePhotoCallback: function(callback) { 371 setAfterSavePhotoCallback(callback); 372 }, 373 changeData : function(){ 374 header_ctl.change(); 375 } 376 } 377}()) 378 379const MEMBER_GROUP = (function () { 380 let modal_type = 'list' 381 let current_member_code, base_url, managers_setting_permission 382 let $group_list, $drop_group_list, $drop_shopping_group_list, $check_drop_group_list, 383 $check_drop_shopping_group_list, $no_group_cnt 384 let group_list_item_tmp, drop_group_list_tmp 385 386 const group_item_html_class = '_group_item' 387 const group_list_data = new DATA() 388 let prev_group_type 389 let prev_drop_group_type 390 391 const setGroupMemberCount = function (data) { 392 group_list_data.data[data.code].member_cnt = data.member_cnt 393 } 394 395 const addGroupList = function (data) { 396 data.idx = parseInt(data.idx) 397 group_list_data.add(data.code, data) 398 addGroupListHtml(data) 399 } 400 401 const setCurrentMemberCode = function (code) { 402 current_member_code = code 403 } 404 405 const updateGroupList = function (code, data) { 406 group_list_data.add(code, data) 407 resetGroupListHtml() 408 } 409 410 const modifyGroupList = function (type, data) { 411 if (type == 'delete') { 412 group_list_data.remove(data.code) 413 } else { 414 if (type == 'add') { 415 data.idx = parseInt(data.idx) 416 } 417 group_list_data.add(data.code, data) 418 } 419 } 420 421 const addDropGroupList = function (data) {
422 let concede_script = '' 423 const group_type = data.group_type 424 let edit_script = "adminMember.openGroupForm('" + data.idx + "');" 425 let li_id = 'group_item_' + data.code 426 427 switch (data.group_type) { 428 case 'shopping': 429 case 'activity': 430 concede_script = "MEMBER_GROUP.concedeChangeSpecialGroup('" + group_type + "',$(this),'" + data.idx + "')" 431 if (data.code == group_type) { 432 edit_script = 'CONFIG_SHOPPING_GROUP.openShoppingGroupDefaultForm();' 433 li_id = group_type + '_group_default' 434 } 435 break 436 case 'admin': 437 case 'shop_in_shop': 438 if (managers_setting_permission) { 439 concede_script = "MEMBER_GROUP.concedeToggleGroup($(this),'" + data.idx + "')" 440 } else { 441 concede_script = "alert(getLocalizeString('ì¤ëª _ì´ìì§ê·¸ë£¹ì¤ì ê¶íì´ììµëë¤', '', 'ì´ìì§ ê·¸ë£¹ ì¤ì ê¶íì´ ììµëë¤.'))" 442 } 443 break 444 case 'member': 445 concede_script = "MEMBER_GROUP.concedeToggleGroup($(this),'" + data.idx + "')" 446 break 447 } 448 $drop_group_list = $('._drop_group_list') 449 $drop_shopping_group_list = $('._drop_shopping_group_list') 450 const $drop_list = (data.group_type == 'shopping') ? $drop_shopping_group_list : $drop_group_list 451 const tmp_data = { 452 id: li_id, 453 class: (data.is_default ? 'default_' : '') + group_type + ' ' + (current_member_code == data.code ? 'active checked ' + group_item_html_class : group_item_html_class), 454 code: data.code, 455 href: base_url + 'member_group=' + data.code, 456 title: group_type === 'member' ? data.title : data.group_type_name + ' - ' + data.title, 457 group_type: data.group_type_name, 458 cnt: data.member_cnt > 0 ? parseInt(data.member_cnt) : '', 459 edit_script: edit_script + 'return false;' 460 } 461 462 if (!prev_drop_group_type || prev_drop_group_type !== group_type) { 463 prev_drop_group_type = group_type 464 var use_div = true 465 } else { 466 var use_div = false 467 } 468 469 $drop_list.each(function () { 470 const group_data = $(this).data('groups') 471 let drop_tmp_data = { 472 class: (data.is_default ? 'default_' : '') + group_type + ' ' + ($.inArray(data.idx, group_data) !== -1 ? 'active checked ' + group_item_html_class : group_item_html_class), 473 idx: data.idx, 474 concede_script 475 } 476 477 drop_tmp_data = $.extend(tmp_data, drop_tmp_data) 478 const $drop_group_list_html = $(getTemplateConvert(drop_group_list_tmp, drop_tmp_data)).data(data) 479 480 appendGroupHtml($(this), $drop_group_list_html, group_type, data.is_default, use_div) 481 }) 482 } 483 484 var addGroupListHtml = function (data) {
485 let concede_script = '' 486 const group_type = data.group_type 487 let edit_script = "adminMember.openGroupForm('" + data.idx + "');" 488 let li_id = 'group_item_' + data.code 489 switch (data.group_type) { 490 case 'shopping': 491 case 'activity': 492 concede_script = "MEMBER_GROUP.concedeChangeSpecialGroup('" + group_type + "',$(this),'" + data.idx + "')" 493 if (data.code == group_type) { 494 edit_script = 'CONFIG_SHOPPING_GROUP.openShoppingGroupDefaultForm();' 495 li_id = group_type + '_group_default' 496 } 497 break 498 case 'admin': 499 case 'shop_in_shop': 500 if (managers_setting_permission) { 501 concede_script = "MEMBER_GROUP.concedeToggleGroup($(this),'" + data.idx + "')" 502 } else { 503 concede_script = "alert(getLocalizeString('ì¤ëª _ì´ìì§ê·¸ë£¹ì¤ì ê¶íì´ììµëë¤', '', 'ì´ìì§ ê·¸ë£¹ ì¤ì ê¶íì´ ììµëë¤.'))" 504 } 505 break 506 case 'member': 507 concede_script = "MEMBER_GROUP.concedeToggleGroup($(this),'" + data.idx + "')" 508 break 509 } 510 511 const tmp_data = { 512 id: li_id, 513 class: (data.is_default ? 'default_' : '') + group_type + ' ' + (current_member_code == data.code ? 'active checked ' + group_item_html_class : group_item_html_class), 514 code: data.code, 515 href: base_url + 'member_group=' + data.code, 516 title: group_type === 'member' ? data.title : data.group_type_name + ' - ' + data.title, 517 group_type: data.group_type_name, 518 cnt: data.member_cnt > 0 ? parseInt(data.member_cnt) : '', 519 edit_script: edit_script + 'return false;' 520 } 521 522 if (data.member_cnt === '9999+') { 523 tmp_data.cnt = '9999+' 524 } 525 526 if (!prev_group_type || prev_group_type !== group_type) { 527 prev_group_type = group_type 528 var use_div = true 529 } else { 530 var use_div = false 531 } 532 const $group_list_html = $(getTemplateConvert(group_list_item_tmp, tmp_data)).data(data) 533 appendGroupHtml($group_list, $group_list_html, group_type, data.is_default, use_div) 534 535 const $drop_list = (data.group_type == 'shopping') ? $drop_shopping_group_list : $drop_group_list 536 $drop_list.each(function () { 537 const group_data = $(this).data('groups') 538 let drop_tmp_data = { 539 class: (data.is_default ? 'default_' : '') + group_type + ' ' + ($.inArray(data.idx, group_data) !== -1 ? 'active checked ' + group_item_html_class : group_item_html_class), 540 idx: data.idx, 541 concede_script 542 } 543 544 drop_tmp_data = $.extend(tmp_data, drop_tmp_data) 545 const $drop_group_list_html = $(getTemplateConvert(drop_group_list_tmp, drop_tmp_data)).data(data) 546 appendGroupHtml($(this), $drop_group_list_html, group_type, data.is_default, use_div) 547 }) 548 549 const $check_drop_list = (data.group_type == 'shopping') ? $check_drop_shopping_group_list : $check_drop_group_list 550 const check_group = $check_drop_list.data('groups') 551 let check_drop_tmp_data = { 552 class: (data.is_default ? 'default_' : '') + group_type + ' ' + ($.inArray(data.idx, check_group) !== -1 ? 'active checked ' + group_item_html_class : group_item_html_class), 553 idx: data.idx, 554 concede_script 555 } 556 check_drop_tmp_data = $.extend(tmp_data, check_drop_tmp_data) 557 const $check_drop_group_list_html = $(getTemplateConvert(drop_group_list_tmp, check_drop_tmp_data)).data(data) 558 appendGroupHtml($check_drop_list, $check_drop_group_list_html, group_type, data.is_default, use_div) 559 } 560 561 // ê´ë¦¬ìíì´ì§ - 그룹 HTML ì¶ê°í ìì¹ ì§ì 562 var appendGroupHtml = function ($obj, $html, _group_type, is_default, use_divider) { 563 const group_type = (is_default ? 'default_' : '') + _group_type 564 use_divider = (use_divider === true) 565 const $divider = '<li class="divider ' + group_item_html_class + '"></li>' 566 if ($obj.find('.' + group_type).length === 0) { 567 let next_element = [] 568 switch (group_type) { 569 case 'default_member' : 570 next_element.push('.member') 571 break 572 case 'member': 573 next_element.push('.admin') 574 break 575 case 'admin': 576 next_element.push('.shopping') 577 break 578 case 'shopping': 579 break 580 } 581 next_element = next_element.length > 0 ? next_element.join(',') : '' 582 const is_first = ($obj.find('.' + group_item_html_class).length === 0) 583 584 if (next_element === '' || $obj.find(next_element).length === 0) { 585 if (use_divider && !is_first) $obj.append($divider) 586 $obj.append($html) 587 } else { 588 $obj.find(next_element).first().before($html) 589 if (use_divider) $obj.find(next_element).first().before($divider) 590 } 591 } else { 592 $obj.find('.' + group_type + ':last').after($html) 593 } 594 } 595 596 var resetGroupListHtml = function () { 597 prev_group_type = '' 598 prev_drop_group_type = '' 599 $('.' + group_item_html_class).remove() 600 $.each(group_list_data.data, function (code, data) { 601 addGroupListHtml(data) 602 }) 603 } 604 605 const init = function (code, url, permission, type) { 606 current_member_code = code 607 base_url = url 608 managers_setting_permission = permission 609 $group_list = $('#group_list') 610 $no_group_cnt = $('._no_group_cnt') 611 modal_type = type 612 group_list_item_tmp = '<li class="{class}" id="{id}" onclick="MEMBER_DATA.changeUrl(null, null, \'{href}\', \'group\', \'{code}\', \'1\')"><a href="#"><span id="group_item_title_{code}">{title}</span> <small id="group_item_count_{code}" class="margin-left-lg text-bold opacity-75">{cnt}</small><button onclick="{edit_script}" class="pull-right btn btn-flat no-padding hover-visible"><i class="zmdi zmdi-settings"></i></button></a></li>' 613 drop_group_list_tmp = '<li class="{class}"><a href="javascript:;" data-idx="{idx}" onclick="{concede_script}">{title}</a></li>' 614 615 $drop_group_list = $('._drop_group_list') 616 $drop_shopping_group_list = $('._drop_shopping_group_list') 617 618 $drop_group_list.each(function () { 619 // 기본 그룹 620 let _new_d = [] 621 $.each($(this).data('groups').toString().split(','), function (e, v) { 622 v = v == '' ? 0 : parseInt(v) 623 if (v > 0) { _new_d.push(v) } 624 }) 625 $(this).data('groups', _new_d) 626 627 // ì´ì©ê¶ 그룹 628 _new_d = [] 629 $.each($(this).data('subscribe_groups').toString().split(','), function (e, v) { 630 v = v == '' ? 0 : parseInt(v) 631 if (v > 0) { _new_d.push(v) } 632 }) 633 $(this).data('subscribe_groups', _new_d) 634 }) 635 636 $drop_shopping_group_list.each(function () { 637 let member_data = '' + $(this).data('groups') 638 member_data = member_data.split(',') 639 const _new_d = [] 640 $.each(member_data, function (e, v) { 641 v = v == '' ? 0 : parseInt(v) 642 _new_d.push(v) 643 }) 644 $(this).data('groups', _new_d) 645 }) 646 647 $check_drop_group_list = $('._check_drop_group_list') 648 $check_drop_group_list.data('member', []) 649 $check_drop_group_list.data('groups', []) 650 651 $check_drop_shopping_group_list = $('._check_drop_shopping_group_list') 652 $check_drop_shopping_group_list.data('member', []) 653 $check_drop_shopping_group_list.data('groups', []) 654 } 655 656 const openGroupForm = function (idx, group_type) { 657 $.ajax({ 658 type: 'POST', 659 data: { idx, type: modal_type, group_type }, 660 url: ('/admin/ajax/config/membership/group_form.cm'), 661 dataType: 'json', 662 async: false, 663 cache: false, 664 success: function (result) { 665 if (result.msg == 'SUCCESS') {
666 $.cocoaDialog.open({ type: 'admin_group_form', custom_popup: result.html, width: 550 }) 667 } else { 668 alert(result.msg) 669 } 670 } 671 }) 672 } 673 674 const concedeChangeSpecialGroup = function (type, obj, idx) { 675 const $list = obj.closest('._drop_shopping_group_list, ._check_drop_shopping_group_list') 676 const member_idx = $list.data('member') 677 678 let _idx = -1 679 680 if (!$.isArray(member_idx)) { 681 if ($list.find('.' + type + '.active.checked').length == 0) return false 682 _idx = $list.find('.' + type + '.active.checked').data('idx') 683 } 684 685 if (idx != _idx) { 686 idx = parseInt(idx) 687 688 let old_data = {} 689 $.ajax({ 690 type: 'POST', 691 data: { group_type: type, member_idx, new_group_code: idx }, 692 url: '/admin/ajax/member/group_concede_proc.cm', 693 dataType: 'json', 694 async: true, 695 cache: false, 696 success: function (result) { 697 if (result.msg == 'SUCCESS') { 698 const new_data = group_list_data.get(obj.parent().data('code')) 699 const _group = new_data.title 700 701 if ($.isArray(member_idx)) { 702 $.each(member_idx, function (e, v) { 703 $('._drop_shopping_group_btn_' + v).html(_group) 704 $('._drop_shopping_group_list_' + v).data('groups', [idx]) 705 706 $.each(group_list_data.data, function (index, item) { 707 if (item.idx === idx) { 708 old_data = item 709 return false 710 } 711 }) 712 713 // old_data = group_list_data.get($('._drop_shopping_group_list_' + v).find('.active.checked').data('code')); 714 old_data.member_cnt -= 1 715 new_data.member_cnt = new_data.member_cnt == '' ? 0 : new_data.member_cnt 716 new_data.member_cnt += 1 717 }) 718 } else { 719 $('._drop_shopping_group_btn_' + member_idx).html(_group) 720 $('._drop_shopping_group_list_' + member_idx).data('groups', [idx]) 721 722 // old_data = group_list_data.get($('._drop_shopping_group_list_' + member_idx).find('.active.checked').data('code')); 723 $.each(group_list_data.data, function (index, item) { 724 if (item.idx === idx) { 725 old_data = item 726 return false 727 } 728 }) 729 old_data.member_cnt -= 1 730 new_data.member_cnt = new_data.member_cnt == '' ? 0 : new_data.member_cnt 731 new_data.member_cnt += 1 732 } 733 734 resetGroupListHtml() 735 MEMBER_DATA.renderGroupCount(idx) 736 } else { 737 alert(result.msg) 738 } 739 } 740 }) 741 742 $list.data('groups', [idx]) 743 } 744 } 745 746 const concedeToggleGroup = function (obj, idx) { 747 idx = parseInt(idx) 748 const $list = obj.closest('._drop_group_list, ._check_drop_group_list') 749 let member_item_group_data = $list.data('groups') 750 let member_item_subscribe_data = $list.data('subscribe_groups') 751 const member_idx = $list.data('member') 752 753 const $item = obj.parent() 754 const item_data = $item.data() 755 const _old_data = group_list_data.get(item_data.code) 756 757 // ë¤ì¤ ì í ì 758 if ($.isArray(member_idx)) { 759 if (member_idx.length > 1) { 760 const confirmationMessage = 'ì íí íìë¤ì ê³µíµ ê·¸ë£¹ì ì´ë² ë³ê²½ì ì ì©íì¬, 모ë ì í íìì 그룹ì ëì¼íê² ì¤ì í©ëë¤.\nê° íìì´ ê°ë³ì ì¼ë¡ ìí ë¤ë¥¸ 그룹ì í´ì ë©ëë¤.\n\nì§ííìê² ìµëê¹?' 761 if (!confirm(confirmationMessage)) return false 762 } 763 764 // ì´ì©ê¶ ê²½ê³ ìì ì·¨ìí´ë 기존 ì í ë°°ì´ì´ ë³ê²½ëì§ ìëë¡ ë³µì¬íë¤. 765 member_item_group_data = member_item_group_data.concat() 766 // ë³ê²½ë ë°ì´í° ë§ë¤ì´ 주기 767 if ($.inArray(idx, member_item_group_data) !== -1) { // ì ê±° 768 member_item_group_data = deleteArrayValue(member_item_group_data, idx) 769 } else { // ì¶ê° 770 member_item_group_data.push(idx) 771 } 772 773 // íì그룹ì´ì©ê¶ 구매 íìì´ í¬í¨ëì´ìëì§ ì²´í¬ 774 let subscribe_group_exist_check = 0 775 $.each(member_idx, function (e, v) { 776 const $drop_list = $('._drop_group_list_' + v) 777 const _member_item_subscribe_data = $drop_list.data('subscribe_groups') 778 if (_member_item_subscribe_data.length > 0) { // ì´ì©ê¶ 구매í´ì í¬í¨ë íìì´ ì¡´ì¬ ì 779 subscribe_group_exist_check++ 780 } 781 }) 782 if ((subscribe_group_exist_check != 0) && 783 !confirm(getLocalizeString('ì¤ëª _íì그룹ì´ì©ê¶êµ¬ë§¤íìí¬í¨ìë´', subscribe_group_exist_check, 'í´ë¹ 그룹ì íì그룹 ì´ì©ê¶ êµ¬ë§¤ë¡ ìë ì§ì ë 그룹 ì¬ì©ìê° %1ëª ì´ì í¬í¨ëì´ ììµëë¤. 그룹 ì§ì ì í´ì íê³ ëì¤ì ë¤ì 그룹ì ì§ì íëë¼ë ìë 그룹 í´ì ì¼ì ìë í´ì ê° ëì§ ìê²ë©ëë¤.\n\n그룹 ì§ì ì í´ì íìê² ìµëê¹?'))) { 784 return false 785 } 786 $list.data('groups', member_item_group_data) 787 788 $.each(member_idx, function (e, v) { 789 const $drop_list = $('._drop_group_list_' + v) 790 const _member_item_group_data = $drop_list.data('groups') 791 $.each(member_item_group_data, function (_e, _v) { 792 if ($.inArray(_v, _member_item_group_data) === -1) { // ìì¼ë©´ ì¶ê° 793 _old_data.member_cnt = _old_data.member_cnt == '' ? 0 : _old_data.member_cnt 794 _old_data.member_cnt = 1 + parseInt(_old_data.member_cnt) 795 } 796 }) 797 $.each(_member_item_group_data, function (_e, _v) { 798 if ($.inArray(_v, member_item_group_data) === -1) { // ìì¼ë©´ ì ê±° 799 let __old_data = false 800 $.each(group_list_data.data, function (__e, __v) { 801 if (__v.idx == _v) { 802 __old_data = group_list_data.get(__e) 803 return false 804 } 805 }) 806 if (__old_data !== false) { 807 __old_data.member_cnt = parseInt(__old_data.member_cnt) - 1 808 } 809 } 810 }) 811 $drop_list.data('groups', member_item_group_data.concat()) 812 $drop_list.data('subscribe_groups', []) 813 }) 814 } 815 // ëì íì ì íëª 816 else { 817 if ($.inArray(idx, member_item_group_data) !== -1) { // ì ê±° 818 if ($.inArray(idx, member_item_subscribe_data) !== -1) { // ì ê±° 819 if (!confirm(getLocalizeString('ì¤ëª _íì그룹ì´ì©ê¶êµ¬ë§¤ë¡ì§ì ë그룹ì ê±°ììë´', '', 'ì´ ê·¸ë£¹ì íì그룹 ì´ì©ê¶ êµ¬ë§¤ë¡ ìë ì§ì ë 그룹ì ëë¤. \n그룹ì§ì ì í´ì íê³ ëì¤ì ë¤ì 그룹ì ì§ì íëë¼ë ìë 그룹 í´ì ì¼ì ìë í´ì ê° ëì§ ìê² ë©ëë¤.\n\n그룹 ì§ì ì í´ì íìê² ìµëê¹?'))) { 820 return false 821 } 822 member_item_subscribe_data = deleteArrayValue(member_item_subscribe_data, idx) 823 $list.data('subscribe_groups', member_item_subscribe_data) 824 } 825 826 member_item_group_data = deleteArrayValue(member_item_group_data, idx) 827 $list.data('groups', member_item_group_data) 828 _old_data.member_cnt = parseInt(_old_data.member_cnt) - 1 829 } else { // ì¶ê° 830 if (typeof member_item_group_data !== 'object') { 831 member_item_group_data = member_item_group_data.split(',') 832 } 833 834 member_item_group_data.push(idx) 835 $list.data('groups', member_item_group_data) 836 _old_data.member_cnt = _old_data.member_cnt == '' ? 0 : _old_data.member_cnt 837 _old_data.member_cnt = 1 + parseInt(_old_data.member_cnt) 838 } 839 } 840 841 $.ajax({ 842 type: 'POST', 843 data: { member_idx, new_group_code: member_item_group_data }, 844 url: ('/admin/ajax/member/group_concede_proc.cm'), 845 dataType: 'json', 846 async: true, 847 cache: false, 848 success: function (result) { 849 if (result.msg == 'SUCCESS') { 850 const check_member = $check_drop_group_list.data('member') 851 checkMember(check_member) 852 853 let main_group_title = '' 854 let i = 0 855 if ($.isArray(member_idx)) { 856 $.each(member_idx, function (e, v) { 857 let main_group_title = '' 858 let i = 0 859 const $drop_list = $('._drop_group_list_' + v) 860 const _member_item_group_data = $drop_list.data('groups') 861 $.each(group_list_data.data, function (code, data) { 862 data.idx = parseInt(data.idx) 863 if ($.inArray(data.idx, _member_item_group_data) !== -1) { 864 if (i == 0) { main_group_title = data.title } 865 i++ 866 } 867 }) 868 let _group = '' 869 if (i == 0) { 870 _group = getLocalizeString('ì¤ëª _그룹ìì', '', '그룹ìì') 871 } else { 872 _group = main_group_title + '<span class="text-primary">' + (i > 1 ? '+' + (i - 1) : '') + '</span>' 873 } 874 875 calculateNoGroup($drop_list, i) 876 $('._drop_group_btn_' + v).html(_group) 877 }) 878 } else { 879 $.each(group_list_data.data, function (code, data) { 880 if ($.inArray(data.idx, member_item_group_data) !== -1) { 881 if (i == 0) { main_group_title = data.title } 882 i++ 883 } 884 }) 885 let _group = '' 886 if (i == 0) { 887 _group = getLocalizeString('ì¤ëª _그룹ìì', '', '그룹ìì') 888 } else { 889 _group = main_group_title + '<span class="text-primary">' + (i > 1 ? '+' + (i - 1) : '') + '</span>' 890 } 891 892 calculateNoGroup($list, i) 893 894 $('._drop_group_btn_' + member_idx).html(_group) 895 } 896 897 resetGroupListHtml() 898 MEMBER_DATA.renderGroupCount(member_item_group_data) 899 } else { 900 alert(result.msg) 901 } 902 } 903 }) 904 } 905 906 var calculateNoGroup = function (obj, cnt) { 907 let _no_group_cnt = $no_group_cnt.text().trim() 908 if (_no_group_cnt === '9999+') { 909 return 910 } 911 _no_group_cnt = _no_group_cnt == '' ? 0 : _no_group_cnt 912 _no_group_cnt = parseInt(_no_group_cnt) 913 if (cnt == 0) { 914 if (obj.data('nogroup') == 'N') { 915 obj.data('nogroup', 'Y') 916 _no_group_cnt = _no_group_cnt + 1 917 $no_group_cnt.text(_no_group_cnt) 918 } 919 } else { 920 if (obj.data('nogroup') == 'Y') { 921 obj.data('nogroup', 'N') 922 _no_group_cnt = _no_group_cnt - 1 923 $no_group_cnt.text(_no_group_cnt) 924 } 925 } 926 } 927 928 var checkMember = function (idxs) { 929 const $list = $('._drop_group_list_' + idxs[0]) 930 931 if ($list.length > 0) { 932 var res = $list.data('groups').concat() 933 $.each(idxs, function (e, v) { 934 res = array_intersect(res, $('._drop_group_list_' + v).data('groups').concat()) 935 }) 936 var result = [] 937 $.each(res, function (e, v) { 938 v = v == '' ? 0 : parseInt(v) 939 if (v > 0) { result.push(v) } 940 }) 941 $check_drop_group_list.data('groups', result) 942 $check_drop_group_list.data('member', idxs) 943 } 944 945 // ì¼íë±ê¸ 946 const $shopping_list = $('._drop_shopping_group_list_' + idxs[0]) 947 if ($shopping_list.length > 0) { 948 var res = $shopping_list.data('groups').concat() 949 $.each(idxs, function (e, v) { 950 res = array_intersect(res, $('._drop_shopping_group_list_' + v).data('groups').concat()) 951 }) 952 var result = [] 953 $.each(res, function (e, v) { 954 v = v == '' ? 0 : parseInt(v) 955 result.push(v) 956 }) 957 $check_drop_shopping_group_list.data('member', idxs) 958 $check_drop_shopping_group_list.data('groups', result) 959 } 960 961 resetGroupListHtml() 962 } 963 964 const getGroupList = function () { 965 return group_list_data 966 } 967 968 const changeJoinTypeDefaultGroup = function (type_code, group_code) { 969 $.ajax({ 970 type: 'POST', 971 data: { type_code, group_code }, 972 url: ('/admin/ajax/member/update_join_type_default_group.cm'), 973 dataType: 'json', 974 async: true, 975 cache: false, 976 success: function (result) { 977 if (result.msg !== 'SUCCESS') { 978 alert(result.msg) 979 } 980 } 981 }) 982 } 983 984 const setGroupCheck = function (idx) { 985 const check_member = $('._drop_group_list_' + idx).data('groups') 986 checkMember(check_member) 987 } 988 989 const setShoppingGroupCheck = function (idx) { 990 const check_member = $('._drop_shopping_group_list_' + idx).data('groups') 991 checkMember(check_member) 992 } 993 994 return { 995 init: function (code, base_url, permission, type) { 996 init(code, base_url, permission, type) 997 }, 998 getModalType: function () { 999 return modal_type 1000 }, 1001 addGroupList: function (data) { 1002 addGroupList(data) 1003 }, 1004 updateGroupList: function (code, data) { 1005 updateGroupList(code, data) 1006 }, 1007 modifyGroupList: function (type, data) { 1008 modifyGroupList(type, data) 1009 }, 1010 openGroupForm: function (idx, type) { 1011 openGroupForm(idx, type) 1012 }, 1013 concedeChangeSpecialGroup: function (type, obj, idx) { 1014 concedeChangeSpecialGroup(type, obj, idx) 1015 }, 1016 concedeToggleGroup: function (obj, idx) { 1017 concedeToggleGroup(obj, idx) 1018 }, 1019 checkMember: function (idxs) { 1020 checkMember(idxs) 1021 }, 1022 getGroupList: function () { 1023 return getGroupList() 1024 }, 1025 changeJoinTypeDefaultGroup: function (type_code, group_code) {
1026 return changeJoinTypeDefaultGroup(type_code, group_code) 1027 }, 1028 addDropGroupList: function (data) { 1029 addDropGroupList(data) 1030 }, 1031 setGroupMemberCount: function (data) { 1032 setGroupMemberCount(data) 1033 }, 1034 setGroupCheck: function (idx) { 1035 setGroupCheck(idx) 1036 }, 1037 setShoppingGroupCheck: function (idx) { 1038 setShoppingGroupCheck(idx) 1039 }, 1040 setCheck: function () { 1041 setCheck() 1042 }, 1043 resetGroupListHtml: function () { 1044 resetGroupListHtml() 1045 }, 1046 setPrevDropGroupType: function (type) { 1047 prev_drop_group_type = type 1048 }, 1049 setCurrentMemberCode: function (code) { 1050 setCurrentMemberCode(code) 1051 } 1052 } 1053}()) 1054 1055const MEMBER_GROUP_SETTING_MODAL = (function () { 1056 let $form, $group_benefit, $member_group_benefit 1057 let group_list = {} 1058 let current_group_type = 'member' 1059 let current_unit_code = '' 1060 1061 const init = function (unit_code, code, type) { 1062 $form = $('#groupf') 1063 $group_benefit = $('#group_benefit_setting') 1064 $member_group_benefit = $('#member_group_benefit_setting') 1065 setGroupListData(code) 1066 1067 current_unit_code = unit_code 1068 addEvent() 1069 1070 if (typeof type !== 'undefined' && type != '') { 1071 changeGroupType(type) 1072 } 1073 } 1074 var addEvent = function () { 1075 $form.find('#group_type').on('change', function () { 1076 changeGroupType($(this).val()) 1077 }) 1078 1079 // ìëë±ê¸ ì¡°ê±´ ì¤ì 1080 $form.find('#shopping_auto_grouping_not_used').on('change', function () { 1081 changeUseAutoGrouping($(this).prop('checked')) 1082 }) 1083 1084 $form.find('.auto_grouping_flag').on('blur', function () { 1085 changeFlagAmount($(this)) 1086 }) 1087 1088 // 구매íí ì¤ì ë¶ë¶ 1089 $form.find('.benefit_type_radio').find(':radio').on('change', function () { 1090 changeBenefitType() 1091 }) 1092 $group_benefit.find('.group_benefit select').on('change', function () { 1093 const is_percent = ($(this).val() == 'percent') 1094 $(this).parents('.input-group').find('.benefit_maximum').toggle(is_percent) 1095 $(this).parents('.input-group').find('.benefit_maximum').find('input').prop('disabled', !is_percent) 1096 1097 // ë³ê²½ì íí ê° ì´ê¸°í 1098 const $amount = $(this).parents('.input-group').find('._benefit_money_format:nth-child(1)') 1099 $amount.val(0) 1100 makeMoneyFormat($amount, !is_percent) 1101 }) 1102 1103 $group_benefit.find('input[type="text"]').on('blur', function () { 1104 const v = parseFloat($(this).val()) 1105 if (v === 0) $(this).val(v) 1106 }) 1107 1108 $form.find('.auto_grouping_flag').each(function () { 1109 makeMoneyFormat($(this), true) 1110 }) 1111 $form.find('._benefit_money_format').each(function () { 1112 let use_format = true 1113 if ($(this).hasClass('_benefit_amount')) { 1114 use_format = ($(this).parents('.input-group').find('select').val() == 'price') 1115 } 1116 makeMoneyFormat($(this), use_format) 1117 }) 1118 } 1119 1120 var makeMoneyFormat = function ($obj, use_format) { 1121 $obj.unbind('keydown.format keyup.format') 1122 if (use_format) { 1123 set_money_format($obj, $obj.data('decimal-count'), $obj.data('decimal-char'), $obj.data('thousand-char')) 1124 } 1125 } 1126 1127 // íì¬ ê·¸ë£¹ ë°ì´í° ê¸°ì¤ ì¡°ê±´ 리ì¤í¸ ìì± 1128 var setGroupListData = function (cd) { 1129 const group_list_data = MEMBER_GROUP.getGroupList() 1130 group_list = { shopping: [], activity: [] } 1131 1132 const auto_set_group_list = ['shopping', 'activity'] 1133 $.each(group_list_data.data, function (code, data) { 1134 if (cd === code) { 1135 current_group_type = data.group_type 1136 return true 1137 } 1138 if (auto_set_group_list.indexOf(data.group_type) < 0) return true 1139 let auto_grouping_data = data.auto_grouping_data 1140 1141 switch (data.group_type) { 1142 case 'shopping': 1143 if (data.use_auto_change != 'Y') break 1144 for (const key in auto_grouping_data) { 1145 if (typeof group_list[data.group_type][key] === 'undefined') { 1146 group_list[data.group_type][key] = [] 1147 } 1148 auto_grouping_data[key] = parseFloat(auto_grouping_data[key]) 1149 group_list[data.group_type][key].push(auto_grouping_data[key]) 1150 } 1151 break 1152 case 'activity': 1153 auto_grouping_data = parseFloat(auto_grouping_data) 1154 group_list[data.group_type].push(auto_grouping_data) 1155 break 1156 } 1157 }) 1158 } 1159
1160 // 그룹 ì í ë³ê²½ ì 1161 var changeGroupType = function (type) { 1162 current_group_type = type 1163 $form.find('.group_setting').hide() 1164 $form.find('.group_setting.' + type + '_group_setting').show() 1165 switch (type) { 1166 case 'member': 1167 case 'admin': 1168 // changeBenefitType(); 1169 break 1170 case 'shopping': 1171 changeBenefitType() 1172 changeUseAutoGrouping($form.find('#shopping_auto_grouping_not_used').prop('checked')) 1173 break 1174 case 'activity': 1175 $group_benefit.hide() 1176 break 1177 } 1178 } 1179 1180 // ì¼íì¤ì - ìë ë±ê¸ ì¬ì© ìí¨ 1181 var changeUseAutoGrouping = function (b) { 1182 $('#auto_grouping_setting').toggle(!b) 1183 } 1184 1185 // ìëë±ê¸ ì¡°ê±´ ê¸ì¡ ë³ê²½ì on blur ì²ë¦¬ 1186 var changeFlagAmount = function ($obj) { 1187 if ($obj.length <= 0) return false 1188 1189 let v = parseFloat($obj.val()) 1190 v = (isNaN(v)) ? 0 : v 1191 $obj.val(v) 1192 const code = $obj.data('code') 1193 1194 $form.find('.help_group_flag_setting_' + code).hide() 1195 1196 if (v < 0) { 1197 $form.find('.help_group_flag_setting_' + $obj.data('code')).html(getLocalizeString('ì¤ëª _ìëë±ê¸ì¡°ê±´ì0ë³´ë¤í°ê°ìì ë ¥í´ì¼í©ëë¤', '', 'ìë ë±ê¸ ì¡°ê±´ì 0ë³´ë¤ í° ê°ì ì ë ¥í´ì¼ í©ëë¤.')).show() 1198 return 'MINUS' 1199 } else { 1200 // ì´ë¯¸ ë±ë¡ë ì¡°ê±´ì¸ì§ ì²´í¬ 1201 if (typeof group_list[current_group_type] !== 'undefined') { 1202 let auto_grouping_list = group_list[current_group_type] 1203 if (typeof code !== 'undefined' && typeof auto_grouping_list[code] !== 'undefined') { 1204 auto_grouping_list = auto_grouping_list[code] 1205 } 1206 1207 if (auto_grouping_list.indexOf(v) > -1) { 1208 $form.find('.help_group_flag_setting_' + code).html(getLocalizeString('ì¤ëª _ë¤ë¥¸ê·¸ë£¹ììì¤ì íì¡°ê±´ê³¼ëì¼íì¡°ê±´ìì ë ¥í ìììµëë¤', '', 'ë¤ë¥¸ 그룹ìì ì¤ì í ì¡°ê±´ê³¼ ëì¼í ì¡°ê±´ì ì ë ¥í ì ììµëë¤.')).show() 1209 return 'EXIST' 1210 } 1211 } 1212 } 1213 1214 return true 1215 } 1216 1217 // ( ê¸ë¡ë² ì¬ì´í¸ ) ì¼ë°íì그룹 구매íí í ë³ê²½ì 1218 const changeMemberGroupBenefitTarget = function (obj) { 1219 const $obj = $(obj) 1220 const unit_code = $obj.data('code') 1221 current_unit_code = unit_code 1222 $('#member_group_benefit_setting_tab').find('li.active').removeClass('active') 1223 $obj.parent('li').addClass('active') 1224 $member_group_benefit.find('._member-group-benefit-tab-content').addClass('hidden') 1225 $member_group_benefit.find('._member-group-benefit-tab-content#member_group_benefit_' + unit_code).removeClass('hidden') 1226 } 1227 1228 // ( ê¸ë¡ë² ì¬ì´í¸ ) 구매íí í ë³ê²½ì 1229 const changeBenefitTarget = function (obj) { 1230 const $obj = $(obj) 1231 const unit_code = $obj.data('code') 1232 current_unit_code = unit_code 1233 1234 $('#benefit_setting_tab').find('li.active').removeClass('active') 1235 $obj.parent('li').addClass('active') 1236 1237 $group_benefit.find('.tab-content').addClass('hidden') 1238 $group_benefit.find('.tab-content#group_benefit_' + unit_code).removeClass('hidden') 1239 } 1240 1241 // 그룹 íí ë³ê²½ ì 1242 var changeBenefitType = function () { 1243 $group_benefit.show() 1244 const $group_benefit_obj = $group_benefit.find('#group_benefit_' + current_unit_code) 1245 $group_benefit_obj.find('.group_benefit').hide() 1246 1247 const benefit_type = $group_benefit_obj.find(':radio:checked').val() 1248 switch (benefit_type) { 1249 case 'dc': 1250 case 'point': 1251 $group_benefit_obj.find('.group_benefit.benefit_type_' + benefit_type).show() 1252 break 1253 case 'all': 1254 $group_benefit_obj.find('.group_benefit').show() 1255 break 1256 } 1257 } 1258 1259 // 구ëªíí ì²´í¬ 1260 const checkBenefit = function () { 1261 if (current_group_type != 'shopping') return true // ì¼íê·¸ë£¹ë§ ì¬ì©í¨ 1262 if ($group_benefit.length <= 0) return true // ì¼í ì¬ì© ìí¨ ë±ì ì´ìë¡ ííì´ ìì ê²½ì° 1263 1264 let $target 1265 const benefit_type = $group_benefit.find(':radio[name=benefit_type]:checked').val() 1266 switch (benefit_type) { 1267 case 'dc': 1268 case 'point': 1269 $target = $group_benefit.find('.group_benefit.benefit_type_' + benefit_type) 1270 break 1271 case 'all': 1272 $target = $group_benefit.find('.group_benefit') 1273 break 1274 } 1275 1276 if (typeof $target === 'undefined') return true 1277 1278 let benefit_error = false 1279 $target.find('input').each(function () { 1280 if ($(this).prop('disabled')) return true 1281 const amt = parseFloat($(this).val()) 1282 if (isNaN(amt) || amt <= 0) { 1283 benefit_error = true 1284 } 1285 }) 1286 return !benefit_error 1287 } 1288 1289 // ì í¨ì± ê²ì¬ 1290 const checkValidateForm = function () { 1291 if (current_group_type == 'activity' || current_group_type == 'shopping') { 1292 let check = true 1293 const $obj = $form.find('.' + current_group_type + '_group_setting').find('.auto_grouping_flag') 1294 if ($obj.length > 0) { 1295 $obj.each(function () { 1296 if (check !== true) return true
1297 check = changeFlagAmount($(this)) 1298 }) 1299 } 1300 if (check !== true) { 1301 switch (check) { 1302 case 'MINUS': 1303 alert(getLocalizeString('ì¤ëª _ìëë±ê¸ì¡°ê±´ì0ë³´ë¤í°ê°ìì ë ¥í´ì¼í©ëë¤', '', 'ìë ë±ê¸ ì¡°ê±´ì 0ë³´ë¤ í° ê°ì ì ë ¥í´ì¼ í©ëë¤.')) 1304 break 1305 case 'EXIST': 1306 alert(getLocalizeString('ì¤ëª _ìëë±ê¸ì¡°ê±´ì´ë¤ë¥¸ë±ê¸ê³¼ëì¼í©ëë¤ìëë±ê¸ì¡°ê±´ììì í´ì£¼ì¸ì', '', 'ìë ë±ê¸ ì¡°ê±´ì´ ë¤ë¥¸ ë±ê¸ê³¼ ëì¼í©ëë¤. ìë ë±ê¸ ì¡°ê±´ì ìì í´ ì£¼ì¸ì.')) 1307 break 1308 } 1309 return false 1310 } 1311 } 1312 if (!checkBenefit()) { 1313 alert(getLocalizeString('ì¤ëª _í ì¸ê¸ì¡ë°ìµëí ì¸ê¸ì¡ì0ë³´ë¤í°ê°ìì ë ¥í´ì¼í©ëë¤', '', 'í ì¸ ê¸ì¡ ë° ìµë í ì¸ ê¸ì¡ì 0ë³´ë¤ í° ê°ì ì ë ¥í´ì¼ í©ëë¤.')) 1314 return false 1315 } 1316 return true 1317 } 1318 1319 // 그룹ì¤ì ì ì¥ 1320 const saveGroupForm = function () { 1321 if (!checkValidateForm()) { 1322 return false 1323 } 1324 const data = $form.serializeObject() 1325 const admin_group_setting = $('.admin_group_setting').find('input').serialize() 1326 data.modal_type = MEMBER_GROUP.getModalType() 1327 if (admin_group_setting == '' && data.group_type == 'admin') { 1328 if (confirm(getLocalizeString('ì¤ëª _1ê°ì´ììê¶íì´ë¶ì¬ëì§ìì그룹ìì¼ë°ê·¸ë£¹ì¼ë¡ì íë©ëë¤', '', '1ê° ì´ìì ê¶íì´ ë¶ì¬ëì§ ìì 그룹ì ì¼ë°ê·¸ë£¹ì¼ë¡ ì íëë©°\ní´ë¹ ì´ì 그룹ìë§ ìí ì¬ì©ìë¤ì ì¼ë°íìì¼ë¡ ì íë©ëë¤.\n그룹 ê¶íì ì ì¥íìê² ìµëê¹?'))) { 1329 $.ajax({ 1330 type: 'POST', 1331 data, 1332 url: ('/admin/ajax/config/membership/group_form_proc.cm'), 1333 dataType: 'json', 1334 async: false, 1335 cache: false, 1336 success: function (result) { 1337 if (result.msg == 'SUCCESS') { 1338 location.reload() 1339 } else { 1340 if (result.msg == 'VERSION ERROR') { 1341 if (confirm(LOCALIZE_ADMIN.ì¤ëª _ì ê·¸ë ì´ëíì´ì§ë¡ì´ëí ê¹ì())) { 1342 window.location.href = '/admin/payment?mode=detail&type=upgrade' 1343 } 1344 } else { 1345 alert(result.msg) 1346 } 1347 } 1348 } 1349 }) 1350 } else { 1351 return false 1352 } 1353 } else { 1354 $.ajax({ 1355 type: 'POST', 1356 data, 1357 url: ('/admin/ajax/config/membership/group_form_proc.cm'), 1358 dataType: 'json', 1359 async: false, 1360 cache: false, 1361 success: function (result) { 1362 if (result.msg == 'SUCCESS') { 1363 location.reload() 1364 } else { 1365 if (result.msg == 'VERSION ERROR') { 1366 if (confirm(LOCALIZE_ADMIN.ì¤ëª _ì ê·¸ë ì´ëíì´ì§ë¡ì´ëí ê¹ì())) { 1367 window.location.href = '/admin/payment?mode=detail&type=upgrade' 1368 } 1369 } else { 1370 alert(result.msg) 1371 } 1372 } 1373 } 1374 }) 1375 } 1376 } 1377 1378 // ì¢ ë£ì ì½ë°± 1379 const saveCallBack = function (result) { 1380 const modal_type = MEMBER_GROUP.getModalType() 1381 result.data.idx = parseInt(result.data.idx) 1382 if (modal_type == 'config') { 1383 // ì¼íì´ë©´ ì¼íì¼ë¡ ë¶ê²ë í´ì¼í¨ 1384 MEMBER_GROUP.modifyGroupList(result.mode, result.data) 1385 if (typeof CONFIG_MEMBERSHIP !== 'undefined') { 1386 CONFIG_MEMBERSHIP.addGroupHtml(result.data) 1387 } 1388 } else { 1389 if (result.mode == 'add') { 1390 MEMBER_GROUP.addGroupList(result.data) 1391 window.doznutadmin.AppForm.initialize() 1392 } else if (result.mode == 'update') { 1393 MEMBER_GROUP.updateGroupList(result.data.code, result.data) 1394 } 1395 } 1396 } 1397 1398 return { 1399 init: function (unit_code, code, type) { 1400 init(unit_code, code, type) 1401 }, 1402 changeBenefitTarget: function (obj) { 1403 changeBenefitTarget(obj) 1404 }, 1405 changeMemberGroupBenefitTarget: function (obj) { 1406 changeMemberGroupBenefitTarget(obj) 1407 }, 1408 saveGroupForm: function () { 1409 saveGroupForm() 1410 } 1411 } 1412}()) 1413 1414 // ì¸ë¶ ë°ì¡Â·ì¶©ì ì°¨ë¨(ìë² íì ). **íì ë¡ì§ì JS ì ë³µì íì§ ìëë¤** â ìë²ê° ë´ë ¤ì¤ 1415 // ë¶ë¦¬ì¸(window.siteOutboundBlocked)ë§ ë³¸ë¤. ì¬ì ë ìë¦¬ì§ ìëë¤(ì°í ì¡°ê±´ ìì° ë°©ì§). 1416 const isSiteOutboundBlocked = function () { 1417 return window.siteOutboundBlocked === true 1418 } 1419 1420 // **ë¹ì© ì¶ë§** 본 ì°¨ë¨(ìë²ê° window.siteOutboundBlockedByCost ë¡ ë´ë ¤ì¤ë¤). ìì ëª ë¨ ë±ë¡Â· 1421 // ì¶©ì ì§ì ì´ ì´ê±¸ ë³¸ë¤ â ê·¸ íë©´ë¤ì ë°ì¡ì ë§ë¤ì§ ìì¼ë¯ë¡ 2ì°¨ ì¸ì¦ ì¶ì 걸면 과차ë¨ì´ë¤ 1422 // (ì¬ì©ì íì , 2026-10-07: #22817 ë¤ 2ì°¨ ì¸ì¦ 미ì¤ì ì¬ì´í¸ìì ì¶©ì Â·ëª ë¨ ë±ë¡ê¹ì§ ë§íë¤). 1423 // 1424 // **구ë²ì íì´ì§(ë¡¤ë§ ë°°í¬ ì°½)ììë 기존 ë¶ë¦¬ì¸ì¼ë¡ ì ëë¤.** ì ë¶ë¦¬ì¸ì ìì§ ì ë´ë ¤ì£¼ë 1425 // ìë²ë¥¼ ë§ëë©´ `undefined` ì´ë¯ë¡, ê·¸ë ì¢ ì ê°(2ì°¨ ì¸ì¦ í¬í¨)ì ê·¸ëë¡ ë°ë¥¸ë¤ â ê·¸ìª½ì´ 1426 // **ë ì격í** íì ì´ë¼ ìë ë°©í¥ì´ ìëë¤(ë¹ì© ì¶ì ë íì 모ëì ë¤ì´ ìë¤). 1427 const isSiteOutboundBlockedByCost = function () { 1428 if (typeof window.siteOutboundBlockedByCost === 'boolean') { 1429 return window.siteOutboundBlockedByCost === true 1430 } 1431 1432 return isSiteOutboundBlocked() 1433 } 1434 1435 // 2ì°¨ ì¸ì¦ ì¬ì ë¡ ë§í ê²½ì°, **ì ë§íëì§ì ì¼ë ë°©ë²**ì ëì´ë¤(ìë²ê° 문구를 ë´ë ¤ì¤ë¤). 1436 // 기존 ì¬ì (ë§ë£Â·ì ê·Â·ë¬´ë£ì²´í)ë ë¬¸êµ¬ê° ë¹ ë¬¸ìì´ì´ë¼ **ì¢ ì ì²ë¼ ì¡°ì©í ëëë¤** â ì¬ì 를 1437 // ìë ¤ 주면 ì°í ì¡°ê±´ì ìì°íë¤(2026-10-01 ê²°ì ). 문구ë ìë²ê° ë§ë¤ê³ JS ë ê·¸ë¦¬ê¸°ë§ íë¤ 1438 // (íì ë¡ì§ì JS ì ë³µì íì§ ìëë¤). 1439 const showSiteOutboundGuide = function () { 1440 if (typeof window.siteOutboundBlockedGuide === 'string' && window.siteOutboundBlockedGuide !== '') { 1441 alert(window.siteOutboundBlockedGuide) 1442 if (typeof window.siteOutboundBlockedGuideUrl === 'string' && window.siteOutboundBlockedGuideUrl !== '') {
1443 // ì¤ì íë©´ì¼ë¡ ë°ë¡ ê° ì ìê² ì ì°½ì¼ë¡ ì°ë¤ â ëª©ë¡ íë©´ ìí를 ìì§ ìëë¤. 1444 window.open(window.siteOutboundBlockedGuideUrl, '_blank') 1445 } 1446 } 1447 return false 1448 } 1449 1450const MEMBER_EXCEL = (function () { 1451 let $member_multi_add_status, $msg_section 1452 let $group_multi_add_status 1453 1454 const resultExcelDownload = (status, result_idx) => { 1455 if(status === 'ìë£'){ 1456 return location.href = `/admin/ajax/member/download_excel_member_in_group_result.cm?result_idx=${result_idx}` 1457 } else if (status === 'ì§íì¤') { 1458 alert('ê²°ê³¼ ìì ìì±ì¤ ì ëë¤.'); 1459 } else { 1460 alert('ê²°ê³¼ ìì ìì±ì´ ì¤í¨ íììµëë¤'); 1461 } 1462 } 1463 const loadGroupExcelResult = function () { 1464 const modalMultiMemberAdd = $('.modal_multi_member_add') 1465 const excelResultTable = modalMultiMemberAdd.find('#_excel_list_body'); 1466 const excelEmptyWrap = modalMultiMemberAdd.find('._excel_empty_wrap'); 1467 $.ajax({ 1468 type: 'GET', 1469 url: ('/admin/ajax/member/get_excel_member_in_group_list.cm'), 1470 dataType: 'json', 1471 success: function (res){ 1472 if(res.length !== 0){ 1473 excelEmptyWrap.hide(); 1474 excelResultTable.empty(); 1475 for(let i = 0; i < res.list.length; i++){ 1476 const excelResult = res.list[i]; 1477 const row = $('<tr>'); 1478 const excelDownloadResultText = excelResult.status === 'ìë£' ? 'ë¤ì´ë¡ë' : 'ìì±ì¤'; 1479 1480 row.append(`<td style="overflow: hidden; max-width: 114px; white-space: nowrap; text-overflow: ellipsis; word-break: break-all">${excelResult.group_name}</td>`); 1481 row.append(`<td>${excelResult.request_datetime}</td>`); 1482 row.append(`<td class="text-center">${excelResult.status}</td>`); 1483 row.append(` 1484 <th class="download_btn text-right make_complete text-primary" 1485 style="padding-right: 20px;" 1486 onclick="MEMBER_EXCEL.resultExcelDownload('${excelResult.status}',${excelResult.result_idx})"> 1487 ${excelResult.status === 'ì¤í¨' ? 'ì¤í¨' : excelDownloadResultText}</th> 1488 <th class="text-right" style="padding-right: 20px;"> 1489 <span class="text-danger" style="cursor: pointer;" 1490 onclick="MEMBER_EXCEL.deleteGroupExcel(${excelResult.result_idx})">ìì </span> 1491 </th> 1492 `); 1493 excelResultTable.append(row); // ìë¡ì´ <tr> ìì ì¶ê° 1494 } 1495 }else{ 1496 excelEmptyWrap.show(); 1497 } 1498 }, 1499 error: function (xhr, status, error) { 1500 console.log("AJAX ìì² ì¤í¨:", error); 1501 } 1502 }) 1503 } 1504 1505 const groupExcelUploadInit = function (groupCode) { 1506 $group_multi_add_status = $('#group_multi_add_status') 1507 const $group_code = groupCode 1508 $group_multi_add_status.fileupload({ 1509 url: '/admin/ajax/excel_upload.cm', 1510 formData: { target_code: 'bulk_member_group_excel' }, 1511 dataType: 'json', 1512 singleFileUploads: true, 1513 limitMultiFileUploads: 1, 1514 start: function (e, data) { 1515 $group_multi_add_status.addClass('file-loading') 1516 }, 1517 done: function (e, data) { 1518 const res_data = data.result 1519 $.ajax({ 1520 type: 'POST', 1521 data: { 1522 file_name: res_data.file_name, 1523 group_code: $group_code 1524 }, 1525 url: ('/admin/ajax/member/upload_excel_member_group.cm'), 1526 dataType: 'json', 1527 success: function (res) { 1528 if (res.msg === 'SUCCESS') { 1529 var interval = setInterval(function () { 1530 alert('ì¬ì©ì 그룹 ì¼ê´ ë±ë¡ ìì²ì´ ìë£ëììµëë¤.'); 1531 $group_multi_add_status.removeClass('file-loading'); 1532 loadGroupExcelResult() 1533 // drawExcelUploadResult() 1534 clearInterval(interval) 1535 }, 2000) 1536 } else { 1537 alert(res.msg) 1538 $group_multi_add_status.removeClass('file-loading') 1539 } 1540 } 1541 }) 1542 } 1543 }) 1544 } 1545 1546 1547 const memberExcelUploadInit = function () { 1548 $member_multi_add_status = $('#member_multi_add_status') 1549 $member_multi_add_status.fileupload({ 1550 url: '/admin/ajax/excel_upload.cm',
1551 formData: { target_code: 'multi_member_excel' }, 1552 dataType: 'json', 1553 singleFileUploads: true, 1554 limitMultiFileUploads: 1, 1555 start: function () { 1556 $member_multi_add_status.addClass('file-loading'); 1557 }, 1558 done: function (e, data) { 1559 const res_data = data.result 1560 $.ajax({ 1561 type: 'POST', 1562 data: { 1563 file_name: res_data.file_name 1564 }, 1565 url: ('/admin/ajax/member/upload_excel_member.cm'), 1566 dataType: 'json', 1567 success: function (res) { 1568 if (res.msg === 'SUCCESS') { 1569 var interval = setInterval(function () { 1570 $member_multi_add_status.removeClass('file-loading') 1571 drawExcelUploadResult() 1572 clearInterval(interval) 1573 }, 2000) 1574 } else { 1575 alert(res.msg) 1576 $member_multi_add_status.removeClass('file-loading') 1577 } 1578 } 1579 }) 1580 }, 1581 fail: function () { 1582 1583 } 1584 }) 1585 } 1586 1587 const drawExcelUploadResult = function () { 1588 $msg_section = $('#msg_section') 1589 $.ajax({ 1590 type: 'POST', 1591 url: ('/admin/ajax/member/get_excel_member_upload.cm'), 1592 dataType: 'json', 1593 async: false, 1594 cache: false, 1595 success: function (res) { 1596 if (res.msg === 'SUCCESS') { 1597 $msg_section.html(res.html).show() 1598 } 1599 }, 1600 error: function (request, status, error) { 1601 // alert("code:"+request.status+"\n"+"message:"+request.responseText+"\n"+"error:"+error); 1602 } 1603 1604 }) 1605 } 1606 1607 const showBulkGroupAdd = function (groupCode) { 1608 // **ë¹ì© ì¶ë§** â 그룹 ì¼ê´ ë±ë¡ì ëª ë¨ **ì¤ë¹**ì´ê³ ë°ì¡ì ë¤ì sendSms/sendPush ê° ë§ëë¤. 1609 if (isSiteOutboundBlockedByCost()) { 1610 return showSiteOutboundGuide() 1611 } 1612 1613 // ì¬ì©ì 그룹 ì¼ê´ ë±ë¡ ëª¨ë¬ 1614 $.cocoaDialog.close() 1615 $.ajax({ 1616 type: 'POST', 1617 data: { 1618 'group_code' : groupCode 1619 }, 1620 url: ('/admin/ajax/open_group_batch.cm'), 1621 dataType: 'html', 1622 async: true, 1623 cache: false, 1624 success: function (html) { 1625 const $html = $(html) 1626 $.cocoaDialog.open({ type: 'multi_member_add', custom_popup: $html }) 1627 } 1628 }) 1629 } 1630 1631 const showMultiMemberAdd = function () { 1632 // **ë¹ì© ì¶ë§** â íì ëª ë¨ ì¼ê´ ë±ë¡(ìì ì ë¡ë)ì ë°ì¡ì´ ìëë¤(upload_excel_member.cm ê³¼ ê°ì íë¨). 1633 if (isSiteOutboundBlockedByCost()) { 1634 return showSiteOutboundGuide() 1635 } 1636 1637 $.cocoaDialog.close() 1638 $.ajax({ 1639 type: 'POST', 1640 data: {}, 1641 url: ('/admin/ajax/open_member_batch.cm'), 1642 dataType: 'html', 1643 async: true, 1644 cache: false, 1645 success: function (html) { 1646 const $html = $(html) 1647 $.cocoaDialog.open({ type: 'multi_member_add', custom_popup: $html }) 1648 } 1649 }) 1650 } 1651 1652 const openModalMemberExcelDownload = function (member_group) { 1653 $.ajax({ 1654 type: 'POST', 1655 url: ('/admin/ajax/member/open_download_excel_member_list.cm'), 1656 data: { member_group }, 1657 dataType: 'json', 1658 async: false, 1659 cache: false, 1660 success: function (res) { 1661 if (res.msg === 'SUCCESS') { 1662 $.cocoaDialog.open({ type: 'admin_member_excel_download', custom_popup: res.html, width: 550 }) 1663 } else { 1664 alert(res.msg) 1665 } 1666 } 1667 }) 1668 } 1669 1670 const loadExcelList = function () { 1671 $.ajax({ 1672 type: 'POST', 1673 url: ('/admin/ajax/member/get_excel_member_list.cm'), 1674 dataType: 'json', 1675 async: false, 1676 cache: false, 1677 success: function (res) { 1678 if (res.msg == 'SUCCESS') { 1679 $('.modal_admin_member_excel_download').find('._excel_empty_wrap').hide() 1680 $('.modal_admin_member_excel_download').find('#_excel_list_body').html(res.html) 1681 } else { 1682 $('.modal_admin_member_excel_download').find('#_excel_list_body').empty() 1683 $('.modal_admin_member_excel_download').find('._excel_empty_wrap').show() 1684 } 1685 } 1686 }) 1687 } 1688 1689 const runMemberExcelMake = function (member_group) { 1690 const $dashboard_loader_sub = $('#dashboard_loader_sub') 1691 const member_privacy = $('#member_privacy').is(':checked') 1692 const join_type = $('#join_type').val() 1693 1694 $.ajax({ 1695 type: 'POST', 1696 url: '/admin/ajax/member/request_excel_member_list.cm', 1697 dataType: 'json', 1698 data: { member_group, member_privacy, join_type }, 1699 cache: false, 1700 beforeSend: function () { 1701 $dashboard_loader_sub.show() 1702 }, 1703 success: function (res) { 1704 if (res.msg === 'SUCCESS') { 1705 var interval = setInterval(function () { 1706 $dashboard_loader_sub.hide() 1707 loadExcelList() 1708 1709 let all_download = true 1710 $('#_excel_list_body .download_btn').each(function (key, el) { 1711 if ($(el).hasClass('make_progress')) { 1712 all_download = false 1713 } 1714 }) 1715 1716 if (all_download) { 1717 clearInterval(interval) 1718 } 1719 }, 2000) 1720 } else { 1721 alert(res.msg) 1722 $dashboard_loader_sub.hide() 1723 } 1724 }, 1725 error: function (res) { 1726 $dashboard_loader_sub.hide() 1727 } 1728 }) 1729 } 1730 const deleteGroupExcel = function (idx) { 1731 if (confirm(getLocalizeString('ì¤ëª _ìì íìê² ìµëê¹', '', 'ìì íìê² ìµëê¹?'))) { 1732 $.ajax({ 1733 type: 'POST', 1734 data: { result_idx : idx }, 1735 url: ('/admin/ajax/member/delete_excel_group.cm'), 1736 dataType: 'json', 1737 async: false, 1738 cache: false, 1739 success: function (res) { 1740 if (res.msg === 'SUCCESS') { 1741 loadGroupExcelResult(); 1742 } else { 1743 alert(res.msg) 1744 } 1745 } 1746 }) 1747 } 1748 } 1749 1750 const deleteGroupUploadExcel = function (idx) { 1751 if (confirm(getLocalizeString('ì¤ëª _ìì íìê² ìµëê¹', '', 'ìì íìê² ìµëê¹?'))) { 1752 $.ajax({ 1753 type: 'POST', 1754 data: { idx }, 1755 url: ('/admin/ajax/member/delete_excel_member.cm'), 1756 dataType: 'json', 1757 async: false, 1758 cache: false, 1759 success: function (res) { 1760 if (res.msg == 'SUCCESS') { 1761 loadExcelList() 1762 } else { 1763 alert(res.msg) 1764 } 1765 } 1766 }) 1767 } 1768 } 1769 const deleteMemberExcel = function (idx) { 1770 if (confirm(getLocalizeString('ì¤ëª _ìì íìê² ìµëê¹', '', 'ìì íìê² ìµëê¹?'))) { 1771 $.ajax({ 1772 type: 'POST', 1773 data: { idx }, 1774 url: ('/admin/ajax/member/delete_excel_member.cm'), 1775 dataType: 'json', 1776 async: false, 1777 cache: false, 1778 success: function (res) { 1779 if (res.msg == 'SUCCESS') { 1780 loadExcelList() 1781 } else { 1782 alert(res.msg) 1783 } 1784 } 1785 }) 1786 } 1787 } 1788 1789 const deleteMemberUploadExcel = function (idx) { 1790 if (confirm(getLocalizeString('ì¤ëª _ìì íìê² ìµëê¹', '', 'ìì íìê² ìµëê¹?'))) { 1791 $.ajax({ 1792 type: 'POST', 1793 data: { idx }, 1794 url: ('/admin/ajax/member/delete_excel_upload_member.cm'), 1795 dataType: 'json', 1796 async: false, 1797 cache: false, 1798 success: function (res) { 1799 if (res.msg == 'SUCCESS') { 1800 drawExcelUploadResult() 1801 } else { 1802 alert(res.msg) 1803 } 1804 } 1805 }) 1806 } 1807 } 1808 1809 return { 1810 init: function () { 1811 init() 1812 }, 1813 memberExcelUploadInit: function () { 1814 memberExcelUploadInit() 1815 }, 1816 resultExcelDownload: function (status, result_idx) { 1817 resultExcelDownload(status, result_idx) 1818 }, 1819 groupExcelUploadInit: function (groupCode) { 1820 groupExcelUploadInit(groupCode) 1821 }, 1822 deleteGroupExcel: function (idx) { 1823 deleteGroupExcel(idx) 1824 }, 1825 loadGroupExcelResult: function () { 1826 loadGroupExcelResult() 1827 }, 1828 drawExcelUploadResult: function () { 1829 drawExcelUploadResult() 1830 }, 1831 showBulkGroupAdd: function (groupCode) { 1832 showBulkGroupAdd(groupCode) 1833 }, 1834 showMultiMemberAdd: function () { 1835 showMultiMemberAdd() 1836 },
1837 openModalMemberExcelDownload: function (member_group) { 1838 openModalMemberExcelDownload(member_group) 1839 }, 1840 loadExcelList: function () { 1841 loadExcelList() 1842 }, 1843 runMemberExcelMake: function (member_group) { 1844 runMemberExcelMake(member_group) 1845 }, 1846 deleteMemberExcel: function (idx) { 1847 deleteMemberExcel(idx) 1848 }, 1849 deleteMemberUploadExcel: function (idx) { 1850 deleteMemberUploadExcel(idx) 1851 } 1852 } 1853}()) 1854 1855/** 1856 * ìë ë©ìì§ ë°ì¡ ì ì¸ì¦ 1857 * send_sms.cm ìëµì data.typeì¼ë¡ ì§ì íê³ , ì¸ì¦ì ì±ê³µíë©´ ê°ì ë°ì¡ì ë¤ì ìì²íë¤. 1858 */ 1859var ADMIN_MESSAGE_STEP_UP = (function () { 1860 const REQUEST_URL = '/admin/ajax/two_factor_auth/request.cm' 1861 const VERIFY_URL = '/admin/ajax/two_factor_auth/verify.cm' 1862 const PURPOSE = 'message_send' 1863 const TYPE_TWO_FACTOR_SETTING_REQUIRED = 'two_factor_setting_required' 1864 const TYPE_TWO_FACTOR_AUTH_REQUIRED = 'two_factor_auth_required' 1865 const TYPE_CHANNEL_SETTING_REQUIRED = 'two_factor_channel_setting_required' 1866 const REDIRECT_LIST = ['/admin/config/security', '/admin/member/mail', '/admin/member/sms', '/admin/'] 1867 const DEFAULT_SETTING_TITLE = '2ì°¨ ì¸ì¦ ì¤ì ì´ íìí©ëë¤' 1868 // ì©ëë³ ë¬¸êµ¬. ìì¼ë©´ ë©ìì§ ë°ì¡ ê¸°ì¤ ë¬¸êµ¬ë¥¼ ì´ë¤. {receiver}ë ìë²ê° ë´ë ¤ì¤ ë§ì¤í¹ ìì ì²ë¤. 1869 const PURPOSE_TEXT = { 1870 security_otp_setting: { 1871 title: 'ì¬ì´í¸ ìì 주 í´ëí° ì¸ì¦', 1872 desc_pending: 'OTP ì¤ì ë° ë³ê²½ì ì¬ì´í¸ ìì 주 í´ëí°ì¼ë¡ ì¸ì¦ë²í¸ ì¸ì¦ì´ íìí©ëë¤. ì¸ì¦ë²í¸ë¥¼ ë³´ë´ë ì¤ì ëë¤.', 1873 desc: 'OTP ì¤ì ë° ë³ê²½ì ì¬ì´í¸ ìì 주 í´ëí°{receiver}ì¼ë¡ ì¸ì¦ë²í¸ ì¸ì¦ì´ íìí©ëë¤. ë°ì ì¸ì¦ë²í¸ë¥¼ ì ë ¥í´ ì£¼ì¸ì.', 1874 confirm: 'ì¸ì¦ í ì ì¥' 1875 }, 1876 sms_sender_setting: { 1877 title: 'ì¬ì´í¸ ìì 주 í´ëí° ì¸ì¦', 1878 desc_pending: 'ë°ì ë²í¸ë¥¼ ë±ë¡íê±°ë ë³ê²½íë ¤ë©´ ì¬ì´í¸ ìì 주 í´ëí° ì¸ì¦ì´ íìí©ëë¤. ì¸ì¦ë²í¸ë¥¼ ë³´ë´ë ì¤ì ëë¤.', 1879 desc: 'ì¬ì´í¸ ìì 주 í´ëí°{receiver}ì¼ë¡ ë°ì ì¸ì¦ë²í¸ë¥¼ ì ë ¥í´ ì£¼ì¸ì. ì¸ì¦ í ë°ì ë²í¸ ë±ë¡ì ìì²í©ëë¤.', 1880 confirm: 'ì¸ì¦ í ë±ë¡' 1881 } 1882 } 1883 let modal_seq = 0 1884 1885 const escapeHtml = function (text) { 1886 return $('<div>').text(text || '').html() 1887 } 1888 1889 const getChannelLabel = function (channel) { 1890 if (channel === 'sms') return 'SMS' 1891 if (channel === 'email') return 'ì´ë©ì¼' 1892 if (channel === 'otp') return 'ì¸ì¦ ì±' 1893 return '' 1894 } 1895 1896 const isSettingRequired = function (data) { 1897 return !!data && typeof data === 'object' && 1898 (data.type === TYPE_TWO_FACTOR_SETTING_REQUIRED || data.type === TYPE_CHANNEL_SETTING_REQUIRED) 1899 } 1900 1901 // ë 모ë¬ì´ í¨ê» ì°ë Clay í í° ì¤íì¼(ë²í¼ì member/send .ms-btnê³¼ ê°ì í í°). scopeë 모ë¬ì header·body·footerì ë¶ëë¤. 1902 const buildBaseStyle = function (s) { 1903 return s + ' .modal-title{color:var(--clay-text);font-size:var(--clay-text-2xlarge);font-weight:var(--clay-font-bold);line-height:var(--clay-leading-8)}' + 1904 s + '.modal-body{color:var(--clay-text-sub);font-size:var(--clay-text-small);line-height:var(--clay-leading-5)}' + 1905 s + ' .btn.step-up-btn{border:var(--clay-border-1) solid transparent;border-radius:var(--clay-rounded-base);box-shadow:none;padding:var(--clay-space-2) var(--clay-space-3);font-family:var(--clay-typeface-base);font-size:var(--clay-text-small);font-weight:var(--clay-font-semibold);line-height:var(--clay-leading-6)}' + 1906 s + ' .btn.step-up-btn--primary,' + s + ' .btn.step-up-btn--primary:focus{background:var(--clay-action-primary);color:var(--clay-text-inverse)}' + 1907 s + ' .btn.step-up-btn--primary:hover{background:var(--clay-action-primary-hover);color:var(--clay-text-inverse)}' + 1908 s + ' .btn.step-up-btn--primary:active{background:var(--clay-action-primary-pressed);color:var(--clay-text-inverse)}' + 1909 s + ' .btn.step-up-btn--primary:disabled{background:var(--clay-action-primary-disabled);color:var(--clay-text-disabled);opacity:1}' + 1910 s + ' .btn.step-up-btn--secondary,' + s + ' .btn.step-up-btn--secondary:focus{background:var(--clay-action-secondary);border-color:var(--clay-border);color:var(--clay-text-secondary)}' + 1911 s + ' .btn.step-up-btn--secondary:hover{background:var(--clay-action-secondary);border-color:var(--clay-border-hover);color:var(--clay-text-secondary)}' + 1912 s + ' .btn.step-up-btn--secondary:active{background:var(--clay-action-secondary);border-color:var(--clay-border-sub);color:var(--clay-text-secondary)}' 1913 } 1914 1915 // ëìì¸ êµì²´ ì ì´ í¨ìë§ ë°ê¾¼ë¤. ì 목·ì¤ëª ·ë¨ì ìê°Â·ì¤ë¥ 문구ë open()ìì textë¡ ì±ì´ë¤. 1916 const buildModalHtml = function (scope) { 1917 const s = '.' + scope
1918 const clock_icon = '<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">' + 1919 '<circle cx="8" cy="8" r="6.25" stroke="currentColor" stroke-width="1.5"/>' + 1920 '<path d="M8 4.75V8l2.25 1.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>' 1921 return '<style>' + 1922 buildBaseStyle(s) + 1923 s + ' .step-up-desc{margin:0 0 var(--clay-space-5);color:var(--clay-text-sub)}' + 1924 s + ' .step-up-label{display:block;margin:0 0 var(--clay-space-2);font-weight:var(--clay-font-semibold);color:var(--clay-text)}' + 1925 s + ' .step-up-input{height:var(--clay-space-10);padding:0 var(--clay-space-3);border:var(--clay-border-1) solid var(--clay-border);border-radius:var(--clay-rounded-medium);box-shadow:none;color:var(--clay-text)}' + 1926 s + ' .step-up-timer{display:flex;align-items:center;justify-content:space-between;margin-top:var(--clay-space-2);padding:var(--clay-space-2) var(--clay-space-3);border-radius:var(--clay-rounded-medium);background:var(--clay-surface-sub)}' + 1927 s + ' .step-up-timer__remain{display:inline-flex;align-items:center;gap:var(--clay-space-15);color:var(--clay-text-sub)}' + 1928 s + ' .step-up-timer__remain strong{color:var(--clay-text-accent);font-weight:var(--clay-font-semibold)}' + 1929 s + ' .step-up-timer__extend{color:var(--clay-text-sub);text-decoration:underline}' + 1930 s + ' .step-up-error{margin:var(--clay-space-2) 0 0;color:var(--clay-text-critical)}' + 1931 s + ' .step-up-error:empty{display:none}' + 1932 s + ' .step-up-otp{margin:0 0 var(--clay-space-5)}' + 1933 // ìì display ì ìì¡´íì§ ìëë¡ ëí¼ë¥¼ flex ë¡ ëë¤(í ë§ê° img·canvas 를 block ì¼ë¡ ë ì ìë¤). 1934 s + ' .step-up-otp__qr-wrap{display:flex;justify-content:center}' + 1935 s + ' .step-up-otp__qr{margin:0 0 var(--clay-space-3)}' + 1936 s + ' .step-up-otp__line{margin:0 0 var(--clay-space-2);color:var(--clay-text-sub)}' + 1937 s + ' .step-up-otp__key{word-break:break-all;color:var(--clay-text);font-weight:var(--clay-font-semibold)}' + 1938 '</style>' + 1939 '<div class="modal-header ' + scope + '">' + 1940 '<h4 class="modal-title _step_up_title"></h4>' + 1941 '</div>' + 1942 '<div class="modal-body ' + scope + '">' + 1943 '<p class="step-up-desc _step_up_desc"></p>' + 1944 '<div class="step-up-otp _step_up_otp" style="display:none">' + 1945 '<div class="step-up-otp__qr-wrap"><div class="step-up-otp__qr _otp_qr"></div></div>' + 1946 '<p class="step-up-otp__line"><a href="javascript:;" class="_step_up_otp_link">í´ëí°ìì ì´ ë§í¬ë¥¼ ëë¬ ë±ë¡</a></p>' + 1947 '<p class="step-up-otp__line">ì§ì ì ë ¥ì© í¤ : <span class="step-up-otp__key _step_up_otp_secret"></span></p>' + 1948 '</div>' + 1949 '<label class="step-up-label" for="' + scope + '_code">ì¸ì¦ë²í¸ ì ë ¥</label>' + 1950 '<input type="text" id="' + scope + '_code" class="form-control step-up-input _step_up_code" inputmode="numeric" autocomplete="one-time-code" maxlength="5" placeholder="ì¸ì¦ë²í¸ë¥¼ ì ë ¥í´ ì£¼ì¸ì">' + 1951 '<div class="step-up-timer _step_up_timer">' + 1952 '<span class="step-up-timer__remain">' + clock_icon + 'ë¨ì ìê° <strong class="_step_up_remain">-</strong></span>' + 1953 '<a href="javascript:;" class="step-up-timer__extend _step_up_resend">ìê° ì°ì¥</a>' + 1954 '</div>' + 1955 '<p class="step-up-error _step_up_error"></p>' + 1956 '</div>' + 1957 '<div class="modal-footer ' + scope + '">' + 1958 '<button type="button" class="btn step-up-btn step-up-btn--secondary" data-dismiss="modal">ì·¨ì</button>' + 1959 '<button type="button" class="btn step-up-btn step-up-btn--primary _step_up_confirm">ì¸ì¦ ë° ë©ìì§ ë³´ë´ê¸°</button>' + 1960 '</div>' 1961 } 1962 1963 const formatRemainTime = function (second) { 1964 const minute = Math.floor(second / 60) 1965 const rest = second % 60 1966 return minute + ':' + (rest < 10 ? '0' : '') + rest 1967 } 1968 1969 const openSettingRequired = function (msg, data) { 1970 modal_seq++ 1971 const scope = '_two_factor_setting_' + modal_seq
1972 let content = escapeHtml(msg) 1973 if (data.sub_msg) content += '<br>' + escapeHtml(data.sub_msg) 1974 const title = typeof data.title === 'string' && data.title !== '' ? data.title : DEFAULT_SETTING_TITLE 1975 const redirect = REDIRECT_LIST.indexOf(data.redirect) > -1 ? data.redirect : '/admin/' 1976 $.cocoaDialog.open({ 1977 type: 'alert_clay', 1978 title: escapeHtml(title), 1979 content: '<style>' + buildBaseStyle('.' + scope) + '</style><div class="' + scope + '">' + content + '</div>', 1980 confirm_text: 'íì¸', 1981 close_block: true 1982 }, function () { 1983 window.location.href = redirect 1984 }) 1985 1986 // alert_clay ê³µì© íì¸ ë²í¼(btn-primary)ì ì´ ëª¨ë¬ììë§ Clay primaryë¡ ë°ê¾¼ë¤. header·body·footerë ë¤ì open ë ìë¡ ë§ë¤ì´ì§ë¤. 1987 const $content = $('.' + scope).closest('.modal-content') 1988 $content.children('.modal-header, .modal-body, .modal-footer').addClass(scope) 1989 $content.find('._confirm').removeClass('btn-primary').addClass('step-up-btn step-up-btn--primary') 1990 } 1991 1992 /** 1993 * @param {function} retry ì¸ì¦ ì±ê³µ í ë°ì í í°ì¼ë¡ ê°ì ë°ì¡ì ë¤ì ìì²íë í¨ì 1994 * @param {string} [channel] ê±°ë¶ ìëµì data.channel(sms|email). 모르면 ì¸ì¦ë²í¸ ìì² ìëµì¼ë¡ ì±ì´ë¤. 1995 * TODO(FS-3681): OMS ìì ì°ëì ìí´ onCancel·ë«ê¸° í¨ì·supportsCancellationì ì¶ê°íë¤. 1996 * ì ê±° ì ì ê· í¸ì¶ì를 íì¸íê³ ê³µíµ ì¸ì¦ UIì 기존 í¸ì¶ìë ì ì§íë¤. 1997 * @param {function} [onCancel] ì·¨ì ëë ì¤ì ìë´ ì í ì ë기 ì¤ì¸ í¸ì¶ì를 í´ì íë¤. 1998 * @param {string} [target_purpose] ê±°ë¶ ìëµì data.purpose. ìì¼ë©´ ë©ìì§ ë°ì¡ ì©ëë¡ ì¸ì¦íë¤. 1999 * @returns {function} íì¬ ì¸ì¦ 모ë¬ì ë«ë í¨ì 2000 */ 2001 const open = function (retry, channel, onCancel, target_purpose) { 2002 modal_seq++ 2003 const purpose = typeof target_purpose === 'string' && target_purpose !== '' ? target_purpose : PURPOSE 2004 // ìë²ê° ë´ë ¤ì¤ ê°ì´ë¼ constructor ê°ì íë¡í íì ìì±ì´ ì¡íì§ ìê² ì기 ìì±ë§ 본ë¤. 2005 const purpose_text = Object.prototype.hasOwnProperty.call(PURPOSE_TEXT, purpose) ? PURPOSE_TEXT[purpose] : null 2006 const scope = '_message_step_up_' + modal_seq 2007 $.cocoaDialog.open({ type: 'message_step_up', custom_popup: buildModalHtml(scope) }) 2008 2009 const $scope = $('.' + scope) 2010 // alert_clay 모ë¬ì ì 목·본문·ë²í¼ ì¤íì¼ì ì¬ì¬ì©íë¤. ë¤ì open ë cocoaDialogê° class를 ì´ê¸°ííë¤. 2011 const $modal = $scope.closest('.modal').addClass('modal_alert_clay') 2012 const $title = $scope.find('._step_up_title') 2013 const $desc = $scope.find('._step_up_desc') 2014 const $code = $scope.find('._step_up_code') 2015 const $remain = $scope.find('._step_up_remain') 2016 const $error = $scope.find('._step_up_error') 2017 const $confirm = $scope.find('._step_up_confirm') 2018 const $otp = $scope.find('._step_up_otp') 2019 const $timer_wrap = $scope.find('._step_up_timer') 2020 let timer = null 2021 let expires_at = 0 2022 let is_busy = false 2023 let request_id = '' 2024 let is_closed = false 2025 let is_completed = false 2026 let is_otp = false 2027 let code_length = 5 2028 let masked_receiver = '' 2029 let is_sent = false 2030 2031 const setChannel = function (target_channel) { 2032 const label = getChannelLabel(target_channel) 2033 is_otp = target_channel === 'otp' 2034 // ì¸ì¦ ì± ì½ëë 6ì리ì´ê³ ë°ì¡ì´ ìì´ ë¨ì ìê°Â·ìê° ì°ì¥ì ì°ì§ ìëë¤. 2035 code_length = is_otp ? 6 : 5 2036 $code.attr('maxlength', code_length) 2037 if (is_otp) { 2038 $title.text('ì¸ì¦ ì± 2ì°¨ ì¸ì¦') 2039 $desc.text('ì¸ì¦ ì±ì íìë 6ì리 ì«ì를 ì ë ¥í´ ì£¼ì¸ì.') 2040 $timer_wrap.hide() 2041 return 2042 } 2043 $timer_wrap.show() 2044 $otp.hide() 2045 if (purpose_text) { 2046 $title.text(purpose_text.title) 2047 // ë°ì¡ ì±ê³µ ìëµ ì ìë ìë£í 문구를 ì°ì§ ìëë¤. 2048 $desc.text(is_sent 2049 ? purpose_text.desc.replace('{receiver}', masked_receiver ? '(' + masked_receiver + ')' : '') 2050 : purpose_text.desc_pending) 2051 return 2052 } 2053 $title.text(label ? label + ' 2ì°¨ ì¸ì¦' : '2ì°¨ ì¸ì¦') 2054 $desc.text(label ? label + 'ë¡ ìì ë ì¸ì¦ë²í¸ë¥¼ ì ë ¥í´ ì£¼ì¸ì.' : 'ìì ë ì¸ì¦ë²í¸ë¥¼ ì ë ¥í´ ì£¼ì¸ì.') 2055 } 2056 setChannel(channel) 2057 if (purpose_text && purpose_text.confirm) $confirm.text(purpose_text.confirm) 2058 2059 // ë±ë¡ ë¨ê³ QR ì ì¬ë´ vendor ë¼ì´ë¸ë¬ë¦¬ë¥¼ ê·¸ëë§ ë°ì 그린ë¤(ì¸ë¶ CDN ê¸ì§). 2060 const renderOtpEnroll = function (data) {
2061 const uri = (data && data.otpauth_uri) || '' 2062 const secret = (data && data.secret) || '' 2063 if (!data || !data.enroll || uri === '' || secret === '') { 2064 $otp.hide() 2065 return 2066 } 2067 $desc.text('ì¸ì¦ ì±ì ìë ê³ì ì ë±ë¡í ë¤, ì±ì íìë 6ì리 ì«ì를 ì ë ¥í´ ì£¼ì¸ì.') 2068 $otp.find('._step_up_otp_link').attr('href', uri) 2069 $otp.find('._step_up_otp_secret').text(secret) 2070 $otp.show() 2071 2072 const $qr = $otp.find('._otp_qr') 2073 const lib = data.qr_lib || '' 2074 $qr.empty().show() 2075 if (lib === '') { 2076 $qr.hide() 2077 return 2078 } 2079 const draw = function () { 2080 try { 2081 new QRCode($qr.get(0), { 2082 text: uri, 2083 width: 160, 2084 height: 160, 2085 correctLevel: QRCode.CorrectLevel.M 2086 }) 2087 } catch (e) { 2088 // QR ì 못 ê·¸ë ¤ë ë§í¬Â·í¤ë¡ ë±ë¡í ì ìê² QR ììë§ ì¨ê¸´ë¤. 2089 $qr.hide() 2090 } 2091 } 2092 if (typeof QRCode !== 'undefined') { 2093 draw() 2094 return 2095 } 2096 $.getScript(lib).done(draw).fail(function () { 2097 $qr.hide() 2098 }) 2099 } 2100 2101 const stopTimer = function () { 2102 if (timer) { 2103 clearInterval(timer) 2104 timer = null 2105 } 2106 } 2107 2108 $modal.one('hidden.bs.modal', function () { 2109 is_closed = true 2110 stopTimer() 2111 if (!is_completed && typeof onCancel === 'function') onCancel() 2112 }) 2113 2114 const tick = function () { 2115 // 모ë¬ì´ ë«íê±°ë ë¤ë¥¸ 모ë¬ë¡ êµì²´ëë©´ íì´ë¨¸ë¥¼ ë©ì¶ë¤. 2116 if (!$.contains(document.body, $scope[0]) || !$modal.is(':visible')) { 2117 stopTimer() 2118 return 2119 } 2120 const remain = Math.max(0, Math.ceil((expires_at - Date.now()) / 1000)) 2121 $remain.text(formatRemainTime(remain)) 2122 if (remain <= 0) { 2123 stopTimer() 2124 $error.text('ì¸ì¦ë²í¸ ì ë ¥ ìê°ì´ ì´ê³¼ëììµëë¤. ìê° ì°ì¥ì ëë¬ ì¸ì¦ë²í¸ë¥¼ ë¤ì ë°ì 주ì¸ì.') 2125 } 2126 } 2127 2128 // ì¸ì¦ 모ë¬ì´ ë«í ë¤ ì¬ìì²í´ì¼ ê²°ê³¼ 모ë¬ì´ ê°ì ë ì´ì´ì ê²¹ì¹ì§ ìëë¤. 2129 const closeAndRetry = function (auth_token) { 2130 if (is_closed) return 2131 is_completed = true 2132 stopTimer() 2133 $modal.one('hidden.bs.modal', function () { 2134 setTimeout(function () { 2135 retry(auth_token) 2136 }, 0) 2137 }) 2138 $modal.modal('hide') 2139 } 2140 2141 // ì´ë¯¸ ë«íê±°ë ë¤ë¥¸ 모ë¬ë¡ êµì²´ë ë¤ ëì°©í ìëµì ìë´íì§ ìëë¤. ë¤ì ë°ì¡ ìì²ì´ ê°ì ê±°ë¶ë¥¼ ë¤ì ë°ëë¤. 2142 const closeAndOpenSettingRequired = function (res) { 2143 stopTimer() 2144 if (is_closed || !$.contains(document.body, $scope[0]) || !$modal.is(':visible')) return 2145 is_completed = true 2146 if (typeof onCancel === 'function') onCancel() 2147 $modal.one('hidden.bs.modal', function () { 2148 setTimeout(function () { 2149 openSettingRequired(res.msg, res.data) 2150 }, 0) 2151 }) 2152 $modal.modal('hide') 2153 } 2154 2155 const request = function (is_resend) { 2156 if (is_busy) return 2157 is_busy = true 2158 $error.text('') 2159 $.ajax({ 2160 type: 'POST', 2161 url: REQUEST_URL, 2162 data: { purpose, resend: is_resend ? 'Y' : 'N' }, 2163 dataType: 'json', 2164 cache: false, 2165 success: function (res) { 2166 if (is_closed || !$.contains(document.body, $scope[0])) return 2167 if (res && res.msg === 'SUCCESS' && res.data) { 2168 request_id = res.data.request_id || '' 2169 masked_receiver = typeof res.data.receiver === 'string' ? res.data.receiver : '' 2170 is_sent = true 2171 if (purpose_text || getChannelLabel(res.data.channel)) setChannel(res.data.channel) 2172 stopTimer() 2173 if (is_otp) { 2174 renderOtpEnroll(res.data) 2175 } else { 2176 expires_at = Date.now() + (parseInt(res.data.expires_in, 10) || 180) * 1000 2177 tick() 2178 timer = setInterval(tick, 1000) 2179 } 2180 $code.val('').trigger('focus') 2181 } else if (isSettingRequired(res && res.data)) { 2182 closeAndOpenSettingRequired(res) 2183 } else { 2184 $error.text((res && res.msg) || 'ì¸ì¦ë²í¸ ì ì¡ì ì¤í¨íìµëë¤.') 2185 } 2186 }, 2187 error: function () { 2188 $error.text('ì¸ì¦ë²í¸ ì ì¡ì ì¤í¨íìµëë¤. ì ì í ë¤ì ìëí´ ì£¼ì¸ì.') 2189 }, 2190 complete: function () { 2191 is_busy = false 2192 } 2193 }) 2194 } 2195 2196 const verify = function () { 2197 if (is_busy) return 2198 const cert_code = $.trim($code.val()) 2199 if (!new RegExp('^[0-9]{' + code_length + '}$').test(cert_code)) { 2200 $error.text(is_otp ? 'ì¸ì¦ ì±ì 6ì리 ì«ì를 ì ë ¥í´ ì£¼ì¸ì.' : 'ì¸ì¦ë²í¸ 5ì리를 ì ë ¥í´ ì£¼ì¸ì.') 2201 return 2202 } 2203 is_busy = true 2204 $error.text('') 2205 $confirm.prop('disabled', true) 2206 $.ajax({ 2207 type: 'POST', 2208 url: VERIFY_URL, 2209 data: { purpose, cert_code, request_id }, 2210 dataType: 'json', 2211 cache: false, 2212 success: function (res) { 2213 if (is_closed || !$.contains(document.body, $scope[0])) return 2214 if (res && res.msg === 'SUCCESS') { 2215 closeAndRetry((res.data && res.data.auth_token) || '') 2216 } else if (isSettingRequired(res && res.data)) { 2217 closeAndOpenSettingRequired(res) 2218 } else { 2219 $error.text((res && res.msg) || 'ì¸ì¦ì ì¤í¨íìµëë¤.') 2220 } 2221 }, 2222 error: function () { 2223 $error.text('ì¸ì¦ì ì¤í¨íìµëë¤. ì ì í ë¤ì ìëí´ ì£¼ì¸ì.') 2224 }, 2225 complete: function () { 2226 is_busy = false 2227 $confirm.prop('disabled', false) 2228 } 2229 }) 2230 } 2231 2232 $code.on('input', function () { 2233 $code.val($code.val().replace(/[^0-9]/g, '').slice(0, code_length)) 2234 }) 2235 $code.on('keydown', function (e) { 2236 if (e.keyCode === 13) { 2237 e.preventDefault() 2238 verify() 2239 } 2240 }) 2241 $scope.find('._step_up_resend').on('click', function () { 2242 request(true) 2243 }) 2244 $confirm.on('click', verify) 2245 2246 request(false) 2247 return function () { 2248 if (!is_closed) $modal.modal('hide') 2249 } 2250 } 2251 2252 /** 2253 * ë°ì¡ ìëµì´ ì¸ì¦ ê²ì´í¸ ê±°ë¶ë©´ ìë´Â·ì¸ì¦ì ììíê³ true를 ëë ¤ì¤ë¤. 2254 * @param {object} res ë°ì¡ ìëí¬ì¸í¸ ìëµ 2255 * @param {function} retry ì¸ì¦ ì±ê³µ í ë°ì í í°(auth_token)ì¼ë¡ ê°ì ë°ì¡ì ë¤ì ìì²íë í¨ì 2256 */ 2257 const handleSendResponse = function (res, retry) { 2258 const data = res && res.data 2259 if (!data || typeof data !== 'object') return false 2260 if (isSettingRequired(data)) { 2261 openSettingRequired(res.msg, data) 2262 return true 2263 } 2264 if (data.type === TYPE_TWO_FACTOR_AUTH_REQUIRED && typeof retry === 'function') { 2265 open(retry, data.channel, undefined, data.purpose) 2266 return true 2267 } 2268 return false 2269 } 2270 2271 return { 2272 handleSendResponse, 2273 supportsCancellation: true, 2274 open 2275 } 2276}()) 2277 2278/** 2279 * TODO(FS-3681): OMS ìì ì¸ì¦ ì°ê²°. ëì²´ ì¸ì¦ ì ì© í ì´ IIFEì order-v1 ìì ë¶ê¸°ë¥¼ ì ê±°íë¤. 2280 * PHPë ì¸ì¦ë§ ì²ë¦¬íë©°, verified를 ë°ì OMS Adminì´ ê¸°ì¡´ APIë¡ ë°ì¡íë¤. 2281 */ 2282var OMS_MANUAL_SMS = (function () { 2283 // ë¶ëª¨ BOì ì¸ì¦ 모ë¬ì ê³µì ëë¯ë¡ ë¤ë¥¸ 주문ì ì¸ì¦ ìì²ê³¼ ê²¹ì¹ì§ ìê² íë¤. 2284 let active = false 2285 2286 const handle = function (event, appOrigin) { 2287 const iframe = document.querySelector('#OMSA iframe') 2288 2289 if ( 2290 !iframe || 2291 event.source !== iframe.contentWindow || 2292 event.origin !== appOrigin || 2293 !event.ports || 2294 event.ports.length !== 1 2295 ) { 2296 return 2297 } 2298 2299 const port = event.ports[0] 2300 const requestId = event.data.requestId 2301 2302 if (typeof requestId !== 'string' || !/^[a-zA-Z0-9-]{1,80}$/.test(requestId)) { 2303 port.close() 2304 return 2305 } 2306 2307 const reply = function (result) { 2308 port.postMessage(Object.assign({ requestId }, result)) 2309 } 2310 2311 if (active) { 2312 reply({ status: 'error', message: 'ì§í ì¤ì¸ ì¸ì¦ì 먼ì ìë£í´ 주ì¸ì.' }) 2313 port.close() 2314 return 2315 } 2316 2317 // 구 member.jsìë ì·¨ì ê²°ê³¼ê° ìì´ OMSê° ê³ì ë기íë¯ë¡ ì¤ë¹ëì§ ìì¼ë©´ ë«ëë¤. 2318 if (typeof ADMIN_MESSAGE_STEP_UP === 'undefined' || !ADMIN_MESSAGE_STEP_UP.supportsCancellation) { 2319 reply({ status: 'error', message: 'ì¸ì¦ 기ë¥ì ì¤ë¹ ì¤ì ëë¤. íì´ì§ë¥¼ ìë¡ê³ ì¹¨í´ ì£¼ì¸ì.' }) 2320 port.close() 2321 return 2322 } 2323 2324 active = true 2325 reply({ status: 'accepted' }) 2326 2327 let settled = false 2328 let sending = false
2329 let cancelModal = null 2330 let controller = null 2331 let watch = null 2332 2333 // ì¸ì¦ ì·¨ì·ë¤í¸ìí¬ ìëµÂ·iframe ì´ëì´ ê²¹ì³ë ìµì¢ ê²°ê³¼ë í ë²ë§ ëë ¤ì¤ë¤. 2334 const finish = function (result) { 2335 if (settled) return 2336 2337 settled = true 2338 active = false 2339 clearInterval(watch) 2340 iframe.removeEventListener('load', cancel) 2341 port.onmessage = null 2342 2343 reply(result) 2344 port.close() 2345 } 2346 2347 const cancel = function () { 2348 if (settled) return 2349 2350 finish({ status: 'cancelled' }) 2351 2352 if (controller) controller.abort() 2353 if (cancelModal) cancelModal() 2354 } 2355 2356 port.onmessage = function (message) { 2357 if (message.data && message.data.type === 'cancel' && message.data.requestId === requestId) { 2358 cancel() 2359 } 2360 } 2361 2362 port.start() 2363 iframe.addEventListener('load', cancel, { once: true }) 2364 2365 // iframe ì ê±°ë load를 ë°ììí¤ì§ ìì ì ìì´ ì°ê²° ìíë íì¸íë¤. 2366 watch = setInterval(function () { 2367 if (!iframe.isConnected || iframe.contentWindow !== event.source) cancel() 2368 }, 500) 2369 2370 const submit = async function (authToken) { 2371 if (settled || sending) return 2372 2373 sending = true 2374 2375 const body = new URLSearchParams() 2376 2377 if (authToken) body.set('two_factor_auth_token', authToken) 2378 2379 controller = new AbortController() 2380 2381 try { 2382 const response = await fetch('/admin/ajax/oms/verify_manual_sms_auth.cm', { 2383 method: 'POST', 2384 credentials: 'same-origin', 2385 body, 2386 signal: controller.signal 2387 }) 2388 2389 if (!response.ok) throw new Error('request_failed') 2390 2391 const result = await response.json() 2392 sending = false 2393 2394 if (settled) return 2395 2396 if (result.msg === 'SUCCESS') { 2397 finish({ status: 'verified' }) 2398 return 2399 } 2400 2401 if (result.data && result.data.type === 'two_factor_auth_required') { 2402 // ì¬í¸ì¶ í í°ì´ ê±°ì ëë©´ ìëì¼ë¡ ì ì¸ì¦ì ë°ë³µíì§ ìëë¤. 2403 if (authToken) { 2404 finish({ status: 'error', message: 'ì¸ì¦ì´ ë§ë£ëììµëë¤. ë¤ì ìëí´ ì£¼ì¸ì.' }) 2405 return 2406 } 2407 2408 cancelModal = ADMIN_MESSAGE_STEP_UP.open( 2409 submit, 2410 result.data.channel, 2411 function () { 2412 finish({ status: 'cancelled' }) 2413 } 2414 ) 2415 return 2416 } 2417 2418 // 101/103ì 기존 PHP ì¤ì ìë´ UIê° ë§¡ê³ , OMSì ì ì¶ ë기ë í´ì íë¤. 2419 if (ADMIN_MESSAGE_STEP_UP.handleSendResponse(result, submit)) { 2420 finish({ status: 'cancelled' }) 2421 return 2422 } 2423 2424 finish({ 2425 status: 'error', 2426 message: typeof result.msg === 'string' ? result.msg : 'ì¸ì¦ ìì²ì ì¤í¨íìµëë¤.' 2427 }) 2428 } catch (error) { 2429 if (!settled) { 2430 finish({ 2431 status: 'error', 2432 message: 'ì¸ì¦ 결과를 íì¸í ì ììµëë¤. ë¤ì ì¸ì¦í´ 주ì¸ì.' 2433 }) 2434 } 2435 } finally { 2436 sending = false 2437 } 2438 } 2439 2440 // ì¸ì¦ íì ì¬ë¶ë PHPê° ê²°ì íë¤. ìµì´ ìì²ìë 2ì°¨ ì¸ì¦ í í°ì ì£ì§ ìëë¤. 2441 submit('') 2442 } 2443 2444 return { handle } 2445}()) 2446 2447const remove_group_list = [] 2448let is_writing = false 2449let is_join_confirm = false 2450var adminMember = { 2451 openGroupForm: function (idx) { 2452 $.ajax({ 2453 type: 'POST', 2454 data: { idx }, 2455 url: ('/admin/ajax/config/membership/group_form.cm'), 2456 dataType: 'json', 2457 async: false, 2458 cache: false, 2459 success: function (result) { 2460 if (result.msg == 'SUCCESS') { 2461 $.cocoaDialog.open({ type: 'admin_group_form', custom_popup: result.html, width: 550 }) 2462 } else { 2463 alert(result.msg) 2464 } 2465 } 2466 }) 2467 }, 2468 deleteGroupForm: function (idx) { 2469 $.ajax({ 2470 type: 'POST', 2471 data: { mode: 'delete', idx }, 2472 url: ('/admin/ajax/config/membership/group_form_proc.cm'), 2473 dataType: 'json', 2474 async: false, 2475 cache: false, 2476 success: function (result) { 2477 if (result.msg == 'SUCCESS') { 2478 // ì±ê³µì ì ì²´ ì¬ì©ìë¡ ë¦¬ë¤ì´ë í¸ 2479 window.location.href = '/admin/member/list'; 2480 } 2481 else alert(result.msg) 2482 } 2483 }) 2484 }, 2485 addGroupForm: function () { 2486 const f = $('#groupf') 2487 const data = f.serializeObject() 2488 $.ajax({ 2489 type: 'POST', 2490 data, 2491 url: ('/admin/ajax/config/membership/group_form_proc.cm'), 2492 dataType: 'json', 2493 async: false, 2494 cache: false, 2495 success: function (result) { 2496 if (result.msg == 'SUCCESS') { 2497 if (result.mode == 'add') { 2498 const base_url = $('#new_group_btn').data('base_url') 2499 const groupCode = String(result.code || '') 2500 const $groupItem = $('<li>', { id: 'group_item_' + groupCode }) 2501 const $groupLink = $('<a>', { href: base_url + '&member_group=' + encodeURIComponent(groupCode) }) 2502 $groupLink.append(document.createTextNode(result.title || '')) 2503 $groupLink.append($('<small>', { 'class': 'margin-left-lg text-bold opacity-75' })) 2504 $groupItem.append($groupLink) 2505 $('#new_group_btn').before($groupItem) 2506 2507 window.doznutadmin.AppForm.initialize() 2508 } else if (result.mode == 'update') { 2509 $('#group_item_title_' + result.code).text(result.title || '') 2510 $('#group_hidden_item_title_' + result.code).text(result.title || '') 2511 $('#group_hidden_list_title').text(result.title || '') 2512 } 2513 $.cocoaDialog.close() 2514 } else { 2515 if (result.msg == 'VERSION ERROR') { 2516 if (confirm(LOCALIZE_ADMIN.ì¤ëª _ì ê·¸ë ì´ëíì´ì§ë¡ì´ëí ê¹ì())) { 2517 window.location.href = '/admin/payment?mode=detail&type=upgrade' 2518 } 2519 } else { 2520 alert(result.msg) 2521 } 2522 } 2523 } 2524 }) 2525 }, 2526 openDeleteMemberGroup: function (code, group_code) { 2527 $.ajax({ 2528 type: 'POST', 2529 data: { code, group_code }, 2530 url: ('/admin/ajax/member/delete_member_group.cm'), 2531 dataType: 'json', 2532 async: false, 2533 cache: false, 2534 success: function (res) { 2535 if (res.msg == 'SUCCESS') { 2536 $.cocoaDialog.open({ 2537 type: 'admin', 2538 custom_popup: res.html, 2539 width: 550, 2540 reopen: true,
2541 use_enter: true, 2542 hide_event: function () { 2543 $(window).unbind('keydown') 2544 } 2545 }) 2546 } else { 2547 alert(res.msg) 2548 } 2549 } 2550 }) 2551 }, 2552 openUpdateMemberConfirm: function (code, type) { 2553 $.ajax({ 2554 type: 'POST', 2555 data: { code, type }, 2556 url: ('/admin/ajax/member/update_member_confirm.cm'), 2557 dataType: 'html', 2558 async: false, 2559 cache: false, 2560 success: function (html) { 2561 $.cocoaDialog.open({ type: 'admin', custom_popup: html }) 2562 } 2563 }) 2564 }, 2565 UpdateMemberConfirm: function (code, type) { 2566 if (is_join_confirm) return 2567 is_join_confirm = true 2568 $.ajax({ 2569 type: 'POST', 2570 data: { code }, 2571 url: ('/admin/ajax/member/update_member_confirm_proc.cm'), 2572 dataType: 'json', 2573 async: false, 2574 cache: false, 2575 success: function (result) { 2576 if (result.msg == 'SUCCESS') { 2577 location.reload() 2578 } else { 2579 alert(result.msg) 2580 is_join_confirm = false 2581 } 2582 } 2583 }) 2584 }, 2585 openDeleteMember: function (data) { 2586 $.ajax({ 2587 type: 'POST', 2588 data: { data }, 2589 url: ('/admin/ajax/member/delete_member.cm'), 2590 dataType: 'html', 2591 async: false, 2592 cache: false, 2593 success: function (html) { 2594 $.cocoaDialog.open({ type: 'admin', custom_popup: html }) 2595 }, 2596 error: function () { 2597 alert(getLocalizeString('ì¤ëª _ì ìíë¤ììëí´ì£¼ì¸ì', '', 'ì ì í ë¤ì ìëí´ì£¼ì¸ì.')) 2598 } 2599 }) 2600 }, 2601 openDeleteInactiveMember: function (code) { 2602 $.ajax({ 2603 type: 'POST', 2604 data: { code: JSON.stringify(code) }, 2605 url: ('/admin/ajax/member/delete_inactive_member.cm'), 2606 dataType: 'html', 2607 async: false, 2608 cache: false, 2609 success: function (html) { 2610 $.cocoaDialog.open({ type: 'admin', custom_popup: html }) 2611 } 2612 }) 2613 }, 2614 openInactiveMember: function (code) { 2615 $.ajax({ 2616 type: 'POST', 2617 data: { code: JSON.stringify(code) }, 2618 url: ('/admin/ajax/member/inactive_member.cm'), 2619 dataType: 'html', 2620 async: false, 2621 cache: false, 2622 success: function (html) { 2623 $.cocoaDialog.open({ type: 'admin', custom_popup: html }) 2624 } 2625 }) 2626 }, 2627 UpdateMemberAutoGroupingSetting: function (code, use) { 2628 $.ajax({ 2629 type: 'POST', 2630 data: { code, use }, 2631 url: '/admin/ajax/member/member_autogrouping_setting_proc.cm', 2632 dataType: 'json', 2633 async: false, 2634 cache: false, 2635 success: function (result) { 2636 if (result.msg == 'SUCCESS') { 2637 location.reload() 2638 } else { alert(result.msg) } 2639 } 2640 }) 2641 }, 2642 deleteMember: function (data) { 2643 $.ajax({ 2644 type: 'POST', 2645 data: { data }, 2646 url: ('/admin/ajax/member/delete_member_proc.cm'), 2647 dataType: 'json', 2648 async: false, 2649 cache: false, 2650 success: function (result) { 2651 if (result.msg == 'SUCCESS') { 2652 mixpanel.track('complete_bo_member_list_delete_item', {'count': JSON.parse(data).length,'site_code': SITE_CODE}
2652); 2653 location.reload() 2654 } else { alert(result.msg) } 2655 } 2656 }) 2657 }, 2658 deleteInactiveMember: function (code) { 2659 $.ajax({ 2660 type: 'POST', 2661 data: { mode: 'delete', code }, 2662 url: ('/admin/ajax/member/delete_inactive_member_proc.cm'), 2663 dataType: 'json', 2664 async: false, 2665 cache: false, 2666 success: function (result) { 2667 if (result.msg == 'SUCCESS') { 2668 location.reload() 2669 } else { alert(result.msg) } 2670 } 2671 }) 2672 }, 2673 updateInactiveMember: function (code) { 2674 $.ajax({ 2675 type: 'POST', 2676 data: { code }, 2677 url: ('/admin/ajax/member/inactive_member_proc.cm'), 2678 dataType: 'json', 2679 async: false, 2680 cache: false, 2681 success: function (result) { 2682 if (result.msg == 'SUCCESS') { 2683 location.reload() 2684 } else { alert(result.msg) } 2685 } 2686 }) 2687 }, 2688 deleteMemberAuth: function (code) { 2689 if (!confirm(getLocalizeString('ì¤ëª _본ì¸ì¸ì¦í´ì ', '', '본ì¸ì¸ì¦ì í´ì íë©´ í´ë¹ íìì ì¤ëª íì¸ ë° ì¤ë³µ ê°ì ë°©ì§, ìì´ë·í¨ì¤ìë 찾기, ì±ì¸ ì¬ë¶ íì¸ ê¸°ë¥ì´ ëìíì§ ìë ì 주ìí´ì£¼ì¸ì. 본ì¸ì¸ì¦ í´ì 를 ì§í íìê² ìµëê¹?'))) { 2690 return false 2691 } 2692 $.ajax({ 2693 type: 'POST', 2694 data: { code }, 2695 url: ('/admin/ajax/member/delete_member_auth.cm'), 2696 dataType: 'json', 2697 async: false, 2698 cache: false, 2699 success: function (result) { 2700 alert(result.msg) 2701 location.reload() 2702 } 2703 }) 2704 }, 2705 openBlockMember: function (idx) { 2706 $.ajax({ 2707 type: 'POST', 2708 data: { idx }, 2709 url: ('/admin/member/list/block_member.cm'), 2710 dataType: 'html', 2711 async: false, 2712 cache: false, 2713 success: function (html) { 2714 $.cocoaDialog.open({ type: 'admin', custom_popup: html }) 2715 } 2716 }) 2717 }, 2718 blockMember: function (idx) { 2719 $.ajax({ 2720 type: 'POST', 2721 data: { idx }, 2722 url: ('/admin/member/list/block_member_proc.cm'), 2723 dataType: 'json', 2724 async: false, 2725 cache: false, 2726 success: function (result) { 2727 if (result.msg == 'SUCCESS') { $('#member_item_' + idx).addClass('block') } else { alert(result.msg) } 2728 } 2729 }) 2730 }, 2731 openMemberPushForm: function (member_code_list) { 2732 $.ajax({ 2733 type: 'POST', 2734 data: { member_code_list }, 2735 url: ('/admin/member/send/member_push_form.cm'), 2736 dataType: 'html', 2737 async: false, 2738 cache: false, 2739 success: function (html) { 2740 $.cocoaDialog.open({ type: 'admin', custom_popup: html, width: 600 }) 2741 } 2742 }) 2743 }, 2744 openMemberSmsForm: function (member_code_list, order_code) { 2745 $.ajax({ 2746 type: 'POST', 2747 data: { member_code_list, order_code }, 2748 url: ('/admin/member/send/member_sms_form.cm'), 2749 dataType: 'html', 2750 async: false, 2751 cache: false, 2752 success: function (html) { 2753 $.cocoaDialog.open({ type: 'admin', custom_popup: html, width: 600 }) 2754 } 2755 }) 2756 }, 2757 sendPush: function (receiver, alarm_subject, alarm_content, url, alarm_img_tmp_idx, alarm_img, all_send, is_booking, booking_time, alarm_token, alarm_token_key) { 2758 if (isSiteOutboundBlocked()) { 2759 return showSiteOutboundGuide() 2760 } 2761 2762 $.ajax({ 2763 type: 'POST', 2764 data: { 2765 receiver, 2766 alarm_subject, 2767 alarm_content, 2768 url, 2769 alarm_img_tmp_idx, 2770 alarm_img, 2771 all_send: (all_send ? 'Y' : 'N'), 2772 is_booking: (is_booking ? 'Y' : 'N'), 2773 booking_time, 2774 alarm_token, 2775 alarm_token_key 2776 }, 2777 url: ('/admin/ajax/send_alarm.cm'), 2778 dataType: 'json', 2779 async: false, 2780 cache: false, 2781 success: function (res) { 2782 if (res.msg == 'SUCCESS') { 2783 $.cocoaDialog.open({ type: 'admin', custom_popup: res.html, width: 550 }) 2784 } else { 2785 if (res.html !== undefined) { 2786 $.cocoaDialog.open({ type: 'admin', custom_popup: res.html, width: 550 }) 2787 } else { 2788 alert(res.msg) 2789 } 2790 } 2791 } 2792 }) 2793 }, 2794 /** 2795 * ì¤ë³µ ì ì¶ ë°©ì§ì© ë²í¼ ì ê¸. **ê°ëê° ìë íë©´ë 커ë²íë¤.** 2796 * 2797 * ê°ë(`MessageSendGuard`)ë SDK ê° ë°°í¬ë ìë²ììë§ ë¶ëë¤(`typeof` ê°ë). ê·¸ ì°½ìì 2798 * ì ê¸ì´ ìì¼ë©´ ìì² ì¤ì ë¤ì ëë¬ ìì²ì´ ë ë² ëê°ê³ **í¬ë ë§ì´ ë ë² ì°¨ê°**ëë¤. 2799 * ê·¸ëì ë²í¼ ìì를 ì§ì ì ê·¼ë¤ â `disabled` ë í´ë¦ì ë§ê³ , jQuery UI ë²í¼ì´ë©´ í´ëì¤ë ë§ì¶ë¤. 2800 * 2801 * ì ê¸ ë²í¼ì íë©´ì´ ì¤ ì íì(ëë ìì)ë¡ ì°¾ëë¤. íë©´ë§ë¤ ë²í¼ id ê° ë¬ë¼ 2802 * (`#sendsms`Â·ëª¨ë¬ í¸í°) í¸ì¶ë¶ê° ì íê² ëë¤. 2803 * 2804 * @param {*} target ì íì | jQuery | DOM. ìì¼ë©´ ì ê·¸ì§ ìëë¤. 2805 * @param {boolean} on true ë©´ ì ê·¸ê³ false ë©´ í¼ë¤. 2806 */ 2807 setSendButtonLock: function (target, on) { 2808 if (!target) return 2809 const $btn = $(target) 2810 if ($btn.length === 0) return 2811 if (on) { 2812 $btn.prop('disabled', true).addClass('disabled') 2813 } else { 2814 $btn.prop('disabled', false).removeClass('disabled') 2815 } 2816 }, 2817 /** 2818 * ì¤ë³µ í´ë¦ ìë´ ë¬¸êµ¬. **íë©´ì ìë¡ê³ 침íì§ ìëë¤** â 첫 ìì²ì´ ê·¸ëë¡ ì´ì ìì´
2819 * ìë¡ê³ 침íë©´ ê²°ê³¼ê° ì¬ë¼ì§ê³ , ì¬ì©ìê° ë¤ì ëë¬ ì¤ë³µ ë°ì¡ì´ ëë¤. 2820 */ 2821 MESSAGE_SENDING: 'ì ì¡ ì¤ì ëë¤. ì ìë§ ê¸°ë¤ë ¤ 주ì¸ì.', 2822 /** 2823 * ìë SMS ë°ì¡. íë©´ì´ ë§ë `MessageSendGuard` 를 9ë²ì§¸ ì¸ìë¡ ë기면 2824 * ë²í¼ ìë ìí ì¹ì ì ê²ì¬ ì¤Â·ì°¨ë¨Â·ì¤í¨ë¥¼ íìíë¤. 2825 * 2826 * ê°ëê° ìì´ë(ë¤ë¥¸ í면·구ë²ì íë©´) ë°ì¡ì ê·¸ëë¡ ëìíë¤ â ìëµ ë¬¸êµ¬ë ìë²ê° ì 본ì´ë¼ 2827 * ê°ëê° ìì¼ë©´ 기존 alert ê²½ë¡ê° ê·¸ 문구를 ë³´ì¬ ì¤ë¤. 2828 * 2829 * **ë¹ë기 XHR ì´ë¤.** ë기(`async:false`)ë©´ ë¸ë¼ì°ì ê° ë ë를 ë©ì¶°, íì ì´ ìµë 13ì´ ê±¸ë¦¬ë 2830 * ëì "ê²ì¬ ì¤" ì¹ì ì´ **í ë²ë ê·¸ë ¤ì§ì§ ìëë¤**(ìëµì´ ì¨ ë¤ìì¼ íë©´ì´ ê°±ì ëë¤). 2831 * ì¤ë³µ ì ì¶ì ê°ëì ë²í¼ ì ê¸ + `is_writing` + ìë ë²í¼ ì§ì ì ê¸ì´ í¨ê» ë§ëë¤. 2832 */ 2833 sendSms: function (receiver, title, msg, chk_agree, booking_time, is_booking, is_advertisement, two_factor_auth_token, guard, send_button) { 2834 if (isSiteOutboundBlocked()) { 2835 // 기존 ì¬ì (ë§ë£Â·ì ê·Â·ë¬´ë£ì²´í)ë©´ **ì¬ì 를 ìë¦¬ì§ ìëë¤** â íë©´ ì§ì ìì²´ê° ë§íê³ 2836 // (outbound_blocked.sub ê° ë¹ ìí를 그린ë¤) ì¬ê¸° ëë¬íë¤ë©´ ì´ë¯¸ ìë´ë¥¼ 본 ìíë¤. 2837 // ê·¸ëì ì¹ì ë§ ì ë¦¬í´ ê¸°ì¡´ ìë´ì 맡긴ë¤(ì¤í¨ 문구를 ëì°ë©´ ì¬ì 를 ìì°íê² ëë¤). 2838 // 2839 // **2ì°¨ ì¸ì¦ ì¬ì ë ìì¸ë¤** â ê·¸ ì¬ì ë ì´ì©ìê° ì¤ì¤ë¡ í´ìí´ì¼ íë ì¤ì ì´ë¼, 2840 // íë©´ ì§ì ì´ ë§íì§ ìë ê²½ë¡(모ë¬Â·ì¬ìë)ììë ì¬ê¸°ì ìë´ë¥¼ ëìì¼ íë¤. 2841 // `showSiteOutboundGuide()` ë ë¬¸êµ¬ê° ë¹ ë¬¸ìì´ì´ë©´ ì무ê²ë í
2841ì§ ìëë¤(ì¢ ì ëì). 2842 if (guard) guard.succeed() 2843 return showSiteOutboundGuide() 2844 } 2845 2846 // ê°ë·ë²í¼ê¹ì§ í¬í¨í´ ë긴ë¤(ì¸ë±ì¤ 8·9). 2ì°¨ ì¸ì¦ ì¬ìë ëë ì ì§ë¼ì¼ 2847 // ì¬ìë ìëµì´ ê°ì ì¹ì ì íìëê³ ê°ì ë²í¼ì´ ì 긴ë¤. 2848 const send_args = Array.prototype.slice.call(arguments, 0, 10) 2849 const retry = function (auth_token) { 2850 const retry_args = send_args.slice() 2851 retry_args[7] = auth_token 2852 // ì¬ìëë ê²ì¬ ì¤ ìíë¡ ëìê°ë¤. ì¬ê¸°ì ì ì¼ë©´ 2ì°¨ ì¸ì¦ì ë§ì¹ê³ ëìì¨ ë¤ 2853 // ì¹ì ì´ ì´ì 문구(ëë ë¹ ìí)ë¡ ë¨ì ì¬ì©ìê° ì§í ì¤ì¸ì§ ì ì ìë¤. 2854 if (guard) guard.start() 2855 adminMember.sendSms.apply(adminMember, retry_args) 2856 } 2857 if (is_writing) { 2858 // **ìë¡ê³ 침íì§ ìëë¤.** 첫 ìì²ì´ ì´ì ìëë° íì´ì§ë¥¼ ê°ì ë²ë¦¬ë©´ ê²°ê³¼ê° ì¬ë¼ì§ê³ , 2859 // ì¬ì©ìê° ë¤ì ëë¬ ì¤ë³µ ë°ì¡Â·ì¤ë³µ ì°¨ê°ì´ ëë¤. ìë´ë§ ëì´ë¤. 2860 // 2861 // **ì´ í´ë¦ì ê°ëë ì¬ê¸°ì ëë¸ë¤.** íë©´ì´ í´ë¦ë§ë¤ `guard.start()` 를 ë¶ë¥´ë¯ë¡, 2862 // ê·¸ë¥ return íë©´ ì´ ê°ëì watchdog íì´ë¨¸ê° ì´ì ë¨ê³ ì¹ì ì´ "ê²ì¬ ì¤"ì¼ë¡ ë¨ëë¤ â 2863 // 첫 ìì²ì´ ëë 결과를 그린 ë¤ìë ì´ ê°ëê° ëì¤ì 문구를 ë®ì´ì´ë¤. 2864 // (ì¹ì ì ë²í¼ íëì ê³µì ëë¯ë¡, 첫 ìì²ì ê°ëê° ìëµ ë ë¤ì 그린ë¤.) 2865 if (guard) guard.succeed() 2866 alert(adminMember.MESSAGE_SENDING) 2867 return false 2868 } 2869 2870 is_writing = true 2871 // ê°ëê° ìì´ë ë²í¼ì ì ê·¼ë¤(ì¤ë³µ ì ì¶ ì°¨ë¨). ê°ëê° ìì¼ë©´ ê°ëë ê°ì ë²í¼ì ì ê·¼ë¤. 2872 adminMember.setSendButtonLock(send_button, true) 2873 const data = { receiver, title, msg, chk_agree, booking_time, is_booking: (is_booking ? 'Y' : 'N'), is_advertisement: (is_advertisement ? 'Y' : 'N') } 2874 if (two_factor_auth_token) data.two_factor_auth_token = two_factor_auth_token 2875 $.ajax({ 2876 type: 'POST', 2877 data, 2878 url: ('/admin/ajax/sms/send_sms.cm'), 2879 dataType: 'json', 2880 async: true, 2881 cache: false, 2882 // íì ìì°(13ì´)ë³´ë¤ ëëíê² ëë¤. ì´ ìê°ì´ ì§ëë©´ `error` ê° ì¤ê³ , ê·¸ë ê°ëê° 2883 // ì¤í¨ 문구를 ëì°ë©° **ë²í¼ ì ê¸ì í¼ë¤**(watchdog ì ì ê¸ì íì§ ìëë¤). 2884 timeout: 60000, 2885 success: function (res) { 2886 // ê°ëê° ìì¼ë©´ ìë² ë¬¸êµ¬ë¥¼ ê·¸ ì¹ì ì ê·¸ëë¡ ë³´ì¬ ì¤ë¤(ì°¨ë¨Â·ì¤í¨Â·ì±ê³µ 모ë). 2887 // íì ì°¨ë¨ ë¬¸êµ¬ë ì¬ê¸°ë¡ ì¤ë¯ë¡ ë³ë ë¶ê¸°ê° íì ìë¤. 2888 const guard_state = guard ? guard.resolve(res) : null 2889 // **ì´ ìëµì ì²ë¦¬ë ì¬ê¸°ì ëë¬ë¤.** ìë `retry`(2ì°¨ ì¸ì¦)ê° `sendSms` 를 ë¤ì ë¶ë¥´ëë°, 2890 // `is_writing` ì ì´ ìëì ëë©´ ì¬ìëê° "ì´ë¯¸ ì ì¡ ì¤"ì¼ë¡ ì í **ì¤ì ë¡ ë°ì¡ëì§ ìëë¤**. 2891 // (ìì ìë ê·¸ ì리를 `window.location.reload()` ê° ë®ì´ ìë¡ê³ 침ì¼ë¡ ë³´ìë¤.) 2892 // ì¬ìëê° ì ìì²ì ììíë©´ 그쪽ìì ë¤ì ì ê·¸ë¯ë¡, ì¬ê¸°ì 먼ì í¸ë ê²ì´ ë§ë¤. 2893 is_writing = false 2894 adminMember.setSendButtonLock(send_button, false) 2895 if (res.msg == 'SUCCESS') { 2896 $.cocoaDialog.open({ type: 'admin', custom_popup: res.html, width: 550, close_block: true }) 2897 } else if (!ADMIN_MESSAGE_STEP_UP.handleSendResponse(res, retry)) { 2898 if (res.html !== undefined) { 2899 $.cocoaDialog.open({ type: 'admin', custom_popup: res.html, width: 550 }) 2900 } else if (guard_state === 'blocked' || guard_state === 'unavailable') { 2901 // ê°ëê° ì´ë¯¸ ê°ì 문구를 ì¹ì ì ëì ë¤. alert ë¡ ë ëì°ë©´ ë ë² ë³´ì¸ë¤. 2902 } else { 2903 alert(res.msg) 2904 } 2905 } 2906 }, 2907 error: function () { 2908 // ë¤í¸ìí¬ ì¤ë¥Â·íë©´ íììì. ê°ë를 ì¤í¨ë¡ ëë´ **ë²í¼ ì ê¸ì í¼ë¤.** 2909 if (guard) guard.fail() 2910 is_writing = false 2911 adminMember.setSendButtonLock(send_button, false) 2912 } 2913 }) 2914 }, 2915 deleteBookingSms: function (sms_log_idx, sms_type) { 2916 if (!confirm(LOCALIZE_ADMIN.ì¤ëª _ì¬ë¬ëª ìê²ì ì¡íë©ì¸ì§ìê²½ì°ì¼ê´ì·¨ìë©ëë¤())) return false 2917 $.ajax({ 2918 type: 'POST', 2919 data: { sms_log_idx, sms_type }, 2920 url: ('/admin/ajax/sms/delete_booking_sms.cm'), 2921 dataType: 'json', 2922 async: false, 2923 cache: false, 2924 success: function (obj) { 2925 if (obj.msg === 'SUCCESS') { 2926 window.location.reload() 2927 } else { 2928 if (obj.msg === 'CONFLICT') { 2929 alert(getLocalizeString('ì¤ëª _ì´ë¯¸ë°ì¡ëë©ì¸ì§ëì·¨ìí ìììµëë¤', '', 'ì´ë¯¸ ë°ì¡ë ë©ì¸ì§ë ì·¨ìí ì ììµëë¤')) 2930 window.location.reload() 2931 } else { 2932 alert(obj.msg) 2933 } 2934 } 2935 } 2936 }) 2937 }, 2938 openSmsDetailList: function (sms_log_idx, search_type, search_keyword) { 2939 $.ajax({ 2940 type: 'POST', 2941 data: { 'sms_log_idx' : sms_log_idx, 'search_type' : search_type, 'search_keyword': search_keyword}, 2942 url: ('/admin/ajax/sms/sms_detail_list.cm'), 2943 dataType: 'html', 2944 async: false, 2945 cache: false, 2946 success: function (html) {
2947 $.cocoaDialog.open({ type: 'admin_sms', custom_popup: html }) 2948 } 2949 }) 2950 }, 2951 refreshMessageCreditCount: function ($root) { 2952 const $targetRoot = $root ? $($root) : $(document) 2953 const $creditCount = $targetRoot.find('._message_credit_count').add($targetRoot.filter('._message_credit_count')) 2954 if ($creditCount.length === 0) { 2955 return 2956 } 2957 2958 $.ajax({ 2959 type: 'GET', 2960 url: ('/admin/ajax/sms/get_sms_credit.cm'), 2961 dataType: 'json', 2962 cache: false, 2963 success: function (res) { 2964 if (res.success !== true || !res.data || typeof res.data.credit === 'undefined') { 2965 return 2966 } 2967 2968 const credit = parseFloat(res.data.credit) 2969 if (isNaN(credit)) { 2970 return 2971 } 2972 2973 $creditCount.text(credit > 0 ? credit.toLocaleString(undefined, { maximumFractionDigits: 1 }) : '0') 2974 } 2975 }) 2976 }, 2977 openChargeSmsform: function (type, redirectUrlOrOnClose) { 2978 const messageCreditChargeConfig = window.messageCreditChargeConfig || {} 2979 const redirectUrl = typeof redirectUrlOrOnClose === 'string' && redirectUrlOrOnClose !== '' ? redirectUrlOrOnClose : window.location.href 2980 const closeHandler = typeof redirectUrlOrOnClose === 'function' ? redirectUrlOrOnClose : null 2981 const runOnClose = function () { 2982 if (typeof closeHandler === 'function') { 2983 closeHandler() 2984 } 2985 } 2986 2987 if (type === 'member' && typeof mixpanel !== 'undefined' && typeof SITE_CODE !== 'undefined') { 2988 mixpanel.track('click_bo_member_message_sms_purchase', { 'site_code': SITE_CODE }) 2989 } 2990 2991 // ë§ë£Â·ì ê·Â·ë¬´ë£ì²´í ì¬ì´í¸ë ì¶©ì 모ë¬ì ì´ì§ ìëë¤. 2992 // **ì¬ì 를 ìë¦¬ì§ ìëë¤** â alert ë¡ ì´ì 를 ìë ¤ 주면 ì°í ì¡°ê±´(72ìê° ë기·ì ë£ ì í)ì 2993 // ìì°íë¤(ì¬ì©ì ê²°ì , 2026-10-01). ê·¸ëì ì¡°ì©í return ë§ íë¤. 2994 // **ë¹ì© ì¶ë§** â ì¶©ì ì ë°ì¡ ê²½ë¡ê° ìëë¤(ì¬ì©ì íì 2026-10-07). 2995 if (isSiteOutboundBlockedByCost()) { 2996 return showSiteOutboundGuide() 2997 } 2998 2999 if (messageCreditChargeConfig.useMessageCreditChargeModal) { 3000 if (messageCreditChargeConfig.isFreeSite) { 3001 if (confirm(LOCALIZE_ADMIN.ì¤ëª _ì ê·¸ë ì´ëíì´ì§ë¡ì´ëí ê¹ì())) { 3002 location.href = '/admin/payment?mode=detail&type=upgrade' 3003 return false 3004 } 3005 3006 runOnClose() 3007 return false 3008 } 3009 3010 if (!messageCreditChargeConfig.canCharge) { 3011 alert(LOCALIZE_ADMIN.ì¤ëª _ê¶íì´ììµëë¤()) 3012 runOnClose() 3013 return false 3014 } 3015 3016 if (messageCreditChargeConfig.isEnabled) { 3017 window.dispatchEvent(new CustomEvent('open:charge')) 3018 runOnClose() 3019 return false 3020 } 3021 } 3022 3023 $.ajax({ 3024 type: 'POST', 3025 data: { 3026 type, 3027 current_url: redirectUrl, 3028 }, 3029 url: ('/admin/ajax/sms/charge_sms.cm'), 3030 dataType: 'html', 3031 async: false, 3032 cache: false, 3033 success: function (html) { 3034 $.cocoaDialog.open({ 3035 type: 'admin_sms', 3036 custom_popup: html, 3037 use_enter: true, 3038 hide_event: function () { 3039 $(window).unbind('keydown') 3040 // ëª¨ë¬ ë«í ì½ë°± ì¤í 3041 runOnClose() 3042 } 3043 }) 3044 } 3045 }) 3046 }, 3047 sendSmsInit: function () { 3048 let url = decodeURIComponent(location.href) 3049 url = decodeURIComponent(url) 3050 url = url.split('#') 3051 if (url.length > 1 && url[1] == 'typednumber') { 3052 $('input[name="send_to"]:radio[value="number"]').attr('checked', true) 3053 $('.form-group.send_to').hide() 3054 $('.form-group.send_to.number').show() 3055 } 3056 }, 3057 openManageMemberPoint: function (code) { 3058 $.ajax({ 3059 type: 'POST', 3060 data: { code }, 3061 url: ('/admin/ajax/member/manage_member_point.cm'), 3062 dataType: 'html', 3063 async: false, 3064 cache: false, 3065 success: function (html) { 3066 $.cocoaDialog.open({ type: 'admin', custom_popup: html }) 3067 } 3068 }) 3069 }, 3070 manageMemberPoint: function (code) { 3071 const $form = $('#shop_member_point') 3072 const data = $form.serializeObject() 3073 $.ajax({ 3074 type: 'POST', 3075 data: { code, data }, 3076 url: ('/admin/ajax/member/manage_member_point_proc.cm'), 3077 dataType: 'json', 3078 async: false, 3079 cache: false, 3080 success: function (result) { 3081 if (result.msg == 'SUCCESS') { 3082 location.reload() 3083 } else { alert(result.msg) } 3084 } 3085 }) 3086 }, 3087 updateAdminMemo: function (member_code, memo, callback) { 3088 $.ajax({ 3089 type: 'POST', 3090 data: { 3091 admin_memo: memo, 3092 code: member_code 3093 }, 3094 url: ('/admin/ajax/member/update_admin_memo.cm'), 3095 dataType: 'json', 3096 async: false, 3097 cache: false, 3098 success: function (res) { 3099 callback(res) 3100 } 3101 }) 3102 }, 3103 openAdminMemoForm: function (member_code) { 3104 $.ajax({ 3105 type: 'POST', 3106 data: { member_code }, 3107 url: ('/admin/ajax/member/admin_memo_form.cm'), 3108 dataType: 'html', 3109 async: false, 3110 cache: false, 3111 success: function (html) {
3112 $.cocoaDialog.open({ type: 'admin', custom_popup: html, width: 550 }, function () { 3113 const $btn_admin_memo = $('#btn_admin_memo') 3114 const $admin_memo = $('#admin_memo') 3115 if ($admin_memo.length > 0) { 3116 const $admin_memo_chars_title = $('#admin_memo_chars_title') 3117 var pre_admin_memo = $admin_memo.val() 3118 $admin_memo_chars_title.html(getByteLength(pre_admin_memo) + '/500') 3119 $admin_memo.off('keyup.admin_memo').on('keyup.admin_memo', function (e) { 3120 const content = $(this).val() 3121 $admin_memo_chars_title.html(getByteLength(content) + '/500') 3122 }) 3123 } 3124 3125 $btn_admin_memo.off('click.btn_admin_memo').on('click.btn_admin_memo', function () { 3126 const memo = $admin_memo.val() 3127 if (pre_admin_memo !== memo) { 3128 pre_admin_memo = memo 3129 3130 if (member_code !== '') { 3131 adminMember.updateAdminMemo(member_code, memo, function (res) { 3132 if (res.msg !== 'SUCCESS') alert(res.msg) 3133 else location.reload() 3134 }) 3135 } 3136 } 3137 }) 3138 }) 3139 } 3140 }) 3141 } 3142} 3143const SMS_DATAIL_PAGE_MODE = (function () { 3144 let page = 1 3145 let end_data = false 3146 const init = function (sms_log_idx, reset) { 3147 getSmsDetailList(sms_log_idx, reset) 3148 } 3149 var getSmsDetailList = function (sms_log_idx, reset) { 3150 if (reset === true) { 3151 page = 1 3152 end_data = false 3153 } 3154 if (end_data) return false 3155 $.ajax({ 3156 type: 'GET', 3157 data: { sms_log_idx, page }, 3158 url: ('/admin/ajax/sms/get_sms_detail_list.cm'), 3159 dataType: 'json', 3160 async: false, 3161 cache: true, 3162 success: function (res) { 3163 if (res.data) { 3164 if (res.data.length >= 30) { 3165 $('#target-parent').css('height', '50vh').css('overflow-y', 'scroll') 3166 } 3167 page++ 3168 res.data.forEach(function (log) { 3169 $('#target').append( 3170 '<tr>' + 3171 '<td class="text-center">' + log.receiver + '</td>\n' + 3172 '<td class="text-center" style="padding : 8px;">' + log.status + '</td>\n' + 3173 '</tr>') 3174 }) 3175 } else { 3176 end_data = true 3177 } 3178 } 3179 }) 3180 } 3181 return { 3182 init: function (sms_log_idx, reset) { 3183 init(sms_log_idx, reset) 3184 }, 3185 getSmsDetailList: function (sms_log_idx, reset) { 3186 getSmsDetailList(sms_log_idx, reset) 3187 } 3188 } 3189}()) 3190const ADMIN_SMS_SEND = (function () { 3191 let send_type 3192 let push_member_data 3193 let $receiver, $sender, $title, $content 3194 3195 const init = function (type) { 3196 send_type = type 3197 $sender = $('#sms_num') 3198 $content = $('#sms_content') 3199 $title = $('#sms_subject') 3200 3201 // ì íë²í¸ íì ì²´í¬ 3202 $('.phonenumber').on('keydown').check_callnum() 3203 3204 // ë´ì© ìì±ì ë°ì´í¸ í기 3205 const lms_max_byte = 2000 3206 $content.keyup(function (e) { 3207 const content = $(this).val() 3208 let msg_byte = getByteLengthForKorean(content) 3209 3210 if (msg_byte > 90) { 3211 if (msg_byte > lms_max_byte) { 3212 alert(LOCALIZE_ADMIN.ì¤ëª _në°ì´í¸ë¥¼ì´ê³¼í ìììµëë¤(lms_max_byte)) 3213 $(this).val(cutByLen(content, lms_max_byte)) 3214 msg_byte = 2000 3215 } 3216 $('#chars_app_title').html(msg_byte + '/2000') 3217 } else { 3218 $('#chars_app_title').html(msg_byte + '/90') 3219 } 3220 }) 3221 3222 const lms_max_subject_byte = 40 3223 $title.keyup(function (e) { 3224 const content = $(this).val() 3225 let msg_byte = getByteLengthForKorean(content) 3226 3227 if (msg_byte > lms_max_subject_byte) { 3228 alert(LOCALIZE_ADMIN.ì¤ëª _në°ì´í¸ë¥¼ì´ê³¼í ìììµëë¤(lms_max_subject_byte)) 3229 $(this).val(cutByLen(content, 40)) 3230 msg_byte = 40 3231 } 3232 $('#chars_subject_cnt').html(msg_byte + '/40') 3233 }) 3234 3235 $('#sms_subject,#sms_content').keyup() 3236 3237 // 주문리ì¤í¸ìì í¸ì¶ ì ì¶ê° ì¤ì 3238 if (send_type == 'npay') $receiver = $('#receiver_num') 3239 if (send_type == 'order') { 3240 $receiver = $('#receiver_num') 3241 $receiver.data('number', $('input[name="receiver_type"]:checked').data('number')) 3242 3243 // ë¼ëì¤ ë²í¼ ë³ê²½ì ìì ë²í¸ ì¸í ì ì´ 3244 $('input[name="receiver_type"]').on('change', function () { 3245 $receiver.val($(this).data('number')) 3246 $receiver.data('number', $(this).data('number')) 3247 }) 3248 3249 // ë²í¸ ì§ì ìì ìì ë¼ëì¤ ì²´í¬ í´ì 3250 $receiver.on('keyup', function () { 3251 if ($(this).data('number') != $(this).val()) { 3252 $('input[name="receiver_type"]:checked').prop('checked', false) 3253 } 3254 }) 3255 } 3256 } 3257 3258 const send_push = function (button_element) { 3259 makeReceiver() 3260 if (push_member_data.length <= 0) { 3261 alert(getLocalizeString('ì¤ëª _ë°ëì¬ëíìí목', '', 'ë°ëì¬ëì íìí목ì ëë¤.')) 3262 return false 3263 } 3264 if ($content.val().trim() === '') { 3265 alert(getLocalizeString('ì¤ëª _ë´ì©íìí목', '', 'ë´ì©ì íì í목ì ëë¤.')) 3266 return false 3267 } 3268 // SMS íë©´ê³¼ ê°ì ê°ë·ë²í¼ ì ê¸ì ì´ë¤. 3269 // 3270 // **ë²í¼ì í´ë¦ë ìì를 ì°ì ì´ë¤**(onclick ì´ ë긴 `this`). í´ëì¤ë¡ ì°¾ì¼ë©´ ì ëë¤ â 3271 // `$.cocoaDialog` ë `#cocoaModal`·`#cocoaSubModal` **ë ìì를 ì¬ì¬ì©**íë©° ë´ì©ì 3272 // `children().detach()` + `append()` ë¡ **êµì²´**íëë°(vendor/js/common.js:4101), 3273 // ë«í 모ë¬ì ë´ì©ì DOM ì ê·¸ëë¡ ë¨ëë¤. ê·¸ëì `$('.js_send_push').get(0)` ì 3274 // 문ì ììê° ìì `#cocoaModal` ì **ì¨ì ì ë²í¼**ì ì§ì ì ìë¤ 3275 // (ë°ê¹¥ 모ë¬ì´ ë ìì¼ë©´ ì ë´ì©ì `#cocoaSubModal` ë¡ ê°ë¤ â ê°ì íì¼ 3897). 3276 // `this` ê° ìì¼ë©´ ë³´ì´ë ê² ì¤ ë§ì§ë§ì ì´ë¤(í´ë°±). 3277 let send_button = button_element || null 3278 if (!send_button) { 3279 send_button = $('.js_send_push:visible').last().get(0) || null 3280 } 3281 const guard = (typeof MessageSendGuard !== 'undefined') ? MessageSendGuard.attach(send_button) : null 3282 if (guard) guard.start() 3283 // ì¸ìë 기존 í¸ì¶ ê·¸ëë¡ `undefined` ë¡ ëë¤ â ë¹ ë¬¸ìì´ë¡ ë°ê¾¸ë©´ ì§ë ¬íëë íëê° 3284 // ë¬ë¼ì§ë¤(ìë²ê° ë°ë í¼ì´ ë°ëë¤). ì¬ê¸°ì ëíë ê²ì ê°ë·ë²í¼ ëë¿ì´ë¤. 3285 adminMember.sendSms(push_member_data, $title.val(), $content.val(), undefined, undefined, undefined, undefined, undefined, guard, send_button) 3286 } 3287 3288 var makeReceiver = function () { 3289 // ì´ê¸°í 3290 push_member_data = [] 3291 switch (send_type) { 3292 case 'npay': 3293 push_member_data.push({ type: 'number', value: $receiver.val(), proof: $('#receiver_num').closest('form').data('direct-sms-proof') }) 3294 break 3295 case 'order': 3296 const $selected = $('input[name="receiver_type"]:checked') 3297 if ($selected.length && $selected.data('number') == $receiver.val() && $selected.val() == 'member') { 3298 push_member_data.push({ type: 'member', value: $selected.data('member-code') }) 3299 } else if ($selected.length && $selected.data('number') == $receiver.val() && $selected.data('proof')) { 3300 push_member_data.push({ type: 'number', value: $receiver.val(), proof: $selected.data('proof') }) 3301 } else { 3302 push_member_data.push({ type: 'number', value: $receiver.val(), proof: $receiver.closest('form').data('direct-sms-proof') }) 3303 } 3304 break 3305 case 'member': 3306 $('.receiver_list:checked').each(function () { 3307 push_member_data.push({ type: 'member', value: $(this).val() }) 3308 }) 3309 break 3310 } 3311 } 3312 return { 3313 init: function (type) { 3314 init(type) 3315 }, 3316 send_push: function (button_element) { 3317 send_push(button_element) 3318 } 3319 } 3320}()) 3321 3322const AUTO_SMS_SETTING = (function () { 3323 let $dialog 3324 let header_ctl 3325 let $form 3326 let $certification_sender_number 3327 let $sms_config_wrap 3328 const MAX_CERT_DOCUMENT_NUMBER = 11 3329 const DOCUMENT_REQUIREMENT = { // íìë¡ ë±ë¡í´ì¼ íë ì¸ì¦ ìë¥ 3330 personal: { 3331 p_owner: [1], // ì¼ë° ìì ì 3332 p_others: [1, 2, 3], // ì¼ë° íì¸
3333 p_other_company: [1, 2, 3, 4, 5] // ì¼ë° íì¬ 3334 }, 3335 business: { 3336 b_owner: [1, 7], // ëíì 3337 b_first_incumbent: [1, 7, 8], // ìì¬(ì¬ì§ì) 3338 b_first_party: [1, 7], // ìì¬ 3339 b_others: [1, 2, 3, 7], // íì¸ 3340 b_other_company: [1, 2, 3, 4, 5, 6, 7, 8, 9] // íì¬ 3341 } 3342 } 3343 const DOCUMENT_REQUIREMENT_ORDER = [1, 2, 7, 8, 6, 4, 5, 3, 9, 11, 10] // ì¸ì¦ ìë¥ ì í¨ì± ê²ì¬ ìì 3344 3345 const init = function ($obj) { 3346 $dialog = $obj 3347 $form = $dialog.find('#sms_setting_form') 3348 $sms_config_wrap = $dialog.find('#sms_config_wrap') 3349 3350 header_ctl = new HEADER_CONTROL() 3351 header_ctl.init2() 3352 header_ctl.addBtn('save', function () { 3353 submit() 3354 }) 3355 3356 createEvent() 3357 } 3358 3359 var createEvent = function () { 3360 $dialog.find('input[type=checkbox],input[type=radio]').not('._message_credit_auto_charge_enabled').off('click').on('click', function () { 3361 header_ctl.change() 3362 }) 3363 $dialog.find('input[type=text]').off('keydown').on('keydown, change, blur', function () { 3364 header_ctl.change() 3365 }) 3366 $dialog.find('select').off('change').on('change', function () { 3367 header_ctl.change() 3368 }) 3369 $dialog.find('input[name="is_use"]').on('change', function () { 3370 if ($(this).prop('checked')) { 3371 $sms_config_wrap.show() 3372 $form.find('#admin_receive_callnum_wrap').show() 3373 $form.find('#sender_callnum_wrap').show() 3374 $form.find('#use_type_wrap').show() 3375 if ($dialog.find('input[name="use_type"]:checked').val() === 'kakao_alimtalk') { 3376 $form.find('#kakao_alimtalk_wrap').show() 3377 } 3378 } else { 3379 $sms_config_wrap.hide() 3380 $form.find('#admin_receive_callnum_wrap').hide() 3381 $form.find('#sender_callnum_wrap').hide() 3382 $form.find('#kakao_alimtalk_wrap').hide() 3383 $form.find('#use_type_wrap').hide() 3384 } 3385 }) 3386 3387 $dialog.find('input[name="use_type"]').on('change', function () { 3388 if ($(this).val() === 'kakao_alimtalk') { 3389 $form.find('#kakao_alimtalk_wrap').show() 3390 } else { 3391 $form.find('#kakao_alimtalk_wrap').hide() 3392 } 3393 }) 3394 3395 $dialog.find('._message_credit_auto_charge_enabled').off('click').on('click', function (event) { 3396 const $checkbox = $(this) 3397 const hasConfig = $form.find('#message_credit_auto_charge_wrap').attr('data-has-auto-charge-config') === 'Y' 3398 const previousChecked = !$checkbox.prop('checked') 3399 const rollbackCheckbox = function () { 3400 event.preventDefault() 3401 $checkbox.prop('checked', previousChecked) 3402 } 3403 3404 if (!guardMessageCreditAutoChargeAction()) { 3405 rollbackCheckbox() 3406 return false 3407 } 3408 3409 if (!hasConfig) { 3410 rollbackCheckbox() 3411 window.dispatchEvent(new CustomEvent('open:auto-charge')) 3412 return false 3413 } 3414 3415 header_ctl.change() 3416 }) 3417 3418 $dialog.find('._message_credit_auto_charge_setting').off('click').on('click', function () { 3419 if (!guardMessageCreditAutoChargeAction()) { 3420 return false 3421 } 3422 3423 window.dispatchEvent(new CustomEvent('open:auto-charge')) 3424 return false 3425 }) 3426 3427 window.removeEventListener('success:charge', refreshMessageCreditCount) 3428 window.removeEventListener('success:auto-charge-config', refreshMessageCreditAutoChargeConfig) 3429 window.addEventListener('success:charge', refreshMessageCreditCount) 3430 window.addEventListener('success:auto-charge-config', refreshMessageCreditAutoChargeConfig) 3431 } 3432 3433 const guardMessageCreditAutoChargeAction = function () { 3434 const messageCreditChargeConfig = window.messageCreditChargeConfig || {} 3435 3436 // **ë¹ì© ì¶ë§** â ìëì¶©ì **ì¤ì **ì ë°ì¡ë, 문구 ìì±ë ìëë¤(sms_setting_update.cm ê³¼ ê°ì íë¨). 3437 if (isSiteOutboundBlockedByCost()) { 3438 return showSiteOutboundGuide() 3439 } 3440 3441 if (messageCreditChargeConfig.isFreeSite) { 3442 if (confirm(LOCALIZE_ADMIN.ì¤ëª _ì ê·¸ë ì´ëíì´ì§ë¡ì´ëí ê¹ì())) { 3443 location.href = '/admin/payment?mode=detail&type=upgrade' 3444 } 3445 return false 3446 } 3447 3448 if (!messageCreditChargeConfig.canCharge) { 3449 alert(LOCALIZE_ADMIN.ì¤ëª _ê¶íì´ììµëë¤()) 3450 return false 3451 } 3452 3453 return true 3454 } 3455 3456 const applyMessageCreditAutoChargeConfig = function (config) { 3457 const $wrap = $form.find('#message_credit_auto_charge_wrap') 3458 if ($wrap.length === 0) { 3459 return 3460 } 3461 3462 const hasConfig = !!config.hasAutoChargeConfig 3463 const thresholdCount = parseInt(config.thresholdCount, 10) || 0 3464 const chargeAmount = parseInt(config.chargeAmount, 10) || 0 3465 const $checkbox = $wrap.find('._message_credit_auto_charge_enabled') 3466 const nextChecked = !!config.isEnabled 3467 3468 $wrap.attr('data-has-auto-charge-config', hasConfig ? 'Y' : 'N') 3469 $checkbox.prop('checked', nextChecked) 3470 if (hasConfig) { 3471 $checkbox.attr({ name: 'auto_charge_is_enabled', value: 'ok' }) 3472 } else { 3473 $checkbox.removeAttr('name').removeAttr('value') 3474 } 3475 3476 if (hasConfig) { 3477 let chargeAmountText = '' 3478 if (chargeAmount) { 3479 chargeAmountText = chargeAmount % 10000 === 0
3480 ? (chargeAmount / 10000).toLocaleString() + 'ë§ì' 3481 : chargeAmount.toLocaleString() + 'ì' 3482 } 3483 3484 $wrap.find('._message_credit_auto_charge_summary_text').empty() 3485 .append($('<strong />').text(thresholdCount.toLocaleString() + ' í¬ë ë§')) 3486 .append(' ë¨ìì ë ') 3487 .append($('<strong />').text(chargeAmountText)) 3488 .append('ì© ìë ì¶©ì ') 3489 $wrap.find('._message_credit_auto_charge_summary').show() 3490 } else { 3491 $wrap.find('._message_credit_auto_charge_summary').hide() 3492 } 3493 } 3494 3495 const refreshMessageCreditAutoChargeConfig = function () { 3496 $.ajax({ 3497 type: 'GET', 3498 url: ('/admin/ajax/member/message_credit_auto_charge_config.cm'), 3499 dataType: 'json', 3500 cache: false, 3501 success: function (res) { 3502 if (res.msg === 'SUCCESS' && res.data) { 3503 applyMessageCreditAutoChargeConfig(res.data) 3504 } 3505 } 3506 }) 3507 } 3508 3509 const refreshMessageCreditCount = function () { 3510 adminMember.refreshMessageCreditCount($form) 3511 } 3512 3513 /*** 3514 * 문ìë°ì ë²í¸ ì¸ì¦ 3515 */ 3516 function setSmsCertification () { 3517 $certification_sender_number = $('#certification_sender_number') 3518 setSmsCertificationLayout() 3519 } 3520 3521 /*** 3522 * 문ì ë°ì ë²í¸ ì¸ì¦ ë ì´ìì êµ¬ì± 3523 */ 3524 function setSmsCertificationLayout () { 3525 const $cert_save_btn = $certification_sender_number.find('._cert_save_btn') 3526 const $document_from = $certification_sender_number.find('._document_from') 3527 const $person_type_p = $document_from.find("select[name='person_type_p']") 3528 const $person_type_b = $document_from.find("select[name='person_type_b']") 3529 let person_type = 'unset' 3530 const applicant_name = $document_from.find("input[name='applicant_name']").val() 3531 const applicant_callnum = $document_from.find("input[name='applicant_callnum']").val() 3532 const applicant_birthday = $document_from.find("input[name='applicant_birthday']").val() 3533 const applicant_encrypt_ci = $document_from.find("input[name='applicant_encrypt_ci']").val(); 3534 let business_type = 'personal' 3535 const $sender_callnum_document = $document_from.find("input[name='sender_callnum']") 3536 const $sender_callnum_info_document = $document_from.find("input[name='sender_callnum_info']") 3537 const $cert_document_comment = $document_from.find("textarea[name='cert_document_comment']") 3538 const $sender_callnum = $document_from.find("input[name='sender_callnum']") 3539 const $sender_callnum_info = $document_from.find("input[name='sender_callnum_info']") 3540 const $use_owner_callnum_form = $document_from.find('._use_owner_callnum_form')
3541 const owner_callnum = $sender_callnum.attr('data-owner-callnum') 3542 const owner_name = $sender_callnum_info.attr('data-owner-name') 3543 const can_use_owner_callnum = $use_owner_callnum_form.length > 0 3544 let use_owner_callnum = false 3545 3546 /* ë°ì ë²í¸ - ì ì¸ ì«ìë§ ì ë ¥íëë¡ ì í (number íì ì ê²½ì° ì¤í¼ë UIê° ì기ë¯ë¡ ì¤í¬ë¦½í¸ë¡ ì²ë¦¬ */ 3547 $sender_callnum.check_key({ 3548 digit: true, 3549 upper: false, 3550 lower: false 3551 }) 3552 3553 /* ìì ìê° ìëë©´ ìì ì í´ëì í ë²í¸ ì¬ì© ë¶ê° */ 3554 if (can_use_owner_callnum) { 3555 use_owner_callnum = (person_type === 'p_owner' || person_type === 'b_owner') && ($sender_callnum.val() && owner_callnum && $sender_callnum.val() == owner_callnum) 3556 } 3557 3558 setPersonTypeLayout(business_type, person_type, use_owner_callnum) 3559 3560 $certification_sender_number.find("input[name='business_type']").click(function () { 3561 business_type = this.value 3562 person_type = 'unset' 3563 use_owner_callnum = false 3564 setPersonTypeLayout(business_type, person_type, use_owner_callnum) 3565 }) 3566 3567 $person_type_p.change(function () { 3568 person_type = this.value 3569 if (can_use_owner_callnum) { 3570 use_owner_callnum = (person_type === 'p_owner' || person_type === 'b_owner') && ($sender_callnum.val() && owner_callnum && $sender_callnum.val() == owner_callnum) 3571 } 3572 setPersonTypeLayout(business_type, person_type, use_owner_callnum) 3573 }) 3574 3575 $person_type_b.change(function () { 3576 person_type = this.value 3577 if (can_use_owner_callnum) { 3578 use_owner_callnum = (person_type === 'p_owner' || person_type === 'b_owner') && ($sender_callnum.val() && owner_callnum && $sender_callnum.val() == owner_callnum) 3579 } 3580 setPersonTypeLayout(business_type, person_type, use_owner_callnum) 3581 }) 3582 3583 $sender_callnum.change(function () { 3584 if (person_type === 'p_owner' || person_type === 'b_owner') { 3585 if (can_use_owner_callnum) { 3586 use_owner_callnum = this.value && this.value == owner_callnum 3587 $sender_callnum_info_document.val(use_owner_callnum ? owner_name : '') 3588 } 3589 setPersonTypeLayout(business_type, person_type, use_owner_callnum) 3590 } 3591 }) 3592 if (can_use_owner_callnum) { 3593 $document_from.find("input[name='use_owner_callnum']").click(function () { 3594 if (person_type === 'p_owner' || person_type === 'b_owner') { 3595 use_owner_callnum = this.checked 3596 $sender_callnum.val(use_owner_callnum ? owner_callnum : '') 3597 ////$sender_callnum_info_document ì¸íë°ì¤ì ë´ì©ì ìì 주 ì´ë¦ì¼ë¡ ì¤ì 3598 $sender_callnum_info_document.val(use_owner_callnum ? owner_name : '') 3599 setPersonTypeLayout(business_type, person_type, use_owner_callnum) 3600 } 3601 }) 3602 } 3603 3604 for (let file_num = 1; file_num <= MAX_CERT_DOCUMENT_NUMBER; file_num++) { 3605 const attach_upload_text = $certification_sender_number.find(`._attach${file_num}_upload_text`) 3606 $certification_sender_number.find(`._attach${file_num}_upload`).fileupload({ 3607 url: '/admin/ajax/upload_file.cm', 3608 formData: { temp: 'Y' }, 3609 dataType: 'json', 3610 target: 'sms_config', 3611 singleFileUploads: true, 3612 limitMultiFileUploads: 1, 3613 dropZone: false, 3614 acceptFileTypes: /(\.|\/)(gif|jpe?g|png|pdf|zip)$/i, 3615 start: function (e, data) { 3616 3617 }, 3618 progress: function (e, data) { 3619 3620 }, 3621 done: function (e, data) { 3622 $.each(data.result.files, function (e, tmp) { 3623 if (tmp.error == null) { 3624 if (file_num === 1) { 3625 /* íµì ìë¹ì¤ ì´ì©ì¦ëª ì ë±ë¡ ì ì í¨ì± ì²´í¬ (íµì í매ì ì ê³ ì¦ í¼ë ë°©ì§) */ 3626 if (tmp.org_name.indexOf('í매ì ') > -1 || tmp.org_name.indexOf('ì ê³ ì¦') > -1) { 3627 alert('íµì ì¬ìì 1ê°ì ì´ë´ ë°ê¸ë°ì íµì ìë¹ì¤ ì´ì©ì¦ëª ìì ë±ë¡í´ 주ì¸ì.') 3628 return false 3629 } 3630 } 3631 $certification_sender_number.find(`input[name='cert_document_attach${file_num}']`).val(tmp.tmp_idx) 3632 attach_upload_text.find('._file_unset').addClass('tw-hidden') 3633 /* @TODO GetFileSize íí íµì¼ */ 3634 attach_upload_text.find('._file_size').text(`(${GetFileSize(tmp.size)}) `) 3635 attach_upload_text.find('._file_name').text(tmp.org_name) 3636 attach_upload_text.find('._file_download').removeClass('tw-hidden') 3637 attach_upload_text.find('._file_remove').removeClass('tw-hidden') 3638 } else { 3639 alert(tmp.error) 3640 } 3641 }) 3642 }, 3643 fail: function (e, data) { 3644 alert(getLocalizeString('ì¤ëª _ì ë¡ëìì¤í¨íììµëë¤', '', 'ì ë¡ëì ì¤í¨ íììµëë¤.')) 3645 } 3646 }) 3647 3648 attach_upload_text.find('._file_remove').on('click', function () { 3649 $certification_sender_number.find(`input[name='cert_document_attach${file_num}']`).val('') 3650 attach_upload_text.find('._file_unset').removeClass('tw-hidden') 3651 attach_upload_text.find('._file_size').text('') 3652 attach_upload_text.find('._file_name').text('') 3653 attach_upload_text.find('._file_download').attr('href', '').addClass('tw-hidden') 3654 attach_upload_text.find('._file_remove').addClass('tw-hidden') 3655 }) 3656 } 3657 3658 // ë°ì ë²í¸ ë±ë¡ ì´ë²¤í¸ 3659 $cert_save_btn.off('click.cert_save_btn').on('click.cert_save_btn', function () { 3660 const person_type = business_type === 'personal' ? $person_type_p.val() : $person_type_b.val() 3661 const sender_callnum = $sender_callnum_document.val() 3662 const sender_callnum_info = $sender_callnum_info_document.val() 3663 const cert_document_comment = $cert_document_comment.val() 3664 const $terms_agree = $certification_sender_number.find('input[name="terms_agree"]') 3665 if (person_type === 'unset') { 3666 alert('ë°ì ë²í¸ ëª ìì를 ì íí´ ì£¼ì¸ì.') 3667 if (business_type === 'personal') { 3668 $person_type_p.focus() 3669 } else { 3670 $person_type_b.focus() 3671 } 3672 return false 3673 } 3674 if (sender_callnum === '') { 3675 alert(getLocalizeString('ì¤ëª _ë°ì ë²í¸ì ë ¥', '', 'ë°ì ë²í¸ë¥¼ ì ë ¥í´ì£¼ì¸ì')) 3676 $sender_callnum_document.focus() 3677 return false 3678 } 3679 if (sender_callnum_info === '') { 3680 alert('ë°ì ë²í¸ ëª ìì ì 보를 ì ë ¥í´ì£¼ì¸ì') 3681 $sender_callnum_info_document.focus() 3682 return false 3683 } 3684 if (cert_document_comment === '') { 3685 alert(getLocalizeString('ì¤ëª _ìì²ì¬ì ì ë ¥', '', 'ìì²ì¬ì 를 ì ë ¥í´ì£¼ì¸ì')) 3686 $cert_document_comment.focus() 3687 return false 3688 } 3689 const ajax_data = { type: 'DOCUMENT', person_type, sender_callnum, sender_callnum_info, cert_document_comment } 3690 if (!use_owner_callnum) { 3691 for (let order = 0; order < DOCUMENT_REQUIREMENT_ORDER.length; order++) { 3692 const file_num = DOCUMENT_REQUIREMENT_ORDER[order] 3693 const $cert_document_attach = $certification_sender_number.find(`input[name='cert_document_attach${file_num}']`) 3694 const cert_document_attach = $cert_document_attach.val() 3695 if (file_num === 10) { // ì¶ê° ìë¥ë íì í¬í¨ëì§ë§ íìë ìë 3696 ajax_data[`cert_document_attach${file_num}`] = cert_document_attach 3697 } else if (DOCUMENT_REQUIREMENT[business_type][person_type].includes(file_num) || (file_num === 11 && $cert_document_attach.length > 0)) { 3698 /* íì ì ì¶ ìë¥ ì²´í¬ (ê´ë¦¬ ììì¥ì ë ¸ì¶ëë ì¼ì´ì¤ì¼ ë íì ì²´í¬ */ 3699 const cert_document_attach_name = $certification_sender_number.find(`._attach${file_num}_form > label`).attr('data-title') 3700 if (cert_document_attach === '') { 3701 alert(`${cert_document_attach_name}ì 첨ë¶í´ì£¼ì¸ì.`) 3702 $cert_document_attach.focus() 3703 return false 3704 } 3705 ajax_data[`cert_document_attach${file_num}`] = cert_document_attach 3706 } 3707 } 3708 } 3709 3710 if (!$terms_agree.prop('checked')) { 3711 alert('ê°ì¸ì ë³´ ìì§âì´ì©ì ëìí´ ì£¼ì¸ì.') 3712 $terms_agree.focus() 3713 return false 3714 } 3715 ajax_data.applicant_name = applicant_name 3716 ajax_data.applicant_callnum = applicant_callnum 3717 ajax_data.applicant_birthday = applicant_birthday 3718 ajax_data.applicant_encrypt_ci = applicant_encrypt_ci 3719 3720 const saveSenderNumber = function (auth_token) { 3721 const request_data = Object.assign({}, ajax_data) 3722 if (typeof auth_token === 'string' && auth_token !== '') request_data.two_factor_auth_token = auth_token 3723 $.ajax({ 3724 type: 'POST', 3725 data: request_data, 3726 url: ('/admin/ajax/member/sender_number_certification_update.cm'), 3727 dataType: 'json', 3728 async: true, 3729 cache: false, 3730 success: function (res) { 3731 if (ADMIN_MESSAGE_STEP_UP.handleSendResponse(res, saveSenderNumber)) return 3732 if (res.msg === 'SUCCESS') { 3733 $form.find('#sender_callnum').text(res.sender_callnum || '') 3734 if (res.status === 'complete') { 3735 $form.find('#sender_status').html(`<span class='text-success'><i style='vertical-align: -10%; margin-left: 8px;' class='icon-check icons'></i> ${getLocalizeString('ì¤ëª _ì¸ì¦ìë£', '', 'ì¸ì¦ ìë£')}</span>`) 3736 alert('ë°ì ë²í¸ ë±ë¡ì´ ìë£ëììµëë¤.') 3737 } else { 3738 $form.find('#sender_status').html(`<span class='text-warning'><i style='vertical-align: -10%; margin-left: 8px;' class='icon-check icons'></i> ${getLocalizeString('ì¤ëª _ìë¥ì¸ì¦ë기ì¤', '', 'ìë¥ ì¸ì¦ ë기ì¤')}</span>`) 3739 alert('ë°ì ë²í¸ ìë¥ ì¸ì¦ì ì²ì´ ìë£ëììµëë¤. 3 ìì ì¼ ì´ë´ì ì²ë¦¬ë ìì ì´ë©° ì²ë¦¬ê° ìë£ë기 ì ê¹ì§ SMS ë°ì¡ì´ ì íë©ëë¤.') 3740 } 3741 $form.find('._failure_description').remove() 3742 $.cocoaDialog.close() 3743 } else { 3744 alert(res.msg) 3745 } 3746 } 3747 }) 3748 } 3749 saveSenderNumber('') 3750 }) 3751 } 3752 3753 /** 3754 * ë°ì ë²í¸ ìë¥ ì¸ì¦ ìì² í¼ ë ì´ìì ì¤ì 3755 * @param b_type ì¬ì ì ì¬ë¶ (personal, business) 3756 * @param p_type ë°ì ë²í¸ ëª ìì 3757 * @param use_owner_callnum ìì ì í´ëì íë²í¸ ì¬ì© ì¬ë¶ (true, false) 3758 */ 3759 function setPersonTypeLayout (b_type = 'personal', p_type = 'unset', use_owner_callnum = false) { 3760 /* ì¬ì ì ì¬ë¶ ì¤ì */ 3761 $certification_sender_number.find(`input[name='business_type']:not([value='${b_type}'])`).prop('checked', false) 3762 $certification_sender_number.find(`input[name='business_type'][value='${b_type}']`).prop('checked', true) 3763 3764 /* ë°ì ë²í¸ ëª ìì ì¤ì */ 3765 const $document_from = $certification_sender_number.find('._document_from') 3766 const $person_type_p = $document_from.find("select[name='person_type_p']") 3767 const $person_type_b = $document_from.find("select[name='person_type_b']") 3768 if (b_type == 'personal') { 3769 $person_type_p.removeClass('tw-hidden') 3770 $person_type_b.addClass('tw-hidden') 3771 $person_type_b.val('unset') 3772 } else { 3773 $person_type_b.removeClass('tw-hidden') 3774 $person_type_p.addClass('tw-hidden') 3775 $person_type_p.val('unset') 3776 } 3777 3778 $certification_sender_number.find('._attach_file_form:not(._attach11_form)').addClass('tw-hidden md:tw-hidden') 3779 $certification_sender_number.find('._example').removeClass('_lg_target') 3780 $certification_sender_number.find('._attach_file_form._attach11_form ._example').addClass('_lg_target') // ê´ë¦¬ ììì¥ì´ ì¡´ì¬íë ì¼ì´ì¤ë íì ë ¸ì¶ 3781 $certification_sender_number.find('._attach10_form').removeClass('tw-hidden md:tw-hidden') // ì¶ê°ìë¥ë íì ë ¸ì¶ 3782 3783 /* ìì ì í´ëì íë²í¸ ì¬ì© ì¤ì */ 3784 const $sender_callnum = $document_from.find("input[name='sender_callnum']") 3785 const $use_owner_callnum_form = $document_from.find('._use_owner_callnum_form') 3786 const $use_owner_callnum = $document_from.find("input[name='use_owner_callnum']") 3787 const $required_document_section = $document_from.find('#required_document_section')
3788 const $sender_callnum_info_document = $document_from.find("input[name='sender_callnum_info']") 3789 $required_document_section.removeClass('tw-hidden') 3790 $sender_callnum_info_document.prop('disabled', false) 3791 let attach3_title = 'ììì(íì¸) ì ë¶ì¦ ì¬ë³¸' 3792 let attach8_title = 'ìì¬ ë´ë¹ì ì¬ì§ì¦ëª ì' 3793 if (p_type === 'p_owner') { 3794 $use_owner_callnum_form.removeClass('tw-hidden') 3795 $sender_callnum.prop('disabled', use_owner_callnum) 3796 $use_owner_callnum.prop('checked', use_owner_callnum) 3797 if (use_owner_callnum) { 3798 /* ìì ì í´ëì íë²í¸ ì¬ì© ì ì ì¶ ìë¥ ìì ì¨ê¹ */ 3799 $required_document_section.addClass('tw-hidden') 3800 //$sender_callnum_info_document ì¸íë°ì¤ ë¹íì±í 3801 $sender_callnum_info_document.prop('disabled', true) 3802 return 3803 } 3804 } else { 3805 if (p_type === 'p_other_company' || p_type === 'b_other_company') { 3806 attach3_title = 'ììì(íì¬) ë´ë¹ì ì ë¶ì¦ ì¬ë³¸' 3807 } 3808 if (p_type === 'b_first_incumbent') { 3809 attach8_title = 'ì¬ì§ì¦ëª ì' 3810 } 3811 $sender_callnum.prop('disabled', false) 3812 $use_owner_callnum.prop('checked', false) 3813 $use_owner_callnum_form.addClass('tw-hidden') 3814 } 3815 $required_document_section.find('._attach3_form > label').attr('data-title', attach3_title).find('> span').text(attach3_title) 3816 $required_document_section.find('._attach3_form > ._example').attr('data-sub-html', attach3_title + ' ìì') 3817 $required_document_section.find('._attach8_form > label').attr('data-title', attach8_title).find('> span').text(attach8_title) 3818 $required_document_section.find('._attach8_form > ._example').attr('data-sub-html', attach8_title + ' ìì') 3819 3820 if (p_type === 'unset') { 3821 $required_document_section.addClass('tw-hidden') 3822 return 3823 } 3824 3825 /* ì ì¶ ìë¥ ì¤ì */ 3826 for (const person_type in DOCUMENT_REQUIREMENT[b_type]) { 3827 if (person_type === p_type) { 3828 for (const document_num in DOCUMENT_REQUIREMENT[b_type][person_type]) { 3829 $certification_sender_number.find(`._attach${DOCUMENT_REQUIREMENT[b_type][person_type][document_num]}_form`).removeClass('tw-hidden md:tw-hidden').find('._example').addClass('_lg_target') 3830 } 3831 break 3832 } 3833 } 3834 3835 /* ìë¥ ë¯¸ë¦¬ë³´ê¸° ì¤ì */ 3836 const lg_data = $document_from.data('lightGallery') 3837 if (typeof lg_data !== 'undefined') lg_data.destroy(true) 3838 const $lg_target = $document_from.find('._lg_target') 3839 if ($lg_target.length > 0) { 3840 3841 $document_from.lightGallery({ 3842 selector: '._lg_target', 3843 thumbnail: true, 3844 hash: false, 3845 speed: 200 3846 }); 3847 } 3848 } 3849 3850 const openEditInformation = function () { 3851 if (confirm('ë°ì ë²í¸ë¥¼ ë±ë¡í기 ìí´ìë í´ëì í 본ì¸ì¸ì¦ì´ íìí©ëë¤. ì§ííìê² ìµëê¹?')) { 3852 const url = TEST_SERVER ? 'https://imtest.me/edit_information' : 'https://imweb.me/edit_information' 3853 window.open(url, '_blank') 3854 } 3855 } 3856 3857 const openAuthService = function (CI_SVCID, Tradeid, Okurl, call_back_data) { 3858 if (confirm('ë°ì ë²í¸ë¥¼ ë±ë¡í기 ìí´ìë í´ëì í 본ì¸ì¸ì¦ì´ íìí©ëë¤. ì§ííìê² ìµëê¹?')) { 3859 AUTH_SERVICE.openMOBILIANSWindow(CI_SVCID, Tradeid, Okurl, call_back_data) 3860 const messageEvent = function (e) { 3861 if (e.data.authorizedData) { 3862 if ( e.data.authorizedData.name && 3863 e.data.authorizedData.call_num && 3864 e.data.authorizedData.birthday && 3865 e.data.authorizedData.encrypt_ci 3866 ) { 3867 window.removeEventListener('message', messageEvent) 3868 openSmsSettingNum( 3869 e.data.authorizedData.name, 3870 e.data.authorizedData.call_num, 3871 e.data.authorizedData.birthday, 3872 e.data.authorizedData.encrypt_ci 3873 ) 3874 } 3875 } 3876 } 3877 window.removeEventListener('message', messageEvent) 3878 window.addEventListener('message', messageEvent, false) 3879 } 3880 } 3881 3882 const openAuthServiceFromBo = function () { 3883 if (confirm('ë°ì ë²í¸ë¥¼ ë±ë¡í기 ìí´ìë í´ëì í 본ì¸ì¸ì¦ì´ íìí©ëë¤. ì§ííìê² ìµëê¹?')) { 3884 AUTH_SERVICE.openMOBILIANSWindowFromBo() 3885 const messageEvent = function (e) { 3886 if (e.data.authorizedData) { 3887 if ( e.data.authorizedData.name && 3888 e.data.authorizedData.call_num && 3889 e.data.authorizedData.birthday && 3890 e.data.authorizedData.encrypt_ci 3891 ) { 3892 window.removeEventListener('message', messageEvent) 3893 openSmsSettingNum( 3894 e.data.authorizedData.name, 3895 e.data.authorizedData.call_num, 3896 e.data.authorizedData.birthday, 3897 e.data.authorizedData.encrypt_ci 3898 ) 3899 } 3900 } 3901 } 3902 window.removeEventListener('message', messageEvent) 3903 window.addEventListener('message', messageEvent, false) 3904 } 3905 } 3906 3907 const group_chang = function (type, $obj, name, code) { 3908 let old_text, new_text 3909 3910 old_text = $obj.find('span').text() 3911 $obj.find('span').text(name) 3912 new_text = $obj.find('span').text() 3913 3914 if (name == 'ì§ì ìí¨') { 3915 $('#group_' + type).val('') 3916 $('#group_' + type + '_name').val('') 3917 } else { 3918 $('#group_' + type).val(code) 3919 $('#group_' + type + '_name').val(name) 3920 } 3921 3922 if (old_text != new_text) { 3923 header_ctl.change() 3924 } 3925 } 3926 3927 var submit = function () { 3928 const data = $form.serializeObject(); 3929 3930 // ë©ì¼ã»SMS ì ì© ì¬ì´í¸ ì´ë¦ ë°ì´í¸ ì²´í¬, 40ë°ì´í¸ ë³´ë¤ í° ê²½ì° ì ì¥ ë¶ê° ì²ë¦¬
3931 const currentSubNameByte = getByteLengthForKorean(data.sub_name); 3932 const maxSubNameByte = 40; 3933 if (currentSubNameByte > maxSubNameByte) { 3934 return window.alert(`ë©ì¼ã»SMS ì ì© ì¬ì´í¸ ì´ë¦ì ${maxSubNameByte}ë°ì´í¸ë¥¼ ì´ê³¼í ì ììµëë¤(íì¬: ${currentSubNameByte}ë°ì´í¸).`); 3935 } 3936 3937 $.ajax({ 3938 type: 'POST', 3939 data, 3940 url: ('/admin/ajax/member/sms_setting_update.cm'), 3941 dataType: 'json', 3942 async: false, 3943 cache: false, 3944 success: function (res) { 3945 if (res.msg == 'SUCCESS') { 3946 header_ctl.save() 3947 } else { 3948 alert(res.msg) 3949 } 3950 } 3951 }) 3952 } 3953 3954 const openSmsPreview = function (type) { 3955 $.ajax({ 3956 type: 'GET', 3957 data: { type }, 3958 url: ('/admin/ajax/member/sms_preview.cm'), 3959 dataType: 'html', 3960 async: false, 3961 cache: true, 3962 success: function (res) { 3963 const $html = $(res) 3964 $.cocoaDialog.open({ type: 'admin', custom_popup: $html, width: 600 }) 3965 } 3966 }) 3967 } 3968 3969 var openSmsSettingNum = function (name, callnum, birthday, encrypt_ci) { 3970 $.cocoaDialog.close() 3971 $.ajax({ 3972 type: 'POST', 3973 data: { name, callnum, birthday, encrypt_ci }, 3974 url: ('/admin/ajax/member/sms_setting_num.cm'), 3975 dataType: 'html', 3976 async: false, 3977 cache: false, 3978 success: function (res) { 3979 if(res === 'alimtalk progress'){ 3980 alert("ì¹´ì¹´ì¤ ìë¦¼í¡ ì ì² ì¤ ë°ì ë²í¸ ë³ê²½ì´ ë¶ê°í©ëë¤.\nìë¦¼í¡ ì ì²ì´ ìë£ëê±°ë ë°ë ¤ ì²ë¦¬ë í ë°ì ë²í¸ ë³ê²½ì ì§íí´ì£¼ì¸ì.") 3981 }else{ 3982 const $html = $(res) 3983 $.cocoaDialog.open({ type: 'admin_sms_num', custom_popup: $html, pc_width: 660, close_block: true }) 3984 } 3985 } 3986 }) 3987 3988 setSmsCertification() 3989 } 3990 3991 const openSmsChargeComplete = function (sms_count, order_no) { 3992 $.ajax({ 3993 type: 'POST', 3994 data: { sms_count, order_no }, 3995 url: ('/admin/ajax/sms/sms_charge_complete.cm'), 3996 dataType: 'html', 3997 async: false, 3998 cache: false, 3999 success: function (html) { 4000 $.cocoaDialog.open({ type: 'admin_sms', custom_popup: html }) 4001 } 4002 }) 4003 } 4004 4005 const requestChangeKakaoIdModal = function () { 4006 $.ajax({ 4007 type: 'POST', 4008 url: '/admin/ajax/open_change_kakao_id_modal.cm', 4009 dataType: 'html', 4010 async: false, 4011 cache: false, 4012 success: function (res) { 4013 $.cocoaDialog.open({ type: 'admin_sms', custom_popup: res }) 4014 } 4015 }) 4016 } 4017 4018 const requestChangeKakaoId = function () { 4019 const data = $('#request_form_change_kakao_id').serializeObject() 4020 $.ajax({ 4021 type: 'POST', 4022 data: { data }, 4023 url: '/admin/ajax/sms/request_change_kakao_id.cm', 4024 dataType: 'json', 4025 async: false, 4026 cache: false, 4027 success: function (res) { 4028 if (res.msg === 'SUCCESS') { 4029 // header_ctl.save(); // ì ì¥ì ìë¡ê³ 침 컨í ìë¨ê² í기 ìí´ 4030 alert('ì¹´ì¹´ì¤ ì±ë ê²ìì© ìì´ëê° ë³ê²½ëììµëë¤.') 4031 location.reload() 4032 } else { 4033 alert('ì ì¥ì ì¤í¨íììµëë¤. ë¤ìíë² ìëí´ì£¼ì¸ì') 4034 } 4035 } 4036 }) 4037 } 4038 4039 const openRequestKakaoAlimTalk = function (idx) { 4040 $.ajax({ 4041 type: 'POST', 4042 data: { idx }, 4043 url: ('/admin/ajax/sms/open_kakao_alimtalk_request.cm'), 4044 dataType: 'html', 4045 async: false, 4046 cache: false, 4047 success: function (html) { 4048 $.cocoaDialog.open({ type: 'admin_sms', custom_popup: html }) 4049 } 4050 }) 4051 } 4052 4053 const requestKakaoAlimTalk = function () { 4054 const data = $('#request_form_kakao_alimtalk').serializeObject() 4055 $.ajax({ 4056 type: 'POST', 4057 data: { data }, 4058 url: ('/admin/ajax/sms/request_kakao_alimtalk.cm'), 4059 dataType: 'json', 4060 async: false, 4061 cache: false, 4062 success: function (res) { 4063 if (res.msg === 'SUCCESS') { 4064 header_ctl.save() // ì ì¥ì ìë¡ê³ 침 컨í ìë¨ê² í기 ìí´ 4065 location.reload() 4066 } else { 4067 alert(res.msg) 4068 } 4069 } 4070 }) 4071 } 4072 4073 return { 4074 init: function ($obj) { 4075 init($obj) 4076 }, 4077 group_chang: function (type, $obj, name, code) { 4078 group_chang(type, $obj, name, code) 4079 }, 4080 openSmsPreview: function (type) { 4081 openSmsPreview(type) 4082 }, 4083 openSmsSettingNum: function (name, callnum, birthday, encrypt_ci) { 4084 openSmsSettingNum(name, callnum, birthday, encrypt_ci) 4085 }, 4086 openEditInformation: function () { 4087 openEditInformation() 4088 }, 4089 openAuthService: function (CI_SVCID, Tradeid, Okurl, call_back_data) { 4090 openAuthService(CI_SVCID, Tradeid, Okurl, call_back_data) 4091 }, 4092 openAuthServiceFromBo: function () { 4093 openAuthServiceFromBo() 4094 }, 4095 openSmsChargeComplete: function (sms_count, order_no) { 4096 openSmsChargeComplete(sms_count, order_no) 4097 }, 4098 openRequestKakaoAlimTalk: function (idx) { 4099 openRequestKakaoAlimTalk(idx) 4100 }, 4101 requestChangeKakaoId: function () { 4102 requestChangeKakaoId() 4103 }, 4104 requestChangeKakaoIdModal: function () { 4105 requestChangeKakaoIdModal() 4106 }, 4107 requestKakaoAlimTalk: function () { 4108 requestKakaoAlimTalk() 4109 } 4110 } 4111}()) 4112const MEMBER_BLOCK = (function () { 4113 const openBlockMember = function (member_code, block_member_code, site_code) { 4114 $.ajax({ 4115 type: 'post', 4116 data: { 4117 member_code, 4118 block_member_code, 4119 site_code 4120 }, 4121 url: '/admin/ajax/member/delete_block_member.cm', 4122 dataType: 'html', 4123 async: false, 4124 cache: false, 4125 success: function (html) {
4126 $.cocoaDialog.open({ type: 'admin', custom_popup: html }) 4127 } 4128 }) 4129 } 4130 const deleteBlock = function (member_code, block_member_code, site_code) { 4131 $.ajax({ 4132 type: 'post', 4133 data: { 4134 member_code, 4135 block_member_code, 4136 site_code 4137 }, 4138 url: '/admin/ajax/member/delete_block.cm', 4139 dataType: 'json', 4140 async: false, 4141 cache: false, 4142 success: function (res) { 4143 if (res.msg === 'SUCCESS') { 4144 // header_ctl.save(); // ì ì¥ì ìë¡ê³ 침 컨í ìë¨ê² í기 ìí´ 4145 location.reload() 4146 } else { 4147 alert(res.msg) 4148 } 4149 } 4150 }) 4151 } 4152 return { 4153 openBlockMember: function (member_code, block_member_code, site_code) { 4154 openBlockMember(member_code, block_member_code, site_code) 4155 }, 4156 deleteBlock: function (member_code, block_member_code, site_code) { 4157 deleteBlock(member_code, block_member_code, site_code) 4158 } 4159 } 4160}()) 4161 4162/** 4163 * íì 목ë¡ê³¼ ìì¸ íë©´ìì ê³µíµì¼ë¡ ì¬ì©íë ì¸ë¼ì¸ íìíê·¸ comboboxì ëë¤. 4164 * 4165 * 목ë¡ììë íì ë°ì´í° ë ëë§ í íê·¸ API를 ì§ì° í¸ì¶íê³ , ìì¸ììë SSRë¡ ì ë¬ë 4166 * ì´ê¸° ë°ì´í°ë¥¼ hydrateí©ëë¤. ì í·í´ì ·ìì±Â·ìì ·ìì ë ì ì¥ ë²í¼ ìì´ ì¦ì ë°ìíë©°, 4167 * ìë² ìì² ì¤í¨ ì ë§ì§ë§ íì ìíë¡ ë³µêµ¬í©ëë¤. 4168 */ 4169var MEMBER_TAG_MANAGE = (function () { 4170 // ì¬ì´í¸ì ë±ë¡ë íê·¸ ì ìì ì¡°í ìë£ ì¬ë¶ë¥¼ 모ë íì íëê° ê³µì í©ëë¤. 4171 let definitions = [] 4172 let definitionsLoaded = false 4173 let definitionRequest = null 4174 4175 // íì ì½ëë³ ì í í그를 ë³´ê´íë©°, 목ë¡ì ëì¼ íì íëê° ì¬ë¬ ê°ì¬ë í¨ê» ê°±ì í©ëë¤. 4176 const memberTagMap = {} 4177 4178 // í ë²ì íëì comboboxë§ ì´ë¦¬ëë¡ íì¬ anchorì í¸ì§ ìí를 ë¨ì¼ ê°ì²´ë¡ ê´ë¦¬í©ëë¤. 4179 let activeState = null 4180 4181 /** 4182 * íìíê·¸ ì ì© ì¤íì¼ì 문ìì í ë²ë§ 주ì í©ëë¤. 4183 * ëª©ë¡ AJAX ë ëë§ê³¼ ìì¸ SSR ì§ì ììê° ë¬ë¼ë ì¤ë³µ style ë ¸ëê° ìê¸°ì§ ììµëë¤. 4184 */ 4185 const ensureStyles = function () { 4186 if ($('#member-tag-manage-style').length > 0) return 4187 4188 $('<style id="member-tag-manage-style">' + 4189 '.member-tag-field{display:flex;width:100%;min-height:32px;align-items:center;align-content:center;flex-wrap:wrap;gap:4px;padding:3px 4px;border-radius:3px;background:transparent;cursor:text;outline:0;}' + 4190 '.member-tag-field:hover{background:#f7f8f9;}' + 4191 '.member-tag-field.is-active{background:#fff;box-shadow:inset 0 0 0 1px #aeb3ba;}' + 4192 '.member-tag-field-readonly{cursor:default;}' + 4193 '.member-tag-field:not(.member-tag-field-list):not(.member-tag-field-readonly){cursor:pointer;transition:background-color .12s,box-shadow .12s;}' + 4194 '.member-tag-field:not(.member-tag-field-list):not(.member-tag-field-readonly):hover,.member-tag-field:not(.member-tag-field-list):not(.member-tag-field-readonly):focus,.member-tag-field:not(.member-tag-field-list):not(.member-tag-field-readonly):focus-within{background:#eef0f2;}' + 4195 '.member-tag-field:not(.member-tag-field-list):not(.member-tag-field-readonly).is-active,.member-tag-field:not(.member-tag-field-list):not(.member-tag-field-readonly).is-active:hover,.member-tag-field:not(.member-tag-field-list):not(.member-tag-field-readonly).is-active:focus,.member-tag-field:not(.member-tag-field-list):not(.member-tag-field-readonly).is-active:focus-within{background:#fff;box-shadow:inset 0 0 0 1px #aeb3ba;cursor:text;}' + 4196 '.member-tag-field-list{min-height:40px;cursor:pointer;transition:background-color .12s,box-shadow .12s;}' + 4197 '.member-tag-field-list:not(.member-tag-field-readonly):hover,.member-tag-field-list:not(.member-tag-field-readonly):focus,.member-tag-field-list:not(.member-tag-field-readonly):focus-within{background:#eef0f2;}' + 4198 '.member-tag-field-list.is-active,.member-tag-field-list.is-active:hover,.member-tag-field-list.is-active:focus,.member-tag-field-list.is-active:focus-within{background:#fff;box-shadow:inset 0 0 0 1px #aeb3ba;cursor:text;}' + 4199 '.member-tag-chip{display:inline-flex;max-width:100%;height:24px;align-items:center;padding:0 6px;border-radius:3px;background:#f1f1ef;color:#37352f;font-size:12px;line-height:24px;white-space:nowrap;}
4199' + 4200 '.member-tag-chip-name{max-width:110px;overflow:hidden;text-overflow:ellipsis;}' + 4201 '.member-tag-field-list .member-tag-chip-name{max-width:none;overflow:visible;text-overflow:clip;}' + 4202 '.member-tag-query-input{min-width:22px;max-width:100%;height:24px;flex:1;padding:0 2px;border:0;background:transparent;color:#37352f;font-size:13px;line-height:24px;outline:0;}' + 4203 '.member-tag-popover{position:fixed;z-index:10050;width:340px;max-width:calc(100vw - 16px);border:1px solid #dfe1e5;border-radius:6px;background:#fff;box-shadow:0 4px 14px rgba(0,0,0,.12);overflow:hidden;}' + 4204 '.member-tag-popover-guide{padding:10px 12px 7px;color:#8b9098;font-size:11px;line-height:16px;}' + 4205 '.member-tag-query-error{padding:0 12px 7px;color:#f44336;font-size:11px;line-height:16px;}' + 4206 '.member-tag-option-list{max-height:240px;overflow-y:auto;padding:2px 0 5px;}' + 4207 '.member-tag-option-item{display:flex;min-height:38px;align-items:center;padding:0 10px;color:#37352f;cursor:pointer;}' + 4208 '.member-tag-option-item:hover,.member-tag-option-item.is-active{background:#f7f8f9;}' + 4209 '.member-tag-option-check{width:18px;flex:0 0 18px;margin-right:6px;visibility:hidden;color:inherit;font-size:13px;text-align:center;}' + 4210 '.member-tag-option-item.is-selected .member-tag-option-check{visibility:visible;}' + 4211 '.member-tag-option-name{min-width:0;flex:1;padding:3px 4px;border-radius:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:text;}' + 4212 '.member-tag-option-name:hover{background:#eceef1;}' + 4213 '.member-tag-option-delete{display:inline-flex;width:26px;height:26px;flex:0 0 26px;align-items:center;justify-content:center;margin-left:4px;padding:0;border:0;border-radius:3px;background:transparent;color:#8b9098;opacity:0;transition:opacity .12s,background-color .12s;}' + 4214 '.member-tag-option-item:hover .member-tag-option-delete,.member-tag-option-item:focus-within .member-tag-option-delete,.member-tag-option-item.is-active .member-tag-option-delete{opacity:1;}' + 4215 '.member-tag-option-delete:hover,.member-tag-option-delete:focus{background:#eceef1;color:#37352f;outline:0;}' + 4216 '.member-tag-create-label{margin-right:6px;color:#717680;font-size:11px;}' + 4217 '.member-tag-option-empty{height:38px;padding:10px 12px;color:#9a9fa8;font-size:12px;}' + 4218 '.member-tag-rename-wrap{display:flex;width:100%;min-height:38px;flex-wrap:wrap;align-items:center;padding:4px 10px 4px 34px;}' + 4219 '.member-tag-rename-wrap .form-control{height:30px;}' + 4220 '.member-tag-inline-error{width:100%;margin-top:3px;color:#f44336;font-size:11px;line-height:16px;}' + 4221 '.member-tag-delete-confirm{position:fixed;z-index:10060;width:264px;padding:12px;border:1px solid #dfe1e5;border-radius:6px;background:#fff;box-shadow:0 4px 14px rgba(0,0,0,.14);}' + 4222 '.member-tag-delete-confirm-title{color:#37352f;font-size:13px;font-weight:600;line-height:19px;}' + 4223 '.member-tag-delete-confirm-description{margin-top:4px;color:#717680;font-size:11px;line-height:17px;}' + 4224 '.member-tag-delete-confirm-actions{display:flex;justify-content:flex-end;gap:6px;margin-top:10px;}' + 4225 '.member-tag-fallback-toast{position:fixed;z-index:11000;right:20px;bottom:20px;max-width:320px;padding:10px 14px;border-radius:4px;background:#37352f;color:#fff;font-size:13px;}' + 4226 '</style>').appendTo('head') 4227 } 4228 4229 /** 4230 * APIë SSRìì ë°ì íê·¸ ë°°ì´ì ë 립ì ì¸ íë©´ ìíë¡ ë³µì í©ëë¤. 4231 * ì본 ìëµ ê°ì²´ë¥¼ ì§ì ë³ê²½íì§ ìëë¡ íë©´ìì ì¬ì©íë íëë§ ì ê°ì²´ë¡ ë§ëëë¤. 4232 * 4233 * @param {Array<{tag_code:string, tag_name:string}>} tags íê·¸ ëª©ë¡ 4234 * @returns {Array<{tag_code:string, tag_name:string}>} 4235 */ 4236 const copyTags = function (tags) { 4237 return (tags || []).map(function (tag) { 4238 return { 4239 tag_code: tag.tag_code, 4240 tag_name: tag.tag_name 4241 } 4242 }) 4243 } 4244 4245 /** 4246 * ì í ì½ë ë°°ì´ì ì¤ë ì·ì ìì±í©ëë¤. 4247 * optimistic update ëì¤ íì ê°ê³¼ íë©´ê°ì´ ê°ì ë°°ì´ì 참조íì§ ìê² í©ëë¤. 4248 * 4249 * @param {string[]} tagCodes íê·¸ ì½ë ëª©ë¡ 4250 * @returns {string[]} 4251 */ 4252 const copyCodes = function (tagCodes) {
4253 return (tagCodes || []).slice() 4254 } 4255 4256 /** 4257 * íê·¸ ì½ëì ê°ìì ììê° ëª¨ë ê°ìì§ ë¹êµí©ëë¤. 4258 * ì ì¥ ì¤ ì¶ê° ì ë ¥ì´ ë°ìíì ë íì ë기íê° íìíì§ íë¨íë ë° ì¬ì©í©ëë¤. 4259 * 4260 * @param {string[]} left ë¹êµ ëì 4261 * @param {string[]} right ë¹êµ ëì 4262 * @returns {boolean} 4263 */ 4264 const isSameCodes = function (left, right) { 4265 return left.length === right.length && left.every(function (tagCode, index) { 4266 return tagCode === right[index] 4267 }) 4268 } 4269 4270 /** 4271 * íê·¸ ì½ë 목ë¡ì íì¬ definitionsì íê·¸ ê°ì²´ 목ë¡ì¼ë¡ ë³íí©ëë¤. 4272 * ìì ëì´ ë ì´ì ì¡´ì¬íì§ ìë ì½ëë íë©´ì ë¤ì ë ¸ì¶íì§ ììµëë¤. 4273 * 4274 * @param {string[]} tagCodes íê·¸ ì½ë ëª©ë¡ 4275 * @returns {Array<{tag_code:string, tag_name:string}>} 4276 */ 4277 const getTagsByCodes = function (tagCodes) { 4278 return tagCodes.map(function (tagCode) { 4279 let matchedDefinition = null 4280 definitions.some(function (definition) { 4281 if (definition.tag_code !== tagCode) return false 4282 4283 matchedDefinition = definition 4284 return true 4285 }) 4286 return matchedDefinition 4287 }).filter(function (definition) { 4288 return !!definition 4289 }) 4290 } 4291 4292 /** 4293 * í¹ì íìì íì¬ íë©´ íê·¸ìì ì½ëë§ ì¶ì¶í©ëë¤. 4294 * popover를 ì´ ë persisted/desired ìíì ëì¼í ì´ê¸°ê°ì¼ë¡ ì¬ì©í©ëë¤. 4295 * 4296 * @param {string} memberCode íì ì½ë 4297 * @returns {string[]} 4298 */ 4299 const getMemberTagCodes = function (memberCode) { 4300 return (memberTagMap[memberCode] || []).map(function (tag) { 4301 return tag.tag_code 4302 }) 4303 } 4304 4305 /** 4306 * ê³µíµ cocoaToastê° ìì¼ë©´ ì¬ì¬ì©íê³ , ìë íë©´ììë ìì toastë¡ ìë´í©ëë¤. 4307 * ì¬ì©ì ì ë ¥ì textë¡ ë£ì´ HTMLì´ ì¤íëì§ ìëë¡ ì²ë¦¬í©ëë¤. 4308 * 4309 * @param {string} message ì¬ì©ì ìë´ ë¬¸êµ¬ 4310 */ 4311 const showToast = function (message) { 4312 const text = message || getLocalizeString('ì¤ëª _ì ìíë¤ììëí´ì£¼ì¸ì', '', 'ì ì í ë¤ì ìëí´ì£¼ì¸ì.') 4313 if ($.cocoaToast && typeof $.cocoaToast.show === 'function') { 4314 $.cocoaToast.show({ html: $('<div>').text(text).html() }) 4315 return 4316 } 4317 4318 const $toast = $('<div class="member-tag-fallback-toast">').text(text).appendTo('body') 4319 setTimeout(function () { 4320 $toast.fadeOut(150, function () { 4321 $toast.remove() 4322 }) 4323 }, 2500) 4324 } 4325 4326 /** 4327 * íìíê·¸ íë íë를 íì¬ ìíì ë§ì¶° ë¤ì 그립ëë¤. 4328 * 목ë¡ê³¼ ìì¸ ëª¨ë ì íë íê·¸ ì 체를 íìíê³ , íì± íëë ë§ì§ë§ chip ë¤ì ì ë ¥ì°½ì íìí©ëë¤. 4329 * 4330 * @param {JQuery} $field ë ëë§í íìíê·¸ íë 4331 * @param {Array<{tag_code:string, tag_name:string}>} tags íìì íê·¸ ëª©ë¡ 4332 */ 4333 const renderField = function ($field, tags) { 4334 const memberCode = String($field.data('member-code') || '') 4335 const isEditable = $field.attr('data-editable') !== 'N' 4336 const isActive = !!activeState && activeState.memberCode === memberCode && activeState.$anchor[0] === $field[0] 4337 const visibleTags = tags || [] 4338 4339 // ì´ì ë ë 결과를 ì ê±°í ë¤ ì ê·¼ì± ìíì ì½ê¸° ì ì© ìí를 íì¬ ê°ì¼ë¡ ë§ì¶¥ëë¤. 4340 $field.empty() 4341 .toggleClass('is-active', isActive) 4342 .toggleClass('member-tag-field-readonly', !isEditable) 4343 .attr('aria-expanded', isActive ? 'true' : 'false') 4344 4345 // ì íë íê·¸ë í´ì ë²í¼ ìì´ #íê·¸ëª chipì¼ë¡ë§ ë ëë§í©ëë¤. 4346 visibleTags.forEach(function (tag) { 4347 const $chip = $('<span class="member-tag-chip">') 4348 .attr('data-tag-code', tag.tag_code) 4349 .append($('<span class="member-tag-chip-name">').text('#' + tag.tag_name)) 4350 4351 $field.append($chip) 4352 }) 4353 4354 // íì± íëì ë§ì§ë§ chip ì¤ë¥¸ìª½ì ê²ì·ìì±ì© í ì¤í¸ cursor를 ì´ì´ ë¶ì ëë¤. 4355 if (isActive) { 4356 $field.append( 4357 $('<input type="text" class="_member_tag_query_input member-tag-query-input" autocomplete="off" aria-autocomplete="list">') 4358 .attr('aria-controls', activeState.optionListId)
4359 .attr('aria-label', 'íìíê·¸ ì í ëë ìì±') 4360 .prop('disabled', activeState.isCreating) 4361 .val(activeState.query) 4362 ) 4363 } 4364 } 4365 4366 /** 4367 * ê°ì íì ì½ë를 ê°ì§ 모ë íë를 ë¤ì 그립ëë¤. 4368 * ëª©ë¡ ì¬ë ëë§ì´ë ìì¸/ëª©ë¡ DOM ì¤ë³µ ìí©ììë íìê°ì ì¼ê´ëê² ì ì§í©ëë¤. 4369 * 4370 * @param {string} memberCode íì ì½ë 4371 */ 4372 const renderMember = function (memberCode) { 4373 $('._member_tag_button[data-member-code="' + memberCode + '"]').each(function () { 4374 renderField($(this), memberTagMap[memberCode] || []) 4375 }) 4376 } 4377 4378 /** 4379 * ëª©ë¡ API ìëµì ê³µì definitionsì íìë³ íê·¸ ìíì ë°ìí©ëë¤. 4380 * ìëµìì ëë½ë ìì² íìì íê·¸ê° ìë íìì¼ë¡ ëª ìì ì¼ë¡ ì´ê¸°íí©ëë¤. 4381 * 4382 * @param {{definitions?:Array, member_tag_map?:Object}} data API ìëµ ë°ì´í° 4383 * @param {string[]} memberCodes ìì²í íì ì½ë ëª©ë¡ 4384 */ 4385 const applyResponse = function (data, memberCodes) { 4386 if (Object.prototype.hasOwnProperty.call(data, 'definitions')) { 4387 definitions = copyTags(data.definitions) 4388 definitionsLoaded = true 4389 } 4390 const responseMemberTagMap = data.member_tag_map || {} 4391 4392 memberCodes.forEach(function (memberCode) { 4393 memberTagMap[memberCode] = [] 4394 }) 4395 Object.keys(responseMemberTagMap).forEach(function (memberCode) { 4396 memberTagMap[memberCode] = copyTags(responseMemberTagMap[memberCode]) 4397 }) 4398 } 4399 4400 /** 4401 * íìë³ íê·¸ì ì íì ì¼ë¡ ì¬ì´í¸ íê·¸ ì ì를 POSTë¡ ì¡°íí©ëë¤. 4402 * success=false ìëµë jQuery fail íë¦ìì ëì¼íê² ì²ë¦¬í ì ìëë¡ rejectë¡ ë³íí©ëë¤. 4403 * 4404 * @param {string[]} memberCodes ì¡°íí íì ì½ë ëª©ë¡ 4405 * @param {boolean} includeDefinitions ì¬ì´í¸ íê·¸ ì ì í¬í¨ ì¬ë¶ 4406 * @returns {JQuery.Promise} 4407 */ 4408 const requestTagData = function (memberCodes, includeDefinitions) { 4409 return $.ajax({ 4410 url: '/admin/ajax/member/member_tag.cm', 4411 type: 'POST', 4412 dataType: 'json', 4413 cache: false, 4414 data: { 4415 action: 'list', 4416 member_codes: memberCodes, 4417 include_definitions: includeDefinitions ? 'Y' : 'N' 4418 } 4419 }).then(function (response) { 4420 if (!response.success) { 4421 return $.Deferred().reject(response.message).promise() 4422 } 4423 4424 applyResponse(response.data, memberCodes) 4425 return response.data 4426 }) 4427 } 4428 4429 /** 4430 * ì¬ì´í¸ íê·¸ ì ì를 ìµì´ í ë²ë§ ì¡°ííê³ ì§í ì¤ì¸ ìì²ë ê³µì í©ëë¤. 4431 * íì ëª©ë¡ ê²ì ì´ê¸°íì íë³ íê·¸ ì§ì° ë¡ë©ì´ ëìì ììëì´ë ê°ì ì ì ì¡°í를 ì¤ë³µ ì ì¡íì§ ììµëë¤. 4432 * 4433 * @returns {JQuery.Promise} 4434 */ 4435 const loadDefinitions = function () { 4436 if (definitionsLoaded) { 4437 return $.Deferred().resolve(copyTags(definitions)).promise() 4438 } 4439 if (definitionRequest) return definitionRequest 4440 4441 definitionRequest = requestTagData([], true).always(function () { 4442 definitionRequest = null 4443 }) 4444 4445 return definitionRequest 4446 } 4447 4448 /** 4449 * ê²ì ìëìì±ìì ì¬ì©í íì¬ ì¬ì´í¸ íê·¸ ì ìì ë³µì¬ë³¸ì ë°íí©ëë¤. 4450 * í¸ì¶ë¶ê° ì ë ¬ì´ë íí°ë§ì ìíí´ë comboboxì ê³µì definitions ììê° ë°ëì§ ììµëë¤. 4451 * 4452 * @returns {Array<{tag_code:string, tag_name:string}>} 4453 */ 4454 const getDefinitions = function () { 4455 return copyTags(definitions) 4456 } 4457 4458 /** 4459 * 기존 íì ê²ìì°½ì ì ë ¥ì íê·¸ ì¡°ê±´ê³¼ ì¼ë° ê²ìì´ë¡ ë¶ë¦¬í©ëë¤. 4460 * `#íê·¸ëª `ì´ íì¬ ì¬ì´í¸ ì ìì ì íí ì¼ì¹í ëë§ íê·¸ íí°ë¡ í´ìíë©°, 4461 * ì¼ì¹íì§ ìì¼ë©´ `#`ì í¬í¨í ì ì²´ ì ë ¥ì 기존 íì ê²ìì´ë¡ ê·¸ëë¡ ì ë¬í©ëë¤. 4462 * 4463 * @param {string} displayKeyword ê²ìì°½ì íìë ì ì²´ ì ë ¥ 4464 * @returns {{keyword:string, memberTagCode:string}} 4465 */ 4466 const getMemberSearchCondition = function (displayKeyword) { 4467 const normalizedKeyword = $.trim(String(displayKeyword || '')) 4468 const defaultCondition = { 4469 keyword: normalizedKeyword, 4470 memberTagCode: '' 4471 } 4472 if (normalizedKeyword.charAt(0) !== '#') return defaultCondition 4473 4474 // íê·¸ëª ì´ ìë¡ ì ëì´ ê´ê³ì¬ë ë 긴 ì´ë¦ì 먼ì ë¹êµí´ ì íí í그를 ì íí©ëë¤. 4475 const sortedDefinitions = getDefinitions().sort(function (left, right) { 4476 return String(right.tag_name || '').length - String(left.tag_name || '').length 4477 }) 4478 const lowerKeyword = normalizedKeyword.toLocaleLowerCase() 4479 let matchedCondition = null 4480 4481 sortedDefinitions.some(function (definition) { 4482 const tagPrefix = '#' + String(definition.tag_name || '') 4483 const lowerTagPrefix = tagPrefix.toLocaleLowerCase() 4484 const isExactTag = lowerKeyword === lowerTagPrefix 4485 const hasFollowingKeyword = lowerKeyword.indexOf(lowerTagPrefix + ' ') === 0 4486 if (!isExactTag && !hasFollowingKeyword) return false 4487 4488 matchedCondition = { 4489 keyword: $.trim(normalizedKeyword.substring(tagPrefix.length)), 4490 memberTagCode: definition.tag_code 4491 } 4492 return true 4493 }) 4494 4495 return matchedCondition || defaultCondition 4496 } 4497 4498 /** 4499 * íì ëª©ë¡ SSR ì´í íì¬ íì´ì§ íìì í그를 í ë²ì ì§ì° ë¡ë©í©ëë¤. 4500 * ì¡°í ì¤í¨ ì ì못ë ì´ì ê°ì´ ë¨ì§ ìëë¡ ìì² ëì ì ì ë¹ ìíë¡ ì ì§í©ëë¤. 4501 * 4502 * @param {string[]} memberCodes íì¬ ëª©ë¡ì íìë íì ì½ë ëª©ë¡ 4503 */ 4504 const loadList = function (memberCodes) { 4505 ensureStyles() 4506 if (!memberCodes || memberCodes.length === 0) return 4507 4508 requestTagData(memberCodes, !definitionsLoaded).done(function () {
4509 memberCodes.forEach(renderMember) 4510 }).fail(function () { 4511 memberCodes.forEach(function (memberCode) { 4512 $('._member_tag_button[data-member-code="' + memberCode + '"]').empty() 4513 }) 4514 }) 4515 } 4516 4517 /** 4518 * DOM ê°±ì ì´ ëë ë¤ì íì± íëì ì ë ¥ì°½ì¼ë¡ focus를 복구í©ëë¤. 4519 * chip ì¬ë ëë§ì¼ë¡ input ë ¸ëê° êµì²´ëë¯ë¡ ë¤ì event loopìì ì ë ¸ë를 ì°¾ìµëë¤. 4520 * 4521 * @param {Object} state íì¬ combobox ìí 4522 */ 4523 const focusQueryInput = function (state) { 4524 if (activeState !== state) return 4525 4526 setTimeout(function () { 4527 if (activeState !== state) return 4528 4529 const $input = state.$anchor.find('._member_tag_query_input') 4530 if ($input.length === 0 || $input.prop('disabled')) return 4531 4532 $input.focus() 4533 const input = $input[0] 4534 if (input && typeof input.setSelectionRange === 'function') { 4535 input.setSelectionRange(input.value.length, input.value.length) 4536 } 4537 }, 0) 4538 } 4539 4540 /** 4541 * popover를 anchor ìëì ë°°ì¹íê³ viewport ë°ì¼ë¡ ëê°ë©´ ì쪽ì¼ë¡ ì íí©ëë¤. 4542 * fixed ì¢íì 문ì ì ì²´ scroll ê°ì§ë¥¼ í¨ê» ì¬ì©í´ í ì´ë¸ overflowì ìë¦¬ì§ ìê² í©ëë¤. 4543 * 4544 * @param {Object} state íì¬ combobox ìí 4545 */ 4546 const positionPopover = function (state) { 4547 if (activeState !== state || !state.$popover || state.$popover.length === 0) return 4548 if (!$.contains(document, state.$anchor[0])) { 4549 closePopover() 4550 return 4551 } 4552 4553 const rect = state.$anchor[0].getBoundingClientRect() 4554 const width = Math.min(340, window.innerWidth - 16) 4555 const height = state.$popover.outerHeight() 4556 const left = Math.max(8, Math.min(rect.left, window.innerWidth - width - 8)) 4557 let top = rect.bottom + 4 4558 4559 // ìë쪽 ê³µê°ì´ ë¶ì¡±íê³ ì쪽 ê³µê°ì´ ì¶©ë¶í ê²½ì° anchor ìë¡ ë¤ì§ìµëë¤. 4560 if (top + height > window.innerHeight - 8 && rect.top - height - 4 >= 8) { 4561 top = rect.top - height - 4 4562 } 4563 top = Math.max(8, Math.min(top, window.innerHeight - height - 8)) 4564 state.$popover.css({ left: left, top: top, width: width }) 4565 if (state.deleteConfirm) positionDeleteConfirm(state) 4566 } 4567 4568 /** 4569 * ìì±Â·ìì ì ì ë¹ íê·¸ëª ë§ ê²ì¬í©ëë¤. 4570 * ê°ìì ê¸¸ì´ ì íì ìë² ê²ì¦ 결과를 ì¬ì©í©ëë¤. 4571 * 4572 * @param {string} tagName íê·¸ëª 4573 * @returns {string} ì¤ë¥ 문구, ì ìì¼ ë ë¹ ë¬¸ìì´ 4574 */ 4575 const validateTagName = function (tagName) { 4576 if (!tagName) return 'íê·¸ëª ì ì ë ¥í´ ì£¼ì¸ì.' 4577 4578 return '' 4579 } 4580 4581 /** 4582 * í¤ë³´ë ëë hoverë¡ ì´ëí optionì ìê° ìíì aria-activedescendantì ë°ìí©ëë¤. 4583 * íì± indexê° ì í¨íì§ ìì¼ë©´ ì ê·¼ì± ì°¸ì¡°ë¥¼ ì ê±°í©ëë¤. 4584 * 4585 * @param {Object} state íì¬ combobox ìí 4586 */ 4587 const updateActiveOption = function (state) { 4588 if (activeState !== state) return 4589 4590 state.$popover.find('._member_tag_option_item').removeClass('is-active') 4591 if (state.activeIndex < 0 || state.activeIndex >= state.visibleItems.length) { 4592 state.$anchor.find('._member_tag_query_input').removeAttr('aria-activedescendant') 4593 return 4594 } 4595 4596 const itemId = state.visibleItems[state.activeIndex].id 4597 state.$popover.find('#' + itemId).addClass('is-active') 4598 state.$anchor.find('._member_tag_query_input').attr('aria-activedescendant', itemId) 4599 } 4600 4601 /** 4602 * ìì ë íê·¸ëª ì definitionsì ì´ë¯¸ ë¡ë©í 모ë íì chipì ì íí©ëë¤. 4603 * íê·¸ ì½ëê° ëì¼í ê°ì²´ë§ ê°±ì íì¬ ë¤ë¥¸ ì¬ì´í¸/íê·¸ ìíìë ìí¥ì ì£¼ì§ ììµëë¤. 4604 * 4605 * @param {{tag_code:string, tag_name:string}} definition ìì API ìëµ 4606 */ 4607 const updateDefinitionState = function (definition) { 4608 definitions.some(function (item, index) { 4609 if (item.tag_code !== definition.tag_code) return false 4610 4611 definitions[index] = { 4612 tag_code: definition.tag_code, 4613 tag_name: definition.tag_name 4614 } 4615 return true 4616 }) 4617 Object.keys(memberTagMap).forEach(function (memberCode) { 4618 memberTagMap[memberCode].forEach(function (tag) { 4619 if (tag.tag_code === definition.tag_code) tag.tag_name = definition.tag_name 4620 }) 4621 renderMember(memberCode) 4622 }) 4623 } 4624 4625 /** 4626 * ìì íì¸ popover를 í´ì§íµ ë²í¼ ìì ë°°ì¹íê³ viewport ì¶©ëì ë³´ì í©ëë¤. 4627 * ì본 ë²í¼ì´ DOMìì ì¬ë¼ì¡ë¤ë©´ íì¸ UI를 ë«ì ê³ ë¦½ë popover를 ë°©ì§í©ëë¤. 4628 * 4629 * @param {Object} state íì¬ combobox ìí 4630 */ 4631 const positionDeleteConfirm = function (state) { 4632 if (activeState !== state || !state.deleteConfirm) return 4633 4634 const confirmState = state.deleteConfirm 4635 if (!$.contains(document, confirmState.$button[0])) { 4636 closeDeleteConfirm(state, false) 4637 return 4638 } 4639 4640 const buttonRect = confirmState.$button[0].getBoundingClientRect() 4641 const width = Math.min(264, window.innerWidth - 16) 4642 const height = confirmState.$popover.outerHeight() 4643 let left = buttonRect.right + 6 4644 4645 if (left + width > window.innerWidth - 8) { 4646 left = buttonRect.left - width - 6 4647 } 4648 left = Math.max(8, Math.min(left, window.innerWidth - width - 8)) 4649 const top = Math.max(8, Math.min(buttonRect.top - 4, window.innerHeight - height - 8)) 4650 confirmState.$popover.css({ left: left, top: top, width: width }) 4651 } 4652 4653 /** 4654 * ìì íì¸ ìíì DOMì ì 리íê³ íìíë©´ combobox ì ë ¥ focus를 복구í©ëë¤. 4655 * 4656 * @param {Object} state íì¬ combobox ìí 4657 * @param {boolean} restoreFocus ì ë ¥ focus 복구 ì¬ë¶ 4658 */ 4659 const closeDeleteConfirm = function (state, restoreFocus) { 4660 if (!state || !state.deleteConfirm) return 4661 4662 state.pendingDefinitionDelete = null 4663 state.deleteConfirm.$popover.remove() 4664 state.deleteConfirm = null 4665 if (restoreFocus) focusQueryInput(state) 4666 } 4667 4668 /** ì´ë¯¸ ë¡ë©í 모ë íìíê·¸ íë를 íì¬ memberTagMap 기ì¤ì¼ë¡ ë¤ì 그립ëë¤. */ 4669 const renderAllLoadedMembers = function () {
4670 Object.keys(memberTagMap).forEach(renderMember) 4671 } 4672 4673 /** 4674 * ì¬ì´í¸ íê·¸ ìì API ì¤í¨ ì optimistic update ì´ì ì¤ë ì·ì¼ë¡ 복구í©ëë¤. 4675 * 복구 ë¤ ìì ì¤ ë°ë¦° íìíê·¸ ë³ê²½ì´ ìì¼ë©´ ë기í를 ë¤ì ììí©ëë¤. 4676 * 4677 * @param {Object} state íì¬ combobox ìí 4678 * @param {Object} snapshot ìì ì§ì definitionsì íìë³ íê·¸ ì¤ë ì· 4679 * @param {string} message ì¤í¨ ìë´ ë¬¸êµ¬ 4680 */ 4681 const restoreDeletedDefinition = function (state, snapshot, message) { 4682 if (!definitions.some(function (definition) { return definition.tag_code === snapshot.definition.tag_code })) { 4683 definitions.splice(snapshot.definitionIndex, 0, snapshot.definition) 4684 } 4685 Object.keys(snapshot.memberTagMap).forEach(function (memberCode) { 4686 memberTagMap[memberCode] = copyTags(snapshot.memberTagMap[memberCode]) 4687 }) 4688 state.desiredTagCodes = copyCodes(snapshot.desiredTagCodes) 4689 state.persistedTagCodes = copyCodes(snapshot.persistedTagCodes) 4690 state.isDeletingDefinition = false 4691 renderAllLoadedMembers() 4692 if (activeState === state) { 4693 renderPopover(state) 4694 focusQueryInput(state) 4695 } 4696 showToast(message) 4697 if (!isSameCodes(state.desiredTagCodes, state.persistedTagCodes)) syncMemberTags(state) 4698 } 4699 4700 /** 4701 * ì¬ì´í¸ íê·¸ ì ì를 ìì íê³ ë¡ë©ë 모ë íìì ëì¼ í그를 ì¦ì ì ê±°í©ëë¤. 4702 * íìíê·¸ ì ì¥ ìì²ê³¼ ìì ìì²ì´ ê²¹ì¹ë©´ ì ì¥ ìë£ í ìì íëë¡ ë³´ë¥í´ ìì ìì ì ë§ìµëë¤. 4703 * 4704 * @param {Object} state íì¬ combobox ìí 4705 * @param {{tag_code:string, tag_name:string}} definition ìì í íê·¸ ì ì 4706 */ 4707 const requestDefinitionDelete = function (state, definition) { 4708 if (state.isDeletingDefinition) return 4709 if (state.isSyncing) { 4710 closeDeleteConfirm(state, false) 4711 state.pendingDefinitionDelete = definition 4712 return 4713 } 4714 4715 const definitionIndex = definitions.map(function (item) { return item.tag_code }).indexOf(definition.tag_code) 4716 if (definitionIndex === -1) { 4717 closeDeleteConfirm(state, true) 4718 return 4719 } 4720 4721 // ìë² ì¤í¨ ì ìë³µí ì ìëë¡ ê³µì definitionsì 모ë ë¡ë© íì ìí를 ê¹ì ë³µì¬í©ëë¤. 4722 const loadedMemberTagMap = {} 4723 Object.keys(memberTagMap).forEach(function (memberCode) { 4724 loadedMemberTagMap[memberCode] = copyTags(memberTagMap[memberCode]) 4725 }) 4726 const snapshot = { 4727 definition: { 4728 tag_code: definition.tag_code, 4729 tag_name: definition.tag_name 4730 }, 4731 definitionIndex: definitionIndex, 4732 memberTagMap: loadedMemberTagMap, 4733 desiredTagCodes: copyCodes(state.desiredTagCodes), 4734 persistedTagCodes: copyCodes(state.persistedTagCodes) 4735 } 4736 4737 // API ìëµì 기ë¤ë¦¬ì§ ìê³ option, chip, ëª©ë¡ ì ìì ìì ëìì 먼ì ì ê±°í©ëë¤. 4738 state.isDeletingDefinition = true 4739 definitions.splice(definitionIndex, 1) 4740 Object.keys(memberTagMap).forEach(function (memberCode) { 4741 memberTagMap[memberCode] = memberTagMap[memberCode].filter(function (tag) { 4742 return tag.tag_code !== definition.tag_code 4743 }) 4744 }) 4745 state.desiredTagCodes = state.desiredTagCodes.filter(function (tagCode) { 4746 return tagCode !== definition.tag_code 4747 }) 4748 state.persistedTagCodes = state.persistedTagCodes.filter(function (tagCode) { 4749 return tagCode !== definition.tag_code 4750 }) 4751 closeDeleteConfirm(state, false) 4752 renderAllLoadedMembers() 4753 if (activeState === state) { 4754 renderPopover(state) 4755 focusQueryInput(state) 4756 } 4757 4758 // ì¬ì´í¸ íê·¸ ì ì ìì ë 모ë íì ì°ê²°ê¹ì§ ì ê±°íë¯ë¡ ë³ë delete_definition actionì í¸ì¶í©ëë¤. 4759 $.ajax({ 4760 url: '/admin/ajax/member/member_tag.cm', 4761 type: 'POST', 4762 dataType: 'json', 4763 data: { 4764 action: 'delete_definition', 4765 tag_code: definition.tag_code 4766 } 4767 }).done(function (response) { 4768 if (!response.success) { 4769 restoreDeletedDefinition(state, snapshot, response.message || 'íìíê·¸ ìì ì ì¤í¨íìµëë¤.') 4770 return 4771 } 4772 4773 state.isDeletingDefinition = false 4774 showToast('#' + definition.tag_name + ' í그를 ìì íìµëë¤.') 4775 if (activeState === state) focusQueryInput(state) 4776 if (!isSameCodes(state.desiredTagCodes, state.persistedTagCodes)) syncMemberTags(state) 4777 }).fail(function () { 4778 restoreDeletedDefinition( 4779 state, 4780 snapshot, 4781 getLocalizeString('ì¤ëª _ì ìíë¤ììëí´ì£¼ì¸ì', '', 'ì ì í ë¤ì ìëí´ì£¼ì¸ì.') 4782 ) 4783 }) 4784 } 4785 4786 /** 4787 * íê·¸ optionì í´ì§íµ ìì ì¬ì´í¸ ì ì²´ ìì íì¸ popover를 ì½ëë¤. 4788 * mousedown/click ì í를 모ë ì°¨ë¨í´ option ì íì´ë ëë¸í´ë¦ ìì ê³¼ ì¶©ëíì§ ìê² í©ëë¤. 4789 * 4790 * @param {Object} state íì¬ combobox ìí 4791 * @param {{tag_code:string, tag_name:string}} definition ìì í íê·¸ ì ì 4792 * @param {JQuery} $button anchor í´ì§íµ ë²í¼ 4793 */ 4794 const openDeleteConfirm = function (state, definition, $button) { 4795 if (activeState !== state || state.editing || state.isCreating || state.isDeletingDefinition || state.pendingDefinitionDelete) return 4796 4797 closeDeleteConfirm(state, false) 4798 const $cancelButton = $('<button type="button" class="btn btn-default btn-xs">').text('ì·¨ì') 4799 const $deleteButton = $('<button type="button" class="btn btn-danger btn-xs">').text('ìì ')
4800 const $popover = $('<div class="_member_tag_delete_confirm member-tag-delete-confirm">') 4801 .append($('<div class="member-tag-delete-confirm-title">').text('#' + definition.tag_name + ' í그를 ìì í ê¹ì?')) 4802 .append('<div class="member-tag-delete-confirm-description">ì´ íê·¸ë ì¬ì´í¸ì 모ë íììê²ì ì ê±°ë©ëë¤.</div>') 4803 .append('<div class="member-tag-delete-confirm-description">íì ìê° ë§ì¼ë©´ ìì ì ìê°ì´ ì¤ë 걸릴 ì ììµëë¤.</div>') 4804 .append($('<div class="member-tag-delete-confirm-actions">').append($cancelButton).append($deleteButton)) 4805 .appendTo('body') 4806 4807 state.deleteConfirm = { 4808 definition: definition, 4809 $button: $button, 4810 $popover: $popover, 4811 $deleteButton: $deleteButton 4812 } 4813 $cancelButton.on('mousedown', function (event) { 4814 event.preventDefault() 4815 event.stopPropagation() 4816 }).on('click', function (event) { 4817 event.preventDefault() 4818 event.stopPropagation() 4819 closeDeleteConfirm(state, true) 4820 }) 4821 $deleteButton.on('mousedown', function (event) { 4822 event.preventDefault() 4823 event.stopPropagation() 4824 }).on('click', function (event) { 4825 event.preventDefault() 4826 event.stopPropagation() 4827 requestDefinitionDelete(state, definition) 4828 }) 4829 $popover.on('keydown', function (event) { 4830 if (event.which !== 27) return 4831 4832 event.preventDefault() 4833 event.stopPropagation() 4834 closeDeleteConfirm(state, true) 4835 }) 4836 positionDeleteConfirm(state) 4837 $cancelButton.focus() 4838 } 4839 4840 /** 4841 * inline íê·¸ëª ìì ì ì ì¥íì§ ìê³ ì·¨ìíê³ option 목ë¡ì¼ë¡ ë³µê·í©ëë¤. 4842 * blurê° ë¤ì´ì´ ë°ìí´ë isCancelled ìí를 íµí´ ì ì¥ ìì²ì´ ì¤íëì§ ììµëë¤. 4843 * 4844 * @param {Object} state íì¬ combobox ìí 4845 */ 4846 const cancelRename = function (state) { 4847 if (activeState !== state || !state.editing) return 4848 4849 state.editing.isCancelled = true 4850 state.editing = null 4851 renderPopover(state) 4852 focusQueryInput(state) 4853 } 4854 4855 /** 4856 * inline inputì íê·¸ëª ì ê²ì¦í ë¤ ì¦ì ìì APIë¡ ì ì¥í©ëë¤. 4857 * ì¤ë¥ë alert ëì íì¬ input íë¨ì ì ì§íê³ , ì±ê³µ í 모ë ë¡ë© íìì chip ì´ë¦ì ê°±ì í©ëë¤. 4858 * 4859 * @param {Object} state íì¬ combobox ìí 4860 */ 4861 const saveRename = function (state) { 4862 if (activeState !== state || !state.editing) return 4863 4864 const editing = state.editing 4865 if (editing.isCancelled || editing.isSaving) return 4866 4867 // 공백ì ì 리í ì¤ì ì ì¥ê°ì¼ë¡ 길ì´ë¥¼ ê²ì¬íê³ ì¤ë¥ë¥¼ input 주ë³ì íìí©ëë¤. 4868 const tagName = $.trim(editing.$input.val()) 4869 const errorMessage = validateTagName(tagName) 4870 if (errorMessage) { 4871 editing.error = errorMessage 4872 editing.$error.text(errorMessage).show() 4873 return 4874 } 4875 if (tagName === editing.definition.tag_name) { 4876 const shouldClose = editing.closeAfterSave 4877 state.editing = null 4878 if (shouldClose) { 4879 closePopover() 4880 } else { 4881 renderPopover(state) 4882 focusQueryInput(state) 4883 } 4884 return 4885 } 4886 4887 // Enterì blurê° ì°ë¬ì ë°ìí´ë ìì²ì´ ì¤ë³µëì§ ìëë¡ ì ì¥ ìí를 먼ì ì ê¸ëë¤. 4888 editing.isSaving = true 4889 editing.error = '' 4890 editing.$error.empty().hide() 4891 editing.$input.prop('disabled', true) 4892 $.ajax({ 4893 url: '/admin/ajax/member/member_tag.cm', 4894 type: 'POST', 4895 dataType: 'json', 4896 data: { 4897 action: 'update_definition', 4898 tag_code: editing.definition.tag_code, 4899 tag_name: tagName 4900 } 4901 }).done(function (response) { 4902 if (!response.success) { 4903 editing.isSaving = false 4904 editing.error = response.message || 'íê·¸ëª ì ì ì¥íì§ ëª»íìµëë¤.' 4905 editing.$input.prop('disabled', false) 4906 editing.$error.text(editing.error).show() 4907 editing.$input.focus().select() 4908 return 4909 } 4910 4911 const shouldClose = editing.closeAfterSave 4912 updateDefinitionState(response.data) 4913 state.editing = null 4914 if (shouldClose) { 4915 closePopover() 4916 } else if (activeState === state) { 4917 renderPopover(state) 4918 focusQueryInput(state) 4919 } 4920 }).fail(function () { 4921 editing.isSaving = false 4922 editing.error = getLocalizeString('ì¤ëª _ì ìíë¤ììëí´ì£¼ì¸ì', '', 'ì ì í ë¤ì ìëí´ì£¼ì¸ì.') 4923 editing.$input.prop('disabled', false) 4924 editing.$error.text(editing.error).show() 4925 editing.$input.focus().select() 4926 }) 4927 } 4928 4929 /** 4930 * ì íë optionì inline inputì¼ë¡ ì ííê³ ì ì²´ ì í ìíë¡ focusí©ëë¤. 4931 * ìì íì¸ì´ë ë¤ë¥¸ ìì ì´ ì§í ì¤ì´ë©´ ìí ì íì íì©íì§ ììµëë¤. 4932 * 4933 * @param {Object} state íì¬ combobox ìí 4934 * @param {{tag_code:string, tag_name:string}} definition ìì í íê·¸ ì ì 4935 */ 4936 const startRename = function (state, definition) { 4937 if (activeState !== state || state.editing || state.deleteConfirm || state.isDeletingDefinition) return 4938 4939 state.editing = { 4940 definition: definition, 4941 isCancelled: false, 4942 isSaving: false, 4943 closeAfterSave: false, 4944 error: '' 4945 } 4946 renderPopover(state) 4947 setTimeout(function () { 4948 if (activeState !== state || !state.editing || !state.editing.$input) return 4949 4950 state.editing.$input.focus().select() 4951 }, 0) 4952 } 4953 4954 /** 4955 * íìíê·¸ ì ì¥ ì¤í¨ ì íë©´ ì íê°ì ë§ì§ë§ ìë² íì ê°ì¼ë¡ ëë립ëë¤. 4956 * popover를 ë«ì§ ìê³ ë¤ì ë ëë§í´ ì¬ì©ìê° ì°ì ìì ì ì´ì´ê° ì ììµëë¤. 4957 * 4958 * @param {Object} state íì¬ combobox ìí 4959 * @param {string} message ì¤í¨ ìë´ ë¬¸êµ¬ 4960 */ 4961 const rollbackMemberSync = function (state, message) { 4962 state.desiredTagCodes = copyCodes(state.persistedTagCodes) 4963 memberTagMap[state.memberCode] = getTagsByCodes(state.desiredTagCodes) 4964 renderMember(state.memberCode) 4965 if (activeState === state) { 4966 renderPopover(state) 4967 focusQueryInput(state) 4968 } 4969 showToast(message) 4970 } 4971 4972 /** 4973 * desiredTagCodes ì 체를 ìë²ì ì ì¥íê³ ìëµê°ì persistedTagCodesë¡ íì í©ëë¤. 4974 * ìì² ì¤ ì¶ê° ì íì´ ë°ìíë©´ íì¬ ìì² ìë£ í ìµì desired ìí를 ë¤ì ì ì¡í©ëë¤. 4975 * 4976 * @param {Object} state íì¬ combobox ìí 4977 */ 4978 const syncMemberTags = function (state) { 4979 if (state.isSyncing || isSameCodes(state.desiredTagCodes, state.persistedTagCodes)) return 4980 4981 // ì ì¡ ìì ì ì íê°ì ê³ ì í´ ìì² ì¤ ì¬ì©ìì ì¶ê° ì¡°ìê³¼ ì
4981ì´ì§ ìê² í©ëë¤. 4982 const payload = copyCodes(state.desiredTagCodes) 4983 let failed = false 4984 state.isSyncing = true 4985 $.ajax({ 4986 url: '/admin/ajax/member/member_tag.cm', 4987 type: 'POST', 4988 dataType: 'json', 4989 data: { 4990 action: 'replace_member_tags', 4991 member_code: state.memberCode, 4992 tag_codes: JSON.stringify(payload) 4993 } 4994 }).done(function (response) { 4995 if (!response.success) { 4996 failed = true 4997 rollbackMemberSync(state, response.message) 4998 return 4999 } 5000 5001 state.persistedTagCodes = copyCodes(response.data.tag_codes) 5002 }).fail(function () { 5003 failed = true 5004 rollbackMemberSync(state, getLocalizeString('ì¤ëª _ì ìíë¤ììëí´ì£¼ì¸ì', '', 'ì ì í ë¤ì ìëí´ì£¼ì¸ì.')) 5005 }).always(function () { 5006 state.isSyncing = false 5007 5008 // íì ì ì¥ ì¤ ìì²ë ì ì ìì 를 먼ì ì²ë¦¬í´ ìì ë íê·¸ê° ë¤ì ì ì¥ëë ê²ì ë§ìµëë¤. 5009 if (state.pendingDefinitionDelete) { 5010 const pendingDefinition = state.pendingDefinitionDelete 5011 state.pendingDefinitionDelete = null 5012 requestDefinitionDelete(state, pendingDefinition) 5013 return 5014 } 5015 // ì ì¥ ìë£ ë¤ desired ê°ì´ ë ìµì ì´ë©´ ë§ì§ë§ ìíê° íì ë ëê¹ì§ í ë² ë ë기íí©ëë¤. 5016 if (!failed && !isSameCodes(state.desiredTagCodes, state.persistedTagCodes)) { 5017 syncMemberTags(state) 5018 } 5019 }) 5020 } 5021 5022 /** 5023 * ì¬ì©ì ì¡°ì 결과를 íë©´ì 먼ì ë°ìí ë¤ ë¹ë기 ì ì¥ì ììí©ëë¤. 5024 * memberTagMap, anchor chip, option ì í ìíê° ëì¼í desired ê°ì ë°ë¼ë³´ê² í©ëë¤. 5025 * 5026 * @param {Object} state íì¬ combobox ìí 5027 * @param {string[]} tagCodes ë³ê²½í íê·¸ ì½ë ëª©ë¡ 5028 */ 5029 const applyDesiredTags = function (state, tagCodes) { 5030 state.desiredTagCodes = copyCodes(tagCodes) 5031 memberTagMap[state.memberCode] = getTagsByCodes(state.desiredTagCodes) 5032 renderMember(state.memberCode) 5033 if (activeState === state) { 5034 renderPopover(state) 5035 focusQueryInput(state) 5036 } 5037 syncMemberTags(state) 5038 } 5039 5040 /** 5041 * íê·¸ ì ì íë를 íì¬ íììê² ì ííê±°ë í´ì í©ëë¤. 5042 * ê°ì ì íì ìë² ìëµì¼ë¡ ê²ì¦íê³ ì¤ì ì ì¥ì applyDesiredTagsì ììí©ëë¤. 5043 * 5044 * @param {Object} state íì¬ combobox ìí 5045 * @param {{tag_code:string, tag_name:string}} definition ì í·í´ì í íê·¸ ì ì 5046 * @param {boolean=} forceSelected trueë©´ ì í, falseë©´ í´ì , ìëµíë©´ toggle 5047 */ 5048 const toggleDefinition = function (state, definition, forceSelected) { 5049 if (!state.ready || state.isCreating || state.deleteConfirm || state.isDeletingDefinition) return 5050 5051 const tagCodes = copyCodes(state.desiredTagCodes) 5052 const currentIndex = tagCodes.indexOf(definition.tag_code) 5053 const shouldSelect = typeof forceSelected === 'boolean' ? forceSelected : currentIndex === -1 5054 5055 if (shouldSelect && currentIndex === -1) { 5056 tagCodes.push(definition.tag_code) 5057 } else if (!shouldSelect && currentIndex !== -1) { 5058 tagCodes.splice(currentIndex, 1) 5059 } else { 5060 return 5061 } 5062 5063 state.query = '' 5064 state.queryError = '' 5065 applyDesiredTags(state, tagCodes) 5066 } 5067 5068 /** 5069 * ì ë ¥ê°ì¼ë¡ ì¬ì´í¸ í그를 ìì±íê³ íì¬ íììê² ì¦ì ì íí©ëë¤. 5070 * ëì¼ ì´ë¦ë§ ì¬ì ê²ì¬íë©° ê°ìì ê¸¸ì´ ì íì ìë² ìëµì¼ë¡ ê²ì¦í©ëë¤. 5071 * 5072 * @param {Object} state íì¬ combobox ìí 5073 */ 5074 const createDefinition = function (state) { 5075 if (activeState !== state || state.isCreating || state.deleteConfirm || state.isDeletingDefinition) return 5076 5077 const tagName = $.trim(state.query) 5078 const errorMessage = validateTagName(tagName) 5079 const duplicated = definitions.some(function (definition) { 5080 return definition.tag_name.toLowerCase() === tagName.toLowerCase() 5081 }) 5082 5083 if (errorMessage) { 5084 state.queryError = errorMessage 5085 renderPopover(state) 5086 focusQueryInput(state) 5087 return 5088 } 5089 if (duplicated) return 5090 5091 // ìì± ìì² ëì ì¤ë³µ Enter를 ë§ê³ íë inputì disabled ìíë¡ ë¤ì ë ëë§í©ëë¤. 5092 state.isCreating = true 5093 state.queryError = '' 5094 renderMember(state.memberCode) 5095 renderPopover(state) 5096 $.ajax({ 5097 url: '/admin/ajax/member/member_tag.cm', 5098 type: 'POST', 5099 dataType: 'json', 5100 data: { 5101 action: 'create_definition', 5102 tag_name: tagName 5103 } 5104 }).done(function (response) { 5105 if (!response.success) { 5106 state.isCreating = false 5107 state.queryError = response.message || 'í그를 ìì±íì§ ëª»íìµëë¤.' 5108 renderMember(state.memberCode) 5109 if (activeState === state) { 5110 renderPopover(state) 5111 focusQueryInput(state) 5112 } 5113 return 5114 } 5115 5116 // ì ì ì를 ê³µì 목ë¡ì ì¶ê°í ë¤ íì¬ íìì desired ì íìë í¬í¨í©ëë¤. 5117 definitions.push({ 5118 tag_code: response.data.tag_code, 5119 tag_name: response.data.tag_name 5120 }) 5121 state.isCreating = false 5122 state.query = '' 5123 state.queryError = '' 5124 const tagCodes = copyCodes(state.desiredTagCodes) 5125 tagCodes.push(response.data.tag_code) 5126 applyDesiredTags(state, tagCodes) 5127 }).fail(function () { 5128 state.isCreating = false 5129 state.queryError = getLocalizeString('ì¤ëª _ì ìíë¤ììëí´ì£¼ì¸ì', '', 'ì ì í ë¤ì ìëí´ì£¼ì¸ì.') 5130 renderMember(state.memberCode) 5131 if (activeState === state) { 5132 renderPopover(state) 5133 focusQueryInput(state) 5134 } 5135 }) 5136 } 5137 5138 /** 5139 * íì¬ keyboard active optionì Enter ëìì¼ë¡ ì¤íí©ëë¤. 5140 * ì í ê°ë¥í optionì´ ìê³ ì ë ¥ê°ë§ ìì¼ë©´ ìì± ëìì¼ë¡ ì°ê²°í©ëë¤. 5141 * 5142 * @param {Object} state íì¬ combobox ìí 5143 */ 5144 const activateVisibleItem = function (state) { 5145 if (state.activeIndex < 0 || state.activeIndex >= state.visibleItems.length) { 5146 if ($.trim(state.query)) createDefinition(state) 5147 return 5148 } 5149 5150 const item = state.visibleItems[state.activeIndex] 5151 if (item.type === 'create') { 5152 createDefinition(state) 5153 } else { 5154 toggleDefinition(state, item.definition) 5155 } 5156 } 5157 5158 /** 5159 * ìì ì¤ì¸ íê·¸ option ì리ì inline inputê³¼ ì¤ë¥ ììì ë ëë§í©ëë¤. 5160 * Enter/blurë ì ì¥, Escë ì·¨ìë¡ ì°ê²°íë©° ì´ë²¤í¸ê° ìì optionì¼ë¡ ì íëì§ ìê² í©ëë¤. 5161 * 5162 * @param {Object} state íì¬ combobox ìí 5163 * @param {JQuery} $optionList option ëª©ë¡ 5164 * @param {{tag_code:string, tag_name:string}} definition ìì í íê·¸ ì ì 5165 * @param {string} itemId aria-activedescendantìì 참조í DOM id 5166 */ 5167 const renderRenameOption = function (state, $optionList, definition, itemId) { 5168 const editing = state.editing 5169 const $input = $('<input type="text" class="form-control input-sm _member_tag_rename_input">').val(editing.definition.tag_name) 5170 const $error = $('<div class="member-tag-inline-error" style="display:none;">') 5171 const $wrap = $('<div class="member-tag-rename-wrap" role="option">').attr('id', itemId).append($input).append($error) 5172 5173 editing.$input = $input 5174 editing.$error = $error 5175 $input.on('keydown', function (event) { 5176 if (event.which === 13) { 5177 event.preventDefault() 5178 event.stopPropagation() 5179 saveRename(state) 5180 } else if (event.which === 27) { 5181 event.preventDefault() 5182 event.stopPropagation() 5183 cancelRename(state) 5184 } 5185 }).on('blur', function () { 5186 saveRename(state) 5187 }) 5188 $optionList.append($wrap) 5189 } 5190 5191 /** 5192 * ì¼ë° íê·¸ option í íì ì í ìí, ìì affordance, ìì ë²í¼ê³¼ í¨ê» ë ëë§í©ëë¤. 5193 * íê·¸ëª single clickì ì í, double clickì ìì ì´ë¯ë¡ ì§§ì timerë¡ ë ì´ë²¤í¸ë¥¼ ë¶ë¦¬í©ëë¤. 5194 * 5195 * @param {Object} state íì¬ combobox ìí 5196 * @param {JQuery} $optionList option ëª©ë¡ 5197 * @param {{tag_code:string, tag_name:string}} definition íê·¸ ì ì 5198 * @param {number} itemIndex visibleItemsì index 5199 */ 5200 const renderDefinitionOption = function (state, $optionList, definition, itemIndex) { 5201 const isSelected = state.desiredTagCodes.indexOf(definition.tag_code) !== -1 5202 const item = state.visibleItems[itemIndex] 5203 const $option = $('<div class="_member_tag_option_item member-tag-option-item" role="option">') 5204 .attr('id', item.id) 5205 .attr('aria-selected', isSelected ? 'true' : 'false') 5206 .toggleClass('is-selected text-primary', isSelected) 5207 .toggleClass('is-active', state.activeIndex === itemIndex) 5208 const $name = $('<span class="_member_tag_option_name member-tag-option-name">').text('#' + definition.tag_name) 5209 const $deleteButton = $('<button type="button" class="_member_tag_option_delete member-tag-option-delete">') 5210 .attr('aria-label', '#' + definition.tag_name + ' íê·¸ ìì ') 5211 .append('<i class="btm bt-trash" aria-hidden="true"></i>')
5212 let clickTimer = null 5213 5214 $option.append('<span class="member-tag-option-check" aria-hidden="true">â</span>').append($name).append($deleteButton) 5215 // mousedown 기본 ëìì ë§ì option ì¡°ì ì¤ìë anchor input focus를 ì ì§í©ëë¤. 5216 $option.on('mousedown', function (event) { 5217 event.preventDefault() 5218 }).on('mouseenter', function () { 5219 if (state.editing || state.deleteConfirm) return 5220 5221 state.activeIndex = itemIndex 5222 updateActiveOption(state) 5223 }).on('click', function (event) { 5224 if (state.editing) return 5225 if ($(event.target).closest('._member_tag_option_name').length > 0) return 5226 5227 toggleDefinition(state, definition) 5228 }) 5229 // single click ì¤íì ì ì ë¦ì¶ê³ dblclickì´ ë¤ì´ì¤ë©´ timer를 ì·¨ìí´ ê¹ë¹¡ìì ë°©ì§í©ëë¤. 5230 $name.on('click', function (event) { 5231 event.preventDefault() 5232 event.stopPropagation() 5233 if (state.editing) return 5234 if (event.detail > 1) { 5235 clearTimeout(clickTimer) 5236 return 5237 } 5238 5239 clearTimeout(clickTimer) 5240 clickTimer = setTimeout(function () { 5241 toggleDefinition(state, definition) 5242 }, 260) 5243 }).on('dblclick', function (event) { 5244 event.preventDefault() 5245 event.stopPropagation() 5246 clearTimeout(clickTimer) 5247 startRename(state, definition) 5248 }) 5249 // ìì ë²í¼ ì´ë²¤í¸ë option ì í·ìì ì´ë²¤í¸ë¡ ì ë ì ííì§ ììµëë¤. 5250 $deleteButton.on('mousedown', function (event) { 5251 event.preventDefault() 5252 event.stopPropagation() 5253 clearTimeout(clickTimer) 5254 }).on('focus', function () { 5255 state.activeIndex = itemIndex 5256 updateActiveOption(state) 5257 }).on('click', function (event) { 5258 event.preventDefault() 5259 event.stopPropagation() 5260 clearTimeout(clickTimer) 5261 openDeleteConfirm(state, definition, $deleteButton) 5262 }) 5263 $optionList.append($option) 5264 } 5265 5266 /** 5267 * ì ë ¥ê°ê³¼ í¸ì§ ìí를 기ì¤ì¼ë¡ ìì± option ë° íê·¸ option ëª©ë¡ ì 체를 ë¤ì 그립ëë¤. 5268 * visibleItemsë í¤ë³´ë ì´ë ììì ëì¼íê² êµ¬ì±íê³ ë ë í popover ìì¹ë¥¼ ì¬ê³ì°í©ëë¤. 5269 * 5270 * @param {Object} state íì¬ combobox ìí 5271 */ 5272 const renderPopover = function (state) { 5273 if (activeState !== state) return 5274 5275 const $optionList = state.$popover.find('._member_tag_option_list').empty() 5276 const $queryError = state.$popover.find('._member_tag_query_error') 5277 const query = $.trim(state.query) 5278 const lowerQuery = query.toLowerCase() 5279 5280 $queryError.text(state.queryError).toggle(!!state.queryError) 5281 state.visibleItems = [] 5282 5283 if (!state.ready) { 5284 $optionList.append('<div class="member-tag-option-empty">í그를 ë¶ë¬ì¤ë ì¤ì ëë¤.</div>') 5285 positionPopover(state) 5286 return 5287 } 5288 5289 // ì ë ¥ê°ì ë³ë ê²ì í¼ ìì´ anchor inputìì ë°ë¡ option íí°ë¡ ì¬ì©í©ëë¤. 5290 const filteredDefinitions = definitions.filter(function (definition) { 5291 return !lowerQuery || definition.tag_name.toLowerCase().indexOf(lowerQuery) !== -1 5292 }) 5293 const hasExactMatch = definitions.some(function (definition) { 5294 return definition.tag_name.toLowerCase() === lowerQuery 5295 }) 5296 const canCreate = query && !hasExactMatch 5297 5298 // ì íí ì¼ì¹íë ì ìê° ìì ë ëª©ë¡ ìµìë¨ì ìì± optionì ë ¸ì¶íê³ ì íì ìë²ìì ê²ì¦í©ëë¤. 5299 if (canCreate) { 5300 const createItem = { 5301 type: 'create', 5302 id: state.optionListId + '-create' 5303 } 5304 const createIndex = state.visibleItems.push(createItem) - 1 5305 const $createOption = $('<div class="_member_tag_option_item member-tag-option-item member-tag-create-option text-primary" role="option" aria-selected="false">') 5306 .attr('id', createItem.id) 5307 .toggleClass('is-active', state.activeIndex === createIndex) 5308 .append('<span class="member-tag-option-check" aria-hidden="true"></span>') 5309 .append($('<span class="member-tag-create-label">').text('ìì±')) 5310 .append($('<span>').text('#' + query)) 5311 5312 $createOption.on('mousedown', function (event) { 5313 event.preventDefault() 5314 }).on('mouseenter', function () { 5315 state.activeIndex = createIndex 5316 updateActiveOption(state) 5317 }).on('click', function () { 5318 createDefinition(state) 5319 }) 5320 $optionList.append($createOption) 5321 } 5322 5323 // ìì ëì optionë§ inline inputì¼ë¡ êµì²´íê³ ë머ì§ë ì¼ë° option íì¼ë¡ ì ì§í©ëë¤. 5324 filteredDefinitions.forEach(function (definition) { 5325 const definitionItem = { 5326 type: 'definition', 5327 definition: definition, 5328 id: state.optionListId + '-' + definition.tag_code 5329 } 5330 const itemIndex = state.visibleItems.push(definitionItem) - 1 5331 5332 if (state.editing && state.editing.definition.tag_code === definition.tag_code) { 5333 renderRenameOption(state, $optionList, definition, definitionItem.id) 5334 } else { 5335 renderDefinitionOption(state, $optionList, definition, itemIndex) 5336 } 5337 }) 5338 5339 if (state.visibleItems.length === 0) { 5340 $optionList.append('<div class="member-tag-option-empty">ì¼ì¹íë íê·¸ê° ììµëë¤.</div>') 5341 state.activeIndex = -1 5342 } else if (state.activeIndex < 0 || state.activeIndex >= state.visibleItems.length) { 5343 state.activeIndex = 0 5344 } 5345 5346 updateActiveOption(state) 5347 positionPopover(state) 5348 } 5349 5350 /** 5351 * íì¬ popoverì ì ì resize/scroll listener를 ì ê±°íê³ anchor를 ë¹íì± íì ìíë¡ ë³µ
5351ìí©ëë¤. 5352 * ìì íì¸ ìíë í¨ê» ì ë¦¬í´ bodyì ê³ ë¦½ë ë³´ì¡° popoverê° ë¨ì§ ìê² í©ëë¤. 5353 */ 5354 const closePopover = function () { 5355 if (!activeState) return 5356 5357 const state = activeState 5358 closeDeleteConfirm(state, false) 5359 activeState = null 5360 $(window).off('.memberTagManagePopover') 5361 if (state.scrollHandler) { 5362 document.removeEventListener('scroll', state.scrollHandler, true) 5363 } 5364 if (state.$popover) state.$popover.remove() 5365 renderField(state.$anchor, memberTagMap[state.memberCode] || []) 5366 } 5367 5368 /** 5369 * body ì§ì fixed popover를 ë§ë¤ê³ viewport ìì¹ ê°±ì listener를 ë±ë¡í©ëë¤. 5370 * í ì´ë¸ê³¼ ì¤ê° 컨í ì´ëì overflow ìí¥ì í¼í기 ìí´ anchor ë´ë¶ì ë£ì§ ììµëë¤. 5371 * 5372 * @param {Object} state íì¬ combobox ìí 5373 */ 5374 const createPopover = function (state) { 5375 state.$popover = $('<div class="_member_tag_popover member-tag-popover">') 5376 .append('<div class="member-tag-popover-guide">ìµì ì í ëë ìì±</div>') 5377 .append('<div class="_member_tag_query_error member-tag-query-error" style="display:none;"></div>') 5378 .append($('<div class="_member_tag_option_list member-tag-option-list" role="listbox" aria-multiselectable="true">').attr('id', state.optionListId)) 5379 .appendTo('body') 5380 5381 $(window).on('resize.memberTagManagePopover scroll.memberTagManagePopover', function () { 5382 positionPopover(state) 5383 }) 5384 state.scrollHandler = function () { 5385 positionPopover(state) 5386 } 5387 document.addEventListener('scroll', state.scrollHandler, true) 5388 } 5389 5390 /** 5391 * íìíê·¸ íë를 íì±ííê³ í´ë¹ anchorì combobox ìíì popover를 ì°ê²°í©ëë¤. 5392 * ë°ì´í°ê° ìì§ ìì¼ë©´ popover를 ì° ìíë¡ íì íê·¸ì definitions를 ì§ì° ì¡°íí©ëë¤. 5393 * 5394 * @param {string} memberCode íì ì½ë 5395 * @param {HTMLElement|JQuery=} anchor í´ë¦ ëë focusë íìíê·¸ íë 5396 * @returns {Object|null} íì± ìí ëë ì´ ì ìì ë null 5397 */ 5398 const open = function (memberCode, anchor) { 5399 ensureStyles() 5400 const $anchor = anchor ? $(anchor) : $('._member_tag_button[data-member-code="' + memberCode + '"]').first() 5401 if ($anchor.length === 0 || $anchor.attr('data-editable') === 'N') return null 5402 if (activeState && activeState.$anchor[0] === $anchor[0]) { 5403 focusQueryInput(activeState) 5404 return activeState 5405 } 5406 5407 closePopover() 5408 const hasMemberData = Object.prototype.hasOwnProperty.call(memberTagMap, memberCode) 5409 const initialCodes = getMemberTagCodes(memberCode) 5410 // persistedë ìë² íì ê°, desiredë optimistic íë©´ê°ì¼ë¡ ë¶ë¦¬í´ ì¤í¨ ìë³µ 기ì¤ì ë³´ì¡´í©ëë¤. 5411 const state = { 5412 memberCode: memberCode, 5413 $anchor: $anchor, 5414 $popover: null, 5415 optionListId: 'member-tag-options-' + memberCode, 5416 query: '', 5417 queryError: '', 5418 activeIndex: 0, 5419 visibleItems: [], 5420 persistedTagCodes: copyCodes(initialCodes), 5421 desiredTagCodes: copyCodes(initialCodes), 5422 ready: definitionsLoaded && hasMemberData, 5423 isCreating: false, 5424 isSyncing: false, 5425 isDeletingDefinition: false, 5426 pendingDefinitionDelete: null, 5427 deleteConfirm: null, 5428 editing: null 5429 } 5430 5431 activeState = state 5432 createPopover(state) 5433 renderField($anchor, memberTagMap[memberCode] || []) 5434 renderPopover(state) 5435 focusQueryInput(state) 5436 5437 // ëª©ë¡ ìµì´ í´ë¦ì²ë¼ ìºìê° ìë ê²½ì° íì¬ íìë§ ì¡°ííê³ íì± ìíê° ì ì§ë ëë§ ë°ìí©ëë¤. 5438 if (!state.ready) { 5439 requestTagData([memberCode], true).done(function () { 5440 if (activeState !== state) return 5441 5442 state.ready = true 5443 state.persistedTagCodes = getMemberTagCodes(memberCode) 5444 state.desiredTagCodes = copyCodes(state.persistedTagCodes) 5445 renderMember(memberCode) 5446 renderPopover(state) 5447 focusQueryInput(state) 5448 }).fail(function (message) { 5449 if (activeState === state) closePopover() 5450 showToast(message) 5451 }) 5452 } 5453 5454 return state 5455 } 5456 5457 /** 5458 * ì·ìë ë°©í¥í¤ì ë°ë¼ active optionì ìí ì´ëíê³ íë©´ ë° optionì ë³´ì´ëë¡ ì¤í¬ë¡¤í©ëë¤. 5459 * 5460 * @param {Object} state íì¬ combobox ìí 5461 * @param {number} delta 1ì ìë, -1ì ì 5462 */ 5463 const moveActiveOption = function (state, delta) { 5464 if (state.visibleItems.length === 0) return 5465 5466 state.activeIndex += delta 5467 if (state.activeIndex < 0) state.activeIndex = state.visibleItems.length - 1 5468 if (state.activeIndex >= state.visibleItems.length) state.activeIndex = 0 5469 updateActiveOption(state) 5470 5471 const item = state.visibleItems[state.activeIndex] 5472 const $item = state.$popover.find('#' + item.id) 5473 if ($item.length > 0 && $item[0].scrollIntoView) { 5474 $item[0].scrollIntoView({ block: 'nearest' }) 5475 } 5476 } 5477 5478 /** 5479 * ëì ì¼ë¡ ì¶ê°ëë ëª©ë¡ íê¹ì§ ì²ë¦¬í ì ìëë¡ document ìì ì´ë²¤í¸ë¥¼ í ë² ë±ë¡í©ëë¤. 5480 * íë ì´ê¸°, ì ë ¥ íí°, í¤ë³´ë ì´ë, ë°ê¹¥ í´ë¦ ë«ê¸°ë¥¼ íëì namespaceë¡ ê´ë¦¬í©ëë¤. 5481 */ 5482 const bindEvents = function () { 5483 // ëª©ë¡ ì ì íë ë°ê¹¥ ì¬ë°±ë ëì¼í combobox anchor를 ì´ì´ ì ì 체를 click targetì¼ë¡ ì ì§í©ëë¤. 5484 $(document).on('click.memberTagManage', 'li.member-tag-cell-editable', function (event) { 5485 if ($(event.target).closest('._member_tag_button').length > 0) return 5486 5487 const $field = $(this).find('._member_tag_button').first() 5488 if ($field.length === 0) return 5489 5490 open(String($field.data('member-code')), $field)
5491 // íë click/Enter/Spaceë ëì¼í open í¨ìë¡ ì°ê²°íê³ ì½ê¸° ì ì© íëë ì ì¸í©ëë¤. 5492 }).on('click.memberTagManage', '._member_tag_button', function (event) { 5493 if ($(this).attr('data-editable') === 'N') return 5494 5495 open(String($(this).data('member-code')), this) 5496 }).on('keydown.memberTagManage', '._member_tag_button', function (event) { 5497 if ($(this).attr('data-editable') === 'N' || $(event.target).is('input,button')) return 5498 if (event.which !== 13 && event.which !== 32) return 5499 5500 event.preventDefault() 5501 open(String($(this).data('member-code')), this) 5502 // ì ë ¥í ëë§ë¤ option íí°ì ìì± optionì ê°±ì íë©° ìë² ìì²ì Enter ì ê¹ì§ ë³´ë´ì§ ììµëë¤. 5503 }).on('input.memberTagManage', '._member_tag_query_input', function () { 5504 if (!activeState || activeState.$anchor[0] !== $(this).closest('._member_tag_button')[0]) return 5505 5506 activeState.query = $(this).val() 5507 activeState.queryError = '' 5508 activeState.activeIndex = 0 5509 renderPopover(activeState) 5510 // ë°©í¥í¤/Enter/Esc/ë¹ ì ë ¥ Backspace를 Notioní combobox í¤ë³´ë ëìì 매íí©ëë¤. 5511 }).on('keydown.memberTagManage', '._member_tag_query_input', function (event) { 5512 const state = activeState 5513 if (!state) return 5514 5515 if (event.which === 40) { 5516 event.preventDefault() 5517 moveActiveOption(state, 1) 5518 } else if (event.which === 38) { 5519 event.preventDefault() 5520 moveActiveOption(state, -1) 5521 } else if (event.which === 13) { 5522 event.preventDefault() 5523 activateVisibleItem(state) 5524 } else if (event.which === 27) { 5525 event.preventDefault() 5526 if (state.deleteConfirm) { 5527 closeDeleteConfirm(state, true) 5528 } else { 5529 closePopover() 5530 } 5531 } else if (event.which === 8 && $(this).val() === '' && state.desiredTagCodes.length > 0) { 5532 event.preventDefault() 5533 const lastTagCode = state.desiredTagCodes[state.desiredTagCodes.length - 1] 5534 const definition = definitions.filter(function (item) { 5535 return item.tag_code === lastTagCode 5536 })[0] 5537 if (definition) toggleDefinition(state, definition, false) 5538 } 5539 // popoverì anchor ë° clickì ë«ë ì ì¥ ì¤ì¸ inline ìì ì ìë£ë ë¤ ë«ëë¡ ë³´ë¥í©ëë¤. 5540 }).on('click.memberTagManageOutside', function (event) { 5541 if (!activeState) return 5542 if (activeState.deleteConfirm) { 5543 if ($(event.target).closest('._member_tag_delete_confirm, ._member_tag_option_delete').length > 0) return 5544 5545 closeDeleteConfirm(activeState, true) 5546 return 5547 } 5548 if ($(event.target).closest('._member_tag_popover, ._member_tag_button').length > 0) return 5549 if (activeState.editing) { 5550 if (activeState.editing.error) return 5551 if (activeState.editing.isSaving) { 5552 activeState.editing.closeAfterSave = true 5553 return 5554 } 5555 } 5556 5557 closePopover() 5558 }) 5559 } 5560 5561 /** 5562 * ìì¸ SSRì´ data attributeë¡ ì ë¬í ì´ê¸° íê·¸ì definitions를 ê³µì ìíì ì ì¬í©ëë¤. 5563 * JSON íì±ì ì¤í¨íë©´ ë¹ ëª©ë¡ì¼ë¡ ìì íê² ì´ê¸°ííê³ ì´í API ì¡°íê° ê°ë¥íëë¡ ì ì§í©ëë¤. 5564 */ 5565 const hydrateInitialFields = function () { 5566 $('._member_tag_button[data-initial-tags]').each(function () { 5567 const $field = $(this) 5568 const memberCode = String($field.data('member-code')) 5569 let initialTags = [] 5570 let initialDefinitions = [] 5571 5572 try { 5573 initialTags = JSON.parse($field.attr('data-initial-tags') || '[]') 5574 initialDefinitions = JSON.parse($field.attr('data-initial-definitions') || '[]') 5575 } catch (error) { 5576 initialTags = [] 5577 initialDefinitions = [] 5578 } 5579 memberTagMap[memberCode] = copyTags(initialTags) 5580 if (initialDefinitions.length > 0 || $field.is('[data-initial-definitions]')) { 5581 definitions = copyTags(initialDefinitions) 5582 definitionsLoaded = true 5583 } 5584 renderField($field, memberTagMap[memberCode]) 5585 }) 5586 } 5587 5588 // 모ë ë¡ë© ì ê³µíµ ì¤íì¼ê³¼ ìì ì´ë²¤í¸ë¥¼ ì¤ë¹íê³ DOM ready í ìì¸ SSR íë를 hydrateí©ëë¤. 5589 ensureStyles() 5590 bindEvents() 5591 $(hydrateInitialFields) 5592 5593 return { 5594 loadList: loadList, 5595 loadDefinitions: loadDefinitions, 5596 getDefinitions: getDefinitions, 5597 getMemberSearchCondition: getMemberSearchCondition, 5598 open: open 5599 } 5600}()) 5601 5602var MEMBER_DATA = (function () { 5603 let $totalCount 5604 let $SITE_CODE 5605 let $UNIT_CODE 5606 let $KEYWORD 5607 let $MEMBER_GROUP 5608 let $PERMISSIONS 5609 let $BASEURL 5610 let $PAGE 5611 let $JOIN_ORDER = 'desc' 5612 let $IS_JOIN_ORDER_FIXED_DESC = false 5613 let $IS_MEMBER_TAG_ENABLED = false 5614 let $LOADING = false 5615 let $USE_PUSH_STATE = false 5616 let $groups = [] 5617 let $memberListRender 5618 const init = function (site_code, unit_code, keyword, member_group, permissions, base_url, current_page, join_order, isJoinOrderFixedDesc, isMemberTagEnabled) { 5619 $SITE_CODE = site_code 5620 $UNIT_CODE = unit_code 5621 $KEYWORD = keyword 5622 $MEMBER_GROUP = member_group 5623 $PERMISSIONS = permissions 5624 $BASEURL = base_url 5625 $PAGE = current_page 5626 $IS_JOIN_ORDER_FIXED_DESC = !!isJoinOrderFixedDesc 5627 $IS_MEMBER_TAG_ENABLED = !!isMemberTagEnabled 5628 $JOIN_ORDER = $IS_JOIN_ORDER_FIXED_DESC ? 'desc' : (join_order || 'desc') 5629 renderMemberTotalCount() 5630 renderGroup() 5631 5632 // `#` ê²ìì¼ë¡ ì§ì í ê²½ì°ìë§ ì ì를 먼ì íë³´í´ ì²« ëª©ë¡ ìì²ë¶í° íê·¸ì ì¼ë° ê²ìì´ë¥¼ ì íí ë¶ë¦¬í©ëë¤. 5633 // ì¼ë° 목ë¡ì ì¦ì ì¡°ííê³ , ì ì ì¡°íê° ì¤í¨í `#` ì ë ¥ì 기존 íì ê²ìì¼ë¡ ìì íê² ì´ì´ê°ëë¤. 5634 if ($IS_MEMBER_TAG_ENABLED && typeof MEMBER_TAG_MANAGE !== 'undefined' && $.trim(String(keyword || '')).charAt(0) === '#') {
5635 MEMBER_TAG_MANAGE.loadDefinitions().always(function () { 5636 renderList(keyword, member_group, permissions, base_url, current_page) 5637 }) 5638 } else { 5639 renderList(keyword, member_group, permissions, base_url, current_page) 5640 } 5641 } 5642 5643 /** 5644 * @param site_code 5645 * @param unit_code 5646 * @param keyword 5647 * @param member_group 5648 */ 5649 var renderList = function (keyword, member_group, permissions, base_url, current_page) { 5650 member_group = member_group || '' // null/undefined를 ë¹ ë¬¸ìì´ë¡ ì ê·í 5651 keyword = String(keyword || '') 5652 $KEYWORD = keyword 5653 $MEMBER_GROUP = member_group 5654 $BASEURL = base_url 5655 $PAGE = current_page 5656 5657 var permissions = JSON.parse($PERMISSIONS) 5658 $LOADING = true 5659 5660 // íë©´ìë ì¬ì©ìê° ì ë ¥í ì본 문ìì´ì ì ì§íê³ ìë²ìë íê·¸ ì½ëì ëë¨¸ì§ ê²ìì´ë¥¼ ë¶ë¦¬í´ ì ë¬í©ëë¤. 5661 // original_keywordë íì´ì§ë¤ì´ì URL ë³µììë§ ì¬ì©íë©°, ì¤ì DB ê²ììë memberSearchCondition.keywordë§ ì¬ì©í©ëë¤. 5662 // ì¼ì¹íë ì¬ì´í¸ íê·¸ê° ìì¼ë©´ memberTagCodeë ë¹ì°ê³ ì본 문ìì´ ì 체를 기존 keywordë¡ ë°íí©ëë¤. 5663 let memberSearchCondition = { 5664 keyword: keyword, 5665 memberTagCode: '' 5666 } 5667 if ($IS_MEMBER_TAG_ENABLED && typeof MEMBER_TAG_MANAGE !== 'undefined') { 5668 memberSearchCondition = MEMBER_TAG_MANAGE.getMemberSearchCondition(keyword) 5669 } 5670 5671 let isEdit = false 5672 let _href = 'javascript:;' 5673 let _onClick = 'alert(LOCALIZE_ADMIN.ì¤ëª _ê¶íì´ììµëë¤())' 5674 if (permissions.admin_member || permissions.manager_setting) { 5675 isEdit = true 5676 _onClick = '' 5677 } 5678 5679 const _key = 'MEMBER_LIST_' + $SITE_CODE 5680 TOKEN.makeToken(5, _key, function (token, tokenKey) { 5681 $memberListRender = $.ajax({ 5682 url: '/admin/ajax/member/get_member.cm', 5683 type: 'GET', 5684 data: { 5685 keyword: memberSearchCondition.keyword, 5686 original_keyword: keyword, 5687 member_tag_code: memberSearchCondition.memberTagCode, 5688 page: current_page, 5689 member_group, 5690 join_order: $JOIN_ORDER, 5691 token, 5692 token_key: tokenKey 5693 }, 5694 dataType: 'json', 5695 async: true, 5696 cache: false, 5697 success: function (result) { 5698 $('#table-header').css('display', ''); 5699 $('#card-head').show() 5700 $('#order_list_loader_sub').hide() 5701 5702 if (result.message) { 5703 alert(result.message) 5704 return 5705 } 5706 5707 $('#total-member-count').text(result.member_count) 5708 5709 const visibleMemberCodes = [] 5710 result.members.forEach(function (member) { 5711 if ($IS_MEMBER_TAG_ENABLED) { 5712 visibleMemberCodes.push(member.code) 5713 } 5714 if (isEdit) { 5715 _href = base_url + '&mode=add&idx=' + member.idx 5716 } 5717 let html = '<ul class="content _tbody" id="member_item_' + member.code + '" data-nick="' + member.name + '" data-app="">' 5718 html += '<li class="check">' + 5719 '<div class="checkbox checkbox-styled no-margin">' + 5720 '<label>' + 5721 '<input type="checkbox" value="' + member.code + '"' + 5722 ' data-idx="' + member.idx + '"' + 5723 ' data-code="' + member.code + '"' + 5724 ' onclick="TABLE_LIST.checkItem(function(idxs){MEMBER_GROUP.checkMember(idxs);});" />' + 5725 '<span></span>' + 5726 '</label>' + 5727 '</div>' + 5728 '</li>' 5729 5730 // ======================================================= 5731 html += '<li class="nick">' 5732 5733 if (member.units) { 5734 if (member.units === 'notfound') { 5735 html += '<span style="margin-right:5px; width: 20px;\n' + 5736 ' height: 20px;\n' + 5737 ' display: inline-block;\n' + 5738 ' background: #fff;\n' + 5739 ' border: 1px solid #ccc;\n' + 5740 ' text-align: center;\n' + 5741 ' border-radius: 50%;"><i class="im-icon im-ico-global" style="display: inline-block;\n' + 5742 ' margin-top: 3px;\n' + 5743 ' font-size: 10px;"></i></span>' 5744 } else { 5745 html += '<img src="' + member.units + '" style="width:20px; margin-right: 5px;">' 5746 } 5747 } 5748 5749 html += '<a data-mixpanel="click_bo_member_list_detail" href="' + _href + '" onclick="' + _onClick + '">' 5750 html += member.name 5751 5752 if (member.is_member_inactive > 0) { 5753 html += '<span class="badge style-primary" style="margin-left: 5px;">' + getLocalizeString('ì¤ëª _í´ë©´ìì ', '', 'í´ë©´ ìì ') + '</span>' 5754 } 5755 5756 if (member.is_admin) { 5757 html += '<span class="badge">' + getLocalizeString('ì¤ëª _ìì ì', '', 'ìì ì') + '</span>' 5758 } else { 5759 if (result.join_types.join_type_allow_type_list[member.join_type_code] !== 'auto' && !member.is_confirm) { 5760 if (result.join_types.join_type_allow_type_list[member.join_type_code] === 'email') { 5761 html += '<span class="badge style-primary">' + getLocalizeString('ì¤ëª _ë©ì¼ë¯¸ì¸ì¦', '', 'ë©ì¼ 미ì¸ì¦') + '</span>' 5762 } else { 5763 html += '<span class="badge style-primary">' + getLocalizeString('ì¤ëª _ì¹ì¸ë기', '', 'ì¹ì¸ ë기') + '</span>' 5764 } 5765 } 5766 } 5767 html += '</a></li>' 5768 5769 // ======================================================= 5770 5771 html += '<li class="account"><a data-mixpanel="click_bo_member_list_detail" href="' + _href + '" onclick="' + _onClick + '">' + member.uid + '</a></li>' 5772 5773 // ======================================================= 5774 5775 if (member.join_type_code) { 5776 html += '<li class="account">' + result.join_types.join_type_name_list[member.join_type_code] + '</li>' 5777 } else { 5778 html += '<li class="account"></li>' 5779 } 5780 5781 // ======================================================= 5782 5783 let _group = '' 5784 html += '<li class="group"><div class="dropdown">' 5785 if (member.groups.has_group) { 5786 _group = member.groups.data.main_group_title 5787 if (member.groups.count > 1) { 5788 _group += '<span class="text-primary"> +' + (member.groups.count - 1) + '</span>' 5789 } 5790 } else { 5791 _group = getLocalizeString('ì¤ëª _그룹ìì', '', '그룹 ìì') 5792 } 5793 if (isEdit) { 5794 html += '<button id="dLabel" type="button" onclick="MEMBER_GROUP.setGroupCheck(' + member.idx + ')" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="btn-flat no-padding _drop_group_btn_' + member.idx + '">' + 5795 _group + 5796 '</button>' + 5797 '<ul class="dropdown-menu animation-dock check" role="menu" aria-labelledby="dLabel">' + 5798 '<div class="select_group _drop_group_list _drop_group_list_' + member.idx + '"' + 5799 'data-member="' + member.idx + '"' 5800 5801 if (member.groups.has_group && member.groups._group_arr) { 5802 html += 'data-groups="[' 5803 html += member.groups._group_arr.join(',') 5804 html += ']"' 5805 } else { 5806 html += 'data-groups=""' 5807 } 5808 5809 if (member.groups.has_group && member.groups._subscribe_group_arr) { 5810 html += 'data-subscribe_groups="' 5811 html += member.groups._subscribe_group_arr.join(',') 5812 html += '"' 5813 } else { 5814 html += 'data-subscribe_groups=""' 5815 } 5816 5817 html += 'data-nogroup="' 5818 if (member.groups.count === 0) { 5819 html += 'Y"' 5820 } else { 5821 html += 'N"' 5822 } 5823 html += '></div>' + 5824 '<div class="footer">' + 5825 '<li class="divider"></li>' + 5826 '<li>' + 5827 '<a href="javascript:;" onclick="MEMBER_GROUP.openGroupForm()">' + getLocalizeString('ì¤ëª _ì그룹', '', 'ì 그룹') + '</a>' + 5828 '</li>' + 5829 '</div>' + 5830 '</ul>' 5831 } else { 5832 html += '<a href="' + _href + '" onclick="' + _onClick + '">' + _group + '</a>' 5833 } 5834 html += '</div></li>' 5835 5836 if (result.shopping_groups.is_shopping_group) { 5837 html += '<li class="rating"><div class="dropdown">' 5838 if (isEdit) { 5839 html += '<button type="button" data-toggle="dropdown" aria-haspopup="true" onclick="MEMBER_GROUP.setShoppingGroupCheck(' + member.idx + ')" aria-expanded="false" class="btn-flat no-padding _drop_shopping_group_btn_' + member.idx + '">' + member.shopping_groups.title + '</button>' + 5840 '<ul class="dropdown-menu animation-dock check" role="menu">' + 5841 '<div class="select_group _drop_shopping_group_list _drop_shopping_group_list_' + member.idx + '"' + 5842 'data-groups="[' 5843 html += member.shopping_groups.idx 5844 html += ']" data-member="' + member.idx + '" data-nogroup="' 5845 if (member.groups.count === 0) { 5846 html += 'Y' 5847 } else { 5848 html += 'N' 5849 } 5850 html += '">' + 5851 '</div>' + 5852 '<div class="footer">' + 5853 '<li class="divider"></li>' + 5854 '<li><a href="javascript:;" onclick="MEMBER_GROUP.openGroupForm(\'\', \'' + member.shopping_groups.group_type + '\')">' + 5855 getLocalizeString('ì¤ëª _ì그룹', '', 'ì 그룹') + '</a></li>' + 5856 '</div>\n' + 5857 '</ul></li>' 5858 html += '</div></li>' 5859 } else { 5860 html += member.shopping_groups.title + '</div></li>' 5861 } 5862 } 5863 5864 // ======================================================= 5865 5866 html += '<li class="date_join">' + member.join_time_message + '</li>' 5867 5868 // ======================================================= 5869 5870 html += '<li class="date_mileage text-right">' + member.point.message + '</li>' 5871 5872 // ======================================================= 5873 5874 html += '<li class="count_post hidden-xs hidden-sm">' + member.post_count + '/ ' + 5875 member.comment_count + '/ ' + member.review_count + '/ ' + member.qna_count + '</li>' 5876 5877 // ======================================================= 5878 5879 html += '<li class="purchase text-right hidden-xs hidden-sm">' + member.purchase.message + '</li>' 5880 5881 // ======================================================= 5882 5883 if ($IS_MEMBER_TAG_ENABLED) {
5884 // íìíê·¸ ì ì ëª©ë¡ ìëµì íê·¸ê°ì ì§ì ì¬ì©íì§ ìê³ ë¹ combobox anchorë§ ë§ëëë¤. 5885 // ëª©ë¡ ì ì© classë¡ ì ì²´ íê·¸ ë ¸ì¶ê³¼ hover/focus ê¸°ë° ì ê±° ë²í¼ì ìì¸ íë©´ê³¼ ë¶ë¦¬í©ëë¤. 5886 html += '<li class="member_tag' + (isEdit ? ' member-tag-cell-editable' : '') + '">' 5887 if (isEdit) { 5888 html += '<div class="_member_tag_button member-tag-field member-tag-field-list" data-member-code="' + member.code + '" data-editable="Y" data-display-mode="list" role="combobox" aria-haspopup="listbox" aria-expanded="false" tabindex="0"></div>' 5889 } else { 5890 html += '<div class="_member_tag_button member-tag-field member-tag-field-list member-tag-field-readonly" data-member-code="' + member.code + '" data-editable="N" data-display-mode="list"></div>' 5891 } 5892 html += '</li>' 5893 } 5894 5895 // ======================================================= 5896 5897 html += '<li class="memo">' 5898 if (member.is_admin_memo) { 5899 html += '<a href="javascript:;" onclick="adminMember.openAdminMemoForm(' + '\'' + member.code + '\'' + ')" class="btn btn-flat">' 5900 } else { 5901 html += '<a href="javascript:;" onclick="adminMember.openAdminMemoForm(' + '\'' + member.code + '\'' + ')" class="btn btn-flat text-gray-bright">' 5902 } 5903 html += '<i class="icon-note"></i>' 5904 if (member.is_admin_memo) { 5905 html += '<div class="admin_memo">' + member.admin_memo + '</div>' 5906 } 5907 html += '</a></li>' 5908 5909 // ======================================================= 5910 5911 // ë쵸ì½ë ì°ëëì§ ìì ê²½ì°ìë§ ì± ê´ë ¨ ì»¬ë¼ íì 5912 if (typeof isNachocodeIntegration === 'undefined' || !isNachocodeIntegration) { 5913 if (member.is_use_android) { 5914 html += '<li class="app_android hidden-xs hidden-sm"><i class="zmdi zmdi-google-play"></i></li>' 5915 } else { 5916 html += '<li class="app_android hidden-xs hidden-sm"></li>' 5917 } 5918 5919 // ======================================================= 5920 5921 if (member.is_use_ios) { 5922 html += '<li class="app_ios hidden-xs hidden-sm"><i class="zmdi zmdi-apple"></i></li>' 5923 } else { 5924 html += '<li class="app_ios hidden-xs hidden-sm"></li>' 5925 } 5926 } 5927 5928 // ======================================================= 5929 5930 html += '<li class="action"><div class="dropdown">' + 5931 '<button id="dLabel" type="button" data-toggle="dropdown"' + 5932 'aria-haspopup="true" aria-expanded="false"' + 5933 'class="btn btn-flat">' + 5934 '<i class="zmdi zmdi-more"></i>' + 5935 '</button>' + 5936 '<ul class="dropdown-menu animation-dock right" role="menu" aria-labelledby="dLabel">' 5937 5938 if (member.is_admin !== 'Y' && result.join_types.join_type_allow_type_list[member.join_type_code] !== 'auto' && !member.is_confirm) { 5939 html += '<li>' + 5940 '<a href="javascript:;" onclick="adminMember.openUpdateMemberConfirm(' + '\'' + member.code + '\'' + ', ' + '\'' + 'list' + '\'' + ');">' + 5941 getLocalizeString('ë²í¼_ê°ì ì¹ì¸', '', 'ê°ì ì¹ì¸') + 5942 '</a>' + 5943 '</li>' + 5944 '<li role="separator" class="divider"></li>' 5945 } 5946 5947 const deleteMember = [{ 5948 member_code: member.code, 5949 delete_old_auth_log: !!member.delete_old_auth_log 5950 }] 5951 5952 html += '<li>' + 5953 '<a href="javascript:;" data-mixpanel="click_bo_member_list_delete_item" data-button-position="dropdown" onclick=\'adminMember.openDeleteMember("' + JSON.stringify(deleteMember).replace(/"/g, '\\"') + '")\'>' + 5954 getLocalizeString('ë²í¼_ìì ', '', 'ìì ') + 5955 '</a>' + 5956 '</li>' + 5957 '<li>' + 5958 '<a href="javascript:;" onclick="adminMember.openMemberPushForm([' + '\'' + member.code + '\'' + ']);">' + 5959 getLocalizeString('ë²í¼_ì림', '', 'ì림') + 5960 '</a>' + 5961 '</li>' + 5962 '<li>' + 5963 '<a href="javascript:;" onclick="adminMember.openMemberSmsForm([' + '\'' + member.code + '\'' + ']);">' + 5964 'SMS' + 5965 '</a>' + 5966 '</li>' + 5967 '<li>' + 5968 '<a href="javascript:;" onclick="adminMember.openManageMemberPoint(' + '\'' + member.code + '\'' + ');">' + 5969 getLocalizeString('ë²í¼_ì 립ê¸ì§ê¸ì°¨ê°', '', 'ì ë¦½ê¸ ì§ê¸/ì°¨ê°') + 5970 '</a>' + 5971 '</li>' + 5972 '</ul>' + 5973 '</li>' 5974 html += '</ul>' 5975 5976 $('#UI_TABLE').append(html) 5977 }) 5978 5979 // FS-3646 IB-ISMS-list : ê²ì ì¡°ê±´ ìì´ ì§ì í ê²½ì° ë¹ í ëì ê²ì ìë´ë¥¼ ë ¸ì¶í©ëë¤. 5980 // ëª©ë¡ ì´ê¸°íë `.content` 를 ë¹ì°ë ë°©ìì´ë¼ ìë´ ììë 매 ìëµë§ë¤ ì§ì ì ê±°í ë¤ ë¤ì ë¶ì ëë¤. 5981 $('#isms-search-guide').remove() 5982 if (result.search_required) { 5983 $('#UI_TABLE').append( 5984 '<div id="isms-search-guide" style="padding:40px 0;text-align:center;color:#999;">' + 5985 getLocalizeString('ì¤ëª _ê°ì¸ì ë³´ë³´í¸ë¥¼ìí´ê²ìíì¡°íê°ë¥', '', 'ê°ì¸ì ë³´ ë³´í¸ë¥¼ ìí´ ê²ì ì¡°ê±´ì ì ë ¥í í ì¡°íí ì ììµëë¤.') + 5986 '</div>' 5987 ) 5988 } 5989 5990 // íì¬ íì´ì§ì í DOM 구ì±ì´ ëë ë¤ íì ì½ë를 ë¬¶ì´ íê·¸ API를 í ë²ë§ ì§ì° í¸ì¶í©ëë¤. 5991 // ìëµì ë°ì MEMBER_TAG_MANAGEê° ê° ë¹ anchorì íìì íê·¸ ì 체를 chipì¼ë¡ ê°±ì í©ëë¤. 5992 if ($IS_MEMBER_TAG_ENABLED && typeof MEMBER_TAG_MANAGE !== 'undefined') { 5993 MEMBER_TAG_MANAGE.loadList(visibleMemberCodes) 5994 } 5995 5996 // ë§ì½ renderGroup ì´ ë¦ê² ë°íëì´ ìì¼ë©´ ì´ë¥¼ ì²ë¦¬í©ëë¤. 5997 if (!$groups) { 5998 var interval = setInterval(function () { 5999 if ($groups) { 6000 clearInterval(interval) 6001 } 6002 }, 10) 6003 } 6004 6005 $groups.forEach(function (group) { 6006 MEMBER_GROUP.addDropGroupList(group) 6007 }) 6008 6009 TABLE_LIST.init($('#UI_TABLE')) 6010 6011 // paginate 6012 $('#paginate').append(result.paginate) 6013 6014 $LOADING = false 6015 6016 const qs = MEMBER_DATA.getUrlParams() 6017 if (qs && qs.mc) { 6018 $('html, body').animate({ scrollTop: $('#member_item_' + qs.mc).offset().top - 55 }, 0) 6019 } 6020 }, 6021 error: function (req, textStatus, error) { 6022 if (req.statusText === 'abort') { 6023 return 6024 } 6025 6026 alert(getLocalizeString('ì¤ëª _ì ìíë¤ììëí´ì£¼ì¸ì', '', 'ì ì í ë¤ì ìëí´ì£¼ì¸ì.')) 6027 } 6028 }) 6029 }) 6030 } 6031 6032 var renderGroup = function () { 6033 $.ajax({ 6034 url: '/admin/ajax/member/get_group.cm', 6035 type: 'GET', 6036 dataType: 'json', 6037 async: true, 6038 cache: false, 6039 success: function (result) { 6040 if (result.groups) { 6041 $groups = result.groups 6042 $groups.forEach(function (group) { 6043 MEMBER_GROUP.addGroupList(group) 6044 }) 6045 } 6046 6047 renderGroupCount() 6048 }, 6049 error: function () { 6050 alert(getLocalizeString('ì¤ëª _ì ìíë¤ììëí´ì£¼ì¸ì', '', 'ì ì í ë¤ì ìëí´ì£¼ì¸ì.')) 6051 } 6052 }) 6053 } 6054 6055 var renderGroupCount = function (changed_member_groups) { 6056 if (!changed_member_groups) { 6057 changed_member_groups = [] 6058 } 6059 6060 $groupCountRender = $.ajax({ 6061 url: '/admin/ajax/member/get_group_count.cm', 6062 type: 'GET', 6063 data: { 6064 changed_member_groups 6065 }, 6066 dataType: 'json', 6067 async: true, 6068 cache: false, 6069 success: function (result) { 6070 if (result.nogroup_cnt) { 6071 $('#total-no-group-count').text(result.nogroup_cnt) 6072 } 6073 result.groups.forEach(function (group) { 6074 const $selector = $('#group_item_count_' + group.code) 6075 if ($selector.length > 0) { 6076 $selector.text(group.member_cnt) 6077 MEMBER_GROUP.setGroupMemberCount(group) 6078 } 6079 }) 6080 }, 6081 error: function (req, textStatus, error) { 6082 if (req.statusText === 'abort') { 6083 return 6084 } 6085 6086 alert(getLocalizeString('ì¤ëª _ì ìíë¤ììëí´ì£¼ì¸ì', '', 'ì ì í ë¤ì ìëí´ì£¼ì¸ì.')) 6087 } 6088 }) 6089 } 6090 6091 var renderMemberTotalCount = function () { 6092 $totalCountRender = $.ajax({ 6093 url: '/admin/ajax/member/get_total_count.cm', 6094 type: 'GET', 6095 dataType: 'json', 6096 async: true, 6097 cache: false, 6098 success: function (result) { 6099 var interval = setInterval(function () { 6100 const $selector = $('#total-left-member-count') 6101 if ($selector.length > 0) { 6102 $totalCount = result.count 6103 $selector.text(result.count) 6104 clearInterval(interval) 6105 } 6106 }, 1) 6107 }, 6108 error: function (req, textStatus, error) { 6109 if (req.statusText === 'abort') { 6110 return 6111 } 6112 6113 alert(getLocalizeString('ì¤ëª _ì ìíë¤ììëí´ì£¼ì¸ì', '', 'ì ì í ë¤ì ìëí´ì£¼ì¸ì.')) 6114 } 6115 }) 6116 } 6117 6118 /** 6119 * 6120 * @param state 6121 * @param title 6122 * @param url 6123 * @param mode 6124 * @param code 6125 * @param page 6126 */ 6127 function toggleJoinOrder () { 6128 if ($LOADING || $IS_JOIN_ORDER_FIXED_DESC) return 6129 6130 $JOIN_ORDER = $JOIN_ORDER === 'desc' ? 'asc' : 'desc' 6131 6132 // ì ë ¬ ìì´ì½ í ê¸ 6133 $('.date_join .md').toggleClass('md-expand-less md-expand-more') 6134 6135 // ëª©ë¡ ì´ê¸°í 6136 if ($('#UI_TABLE').find('.content').length > 0) { 6137 TABLE_LIST.cancelCheckItem() 6138 } 6139 $('#card-head').hide() 6140 $('#table-header').css('display', 'none') 6141 $('.content').html('') 6142 TABLE_LIST.init($('#UI_TABLE')) 6143 $('#paginate').html('') 6144 $('#order_list_loader_sub').show() 6145 6146 // íì´ì§ 1ë¡ ë¦¬ì í ë°ì´í° 리ë¡ë 6147 $PAGE = 1 6148 renderList($KEYWORD, $MEMBER_GROUP, $PERMISSIONS, $BASEURL, 1) 6149 6150 // URL ì ë°ì´í¸ (íì¬ URLì join_order íë¼ë¯¸í° ì¶ê°/ë³ê²½) 6151 if (typeof history.pushState !== 'undefined') { 6152 var url = new URL(window.location.href) 6153 url.searchParams.set('join_order', $JOIN_ORDER) 6154 history.pushState(null, null, url.toString()) 6155 } 6156 } 6157 6158 function changeUrl (state, title, url, mode, code, page) { 6159 if (typeof (history.pushState) === 'undefined') { 6160 location.href = url 6161 return 6162 } 6163 6164 // ë°ì´í°ë¥¼ ë¶ë¬ì¬ ë ë¤ë¥¸ ë©ë´ ì´ëì´ ë¶ê°ë¥íëë¡ -> xhr disconnect ëëë¡ ê°ì 6165 if ($LOADING) { 6166 $memberListRender.abort() 6167 } else { 6168 renderMemberTotalCount() 6169 renderGroupCount() 6170 } 6171 6172 $LOADING = true 6173 6174 if ($("input[name='keyword']").val()) { 6175 $KEYWORD = $("input[name='keyword']").val() 6176 6177 if (mode === 'group') { // 그룹 ì´ëì ê²½ì° clear keyword 6178 $("input[name='keyword']").val('') 6179 $KEYWORD = '' 6180 } 6181 } else { 6182 $KEYWORD = '' 6183 } 6184 6185 if (mode === 'group' || mode === 'search' || mode === 'paginate') { 6186 if ($('#UI_TABLE').find('.content').length > 0) { 6187 TABLE_LIST.cancelCheckItem() 6188 } 6189 $('#card-head').hide() 6190 $('#table-header').css('display', 'none'); 6191 6192 // 기존 ë°ì´í° í´ë¦¬ì´ 6193 $('.content').html('') 6194 TABLE_LIST.init($('#UI_TABLE')) 6195 $('#paginate').html('') 6196 6197 $('#order_list_loader_sub').show() 6198 6199 $PAGE = page 6200 } 6201 6202 if (mode === 'group' || mode === 'search') { 6203 $('#group_list').find('.active').removeClass('active') 6204 $('#group_list').find('.checked').removeClass('checked') 6205 6206 if (!code) { 6207 $('#group_item_total').addClass('active checked') 6208 } else { 6209 if (code === 'shopping') { 6210 $('#shopping_group_default').addClass('active checked') 6211 } else { 6212 $('#group_item_' + code).addClass('active checked') 6213 } 6214 } 6215 _member_group = code 6216
6217 renderList($KEYWORD, code, $PERMISSIONS, $BASEURL, $PAGE) 6218 } else if (mode === 'paginate') { 6219 renderList($KEYWORD, code, $PERMISSIONS, $BASEURL, $PAGE) 6220 } 6221 6222 $USE_PUSH_STATE = true 6223 history.pushState(state, title, url) 6224 MEMBER_GROUP.setCurrentMemberCode(code) 6225 } 6226 6227 return { 6228 init: function (site_code, unit_code, keyword, member_group, permissions, base_url, current_page, join_order, isJoinOrderFixedDesc, isMemberTagEnabled) { 6229 return init(site_code, unit_code, keyword, member_group, permissions, base_url, current_page, join_order, isJoinOrderFixedDesc, isMemberTagEnabled) 6230 }, 6231 toggleJoinOrder: function () { 6232 return toggleJoinOrder() 6233 }, 6234 changeUrl: function (state, title, url, mode, code, page) { 6235 return changeUrl(state, title, url, mode, code, page) 6236 }, 6237 getUsePushState: function () { 6238 return typeof (history.pushState) !== 'undefined' 6239 }, 6240 renderGroupCount: function (changed_member_groups) { 6241 // MEMBER_GROUP.resetGroupListHtml(); 6242 return renderGroupCount(changed_member_groups) 6243 }, 6244 getUrlParams: function () { 6245 const params = {} 6246 6247 window.location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi, 6248 function (str, key, value) { 6249 params[key] = value 6250 } 6251 ) 6252 6253 return params 6254 } 6255 } 6256}()) 6257 6258/** 080 ìì ì°¨ë¨ ìë¹ì¤ ê´ë ¨ ë¡ì§ */ 6259const OPTOUT_NUMBER = (function() { 6260 const http = ({ url, data }) => { 6261 return new Promise((resolve, reject) => { 6262 $.ajax({ 6263 url, 6264 data, 6265 async: true, 6266 cache: false, 6267 type: 'POST', 6268 dataType: 'json', 6269 success: function(res) { 6270 if (!res.success) { 6271 return reject(res.message); 6272 } 6273 6274 resolve(res.data); 6275 }, 6276 }); 6277 }); 6278 }; 6279 6280 const httpUpload = ({ url, file }) => { 6281 return new Promise((resolve, reject) => { 6282 const formData = new FormData(); 6283 6284 formData.append('file', file); 6285 6286 $.ajax({ 6287 url, 6288 data: formData, 6289 async: true, 6290 cache: false, 6291 type: 'POST', 6292 dataType: 'json', 6293 processData: false, 6294 contentType: false, 6295 success: function(res) { 6296 if (!res.success) { 6297 return reject(res.message); 6298 } 6299 6300 resolve(res.data); 6301 }, 6302 }); 6303 }); 6304 }; 6305 6306 const hideModal = () => { 6307 $.cocoaDialog.hide(); 6308 } 6309 6310 const modalAlert = ({ title, content, cancelButtonText, submitButtonText }) => { 6311 return http({ 6312 url: '/admin/ajax/optout_number/modal/modal_alert.cm', 6313 data: { 6314 title, 6315 content, 6316 cancel_button_text: cancelButtonText, 6317 submit_button_text: submitButtonText, 6318 }, 6319 }).then((data) => { 6320 $.cocoaDialog.open({ type: "optout_number_alert", custom_popup: data.html }); 6321 }).catch((message) => window.alert(message)); 6322 } 6323 6324 const modalPriceTableOptoutNumber = () => { 6325 return http({ 6326 url: '/admin/ajax/optout_number/modal/modal_price_table_optout_number.cm', 6327 data: {}, 6328 }).then((data) => { 6329 $.cocoaDialog.open({ type: "price_table_optout_number", custom_popup: data.html }); 6330 }).catch((message) => window.alert(message)); 6331 } 6332 6333 const modalPaymentOptoutNumber = () => { 6334 return http({ 6335 url: '/admin/ajax/optout_number/modal/modal_payment_optout_number.cm', 6336 data: {}, 6337 }).then((data) => { 6338 $.cocoaDialog.open({ type: "payment_optout_number", custom_popup: data.html, pc_width: 348, width: 348 }); 6339 }).catch((message) => window.alert(message)); 6340 } 6341 6342 const modalChangePaymentMethodOptoutNumber = () => { 6343 return http({ 6344 url: '/admin/ajax/optout_number/modal/modal_change_payment_method_optout_number.cm', 6345 data: {}, 6346 }).then((data) => { 6347 $.cocoaDialog.open({ type: "change_payment_method_optout_number", custom_popup: data.html, pc_width: 348, width: 348 }); 6348 }).catch((message) => window.alert(message)); 6349 } 6350 6351 /** 080 ìì ì°¨ë¨ ìë¹ì¤ í´ì§ */ 6352 const cancelOptoutNumberService = () => { 6353 return http({ 6354 url: '/admin/ajax/optout_number/cancel_optout_number_service.cm', 6355 data: {}, 6356 }); 6357 }; 6358 6359 /** 080 ìì ì°¨ë¨ ìë¹ì¤ í´ì§ ì·¨ì */ 6360 const revertCancelOptoutNumberService = () => { 6361 return http({ 6362 url: '/admin/ajax/optout_number/revert_cancel_optout_number_service.cm', 6363 data: {}, 6364 }); 6365 }; 6366 6367 /** ìì ê±°ë¶ ë´ì ì¼ê´ ì ë¡ë */ 6368 const bulkUploadOptoutNumber = ({ file }) => { 6369 return httpUpload({ 6370 url: '/admin/ajax/optout_number/bulk_upload_optout_target.cm', 6371 file, 6372 }); 6373 }; 6374 6375 /** ì 기 ê²°ì */ 6376 const paymentOptoutNumber = function() { 6377 const data = $("#form_payment_optout_number").serializeObject(); 6378 6379 return new Promise((resolve, reject) => { 6380 $.ajax({ 6381 async: true, 6382 cache: false, 6383 type: 'POST', 6384 dataType: 'json', 6385 url: '/payment/index.cm', 6386 data: data, 6387 success: function(res){ 6388 if(res.result !== 'success'){ 6389 return reject(res.msg); 6390 } 6391 6392 resolve(res); 6393 }, 6394 }); 6395 }); 6396 } 6397 6398 /** ê²°ì ìë¨ ë³ê²½ */ 6399 const changePaymentMethod = function() {
6400 const data = $("#form_change_payment_method").serializeObject(); 6401 6402 return http({ 6403 url: '/admin/ajax/optout_number/change_billing_method.cm', 6404 data: { 6405 billing_code: data.billing_code, 6406 }, 6407 }); 6408 } 6409 6410 return { 6411 hideModal, 6412 modalAlert, 6413 modalPriceTableOptoutNumber, 6414 modalPaymentOptoutNumber, 6415 modalChangePaymentMethodOptoutNumber, 6416 cancelOptoutNumberService, 6417 revertCancelOptoutNumberService, 6418 bulkUploadOptoutNumber, 6419 paymentOptoutNumber, 6420 changePaymentMethod, 6421 }; 6422})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.