menu.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. /**
  2. * admin/menu
  3. */
  4. var mcare_admin_menu = function( language_code ){
  5. //상속
  6. mcare_admin.call(this);
  7. var self = this;
  8. //언어코드
  9. var DEFAULT_LANGUAGE = language_code;
  10. //변수
  11. var $wrapper = $(".main-wrapper #wrapper"),
  12. $addItem = $("#add-item"),
  13. $saveItem = $("#save-item"),
  14. $reloadItem = $("#reload-item"),
  15. $removeItem = $("#remove-item"),
  16. $deselectItem = $("#deselect-item"),
  17. $treeView = $("#tree-view"),
  18. $i18nGrid = $("#i18ns"),
  19. $menuOrder = $("#menuOrder"),
  20. $menuType = $("#menuType"),
  21. $reqParams = $("#reqParams"),
  22. $menuDesc = $("#menuDesc"),
  23. $menuAuths = $("#menuAuths"),
  24. $authSelector = $("#authSelector"),
  25. $crudServiceBaseUrl = contextPath + "/admin/menu",
  26. $authCrudServiceBaseUrl = contextPath + "/admin/auth"; //속성 관련 요청을 위해 별도로 작성
  27. //트리
  28. this.treeView;
  29. this.i18nGrid;
  30. this.menuAuthsGrid;
  31. this.reqParamsGrid = null;
  32. /**
  33. * 객체 초기화
  34. */
  35. this.init = function(){
  36. initSplitter();
  37. initTree();
  38. initGrid();
  39. initNumBox();
  40. initDropDownList();
  41. //설명 글자수 이벤트 - core에 선언
  42. self.checkDescBytes($menuDesc);
  43. addEvent();
  44. initAuths();
  45. };
  46. /**
  47. * 이벤트 등록
  48. */
  49. var addEvent = function(){
  50. // 아이템 생성
  51. $addItem.on("click", function(e) {
  52. addItem(e);
  53. });
  54. // 아이템 저장
  55. $saveItem.on("click",function(e) {
  56. saveItem(e);
  57. });
  58. // 아이템 갱신 (to 모바일 서버)
  59. $reloadItem.on("click",function(e) {
  60. reloadItem(e);
  61. });
  62. // 아이템 삭제
  63. $removeItem.on("click",function(e) {
  64. removeItem(e);
  65. });
  66. // 아이템 선택 해제
  67. $deselectItem.on("click",function(e) {
  68. deselectItem(e);
  69. });
  70. };
  71. var initSplitter = function(){
  72. $wrapper.kendoSplitter({
  73. panes: [
  74. { collapsible: true, resizable: true, size: '240px' },
  75. { collapsible: false }
  76. ]
  77. });
  78. $wrapper.data("kendoSplitter").trigger("resize");
  79. };
  80. /**
  81. * 트리 아이템 신규 이벤트
  82. * @private
  83. */
  84. var addItem = function(e){
  85. var treeView = self.treeView;
  86. addedNodeCheck(e, treeView.dataSource.data().toJSON());
  87. if (addedNodeArr.length > 0) {
  88. alert("저장하지 않은 아이템 [ " + addedNodeArr[0].menuName + " ] (이)가 있습니다");
  89. addedNodeArr = [];
  90. return false;
  91. }
  92. var node = treeView.select(),
  93. item = treeView.dataItem(node);
  94. var nodeData = null,
  95. defData = {
  96. menuType: "CONT",
  97. menuName: "NewItem",
  98. menuOrder: 0,
  99. enabledYn: "Y",
  100. authYn: "Y",
  101. authViewYn: "N",
  102. aggYn: "N",
  103. accessUriAddr: "",
  104. imageUriAddr: "",
  105. menuDesc: "",
  106. childCount: 0,
  107. i18ns: [],
  108. addedNode: true,
  109. selected: false,
  110. menuParam : [],
  111. menuAuths : [],
  112. };
  113. if( node.length === 0 ) {
  114. node = null;
  115. nodeData = $.extend(true, {}, {
  116. menuType: 'MAIN'
  117. }, defData);
  118. } else {
  119. if( item.childCount === 0 ) {
  120. item.loaded(true);
  121. }
  122. nodeData = $.extend( true, {}, item.toJSON(), {
  123. menuId: null,
  124. parentMenuId: item.menuId
  125. }, defData);
  126. }
  127. treeView.append(nodeData, node);
  128. };
  129. // 다국어 코드 중복 체크
  130. var i18nArr = [];
  131. /**
  132. * 트리 아이템 저장 이벤트
  133. * @private
  134. */
  135. var saveItem = function(e){
  136. var treeView = self.treeView;
  137. var node = treeView.select(),
  138. item = treeView.dataItem(node);
  139. if( node.length === 0 ) {
  140. alert("선택한 아이템이 없습니다");
  141. return false;
  142. }
  143. if( item.menuId === null || item.menuId === "" ) {
  144. alert( "아이디가 누락되었습니다" );
  145. return false;
  146. }
  147. var pnode = item.parentNode();
  148. if( pnode ) {
  149. if( pnode.menuType === "CONT" && item.menuType !== "CONT" ) {
  150. alert( "콘텐츠 하위에는 콘텐츠만 등록할 수 있습니다" );
  151. return false;
  152. }
  153. if( item.menuType === "SIDE" ){
  154. alert( "메뉴타입을 사이드바로 지정할 수 없습니다." );
  155. return false;
  156. }
  157. }
  158. console.log(self.util.stringifyJson($menuAuths.data("kendoGrid").dataSource.data()));
  159. var param = $.extend(true, {}, item, {
  160. i18ns: $i18nGrid.data("kendoGrid").dataSource.data(),
  161. menuParam : $reqParams.data("kendoGrid").dataSource.data(),
  162. menuAuth : $menuAuths.data("kendoGrid").dataSource.data(),
  163. }, null);
  164. // 다국어 코드 중복 체크
  165. for( var i = 0; i < param.i18ns.length; i++ ) {
  166. i18nCd = param.i18ns[i].i18nCd;
  167. if( $.inArray( i18nCd, i18nArr ) > -1 ) {
  168. alert("다국어 코드는 중복될 수 없습니다");
  169. return false;
  170. } else {
  171. i18nArr.push( i18nCd );
  172. }
  173. }
  174. param.accessUriAddr = $("input#accessUriAddr.k-textbox").val();
  175. if( param.accessUriAddr.indexOf("javascript:") > -1 && param.aggYn === "Y" ){
  176. alert( "스크립트 메뉴는 통계여부를 '아니오'로 설정해주세요.")
  177. return false;
  178. }
  179. kendo.ui.progress( $wrapper, true );
  180. // $.ajax({
  181. // url : $crudServiceBaseUrl + "/save.json",
  182. // method : "POST",
  183. // data : self.util.stringifyJson(param),
  184. // dataType : "json",
  185. // contentType: "application/json; charset=UTF-8",
  186. // success : function(data){
  187. // if( data.msg !== undefined ) {
  188. // alert("수행 중 에러가 발생하였습니다");
  189. // console.log(data.msg);
  190. // return false;
  191. // }
  192. // alert("저장 되었습니다");
  193. // location.reload();
  194. // },
  195. // error : function(xhr,d,t){
  196. // console.log(xhr);
  197. // console.log(t);
  198. // },
  199. // complete : function(){
  200. // kendo.ui.progress( $wrapper, false );
  201. // }
  202. // });
  203. var opt = {
  204. url : $crudServiceBaseUrl + "/save.json",
  205. method : "POST",
  206. data : self.util.stringifyJson(param),
  207. dataType : "json",
  208. contentType: "application/json; charset=UTF-8",
  209. complete : function(){
  210. kendo.ui.progress( $wrapper, false );
  211. }
  212. };
  213. var success = function(data){
  214. alert("저장 되었습니다");
  215. location.reload(true);
  216. };
  217. var error = function(xhr,d,t){
  218. console.log(xhr);
  219. console.log(t);
  220. };
  221. self.ajaxAdmin( opt, success, error );
  222. };
  223. /**
  224. * 트리 아이템 reload 이벤트
  225. * @private
  226. */
  227. var reloadItem = function(e){
  228. kendo.ui.progress( $wrapper, true );
  229. // $.ajax({
  230. // url : $crudServiceBaseUrl + "/cacheReload.json",
  231. // type : "POST",
  232. // contentType: "application/json; charset=UTF-8",
  233. // success : function(data){
  234. // if( data === 1 ) {
  235. // alert("갱신 되었습니다");
  236. // } else {
  237. // alert( "수행 중 에러가 발생하였습니다" );
  238. // }
  239. // },
  240. // error : function(xhr,d,t){
  241. // console.log(xhr);
  242. // console.log(t);
  243. // },
  244. // complete : function(){
  245. // kendo.ui.progress( $wrapper, false );
  246. // }
  247. // });
  248. var opt = {
  249. url : $crudServiceBaseUrl + "/cacheReload.json",
  250. type : "POST",
  251. contentType: "application/json; charset=UTF-8",
  252. complete : function(){
  253. kendo.ui.progress( $wrapper, false );
  254. }
  255. };
  256. var success = function(data){
  257. if( data === 1 ) {
  258. alert("갱신 되었습니다");
  259. } else {
  260. alert( "수행 중 에러가 발생하였습니다" );
  261. }
  262. };
  263. var error = function(xhr,d,t){
  264. console.log(xhr);
  265. console.log(t);
  266. };
  267. self.ajaxAdmin( opt, success, error );
  268. };
  269. /**
  270. * 트리 아이템 삭제 이벤트
  271. * @private
  272. */
  273. var removeItem = function(e){
  274. var treeView = self.treeView;
  275. var node = treeView.select(),
  276. item = treeView.dataItem(node);
  277. if( node.length === 0 ) {
  278. alert( "선택한 아이템이 없습니다." );
  279. return false;
  280. }
  281. kendo.unbind( $wrapper );
  282. if( item.addedNode === true ) {
  283. treeView.remove(node);
  284. } else {
  285. if( item.childCount > 0 ) {
  286. alert( "하위 아이템이 존재하여 삭제할 수 없습니다." );
  287. return false;
  288. }
  289. if( !confirm( "삭제 하시겠습니까?" ) ) {
  290. return false;
  291. }
  292. kendo.ui.progress( $wrapper, true );
  293. // $.ajax({
  294. // url : $crudServiceBaseUrl + "/remove.json",
  295. // type : "POST",
  296. // data : { menuId : item.menuId },
  297. // dataType : "json",
  298. // success : function(data){
  299. // if( data.msg !== undefined ) {
  300. // alert( "수행 중 에러가 발생하였습니다" );
  301. // console.log( data.msg );
  302. // return false;
  303. // }
  304. // alert( "삭제 되었습니다" );
  305. // location.reload();
  306. // },
  307. // error : function(xhr,d,t){
  308. // console.log(xhr);
  309. // console.log(t);
  310. // },
  311. // complete : function(){
  312. // kendo.ui.progress( $wrapper, false );
  313. // }
  314. // });
  315. var opt = {
  316. url : $crudServiceBaseUrl + "/remove.json",
  317. type : "POST",
  318. data : { menuId : item.menuId },
  319. dataType : "json",
  320. complete : function(){
  321. kendo.ui.progress( $wrapper, false );
  322. }
  323. };
  324. var success = function(data){
  325. alert( "삭제 되었습니다" );
  326. location.reload(true);
  327. };
  328. var error = function(xhr,d,t){
  329. console.log(xhr);
  330. console.log(t);
  331. };
  332. self.ajaxAdmin( opt, success, error );
  333. }
  334. };
  335. /**
  336. * 트리 아이템 선택 해제 이벤트
  337. * @private
  338. */
  339. var deselectItem = function(e){
  340. self.treeView.select( null );
  341. };
  342. var initNumBox = function(){
  343. $menuOrder.kendoNumericTextBox({
  344. format: '0',
  345. min: 0,
  346. max: 1000,
  347. step: 1
  348. });
  349. };
  350. /**
  351. * 속성 데이터 가져오기
  352. */
  353. var authList;
  354. var initAuths = function() {
  355. $.ajax({
  356. url : $authCrudServiceBaseUrl + "/getList.json",
  357. method : "POST",
  358. dataType : "json",
  359. contentType : "application/json",
  360. success : function(data){
  361. authList = data;
  362. console.log(self.util.stringifyJson(data));
  363. //
  364. // //추가 업무 목록 Selecter 만들기
  365. for (var i = 0; i < data.length; i++) {
  366. var auth = data[i];
  367. $authSelector.append('<option value="'+ auth.authId +'">' + auth.authName + '</option>');
  368. }
  369. },
  370. error : function(xhr,d,t){
  371. },
  372. complete: function(){
  373. }
  374. });
  375. }
  376. var initDropDownList = function(){
  377. self.dropDownList( $menuType, {
  378. change:function(e){
  379. //네비게이션이면
  380. if( e.sender.value() === "NAVI" ){
  381. $("input#accessUriAddr.k-textbox").val("/navigation.page");
  382. } else {
  383. var text = $("input#accessUriAddr.k-textbox").val();
  384. text = (text!==""&& text !=="/navigation.page")?text:"";
  385. $("input#accessUriAddr.k-textbox").val(text);
  386. }
  387. }
  388. } );
  389. };
  390. /**
  391. * 데이터소스 설정
  392. */
  393. // tree 데이터소스
  394. var treeDataSource = new kendo.data.HierarchicalDataSource({
  395. transport: {
  396. read: {
  397. url: $crudServiceBaseUrl + "/getList.json",
  398. method : "post",
  399. dataType: "json"
  400. }
  401. },
  402. schema : {
  403. model : {
  404. id: "menuId",
  405. hasChildren: function(){
  406. return (this.get("childCount") > 0);
  407. }
  408. }
  409. }
  410. });
  411. //grid 데이터 소스
  412. var gridDataSource = {
  413. transport: {
  414. read: {
  415. url: $crudServiceBaseUrl + "/getI18nList.json",
  416. method: "get",
  417. dataType: "json"
  418. }
  419. },
  420. schema: {
  421. data : function(d){
  422. if( d.msg !== undefined ){
  423. return [];
  424. } else {
  425. return d;
  426. }
  427. },
  428. model: {
  429. id: "menuId",
  430. fields: {
  431. i18nCd: {type: "string", defaultValue : DEFAULT_LANGUAGE},
  432. cdText: {type: "string", editable : true}
  433. }
  434. }
  435. }
  436. };
  437. //grid 데이터 소스
  438. var gridMenuAuhtDataSource = new kendo.data.DataSource({
  439. transport: {
  440. read: {
  441. url: $crudServiceBaseUrl + "/getMenuAuthList.json",
  442. method: "get",
  443. dataType: "json"
  444. }
  445. },
  446. schema: {
  447. autoSync: true,
  448. data : function(d){
  449. if( d.msg !== undefined ){
  450. return [];
  451. } else {
  452. return d;
  453. }
  454. },
  455. model: {
  456. id: "authId",
  457. fields: {
  458. authId: { type: "string", nullable: false, validation: { required: true }},
  459. authName: {defaultValue: ""},
  460. }
  461. }
  462. }
  463. });
  464. /**
  465. * 트리 초기화
  466. */
  467. var initTree = function(){
  468. //kendo tree
  469. var option = {
  470. loadOnDemand: false,
  471. dataSource : treeDataSource,
  472. dataTextField : "menuName",
  473. template : treeTemplate,
  474. select : treeSelect,
  475. expand : treeExpand
  476. };
  477. self.treeView = self.tree( $treeView, option );
  478. /**
  479. * tree template
  480. * @private
  481. * @description 트리 구성
  482. */
  483. function treeTemplate(o){
  484. var span = $("<span></span>").addClass("k-sprite");
  485. if( o.item.menuType === "NAVI" ){
  486. span.addClass("folder");
  487. } else if( o.item.menuType === "CONT" ){
  488. span.addClass("html");
  489. } else {
  490. span.addClass("rootfolder");
  491. }
  492. return span[0].outerHTML + o.item.menuName;
  493. };
  494. /**
  495. * tree select
  496. * @private
  497. * @description 트리 선택
  498. */
  499. function treeSelect(o){
  500. kendo.unbind( $wrapper );
  501. var item = this.dataItem( o.node );
  502. var observer = new kendo.observable( item );
  503. observer.bind("change", function(o) {
  504. });
  505. self.i18nGrid.dataSource.read({ "menuId" : item.menuId });
  506. self.reqParamsGrid.dataSource.read({"menuId" : item.menuId} );
  507. self.menuAuthsGrid.dataSource.read({"menuId" : item.menuId} );
  508. kendo.bind( $wrapper, observer );
  509. if( observer.menuId !== undefined && observer.menuId !== null ){
  510. $("#menuId").prop("disabled",true);
  511. } else {
  512. $("#menuId").prop("disabled",false);
  513. }
  514. //설명 글자수제한 초기화
  515. $menuDesc.trigger("keyup");
  516. };
  517. /**
  518. * tree expand
  519. * @private
  520. * @description 트리 펼치기
  521. */
  522. function treeExpand(o){
  523. // var sourceData = this.dataItem(o.node);
  524. // if( !sourceData.get("enabled") ) {
  525. // return o.preventDefault();
  526. // }
  527. };
  528. };
  529. /**
  530. * 그리드 초기화
  531. */
  532. var initGrid = function(){
  533. var option = {
  534. dataSource : gridDataSource,
  535. toolbar : [ {name: "create", text: "추가"} ],
  536. editable : { createAt : "bottom" },
  537. columns : [
  538. {field: "i18nCd", title: "다국어 코드", width: 100, editor: i18nDropDownEditor, template: "#=i18nCd#"},
  539. {field: "cdText", title: "코드 텍스트", width: 200, attributes: {style: "text-align: center;"}},
  540. {command: "destroy", title: '', width: 92, attributes: {style: "text-align: center;"}}
  541. ]
  542. };
  543. var menuAuthOption = {
  544. dataSource : gridMenuAuhtDataSource,
  545. toolbar : [ {name: "create", text: "추가"} ],
  546. editable : { createAt : "bottom" },
  547. columns : [
  548. {field: "authId", title: "권한 이름", width: 100, editor: authsDropDownEditor, template: authValueConvert
  549. },
  550. /*{field: "authName", title: "권한 ID", width: 100, editor: authsDropDownEditor, template: "#=authName#"},*/
  551. // {field: "authId", title: "권한 ID", width: 200, attributes: {style: "text-align: center;"}},
  552. {command: "destroy", title: '', width: 92, attributes: {style: "text-align: center;"}}
  553. ]
  554. };
  555. var reqParamOption = {
  556. dataSource : {
  557. transport : {
  558. read : {
  559. url : $crudServiceBaseUrl + "/getParamList.json",
  560. method : "get",
  561. dataType : "json",
  562. contentType : "application/json"
  563. }
  564. },
  565. schema : {
  566. data : function(d){
  567. if( d.msg !== undefined ){
  568. return [];
  569. } else {
  570. return d;
  571. }
  572. },
  573. model : {
  574. id : "menuParamSeq",
  575. fields : {
  576. menuParamName : {type : "string", validation : { required : true}},
  577. dataType : {type : "string",defaultValue : "STRING"},
  578. paramValue : {type : "string"},
  579. paramDesc : {type : "string"}
  580. }
  581. }
  582. }
  583. },
  584. toolbar : [{name: "create", text: "추가"}],
  585. editable : { createAt : "bottom"},
  586. columns : [
  587. {title:"no",template:"#= getNum()#",width:30,attributes: {style: "text-align: center;"}}
  588. ,{field : "paramName", title : "이름", attributes: {style: "text-align: center;"}}
  589. ,{field : "dataType", title : "타입", editor : reqParamTypeDropDownEditor, template: "#=dataType#"}
  590. ,{field : "paramValue", title : "파라미터값", attributes: {style: "text-align: center;"}}
  591. ,{field : "paramDesc", title : "설명", attributes: {style: "text-align: center;"}}
  592. ,{command : "destroy", title : "", attributes: {style: "text-align: center;"}}
  593. ]
  594. };
  595. function i18nDropDownEditor(container, options) {
  596. $("[data-id='i18nDropDownEditor']:first").clone().attr("data-bind", "value:" + options.field).appendTo(container).kendoDropDownList({autoBind: false});
  597. }
  598. /**
  599. * 파라미터 LOV
  600. */
  601. function reqParamTypeDropDownEditor(container, options) {
  602. $("[data-id='reqParamTypeDropDownEditor']:first").clone().attr("data-bind", "value:" + options.field).appendTo(container).kendoDropDownList({autoBind: false});
  603. }
  604. function authsDropDownEditor(container, options) {
  605. /*$("[data-id='authsDropDownEditor']:first").clone().attr("data-bind", "value:authId").appendTo(container).kendoDropDownList({autoBind: false});*/
  606. /*$('<input />')
  607. .attr('data-bind', 'value:authId')
  608. .appendTo(container)
  609. .kendoDropDownList({
  610. autoBind: false,
  611. dataSource: authList,
  612. dataTextField: 'authName',
  613. dataValueField: 'authId'
  614. });*/
  615. $('<input required name="' + options.field + '"/>')
  616. .appendTo(container)
  617. .kendoDropDownList({
  618. autoBind: false,
  619. dataTextField: "authName",
  620. dataValueField: "authId",
  621. dataSource: authList,
  622. optionLabel:{
  623. authName: "선택",
  624. authId: ""
  625. }
  626. });
  627. }
  628. function authValueConvert(row){
  629. for(var i=0; i<authList.length; i++){
  630. if(authList[i].authId==row.authId){
  631. return authList[i].authName;
  632. }
  633. }
  634. };
  635. self.i18nGrid = self.grid( $i18nGrid , option );
  636. self.reqParamsGrid = self.grid ( $reqParams, reqParamOption );
  637. self.menuAuthsGrid = self.grid ($menuAuths, menuAuthOption);
  638. };
  639. // 저장하지 않은 아이템 배열
  640. var addedNodeArr = [];
  641. /**
  642. * 트리 저장하지 않은 아이템 확인
  643. */
  644. var addedNodeCheck = function(e, treeViewData) {
  645. if( treeViewData ) {
  646. for( var n = 0; n < treeViewData.length; n++ ) {
  647. var childData = treeViewData[n];
  648. if( childData.addedNode === true ){
  649. addedNodeArr.push( childData );
  650. return;
  651. } else {
  652. var child = childData.items;
  653. if( child ) {
  654. if( child.length > 0 ){
  655. addedNodeCheck( e, child );
  656. }
  657. }
  658. }
  659. }
  660. }
  661. };
  662. };
  663. var rowNum = 0;
  664. function resetRowNum(){
  665. rowNum = 0;
  666. }
  667. function getNum(){
  668. return ++rowNum;
  669. }