ide-assi 0.493.0 → 0.495.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -121079,7 +121079,29 @@ class nxTab extends HTMLElement {
121079
121079
  }
121080
121080
 
121081
121081
  initialize = () => {
121082
+ this.shadowRoot.querySelectorAll(".tab-button").forEach((el, i) => {
121083
+ el.classList.remove("active");
121084
+ });
121085
+
121086
+ const activeButton = this.shadowRoot.querySelector('.tab-button:not([style*="display: none"])');
121087
+ console.log(activeButton);
121088
+ console.log(activeButton.getAttribute('data-target'), activeButton.data);
121089
+ //const tabPage = this.shadowRoot.querySelector(`#${activeButton.data}`);
121090
+
121091
+ if (activeButton) {
121092
+ activeButton.click(); // 자동으로 탭 전환
121093
+ }
121082
121094
 
121095
+ /**
121096
+ const activeTab = this.shadowRoot.querySelector('.tab-button.active');
121097
+
121098
+ // 현재 탭이 숨겨졌다면 첫 번째 visible 탭으로 이동
121099
+ if (activeTab && activeTab.style.display === 'none') {
121100
+ const nextVisibleTab = this.shadowRoot.querySelector('.tab-button:not([style*="display: none"])');
121101
+ if (nextVisibleTab) {
121102
+ nextVisibleTab.click(); // 자동으로 탭 전환
121103
+ }
121104
+ }*/
121083
121105
  }
121084
121106
 
121085
121107
  #renderTabs() {
@@ -121087,7 +121109,6 @@ class nxTab extends HTMLElement {
121087
121109
  const contents = this.shadowRoot.querySelector('.tab-pages');
121088
121110
  const tabItems = this.querySelectorAll('nx-tab-page');
121089
121111
 
121090
- /**
121091
121112
  tabItems.forEach((item, index) => {
121092
121113
  const tab = document.createElement('div');
121093
121114
  tab.classList.add('tab-button');
@@ -121100,20 +121121,6 @@ class nxTab extends HTMLElement {
121100
121121
  content.classList.add('tab-page');
121101
121122
  content.innerHTML = item.innerHTML;
121102
121123
  contents.appendChild(content);
121103
- }); */
121104
-
121105
- tabItems.forEach((item, index) => {
121106
- const tab = document.createElement('div');
121107
- tab.classList.add('tab-button');
121108
- tab.textContent = item.getAttribute('caption');
121109
- tab.setAttribute('data-target', `content${index}`);
121110
- tabs.appendChild(tab);
121111
-
121112
- const content = document.createElement('nx-tab-page');
121113
- content.id = `content${index}`;
121114
- content.classList.add('tab-page');
121115
- content.innerHTML = item.innerHTML;
121116
- contents.appendChild(content);
121117
121124
  });
121118
121125
 
121119
121126
  tabItems.forEach((item) => {
@@ -202617,6 +202624,351 @@ class IdeAssi extends HTMLElement
202617
202624
  //this.shadowRoot.querySelector('ide-diff-popup').remove();
202618
202625
 
202619
202626
  this.shadowRoot.appendChild(document.createElement('ide-diff-popup'));
202627
+
202628
+ //setTimeout(() => {
202629
+ let src1 = `
202630
+ import React, { useRef, useEffect } from "react" adfa;
202631
+ import { api, ai } from "ide-assi";
202632
+ import ninegrid from "ninegrid2";
202633
+
202634
+ const DocManager = () => {
202635
+ const tabRef = useRef(null);
202636
+ const gridRef = useRef(null);
202637
+
202638
+ const selectList = async (params) => {
202639
+ if (!gridRef.current) return;
202640
+ gridRef.current.classList.add("loading");
202641
+ api.post(\`/api/tmpl-a/doc-manager/selectList\`, params).then((res) => {
202642
+ gridRef.current.data.source = res.list;
202643
+ });
202644
+ };
202645
+
202646
+ const handleNaturalLanguageSearch = async () => {
202647
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
202648
+ const searchText = searchTextElement ? searchTextElement.value : "";
202649
+
202650
+ if (!gridRef.current) return;
202651
+ gridRef.current.classList.add("loading");
202652
+
202653
+ let params = {};
202654
+ if (searchText) {
202655
+ params = {
202656
+ _whereClause: await ai.generateWhereCause(
202657
+ "tmpla/DocManagerMapper.xml",
202658
+ "selectList",
202659
+ searchText,
202660
+ import.meta.env.VITE_GEMINI_API_KEY
202661
+ ),
202662
+ };
202663
+ }
202664
+ selectList(params);
202665
+ };
202666
+
202667
+ const handleClassicSearch = () => {
202668
+ if (!gridRef.current) return;
202669
+ gridRef.current.classList.add("loading");
202670
+
202671
+ const form2Element = ninegrid.querySelector(".form2", tabRef.current);
202672
+ const params = form2Element ? form2Element.getData() : {};
202673
+ selectList(params);
202674
+ };
202675
+
202676
+ useEffect(() => {
202677
+ selectList({});
202678
+
202679
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
202680
+ const searchButton = ninegrid.querySelector(".search", tabRef.current);
202681
+
202682
+ const handleKeyDown = (e) => {
202683
+ if (e.key === "Enter" && !e.isComposing) {
202684
+ handleNaturalLanguageSearch();
202685
+ }
202686
+ };
202687
+
202688
+ const handleClick = () => {
202689
+ handleClassicSearch();
202690
+ };
202691
+
202692
+ if (searchTextElement) {
202693
+ searchTextElement.addEventListener("keydown", handleKeyDown);
202694
+ }
202695
+ if (searchButton) {
202696
+ searchButton.addEventListener("click", handleClick);
202697
+ }
202698
+
202699
+ return () => {
202700
+ if (searchTextElement) {
202701
+ searchTextElement.removeEventListener("keydown", handleKeyDown);
202702
+ }
202703
+ if (searchButton) {
202704
+ searchButton.removeEventListener("click", handleClick);
202705
+ }
202706
+ };
202707
+ }, []);
202708
+
202709
+ return (
202710
+ <div className="wrapper">
202711
+ <nx-collapse target="nx-tab" className="search-collapse"></nx-collapse>
202712
+ <div className="list-wrapper">
202713
+ <nx-tab theme="theme-3" ref={tabRef}>
202714
+ <nx-tab-page caption="자연어 검색">
202715
+ <nx-form className="form1">
202716
+ <input
202717
+ type="text"
202718
+ id="searchText"
202719
+ name="searchText"
202720
+ placeholder="자연어 검색어를 입력하세요 (ex: 작성자가 홍길동인 데이타를 찾아줘)"
202721
+ />
202722
+ </nx-form>
202723
+ </nx-tab-page>
202724
+ <nx-tab-page caption="클래식 검색">
202725
+ <nx-form className="form2">
202726
+ <label>문서명: <input type="text" name="docNm" /></label>
202727
+ <label>매출액:
202728
+ <input type="number" name="minAmt" placeholder="최소" /> ~
202729
+ <input type="number" name="maxAmt" placeholder="최대" />
202730
+ </label>
202731
+ </nx-form>
202732
+ <button className="search">검색</button>
202733
+ </nx-tab-page>
202734
+ </nx-tab>
202735
+
202736
+ <div className="grid-wrapper">
202737
+ <nine-grid
202738
+ ref={gridRef}
202739
+ caption="문서관리"
202740
+ select-type="row"
202741
+ show-title-bar="true"
202742
+ show-menu-icon="true"
202743
+ show-status-bar="true"
202744
+ enable-fixed-col="true"
202745
+ row-resizable="false"
202746
+ col-movable="true"
202747
+ >
202748
+ <table>
202749
+ <colgroup>
202750
+ <col width="50" fixed="left" background-color="gray" />
202751
+ <col width="100" />
202752
+ <col width="100" />
202753
+ <col width="200" />
202754
+ <col width="120" />
202755
+ <col width="100" />
202756
+ <col width="150" />
202757
+ <col width="150" />
202758
+ </colgroup>
202759
+ <thead>
202760
+ <tr>
202761
+ <th>No.</th>
202762
+ <th>최종수정자</th>
202763
+ <th>문서ID</th>
202764
+ <th>문서명</th>
202765
+ <th>매출액</th>
202766
+ <th>최초등록자</th>
202767
+ <th>최초등록일</th>
202768
+ <th>최종수정일</th>
202769
+ </tr>
202770
+ </thead>
202771
+ <tbody>
202772
+ <tr>
202773
+ <th><ng-row-indicator /></th>
202774
+ <td data-bind="updateUser" text-align="center"></td>
202775
+ <td data-bind="docId" text-align="center"></td>
202776
+ <td data-bind="docNm" text-align="left"></td>
202777
+ <td
202778
+ data-bind="amt"
202779
+ data-expr="data.amt.toLocaleString()"
202780
+ text-align="right"
202781
+ show-icon="true"
202782
+ icon-type="sphere"
202783
+ icon-color="data.amt >= 2000 ? 'red' : 'gray'"
202784
+ ></td>
202785
+ <td data-bind="insertUser" text-align="center"></td>
202786
+ <td data-bind="insertDt" text-align="center"></td>
202787
+ <td data-bind="updateDt" text-align="center"></td>
202788
+ </tr>
202789
+ </tbody>
202790
+ </table>
202791
+ </nine-grid>
202792
+ </div>
202793
+ </div>
202794
+ </div>
202795
+ );
202796
+ };
202797
+
202798
+ export default DocManager;
202799
+ `;
202800
+
202801
+ let src2 = `
202802
+ import React, { useRef, useEffect } from "react";
202803
+ import { api, ai } from "ide-assi";
202804
+ import ninegrid from "ninegrid2";
202805
+
202806
+ const DocManager = () => {
202807
+ const tabRef = useRef(null);
202808
+ const gridRef = useRef(null);
202809
+
202810
+ const selectList = async (params) => {
202811
+ if (!gridRef.current) return;
202812
+ gridRef.current.classList.add("loading");
202813
+ api.post(\`/api/tmpl-a/doc-manager/selectList\`, params).then((res) => {
202814
+ gridRef.current.data.source = res.list;
202815
+ });
202816
+ };
202817
+
202818
+ const handleNaturalLanguageSearch = async () => {
202819
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
202820
+ const searchText = searchTextElement ? searchTextElement.value : "";
202821
+
202822
+ if (!gridRef.current) return;
202823
+ gridRef.current.classList.add("loading");
202824
+
202825
+ let params = {};
202826
+ if (searchText) {
202827
+ params = {
202828
+ _whereClause: await ai.generateWhereCause(
202829
+ "tmpla/DocManagerMapper.xml",
202830
+ "selectList",
202831
+ searchText,
202832
+ import.meta.env.VITE_GEMINI_API_KEY
202833
+ ),
202834
+ };
202835
+ }
202836
+ selectList(params);
202837
+ };
202838
+
202839
+ const handleClassicSearch = () => {
202840
+ if (!gridRef.current) return;
202841
+ gridRef.current.classList.add("loading");
202842
+
202843
+ const form2Element = ninegrid.querySelector(".form2", tabRef.current);
202844
+ const params = form2Element ? form2Element.getData() : {};
202845
+ selectList(params);
202846
+ };
202847
+
202848
+ useEffect(() => {
202849
+ selectList({});
202850
+
202851
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
202852
+ const searchButton = ninegrid.querySelector(".search", tabRef.current);
202853
+
202854
+ const handleKeyDown = (e) => {
202855
+ if (e.key === "Enter" && !e.isComposing) {
202856
+ handleNaturalLanguageSearch();
202857
+ }
202858
+ };
202859
+
202860
+ const handleClick = () => {
202861
+ handleClassicSearch();
202862
+ };
202863
+
202864
+ if (searchTextElement) {
202865
+ searchTextElement.addEventListener("keydown", handleKeyDown);
202866
+ }
202867
+ if (searchButton) {
202868
+ searchButton.addEventListener("click", handleClick);
202869
+ }
202870
+
202871
+ return () => {
202872
+ if (searchTextElement) {
202873
+ searchTextElement.removeEventListener("keydown", handleKeyDown);
202874
+ }
202875
+ if (searchButton) {
202876
+ searchButton.removeEventListener("click", handleClick);
202877
+ }
202878
+ };
202879
+ }, []);
202880
+
202881
+ return (
202882
+ <div className="wrapper">
202883
+ <nx-collapse target="nx-tab" className="search-collapse"></nx-collapse>
202884
+ <div className="list-wrapper">
202885
+ <nx-tab theme="theme-3" ref={tabRef}>
202886
+ <nx-tab-page caption="자연어 검색">
202887
+ <nx-form className="form1">
202888
+ <input
202889
+ type="text"
202890
+ id="searchText"
202891
+ name="searchText"
202892
+ placeholder="자연어 검색어를 입력하세요 (ex: 작성자가 홍길동인 데이타를 찾아줘)"
202893
+ />
202894
+ </nx-form>
202895
+ </nx-tab-page>
202896
+ <nx-tab-page caption="클래식 검색">
202897
+ <nx-form className="form2">
202898
+ <label>문서명: <input type="text" name="docNm" /></label>
202899
+ <label>매출액:
202900
+ <input type="number" name="minAmt" placeholder="최소" /> ~
202901
+ <input type="number" name="maxAmt" placeholder="최대" />
202902
+ </label>
202903
+ </nx-form>
202904
+ <button className="search">검색</button>
202905
+ </nx-tab-page>
202906
+ </nx-tab>
202907
+
202908
+ <div className="grid-wrapper">
202909
+ <nine-grid
202910
+ ref={gridRef}
202911
+ caption="매출 문서 관리"
202912
+ select-type="row"
202913
+ show-title-bar="true"
202914
+ show-menu-icon="true"
202915
+ show-status-bar="true"
202916
+ enable-fixed-col="true"
202917
+ row-resizable="false"
202918
+ col-movable="true"
202919
+ >
202920
+ <table>
202921
+ <colgroup>
202922
+ <col width="50" fixed="left" background-color="gray" />
202923
+ <col width="100" />
202924
+ <col width="120" />
202925
+ <col width="100" />
202926
+ <col width="200" />
202927
+ <col width="100" />
202928
+ <col width="150" />
202929
+ <col width="150" />
202930
+ </colgroup>
202931
+ <thead>
202932
+ <tr>
202933
+ <th>No.</th>
202934
+ <th>문서ID</th>
202935
+ <th>매출액</th>
202936
+ <th>최종수정자</th>
202937
+ <th>문서명</th>
202938
+ <th>최초등록자</th>
202939
+ <th>최초등록일</th>
202940
+ <th>최종수정일</th>
202941
+ </tr>
202942
+ </thead>
202943
+ <tbody>
202944
+ <tr>
202945
+ <th><ng-row-indicator /></th>
202946
+ <td data-bind="docId" text-align="center"></td>
202947
+ <td
202948
+ data-bind="amt"
202949
+ data-expr="data.amt.toLocaleString()"
202950
+ text-align="right"
202951
+ show-icon="true"
202952
+ icon-type="sphere"
202953
+ icon-color="data.amt >= 2000 ? 'red' : 'gray'"
202954
+ ></td>
202955
+ <td data-bind="updateUser" text-align="center"></td>
202956
+ <td data-bind="docNm" text-align="left"></td>
202957
+ <td data-bind="insertUser" text-align="center"></td>
202958
+ <td data-bind="insertDt" text-align="center"></td>
202959
+ <td data-bind="updateDt" text-align="center"></td>
202960
+ </tr>
202961
+ </tbody>
202962
+ </table>
202963
+ </nine-grid>
202964
+ </div>
202965
+ </div>
202966
+ </div>
202967
+ );
202968
+ };
202969
+
202970
+ export default DocManager;
202971
+ `;
202620
202972
  /**
202621
202973
  src1 = `
202622
202974
  <tr>
@@ -202642,63 +202994,14 @@ class IdeAssi extends HTMLElement
202642
202994
  <th>최종수정일</th>
202643
202995
  </tr>
202644
202996
  `; */
202645
-
202646
- //this.shadowRoot.querySelector("ide-diff-popup").popup(src1, src2);
202647
-
202648
- //return;
202649
-
202650
-
202651
-
202652
-
202653
-
202654
- const apply = {
202655
- mybatis: this.shadowRoot.querySelector("#mybatis").checked,
202656
- service: this.shadowRoot.querySelector("#service").checked,
202657
- controller: this.shadowRoot.querySelector("#controller").checked,
202658
- javascript: this.shadowRoot.querySelector("#javascript").checked,
202659
- };
202660
-
202661
- if (!apply.mybatis && !apply.service && !apply.controller && !apply.javascript) return;
202662
-
202663
- const userPrompt = e.target.value.trim();
202664
- if (!userPrompt) return;
202665
-
202666
- if (this.#ing) return;
202667
- this.#ing = true;
202668
-
202669
- /**
202670
- * 옵션저장
202671
- */
202672
- this.#saveLocalSettings(apply);
202673
-
202674
-
202675
-
202676
- /**
202677
- * setTimeout 없으면, 맥에서 한글 잔상이 남음
202678
- * setTimeout 내에서 e.target이 nx-ai-container가 된다.
202679
- */
202680
- setTimeout(() => {
202681
- this.shadowRoot.querySelector("textarea").value = "";
202682
- });
202683
-
202684
- const elAiChat = this.shadowRoot.querySelector("nx-ai-chat");
202685
-
202686
-
202687
- elAiChat.add("me", userPrompt);
202688
- elAiChat.add("ing", "...");
202689
-
202690
-
202691
- try {
202692
- const changedSource = await this.#ai.generateSourceClient(userPrompt, apply);
202693
- if (changedSource) {
202694
- this.shadowRoot.querySelector("ide-diff-popup").popup(changedSource);
202997
+ this.shadowRoot.querySelector("ide-diff-popup").popup({
202998
+ javascript: {
202999
+ asis: src1,
203000
+ tobe: src2
202695
203001
  }
202696
- } catch (error) {
202697
- console.error(error);
202698
- elAiChat.add("ai", String(error).replace("Error:", ""));
202699
- }
203002
+ });
202700
203003
 
202701
- this.#ing = false;
203004
+ return;
202702
203005
  }
202703
203006
 
202704
203007
  #toggleCollapseHandler = () => {
@@ -202917,6 +203220,7 @@ class IdeDiffPopup extends HTMLElement
202917
203220
  const tab = this.shadowRoot.querySelector('nx-tab');
202918
203221
 
202919
203222
  setTimeout(() => {
203223
+
202920
203224
  for (const item of changedSource) {
202921
203225
  const [type, diffData] = Object.entries(item)[0]; // 예: type = "mybatis", diffData = { asis, tobe }
202922
203226
  const diff = ninegrid.querySelector(`ide-diff.${type}`, this.shadowRoot);
@@ -202929,6 +203233,8 @@ class IdeDiffPopup extends HTMLElement
202929
203233
  );
202930
203234
  }
202931
203235
 
203236
+ tab.tabpage.showAll();
203237
+
202932
203238
  const types = changedSource.map(item => Object.keys(item)[0]);
202933
203239
  ninegrid.querySelectorAll("ide-diff", this.shadowRoot).forEach(el => {
202934
203240
  const type = el.className.trim();
@@ -202938,6 +203244,8 @@ class IdeDiffPopup extends HTMLElement
202938
203244
  });
202939
203245
  //this.shadowRoot.querySelector('nx-tab').tabpage.hide("mybatis");
202940
203246
 
203247
+ tab.initialize();
203248
+
202941
203249
  this.shadowRoot.querySelector('nx-dialog')?.showModal();
202942
203250
  }, 100);
202943
203251
  };
@@ -121075,7 +121075,29 @@ class nxTab extends HTMLElement {
121075
121075
  }
121076
121076
 
121077
121077
  initialize = () => {
121078
+ this.shadowRoot.querySelectorAll(".tab-button").forEach((el, i) => {
121079
+ el.classList.remove("active");
121080
+ });
121081
+
121082
+ const activeButton = this.shadowRoot.querySelector('.tab-button:not([style*="display: none"])');
121083
+ console.log(activeButton);
121084
+ console.log(activeButton.getAttribute('data-target'), activeButton.data);
121085
+ //const tabPage = this.shadowRoot.querySelector(`#${activeButton.data}`);
121086
+
121087
+ if (activeButton) {
121088
+ activeButton.click(); // 자동으로 탭 전환
121089
+ }
121078
121090
 
121091
+ /**
121092
+ const activeTab = this.shadowRoot.querySelector('.tab-button.active');
121093
+
121094
+ // 현재 탭이 숨겨졌다면 첫 번째 visible 탭으로 이동
121095
+ if (activeTab && activeTab.style.display === 'none') {
121096
+ const nextVisibleTab = this.shadowRoot.querySelector('.tab-button:not([style*="display: none"])');
121097
+ if (nextVisibleTab) {
121098
+ nextVisibleTab.click(); // 자동으로 탭 전환
121099
+ }
121100
+ }*/
121079
121101
  }
121080
121102
 
121081
121103
  #renderTabs() {
@@ -121083,7 +121105,6 @@ class nxTab extends HTMLElement {
121083
121105
  const contents = this.shadowRoot.querySelector('.tab-pages');
121084
121106
  const tabItems = this.querySelectorAll('nx-tab-page');
121085
121107
 
121086
- /**
121087
121108
  tabItems.forEach((item, index) => {
121088
121109
  const tab = document.createElement('div');
121089
121110
  tab.classList.add('tab-button');
@@ -121096,20 +121117,6 @@ class nxTab extends HTMLElement {
121096
121117
  content.classList.add('tab-page');
121097
121118
  content.innerHTML = item.innerHTML;
121098
121119
  contents.appendChild(content);
121099
- }); */
121100
-
121101
- tabItems.forEach((item, index) => {
121102
- const tab = document.createElement('div');
121103
- tab.classList.add('tab-button');
121104
- tab.textContent = item.getAttribute('caption');
121105
- tab.setAttribute('data-target', `content${index}`);
121106
- tabs.appendChild(tab);
121107
-
121108
- const content = document.createElement('nx-tab-page');
121109
- content.id = `content${index}`;
121110
- content.classList.add('tab-page');
121111
- content.innerHTML = item.innerHTML;
121112
- contents.appendChild(content);
121113
121120
  });
121114
121121
 
121115
121122
  tabItems.forEach((item) => {
@@ -202613,6 +202620,351 @@ class IdeAssi extends HTMLElement
202613
202620
  //this.shadowRoot.querySelector('ide-diff-popup').remove();
202614
202621
 
202615
202622
  this.shadowRoot.appendChild(document.createElement('ide-diff-popup'));
202623
+
202624
+ //setTimeout(() => {
202625
+ let src1 = `
202626
+ import React, { useRef, useEffect } from "react" adfa;
202627
+ import { api, ai } from "ide-assi";
202628
+ import ninegrid from "ninegrid2";
202629
+
202630
+ const DocManager = () => {
202631
+ const tabRef = useRef(null);
202632
+ const gridRef = useRef(null);
202633
+
202634
+ const selectList = async (params) => {
202635
+ if (!gridRef.current) return;
202636
+ gridRef.current.classList.add("loading");
202637
+ api.post(\`/api/tmpl-a/doc-manager/selectList\`, params).then((res) => {
202638
+ gridRef.current.data.source = res.list;
202639
+ });
202640
+ };
202641
+
202642
+ const handleNaturalLanguageSearch = async () => {
202643
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
202644
+ const searchText = searchTextElement ? searchTextElement.value : "";
202645
+
202646
+ if (!gridRef.current) return;
202647
+ gridRef.current.classList.add("loading");
202648
+
202649
+ let params = {};
202650
+ if (searchText) {
202651
+ params = {
202652
+ _whereClause: await ai.generateWhereCause(
202653
+ "tmpla/DocManagerMapper.xml",
202654
+ "selectList",
202655
+ searchText,
202656
+ import.meta.env.VITE_GEMINI_API_KEY
202657
+ ),
202658
+ };
202659
+ }
202660
+ selectList(params);
202661
+ };
202662
+
202663
+ const handleClassicSearch = () => {
202664
+ if (!gridRef.current) return;
202665
+ gridRef.current.classList.add("loading");
202666
+
202667
+ const form2Element = ninegrid.querySelector(".form2", tabRef.current);
202668
+ const params = form2Element ? form2Element.getData() : {};
202669
+ selectList(params);
202670
+ };
202671
+
202672
+ useEffect(() => {
202673
+ selectList({});
202674
+
202675
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
202676
+ const searchButton = ninegrid.querySelector(".search", tabRef.current);
202677
+
202678
+ const handleKeyDown = (e) => {
202679
+ if (e.key === "Enter" && !e.isComposing) {
202680
+ handleNaturalLanguageSearch();
202681
+ }
202682
+ };
202683
+
202684
+ const handleClick = () => {
202685
+ handleClassicSearch();
202686
+ };
202687
+
202688
+ if (searchTextElement) {
202689
+ searchTextElement.addEventListener("keydown", handleKeyDown);
202690
+ }
202691
+ if (searchButton) {
202692
+ searchButton.addEventListener("click", handleClick);
202693
+ }
202694
+
202695
+ return () => {
202696
+ if (searchTextElement) {
202697
+ searchTextElement.removeEventListener("keydown", handleKeyDown);
202698
+ }
202699
+ if (searchButton) {
202700
+ searchButton.removeEventListener("click", handleClick);
202701
+ }
202702
+ };
202703
+ }, []);
202704
+
202705
+ return (
202706
+ <div className="wrapper">
202707
+ <nx-collapse target="nx-tab" className="search-collapse"></nx-collapse>
202708
+ <div className="list-wrapper">
202709
+ <nx-tab theme="theme-3" ref={tabRef}>
202710
+ <nx-tab-page caption="자연어 검색">
202711
+ <nx-form className="form1">
202712
+ <input
202713
+ type="text"
202714
+ id="searchText"
202715
+ name="searchText"
202716
+ placeholder="자연어 검색어를 입력하세요 (ex: 작성자가 홍길동인 데이타를 찾아줘)"
202717
+ />
202718
+ </nx-form>
202719
+ </nx-tab-page>
202720
+ <nx-tab-page caption="클래식 검색">
202721
+ <nx-form className="form2">
202722
+ <label>문서명: <input type="text" name="docNm" /></label>
202723
+ <label>매출액:
202724
+ <input type="number" name="minAmt" placeholder="최소" /> ~
202725
+ <input type="number" name="maxAmt" placeholder="최대" />
202726
+ </label>
202727
+ </nx-form>
202728
+ <button className="search">검색</button>
202729
+ </nx-tab-page>
202730
+ </nx-tab>
202731
+
202732
+ <div className="grid-wrapper">
202733
+ <nine-grid
202734
+ ref={gridRef}
202735
+ caption="문서관리"
202736
+ select-type="row"
202737
+ show-title-bar="true"
202738
+ show-menu-icon="true"
202739
+ show-status-bar="true"
202740
+ enable-fixed-col="true"
202741
+ row-resizable="false"
202742
+ col-movable="true"
202743
+ >
202744
+ <table>
202745
+ <colgroup>
202746
+ <col width="50" fixed="left" background-color="gray" />
202747
+ <col width="100" />
202748
+ <col width="100" />
202749
+ <col width="200" />
202750
+ <col width="120" />
202751
+ <col width="100" />
202752
+ <col width="150" />
202753
+ <col width="150" />
202754
+ </colgroup>
202755
+ <thead>
202756
+ <tr>
202757
+ <th>No.</th>
202758
+ <th>최종수정자</th>
202759
+ <th>문서ID</th>
202760
+ <th>문서명</th>
202761
+ <th>매출액</th>
202762
+ <th>최초등록자</th>
202763
+ <th>최초등록일</th>
202764
+ <th>최종수정일</th>
202765
+ </tr>
202766
+ </thead>
202767
+ <tbody>
202768
+ <tr>
202769
+ <th><ng-row-indicator /></th>
202770
+ <td data-bind="updateUser" text-align="center"></td>
202771
+ <td data-bind="docId" text-align="center"></td>
202772
+ <td data-bind="docNm" text-align="left"></td>
202773
+ <td
202774
+ data-bind="amt"
202775
+ data-expr="data.amt.toLocaleString()"
202776
+ text-align="right"
202777
+ show-icon="true"
202778
+ icon-type="sphere"
202779
+ icon-color="data.amt >= 2000 ? 'red' : 'gray'"
202780
+ ></td>
202781
+ <td data-bind="insertUser" text-align="center"></td>
202782
+ <td data-bind="insertDt" text-align="center"></td>
202783
+ <td data-bind="updateDt" text-align="center"></td>
202784
+ </tr>
202785
+ </tbody>
202786
+ </table>
202787
+ </nine-grid>
202788
+ </div>
202789
+ </div>
202790
+ </div>
202791
+ );
202792
+ };
202793
+
202794
+ export default DocManager;
202795
+ `;
202796
+
202797
+ let src2 = `
202798
+ import React, { useRef, useEffect } from "react";
202799
+ import { api, ai } from "ide-assi";
202800
+ import ninegrid from "ninegrid2";
202801
+
202802
+ const DocManager = () => {
202803
+ const tabRef = useRef(null);
202804
+ const gridRef = useRef(null);
202805
+
202806
+ const selectList = async (params) => {
202807
+ if (!gridRef.current) return;
202808
+ gridRef.current.classList.add("loading");
202809
+ api.post(\`/api/tmpl-a/doc-manager/selectList\`, params).then((res) => {
202810
+ gridRef.current.data.source = res.list;
202811
+ });
202812
+ };
202813
+
202814
+ const handleNaturalLanguageSearch = async () => {
202815
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
202816
+ const searchText = searchTextElement ? searchTextElement.value : "";
202817
+
202818
+ if (!gridRef.current) return;
202819
+ gridRef.current.classList.add("loading");
202820
+
202821
+ let params = {};
202822
+ if (searchText) {
202823
+ params = {
202824
+ _whereClause: await ai.generateWhereCause(
202825
+ "tmpla/DocManagerMapper.xml",
202826
+ "selectList",
202827
+ searchText,
202828
+ import.meta.env.VITE_GEMINI_API_KEY
202829
+ ),
202830
+ };
202831
+ }
202832
+ selectList(params);
202833
+ };
202834
+
202835
+ const handleClassicSearch = () => {
202836
+ if (!gridRef.current) return;
202837
+ gridRef.current.classList.add("loading");
202838
+
202839
+ const form2Element = ninegrid.querySelector(".form2", tabRef.current);
202840
+ const params = form2Element ? form2Element.getData() : {};
202841
+ selectList(params);
202842
+ };
202843
+
202844
+ useEffect(() => {
202845
+ selectList({});
202846
+
202847
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
202848
+ const searchButton = ninegrid.querySelector(".search", tabRef.current);
202849
+
202850
+ const handleKeyDown = (e) => {
202851
+ if (e.key === "Enter" && !e.isComposing) {
202852
+ handleNaturalLanguageSearch();
202853
+ }
202854
+ };
202855
+
202856
+ const handleClick = () => {
202857
+ handleClassicSearch();
202858
+ };
202859
+
202860
+ if (searchTextElement) {
202861
+ searchTextElement.addEventListener("keydown", handleKeyDown);
202862
+ }
202863
+ if (searchButton) {
202864
+ searchButton.addEventListener("click", handleClick);
202865
+ }
202866
+
202867
+ return () => {
202868
+ if (searchTextElement) {
202869
+ searchTextElement.removeEventListener("keydown", handleKeyDown);
202870
+ }
202871
+ if (searchButton) {
202872
+ searchButton.removeEventListener("click", handleClick);
202873
+ }
202874
+ };
202875
+ }, []);
202876
+
202877
+ return (
202878
+ <div className="wrapper">
202879
+ <nx-collapse target="nx-tab" className="search-collapse"></nx-collapse>
202880
+ <div className="list-wrapper">
202881
+ <nx-tab theme="theme-3" ref={tabRef}>
202882
+ <nx-tab-page caption="자연어 검색">
202883
+ <nx-form className="form1">
202884
+ <input
202885
+ type="text"
202886
+ id="searchText"
202887
+ name="searchText"
202888
+ placeholder="자연어 검색어를 입력하세요 (ex: 작성자가 홍길동인 데이타를 찾아줘)"
202889
+ />
202890
+ </nx-form>
202891
+ </nx-tab-page>
202892
+ <nx-tab-page caption="클래식 검색">
202893
+ <nx-form className="form2">
202894
+ <label>문서명: <input type="text" name="docNm" /></label>
202895
+ <label>매출액:
202896
+ <input type="number" name="minAmt" placeholder="최소" /> ~
202897
+ <input type="number" name="maxAmt" placeholder="최대" />
202898
+ </label>
202899
+ </nx-form>
202900
+ <button className="search">검색</button>
202901
+ </nx-tab-page>
202902
+ </nx-tab>
202903
+
202904
+ <div className="grid-wrapper">
202905
+ <nine-grid
202906
+ ref={gridRef}
202907
+ caption="매출 문서 관리"
202908
+ select-type="row"
202909
+ show-title-bar="true"
202910
+ show-menu-icon="true"
202911
+ show-status-bar="true"
202912
+ enable-fixed-col="true"
202913
+ row-resizable="false"
202914
+ col-movable="true"
202915
+ >
202916
+ <table>
202917
+ <colgroup>
202918
+ <col width="50" fixed="left" background-color="gray" />
202919
+ <col width="100" />
202920
+ <col width="120" />
202921
+ <col width="100" />
202922
+ <col width="200" />
202923
+ <col width="100" />
202924
+ <col width="150" />
202925
+ <col width="150" />
202926
+ </colgroup>
202927
+ <thead>
202928
+ <tr>
202929
+ <th>No.</th>
202930
+ <th>문서ID</th>
202931
+ <th>매출액</th>
202932
+ <th>최종수정자</th>
202933
+ <th>문서명</th>
202934
+ <th>최초등록자</th>
202935
+ <th>최초등록일</th>
202936
+ <th>최종수정일</th>
202937
+ </tr>
202938
+ </thead>
202939
+ <tbody>
202940
+ <tr>
202941
+ <th><ng-row-indicator /></th>
202942
+ <td data-bind="docId" text-align="center"></td>
202943
+ <td
202944
+ data-bind="amt"
202945
+ data-expr="data.amt.toLocaleString()"
202946
+ text-align="right"
202947
+ show-icon="true"
202948
+ icon-type="sphere"
202949
+ icon-color="data.amt >= 2000 ? 'red' : 'gray'"
202950
+ ></td>
202951
+ <td data-bind="updateUser" text-align="center"></td>
202952
+ <td data-bind="docNm" text-align="left"></td>
202953
+ <td data-bind="insertUser" text-align="center"></td>
202954
+ <td data-bind="insertDt" text-align="center"></td>
202955
+ <td data-bind="updateDt" text-align="center"></td>
202956
+ </tr>
202957
+ </tbody>
202958
+ </table>
202959
+ </nine-grid>
202960
+ </div>
202961
+ </div>
202962
+ </div>
202963
+ );
202964
+ };
202965
+
202966
+ export default DocManager;
202967
+ `;
202616
202968
  /**
202617
202969
  src1 = `
202618
202970
  <tr>
@@ -202638,63 +202990,14 @@ class IdeAssi extends HTMLElement
202638
202990
  <th>최종수정일</th>
202639
202991
  </tr>
202640
202992
  `; */
202641
-
202642
- //this.shadowRoot.querySelector("ide-diff-popup").popup(src1, src2);
202643
-
202644
- //return;
202645
-
202646
-
202647
-
202648
-
202649
-
202650
- const apply = {
202651
- mybatis: this.shadowRoot.querySelector("#mybatis").checked,
202652
- service: this.shadowRoot.querySelector("#service").checked,
202653
- controller: this.shadowRoot.querySelector("#controller").checked,
202654
- javascript: this.shadowRoot.querySelector("#javascript").checked,
202655
- };
202656
-
202657
- if (!apply.mybatis && !apply.service && !apply.controller && !apply.javascript) return;
202658
-
202659
- const userPrompt = e.target.value.trim();
202660
- if (!userPrompt) return;
202661
-
202662
- if (this.#ing) return;
202663
- this.#ing = true;
202664
-
202665
- /**
202666
- * 옵션저장
202667
- */
202668
- this.#saveLocalSettings(apply);
202669
-
202670
-
202671
-
202672
- /**
202673
- * setTimeout 없으면, 맥에서 한글 잔상이 남음
202674
- * setTimeout 내에서 e.target이 nx-ai-container가 된다.
202675
- */
202676
- setTimeout(() => {
202677
- this.shadowRoot.querySelector("textarea").value = "";
202678
- });
202679
-
202680
- const elAiChat = this.shadowRoot.querySelector("nx-ai-chat");
202681
-
202682
-
202683
- elAiChat.add("me", userPrompt);
202684
- elAiChat.add("ing", "...");
202685
-
202686
-
202687
- try {
202688
- const changedSource = await this.#ai.generateSourceClient(userPrompt, apply);
202689
- if (changedSource) {
202690
- this.shadowRoot.querySelector("ide-diff-popup").popup(changedSource);
202993
+ this.shadowRoot.querySelector("ide-diff-popup").popup({
202994
+ javascript: {
202995
+ asis: src1,
202996
+ tobe: src2
202691
202997
  }
202692
- } catch (error) {
202693
- console.error(error);
202694
- elAiChat.add("ai", String(error).replace("Error:", ""));
202695
- }
202998
+ });
202696
202999
 
202697
- this.#ing = false;
203000
+ return;
202698
203001
  }
202699
203002
 
202700
203003
  #toggleCollapseHandler = () => {
@@ -202913,6 +203216,7 @@ class IdeDiffPopup extends HTMLElement
202913
203216
  const tab = this.shadowRoot.querySelector('nx-tab');
202914
203217
 
202915
203218
  setTimeout(() => {
203219
+
202916
203220
  for (const item of changedSource) {
202917
203221
  const [type, diffData] = Object.entries(item)[0]; // 예: type = "mybatis", diffData = { asis, tobe }
202918
203222
  const diff = ninegrid.querySelector(`ide-diff.${type}`, this.shadowRoot);
@@ -202925,6 +203229,8 @@ class IdeDiffPopup extends HTMLElement
202925
203229
  );
202926
203230
  }
202927
203231
 
203232
+ tab.tabpage.showAll();
203233
+
202928
203234
  const types = changedSource.map(item => Object.keys(item)[0]);
202929
203235
  ninegrid.querySelectorAll("ide-diff", this.shadowRoot).forEach(el => {
202930
203236
  const type = el.className.trim();
@@ -202934,6 +203240,8 @@ class IdeDiffPopup extends HTMLElement
202934
203240
  });
202935
203241
  //this.shadowRoot.querySelector('nx-tab').tabpage.hide("mybatis");
202936
203242
 
203243
+ tab.initialize();
203244
+
202937
203245
  this.shadowRoot.querySelector('nx-dialog')?.showModal();
202938
203246
  }, 100);
202939
203247
  };
@@ -491,10 +491,14 @@ export default DocManager;
491
491
  <th>최종수정일</th>
492
492
  </tr>
493
493
  `; */
494
+ this.shadowRoot.querySelector("ide-diff-popup").popup({
495
+ javascript: {
496
+ asis: src1,
497
+ tobe: src2
498
+ }
499
+ });
494
500
 
495
- //this.shadowRoot.querySelector("ide-diff-popup").popup(src1, src2);
496
-
497
- //return;
501
+ return;
498
502
 
499
503
 
500
504
 
@@ -41,6 +41,7 @@ class IdeDiffPopup extends HTMLElement
41
41
  const tab = this.shadowRoot.querySelector('nx-tab');
42
42
 
43
43
  setTimeout(() => {
44
+
44
45
  for (const item of changedSource) {
45
46
  const [type, diffData] = Object.entries(item)[0]; // 예: type = "mybatis", diffData = { asis, tobe }
46
47
  const diff = ninegrid.querySelector(`ide-diff.${type}`, this.shadowRoot);
@@ -53,6 +54,8 @@ class IdeDiffPopup extends HTMLElement
53
54
  );
54
55
  }
55
56
 
57
+ tab.tabpage.showAll();
58
+
56
59
  const types = changedSource.map(item => Object.keys(item)[0]);
57
60
  ninegrid.querySelectorAll("ide-diff", this.shadowRoot).forEach(el => {
58
61
  const type = el.className.trim();
@@ -62,6 +65,8 @@ class IdeDiffPopup extends HTMLElement
62
65
  });
63
66
  //this.shadowRoot.querySelector('nx-tab').tabpage.hide("mybatis");
64
67
 
68
+ tab.initialize();
69
+
65
70
  this.shadowRoot.querySelector('nx-dialog')?.showModal();
66
71
  }, 100);
67
72
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ide-assi",
3
3
  "type": "module",
4
- "version": "0.493.0",
4
+ "version": "0.495.0",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {
@@ -491,10 +491,14 @@ export default DocManager;
491
491
  <th>최종수정일</th>
492
492
  </tr>
493
493
  `; */
494
+ this.shadowRoot.querySelector("ide-diff-popup").popup({
495
+ javascript: {
496
+ asis: src1,
497
+ tobe: src2
498
+ }
499
+ });
494
500
 
495
- //this.shadowRoot.querySelector("ide-diff-popup").popup(src1, src2);
496
-
497
- //return;
501
+ return;
498
502
 
499
503
 
500
504
 
@@ -41,6 +41,7 @@ class IdeDiffPopup extends HTMLElement
41
41
  const tab = this.shadowRoot.querySelector('nx-tab');
42
42
 
43
43
  setTimeout(() => {
44
+
44
45
  for (const item of changedSource) {
45
46
  const [type, diffData] = Object.entries(item)[0]; // 예: type = "mybatis", diffData = { asis, tobe }
46
47
  const diff = ninegrid.querySelector(`ide-diff.${type}`, this.shadowRoot);
@@ -53,6 +54,8 @@ class IdeDiffPopup extends HTMLElement
53
54
  );
54
55
  }
55
56
 
57
+ tab.tabpage.showAll();
58
+
56
59
  const types = changedSource.map(item => Object.keys(item)[0]);
57
60
  ninegrid.querySelectorAll("ide-diff", this.shadowRoot).forEach(el => {
58
61
  const type = el.className.trim();
@@ -62,6 +65,8 @@ class IdeDiffPopup extends HTMLElement
62
65
  });
63
66
  //this.shadowRoot.querySelector('nx-tab').tabpage.hide("mybatis");
64
67
 
68
+ tab.initialize();
69
+
65
70
  this.shadowRoot.querySelector('nx-dialog')?.showModal();
66
71
  }, 100);
67
72
  };