ide-assi 0.354.0 → 0.355.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.
@@ -201852,54 +201852,354 @@ class IdeAssi extends HTMLElement
201852
201852
 
201853
201853
  this.shadowRoot.appendChild(document.createElement('ide-diff-popup'));
201854
201854
 
201855
- //this.shadowRoot.querySelector("ide-diff-popup").popup(src1, src2);
201855
+ //setTimeout(() => {
201856
+ const src1 = `
201857
+ import React, { useRef, useEffect } from "react";
201858
+ import { api, ai } from "ide-assi";
201859
+ import ninegrid from "ninegrid2";
201860
+
201861
+ const DocManager = () => {
201862
+ const tabRef = useRef(null);
201863
+ const gridRef = useRef(null);
201864
+
201865
+ const selectList = async (params) => {
201866
+ if (!gridRef.current) return;
201867
+ gridRef.current.classList.add("loading");
201868
+ api.post(\`/api/tmpl-a/doc-manager/selectList\`, params).then((res) => {
201869
+ gridRef.current.data.source = res.list;
201870
+ });
201871
+ };
201856
201872
 
201857
- //return;
201873
+ const handleNaturalLanguageSearch = async () => {
201874
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
201875
+ const searchText = searchTextElement ? searchTextElement.value : "";
201876
+
201877
+ if (!gridRef.current) return;
201878
+ gridRef.current.classList.add("loading");
201879
+
201880
+ let params = {};
201881
+ if (searchText) {
201882
+ params = {
201883
+ _whereClause: await ai.generateWhereCause(
201884
+ "tmpla/DocManagerMapper.xml",
201885
+ "selectList",
201886
+ searchText,
201887
+ import.meta.env.VITE_GEMINI_API_KEY
201888
+ ),
201889
+ };
201890
+ }
201891
+ selectList(params);
201892
+ };
201858
201893
 
201859
- const apply = {
201860
- mybatis: this.shadowRoot.querySelector("#mybatis").checked,
201861
- service: this.shadowRoot.querySelector("#service").checked,
201862
- controller: this.shadowRoot.querySelector("#controller").checked,
201863
- javascript: this.shadowRoot.querySelector("#javascript").checked,
201864
- };
201894
+ const handleClassicSearch = () => {
201895
+ if (!gridRef.current) return;
201896
+ gridRef.current.classList.add("loading");
201865
201897
 
201866
- if (!apply.mybatis && !apply.service && !apply.controller && !apply.javascript) return;
201898
+ const form2Element = ninegrid.querySelector(".form2", tabRef.current);
201899
+ const params = form2Element ? form2Element.getData() : {};
201900
+ selectList(params);
201901
+ };
201867
201902
 
201868
- const userPrompt = e.target.value.trim();
201869
- if (!userPrompt) return;
201903
+ useEffect(() => {
201904
+ selectList({});
201870
201905
 
201871
- if (this.#ing) return;
201872
- this.#ing = true;
201906
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
201907
+ const searchButton = ninegrid.querySelector(".search", tabRef.current);
201873
201908
 
201874
- /**
201875
- * 옵션저장
201876
- */
201877
- this.#saveLocalSettings(apply);
201909
+ const handleKeyDown = (e) => {
201910
+ if (e.key === "Enter" && !e.isComposing) {
201911
+ handleNaturalLanguageSearch();
201912
+ }
201913
+ };
201878
201914
 
201915
+ const handleClick = () => {
201916
+ handleClassicSearch();
201917
+ };
201879
201918
 
201919
+ if (searchTextElement) {
201920
+ searchTextElement.addEventListener("keydown", handleKeyDown);
201921
+ }
201922
+ if (searchButton) {
201923
+ searchButton.addEventListener("click", handleClick);
201924
+ }
201880
201925
 
201881
- /**
201882
- * setTimeout 없으면, 맥에서 한글 잔상이 남음
201883
- * setTimeout 내에서 e.target이 nx-ai-container가 된다.
201884
- */
201885
- setTimeout(() => {
201886
- this.shadowRoot.querySelector("textarea").value = "";
201887
- });
201926
+ return () => {
201927
+ if (searchTextElement) {
201928
+ searchTextElement.removeEventListener("keydown", handleKeyDown);
201929
+ }
201930
+ if (searchButton) {
201931
+ searchButton.removeEventListener("click", handleClick);
201932
+ }
201933
+ };
201934
+ }, []);
201888
201935
 
201889
- const elAiChat = this.shadowRoot.querySelector("nx-ai-chat");
201936
+ return (
201937
+ <div className="wrapper">
201938
+ <nx-collapse target="nx-tab" className="search-collapse"></nx-collapse>
201939
+ <div className="list-wrapper">
201940
+ <nx-tab theme="theme-3" ref={tabRef}>
201941
+ <nx-tab-page caption="자연어 검색">
201942
+ <nx-form className="form1">
201943
+ <input
201944
+ type="text"
201945
+ id="searchText"
201946
+ name="searchText"
201947
+ placeholder="자연어 검색어를 입력하세요 (ex: 작성자가 홍길동인 데이타를 찾아줘)"
201948
+ />
201949
+ </nx-form>
201950
+ </nx-tab-page>
201951
+ <nx-tab-page caption="클래식 검색">
201952
+ <nx-form className="form2">
201953
+ <label>문서명: <input type="text" name="docNm" /></label>
201954
+ <label>매출액:
201955
+ <input type="number" name="minAmt" placeholder="최소" /> ~
201956
+ <input type="number" name="maxAmt" placeholder="최대" />
201957
+ </label>
201958
+ </nx-form>
201959
+ <button className="search">검색</button>
201960
+ </nx-tab-page>
201961
+ </nx-tab>
201962
+
201963
+ <div className="grid-wrapper">
201964
+ <nine-grid
201965
+ ref={gridRef}
201966
+ caption="문서관리"
201967
+ select-type="row"
201968
+ show-title-bar="true"
201969
+ show-menu-icon="true"
201970
+ show-status-bar="true"
201971
+ enable-fixed-col="true"
201972
+ row-resizable="false"
201973
+ col-movable="true"
201974
+ >
201975
+ <table>
201976
+ <colgroup>
201977
+ <col width="50" fixed="left" background-color="gray" />
201978
+ <col width="100" />
201979
+ <col width="100" />
201980
+ <col width="200" />
201981
+ <col width="120" />
201982
+ <col width="100" />
201983
+ <col width="150" />
201984
+ <col width="150" />
201985
+ </colgroup>
201986
+ <thead>
201987
+ <tr>
201988
+ <th>No.</th>
201989
+ <th>최종수정자</th>
201990
+ <th>문서ID</th>
201991
+ <th>문서명</th>
201992
+ <th>매출액</th>
201993
+ <th>최초등록자</th>
201994
+ <th>최초등록일</th>
201995
+ <th>최종수정일</th>
201996
+ </tr>
201997
+ </thead>
201998
+ <tbody>
201999
+ <tr>
202000
+ <th><ng-row-indicator /></th>
202001
+ <td data-bind="updateUser" text-align="center"></td>
202002
+ <td data-bind="docId" text-align="center"></td>
202003
+ <td data-bind="docNm" text-align="left"></td>
202004
+ <td
202005
+ data-bind="amt"
202006
+ data-expr="data.amt.toLocaleString()"
202007
+ text-align="right"
202008
+ show-icon="true"
202009
+ icon-type="sphere"
202010
+ icon-color="data.amt >= 2000 ? 'red' : 'gray'"
202011
+ ></td>
202012
+ <td data-bind="insertUser" text-align="center"></td>
202013
+ <td data-bind="insertDt" text-align="center"></td>
202014
+ <td data-bind="updateDt" text-align="center"></td>
202015
+ </tr>
202016
+ </tbody>
202017
+ </table>
202018
+ </nine-grid>
202019
+ </div>
202020
+ </div>
202021
+ </div>
202022
+ );
202023
+ };
201890
202024
 
201891
- elAiChat.add("me", userPrompt);
201892
- elAiChat.add("ing", "...");
202025
+ export default DocManager;
202026
+ `;
201893
202027
 
201894
- try {
201895
- const r = await this.#ai.generateSourceClient(userPrompt, apply);
201896
- elAiChat.add("ai", r);
201897
- } catch (error) {
201898
- console.error(error);
201899
- elAiChat.add("ai", String(error).replace("Error:", ""));
201900
- }
202028
+ const src2 = `
202029
+ import React, { useRef, useEffect } from "react";
202030
+ import { api, ai } from "ide-assi";
202031
+ import ninegrid from "ninegrid2";
201901
202032
 
201902
- this.#ing = false;
202033
+ const DocManager = () => {
202034
+ const tabRef = useRef(null);
202035
+ const gridRef = useRef(null);
202036
+
202037
+ const selectList = async (params) => {
202038
+ if (!gridRef.current) return;
202039
+ gridRef.current.classList.add("loading");
202040
+ api.post(\`/api/tmpl-a/doc-manager/selectList\`, params).then((res) => {
202041
+ gridRef.current.data.source = res.list;
202042
+ });
202043
+ };
202044
+
202045
+ const handleNaturalLanguageSearch = async () => {
202046
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
202047
+ const searchText = searchTextElement ? searchTextElement.value : "";
202048
+
202049
+ if (!gridRef.current) return;
202050
+ gridRef.current.classList.add("loading");
202051
+
202052
+ let params = {};
202053
+ if (searchText) {
202054
+ params = {
202055
+ _whereClause: await ai.generateWhereCause(
202056
+ "tmpla/DocManagerMapper.xml",
202057
+ "selectList",
202058
+ searchText,
202059
+ import.meta.env.VITE_GEMINI_API_KEY
202060
+ ),
202061
+ };
202062
+ }
202063
+ selectList(params);
202064
+ };
202065
+
202066
+ const handleClassicSearch = () => {
202067
+ if (!gridRef.current) return;
202068
+ gridRef.current.classList.add("loading");
202069
+
202070
+ const form2Element = ninegrid.querySelector(".form2", tabRef.current);
202071
+ const params = form2Element ? form2Element.getData() : {};
202072
+ selectList(params);
202073
+ };
202074
+
202075
+ useEffect(() => {
202076
+ selectList({});
202077
+
202078
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
202079
+ const searchButton = ninegrid.querySelector(".search", tabRef.current);
202080
+
202081
+ const handleKeyDown = (e) => {
202082
+ if (e.key === "Enter" && !e.isComposing) {
202083
+ handleNaturalLanguageSearch();
202084
+ }
202085
+ };
202086
+
202087
+ const handleClick = () => {
202088
+ handleClassicSearch();
202089
+ };
202090
+
202091
+ if (searchTextElement) {
202092
+ searchTextElement.addEventListener("keydown", handleKeyDown);
202093
+ }
202094
+ if (searchButton) {
202095
+ searchButton.addEventListener("click", handleClick);
202096
+ }
202097
+
202098
+ return () => {
202099
+ if (searchTextElement) {
202100
+ searchTextElement.removeEventListener("keydown", handleKeyDown);
202101
+ }
202102
+ if (searchButton) {
202103
+ searchButton.removeEventListener("click", handleClick);
202104
+ }
202105
+ };
202106
+ }, []);
202107
+
202108
+ return (
202109
+ <div className="wrapper">
202110
+ <nx-collapse target="nx-tab" className="search-collapse"></nx-collapse>
202111
+ <div className="list-wrapper">
202112
+ <nx-tab theme="theme-3" ref={tabRef}>
202113
+ <nx-tab-page caption="자연어 검색">
202114
+ <nx-form className="form1">
202115
+ <input
202116
+ type="text"
202117
+ id="searchText"
202118
+ name="searchText"
202119
+ placeholder="자연어 검색어를 입력하세요 (ex: 작성자가 홍길동인 데이타를 찾아줘)"
202120
+ />
202121
+ </nx-form>
202122
+ </nx-tab-page>
202123
+ <nx-tab-page caption="클래식 검색">
202124
+ <nx-form className="form2">
202125
+ <label>문서명: <input type="text" name="docNm" /></label>
202126
+ <label>매출액:
202127
+ <input type="number" name="minAmt" placeholder="최소" /> ~
202128
+ <input type="number" name="maxAmt" placeholder="최대" />
202129
+ </label>
202130
+ </nx-form>
202131
+ <button className="search">검색</button>
202132
+ </nx-tab-page>
202133
+ </nx-tab>
202134
+
202135
+ <div className="grid-wrapper">
202136
+ <nine-grid
202137
+ ref={gridRef}
202138
+ caption="매출 문서 관리"
202139
+ select-type="row"
202140
+ show-title-bar="true"
202141
+ show-menu-icon="true"
202142
+ show-status-bar="true"
202143
+ enable-fixed-col="true"
202144
+ row-resizable="false"
202145
+ col-movable="true"
202146
+ >
202147
+ <table>
202148
+ <colgroup>
202149
+ <col width="50" fixed="left" background-color="gray" />
202150
+ <col width="100" />
202151
+ <col width="120" />
202152
+ <col width="100" />
202153
+ <col width="200" />
202154
+ <col width="100" />
202155
+ <col width="150" />
202156
+ <col width="150" />
202157
+ </colgroup>
202158
+ <thead>
202159
+ <tr>
202160
+ <th>No.</th>
202161
+ <th>문서ID</th>
202162
+ <th>매출액</th>
202163
+ <th>최종수정자</th>
202164
+ <th>문서명</th>
202165
+ <th>최초등록자</th>
202166
+ <th>최초등록일</th>
202167
+ <th>최종수정일</th>
202168
+ </tr>
202169
+ </thead>
202170
+ <tbody>
202171
+ <tr>
202172
+ <th><ng-row-indicator /></th>
202173
+ <td data-bind="docId" text-align="center"></td>
202174
+ <td
202175
+ data-bind="amt"
202176
+ data-expr="data.amt.toLocaleString()"
202177
+ text-align="right"
202178
+ show-icon="true"
202179
+ icon-type="sphere"
202180
+ icon-color="data.amt >= 2000 ? 'red' : 'gray'"
202181
+ ></td>
202182
+ <td data-bind="updateUser" text-align="center"></td>
202183
+ <td data-bind="docNm" text-align="left"></td>
202184
+ <td data-bind="insertUser" text-align="center"></td>
202185
+ <td data-bind="insertDt" text-align="center"></td>
202186
+ <td data-bind="updateDt" text-align="center"></td>
202187
+ </tr>
202188
+ </tbody>
202189
+ </table>
202190
+ </nine-grid>
202191
+ </div>
202192
+ </div>
202193
+ </div>
202194
+ );
202195
+ };
202196
+
202197
+ export default DocManager;
202198
+ `;
202199
+
202200
+ this.shadowRoot.querySelector("ide-diff-popup").popup(src1, src2);
202201
+
202202
+ return;
201903
202203
  }
201904
202204
 
201905
202205
  #toggleCollapseHandler = () => {
@@ -201848,54 +201848,354 @@ class IdeAssi extends HTMLElement
201848
201848
 
201849
201849
  this.shadowRoot.appendChild(document.createElement('ide-diff-popup'));
201850
201850
 
201851
- //this.shadowRoot.querySelector("ide-diff-popup").popup(src1, src2);
201851
+ //setTimeout(() => {
201852
+ const src1 = `
201853
+ import React, { useRef, useEffect } from "react";
201854
+ import { api, ai } from "ide-assi";
201855
+ import ninegrid from "ninegrid2";
201856
+
201857
+ const DocManager = () => {
201858
+ const tabRef = useRef(null);
201859
+ const gridRef = useRef(null);
201860
+
201861
+ const selectList = async (params) => {
201862
+ if (!gridRef.current) return;
201863
+ gridRef.current.classList.add("loading");
201864
+ api.post(\`/api/tmpl-a/doc-manager/selectList\`, params).then((res) => {
201865
+ gridRef.current.data.source = res.list;
201866
+ });
201867
+ };
201852
201868
 
201853
- //return;
201869
+ const handleNaturalLanguageSearch = async () => {
201870
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
201871
+ const searchText = searchTextElement ? searchTextElement.value : "";
201872
+
201873
+ if (!gridRef.current) return;
201874
+ gridRef.current.classList.add("loading");
201875
+
201876
+ let params = {};
201877
+ if (searchText) {
201878
+ params = {
201879
+ _whereClause: await ai.generateWhereCause(
201880
+ "tmpla/DocManagerMapper.xml",
201881
+ "selectList",
201882
+ searchText,
201883
+ import.meta.env.VITE_GEMINI_API_KEY
201884
+ ),
201885
+ };
201886
+ }
201887
+ selectList(params);
201888
+ };
201854
201889
 
201855
- const apply = {
201856
- mybatis: this.shadowRoot.querySelector("#mybatis").checked,
201857
- service: this.shadowRoot.querySelector("#service").checked,
201858
- controller: this.shadowRoot.querySelector("#controller").checked,
201859
- javascript: this.shadowRoot.querySelector("#javascript").checked,
201860
- };
201890
+ const handleClassicSearch = () => {
201891
+ if (!gridRef.current) return;
201892
+ gridRef.current.classList.add("loading");
201861
201893
 
201862
- if (!apply.mybatis && !apply.service && !apply.controller && !apply.javascript) return;
201894
+ const form2Element = ninegrid.querySelector(".form2", tabRef.current);
201895
+ const params = form2Element ? form2Element.getData() : {};
201896
+ selectList(params);
201897
+ };
201863
201898
 
201864
- const userPrompt = e.target.value.trim();
201865
- if (!userPrompt) return;
201899
+ useEffect(() => {
201900
+ selectList({});
201866
201901
 
201867
- if (this.#ing) return;
201868
- this.#ing = true;
201902
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
201903
+ const searchButton = ninegrid.querySelector(".search", tabRef.current);
201869
201904
 
201870
- /**
201871
- * 옵션저장
201872
- */
201873
- this.#saveLocalSettings(apply);
201905
+ const handleKeyDown = (e) => {
201906
+ if (e.key === "Enter" && !e.isComposing) {
201907
+ handleNaturalLanguageSearch();
201908
+ }
201909
+ };
201874
201910
 
201911
+ const handleClick = () => {
201912
+ handleClassicSearch();
201913
+ };
201875
201914
 
201915
+ if (searchTextElement) {
201916
+ searchTextElement.addEventListener("keydown", handleKeyDown);
201917
+ }
201918
+ if (searchButton) {
201919
+ searchButton.addEventListener("click", handleClick);
201920
+ }
201876
201921
 
201877
- /**
201878
- * setTimeout 없으면, 맥에서 한글 잔상이 남음
201879
- * setTimeout 내에서 e.target이 nx-ai-container가 된다.
201880
- */
201881
- setTimeout(() => {
201882
- this.shadowRoot.querySelector("textarea").value = "";
201883
- });
201922
+ return () => {
201923
+ if (searchTextElement) {
201924
+ searchTextElement.removeEventListener("keydown", handleKeyDown);
201925
+ }
201926
+ if (searchButton) {
201927
+ searchButton.removeEventListener("click", handleClick);
201928
+ }
201929
+ };
201930
+ }, []);
201884
201931
 
201885
- const elAiChat = this.shadowRoot.querySelector("nx-ai-chat");
201932
+ return (
201933
+ <div className="wrapper">
201934
+ <nx-collapse target="nx-tab" className="search-collapse"></nx-collapse>
201935
+ <div className="list-wrapper">
201936
+ <nx-tab theme="theme-3" ref={tabRef}>
201937
+ <nx-tab-page caption="자연어 검색">
201938
+ <nx-form className="form1">
201939
+ <input
201940
+ type="text"
201941
+ id="searchText"
201942
+ name="searchText"
201943
+ placeholder="자연어 검색어를 입력하세요 (ex: 작성자가 홍길동인 데이타를 찾아줘)"
201944
+ />
201945
+ </nx-form>
201946
+ </nx-tab-page>
201947
+ <nx-tab-page caption="클래식 검색">
201948
+ <nx-form className="form2">
201949
+ <label>문서명: <input type="text" name="docNm" /></label>
201950
+ <label>매출액:
201951
+ <input type="number" name="minAmt" placeholder="최소" /> ~
201952
+ <input type="number" name="maxAmt" placeholder="최대" />
201953
+ </label>
201954
+ </nx-form>
201955
+ <button className="search">검색</button>
201956
+ </nx-tab-page>
201957
+ </nx-tab>
201958
+
201959
+ <div className="grid-wrapper">
201960
+ <nine-grid
201961
+ ref={gridRef}
201962
+ caption="문서관리"
201963
+ select-type="row"
201964
+ show-title-bar="true"
201965
+ show-menu-icon="true"
201966
+ show-status-bar="true"
201967
+ enable-fixed-col="true"
201968
+ row-resizable="false"
201969
+ col-movable="true"
201970
+ >
201971
+ <table>
201972
+ <colgroup>
201973
+ <col width="50" fixed="left" background-color="gray" />
201974
+ <col width="100" />
201975
+ <col width="100" />
201976
+ <col width="200" />
201977
+ <col width="120" />
201978
+ <col width="100" />
201979
+ <col width="150" />
201980
+ <col width="150" />
201981
+ </colgroup>
201982
+ <thead>
201983
+ <tr>
201984
+ <th>No.</th>
201985
+ <th>최종수정자</th>
201986
+ <th>문서ID</th>
201987
+ <th>문서명</th>
201988
+ <th>매출액</th>
201989
+ <th>최초등록자</th>
201990
+ <th>최초등록일</th>
201991
+ <th>최종수정일</th>
201992
+ </tr>
201993
+ </thead>
201994
+ <tbody>
201995
+ <tr>
201996
+ <th><ng-row-indicator /></th>
201997
+ <td data-bind="updateUser" text-align="center"></td>
201998
+ <td data-bind="docId" text-align="center"></td>
201999
+ <td data-bind="docNm" text-align="left"></td>
202000
+ <td
202001
+ data-bind="amt"
202002
+ data-expr="data.amt.toLocaleString()"
202003
+ text-align="right"
202004
+ show-icon="true"
202005
+ icon-type="sphere"
202006
+ icon-color="data.amt >= 2000 ? 'red' : 'gray'"
202007
+ ></td>
202008
+ <td data-bind="insertUser" text-align="center"></td>
202009
+ <td data-bind="insertDt" text-align="center"></td>
202010
+ <td data-bind="updateDt" text-align="center"></td>
202011
+ </tr>
202012
+ </tbody>
202013
+ </table>
202014
+ </nine-grid>
202015
+ </div>
202016
+ </div>
202017
+ </div>
202018
+ );
202019
+ };
201886
202020
 
201887
- elAiChat.add("me", userPrompt);
201888
- elAiChat.add("ing", "...");
202021
+ export default DocManager;
202022
+ `;
201889
202023
 
201890
- try {
201891
- const r = await this.#ai.generateSourceClient(userPrompt, apply);
201892
- elAiChat.add("ai", r);
201893
- } catch (error) {
201894
- console.error(error);
201895
- elAiChat.add("ai", String(error).replace("Error:", ""));
201896
- }
202024
+ const src2 = `
202025
+ import React, { useRef, useEffect } from "react";
202026
+ import { api, ai } from "ide-assi";
202027
+ import ninegrid from "ninegrid2";
201897
202028
 
201898
- this.#ing = false;
202029
+ const DocManager = () => {
202030
+ const tabRef = useRef(null);
202031
+ const gridRef = useRef(null);
202032
+
202033
+ const selectList = async (params) => {
202034
+ if (!gridRef.current) return;
202035
+ gridRef.current.classList.add("loading");
202036
+ api.post(\`/api/tmpl-a/doc-manager/selectList\`, params).then((res) => {
202037
+ gridRef.current.data.source = res.list;
202038
+ });
202039
+ };
202040
+
202041
+ const handleNaturalLanguageSearch = async () => {
202042
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
202043
+ const searchText = searchTextElement ? searchTextElement.value : "";
202044
+
202045
+ if (!gridRef.current) return;
202046
+ gridRef.current.classList.add("loading");
202047
+
202048
+ let params = {};
202049
+ if (searchText) {
202050
+ params = {
202051
+ _whereClause: await ai.generateWhereCause(
202052
+ "tmpla/DocManagerMapper.xml",
202053
+ "selectList",
202054
+ searchText,
202055
+ import.meta.env.VITE_GEMINI_API_KEY
202056
+ ),
202057
+ };
202058
+ }
202059
+ selectList(params);
202060
+ };
202061
+
202062
+ const handleClassicSearch = () => {
202063
+ if (!gridRef.current) return;
202064
+ gridRef.current.classList.add("loading");
202065
+
202066
+ const form2Element = ninegrid.querySelector(".form2", tabRef.current);
202067
+ const params = form2Element ? form2Element.getData() : {};
202068
+ selectList(params);
202069
+ };
202070
+
202071
+ useEffect(() => {
202072
+ selectList({});
202073
+
202074
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
202075
+ const searchButton = ninegrid.querySelector(".search", tabRef.current);
202076
+
202077
+ const handleKeyDown = (e) => {
202078
+ if (e.key === "Enter" && !e.isComposing) {
202079
+ handleNaturalLanguageSearch();
202080
+ }
202081
+ };
202082
+
202083
+ const handleClick = () => {
202084
+ handleClassicSearch();
202085
+ };
202086
+
202087
+ if (searchTextElement) {
202088
+ searchTextElement.addEventListener("keydown", handleKeyDown);
202089
+ }
202090
+ if (searchButton) {
202091
+ searchButton.addEventListener("click", handleClick);
202092
+ }
202093
+
202094
+ return () => {
202095
+ if (searchTextElement) {
202096
+ searchTextElement.removeEventListener("keydown", handleKeyDown);
202097
+ }
202098
+ if (searchButton) {
202099
+ searchButton.removeEventListener("click", handleClick);
202100
+ }
202101
+ };
202102
+ }, []);
202103
+
202104
+ return (
202105
+ <div className="wrapper">
202106
+ <nx-collapse target="nx-tab" className="search-collapse"></nx-collapse>
202107
+ <div className="list-wrapper">
202108
+ <nx-tab theme="theme-3" ref={tabRef}>
202109
+ <nx-tab-page caption="자연어 검색">
202110
+ <nx-form className="form1">
202111
+ <input
202112
+ type="text"
202113
+ id="searchText"
202114
+ name="searchText"
202115
+ placeholder="자연어 검색어를 입력하세요 (ex: 작성자가 홍길동인 데이타를 찾아줘)"
202116
+ />
202117
+ </nx-form>
202118
+ </nx-tab-page>
202119
+ <nx-tab-page caption="클래식 검색">
202120
+ <nx-form className="form2">
202121
+ <label>문서명: <input type="text" name="docNm" /></label>
202122
+ <label>매출액:
202123
+ <input type="number" name="minAmt" placeholder="최소" /> ~
202124
+ <input type="number" name="maxAmt" placeholder="최대" />
202125
+ </label>
202126
+ </nx-form>
202127
+ <button className="search">검색</button>
202128
+ </nx-tab-page>
202129
+ </nx-tab>
202130
+
202131
+ <div className="grid-wrapper">
202132
+ <nine-grid
202133
+ ref={gridRef}
202134
+ caption="매출 문서 관리"
202135
+ select-type="row"
202136
+ show-title-bar="true"
202137
+ show-menu-icon="true"
202138
+ show-status-bar="true"
202139
+ enable-fixed-col="true"
202140
+ row-resizable="false"
202141
+ col-movable="true"
202142
+ >
202143
+ <table>
202144
+ <colgroup>
202145
+ <col width="50" fixed="left" background-color="gray" />
202146
+ <col width="100" />
202147
+ <col width="120" />
202148
+ <col width="100" />
202149
+ <col width="200" />
202150
+ <col width="100" />
202151
+ <col width="150" />
202152
+ <col width="150" />
202153
+ </colgroup>
202154
+ <thead>
202155
+ <tr>
202156
+ <th>No.</th>
202157
+ <th>문서ID</th>
202158
+ <th>매출액</th>
202159
+ <th>최종수정자</th>
202160
+ <th>문서명</th>
202161
+ <th>최초등록자</th>
202162
+ <th>최초등록일</th>
202163
+ <th>최종수정일</th>
202164
+ </tr>
202165
+ </thead>
202166
+ <tbody>
202167
+ <tr>
202168
+ <th><ng-row-indicator /></th>
202169
+ <td data-bind="docId" text-align="center"></td>
202170
+ <td
202171
+ data-bind="amt"
202172
+ data-expr="data.amt.toLocaleString()"
202173
+ text-align="right"
202174
+ show-icon="true"
202175
+ icon-type="sphere"
202176
+ icon-color="data.amt >= 2000 ? 'red' : 'gray'"
202177
+ ></td>
202178
+ <td data-bind="updateUser" text-align="center"></td>
202179
+ <td data-bind="docNm" text-align="left"></td>
202180
+ <td data-bind="insertUser" text-align="center"></td>
202181
+ <td data-bind="insertDt" text-align="center"></td>
202182
+ <td data-bind="updateDt" text-align="center"></td>
202183
+ </tr>
202184
+ </tbody>
202185
+ </table>
202186
+ </nine-grid>
202187
+ </div>
202188
+ </div>
202189
+ </div>
202190
+ );
202191
+ };
202192
+
202193
+ export default DocManager;
202194
+ `;
202195
+
202196
+ this.shadowRoot.querySelector("ide-diff-popup").popup(src1, src2);
202197
+
202198
+ return;
201899
202199
  }
201900
202200
 
201901
202201
  #toggleCollapseHandler = () => {
@@ -124,7 +124,7 @@ export class IdeAssi extends HTMLElement
124
124
 
125
125
  //setTimeout(() => {
126
126
  const src1 = `
127
- import React, { useRef, useEffect } from "react";
127
+ import React, { useRef, useEffect } from "react";
128
128
  import { api, ai } from "ide-assi";
129
129
  import ninegrid from "ninegrid2";
130
130
 
@@ -162,6 +162,9 @@ const DocManager = () => {
162
162
  };
163
163
 
164
164
  const handleClassicSearch = () => {
165
+ if (!gridRef.current) return;
166
+ gridRef.current.classList.add("loading");
167
+
165
168
  const form2Element = ninegrid.querySelector(".form2", tabRef.current);
166
169
  const params = form2Element ? form2Element.getData() : {};
167
170
  selectList(params);
@@ -293,7 +296,7 @@ export default DocManager;
293
296
  `;
294
297
 
295
298
  const src2 = `
296
- import React, { useRef, useEffect } from 'react';
299
+ import React, { useRef, useEffect } from "react";
297
300
  import { api, ai } from "ide-assi";
298
301
  import ninegrid from "ninegrid2";
299
302
 
@@ -301,72 +304,73 @@ const DocManager = () => {
301
304
  const tabRef = useRef(null);
302
305
  const gridRef = useRef(null);
303
306
 
304
- const toCamelCase = (s) => {
305
- return s.toLowerCase().replace(/_([a-z])/g, (g) => g[1].toUpperCase());
307
+ const selectList = async (params) => {
308
+ if (!gridRef.current) return;
309
+ gridRef.current.classList.add("loading");
310
+ api.post(\`/api/tmpl-a/doc-manager/selectList\`, params).then((res) => {
311
+ gridRef.current.data.source = res.list;
312
+ });
306
313
  };
307
314
 
308
- const tableDefinitions = JSON.parse(\`{"list":[{"columns":[{"COLUMN_NAME":"doc_id","COLUMN_ID":1,"COLUMN_COMMENT":"문서ID"},{"COLUMN_NAME":"doc_nm","COLUMN_ID":2,"COLUMN_COMMENT":"문서명"},{"COLUMN_NAME":"amt","COLUMN_ID":3,"COLUMN_COMMENT":"매출액"},{"COLUMN_NAME":"insert_user","COLUMN_ID":4,"COLUMN_COMMENT":"최초등록자"},{"COLUMN_NAME":"insert_dt","COLUMN_ID":5,"COLUMN_COMMENT":"최초등록일"},{"COLUMN_NAME":"update_user","COLUMN_ID":6,"COLUMN_COMMENT":"최종수정자"},{"COLUMN_NAME":"update_dt","COLUMN_ID":7,"COLUMN_COMMENT":"최종수정일"}],"table":"t_doc"},{"columns":[{"COLUMN_NAME":"file_id","COLUMN_ID":1,"COLUMN_COMMENT":""},{"COLUMN_NAME":"doc_id","COLUMN_ID":2,"COLUMN_COMMENT":""},{"COLUMN_NAME":"download_cnt","COLUMN_ID":3,"COLUMN_COMMENT":""},{"COLUMN_NAME":"file_nm","COLUMN_ID":4,"COLUMN_COMMENT":""},{"COLUMN_NAME":"file_size","COLUMN_ID":5,"COLUMN_COMMENT":""},{"COLUMN_NAME":"file_contents","COLUMN_ID":6,"COLUMN_COMMENT":""},{"COLUMN_NAME":"insert_user","COLUMN_ID":7,"COLUMN_COMMENT":""},{"COLUMN_NAME":"insert_dt","COLUMN_ID":8,"COLUMN_COMMENT":""}],"table":"t_doc_file"},{"columns":[{"COLUMN_NAME":"file_id","COLUMN_ID":1,"COLUMN_COMMENT":""},{"COLUMN_NAME":"page","COLUMN_ID":2,"COLUMN_COMMENT":""},{"COLUMN_NAME":"text","COLUMN_ID":3,"COLUMN_COMMENT":""},{"COLUMN_NAME":"image","COLUMN_ID":4,"COLUMN_COMMENT":""},{"COLUMN_NAME":"vector_text","COLUMN_ID":5,"COLUMN_COMMENT":""},{"COLUMN_NAME":"vector_image","COLUMN_ID":6,"COLUMN_COMMENT":""}],"table":"t_doc_file_page"}]}\`);
309
- const mainTableColumns = tableDefinitions.list[0].columns;
315
+ const handleNaturalLanguageSearch = async () => {
316
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
317
+ const searchText = searchTextElement ? searchTextElement.value : "";
310
318
 
311
- const selectList = async (formData = {}) => {
312
319
  if (!gridRef.current) return;
313
-
314
320
  gridRef.current.classList.add("loading");
315
- /**
316
- const form1Data = ninegrid.querySelector(".form1", tabRef.current).getData();
317
- const form2Data = ninegrid.querySelector(".form2", tabRef.current).getData();
318
- const formData = { ...form1Data, ...form2Data };
319
321
 
320
- const formData1 = {
321
- "_whereClause": await getWhere(),
322
+ let params = {};
323
+ if (searchText) {
324
+ params = {
325
+ _whereClause: await ai.generateWhereCause(
326
+ "tmpla/DocManagerMapper.xml",
327
+ "selectList",
328
+ searchText,
329
+ import.meta.env.VITE_GEMINI_API_KEY
330
+ ),
331
+ };
322
332
  }
323
- console.log(formData1);
324
- */
325
-
326
- console.log(formData);
327
-
328
- api.post(\`/api/tmpl-a/doc-manager/selectList\`, formData).then((res) => {
329
- gridRef.current.data.source = res.list;
330
- });
333
+ selectList(params);
331
334
  };
332
335
 
333
- const getWhere = async () => {
334
- return await ai.generateWhereCause("tmpla/DocManagerMapper.xml", "selectList", ninegrid.querySelector("#searchText", tabRef.current).value, import.meta.env.VITE_GEMINI_API_KEY);
336
+ const handleClassicSearch = () => {
337
+ if (!gridRef.current) return;
338
+ gridRef.current.classList.add("loading");
339
+
340
+ const form2Element = ninegrid.querySelector(".form2", tabRef.current);
341
+ const params = form2Element ? form2Element.getData() : {};
342
+ selectList(params);
335
343
  };
336
344
 
337
345
  useEffect(() => {
338
- selectList();
346
+ selectList({});
339
347
 
340
- const searchTextInput = ninegrid.querySelector("#searchText", tabRef.current);
348
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
341
349
  const searchButton = ninegrid.querySelector(".search", tabRef.current);
342
350
 
343
- const handleSearchTextKeydown = (e) => {
344
- if (e.key === 'Enter' && !e.isComposing) {
345
-
346
- //getWhere();
347
- getWhere().then(res => {
348
- selectList({"_whereClause":res});
349
- });
351
+ const handleKeyDown = (e) => {
352
+ if (e.key === "Enter" && !e.isComposing) {
353
+ handleNaturalLanguageSearch();
350
354
  }
351
355
  };
352
356
 
353
- const handleSearchButtonClick = () => {
354
- selectList(ninegrid.querySelector(".form2", tabRef.current).getData());
357
+ const handleClick = () => {
358
+ handleClassicSearch();
355
359
  };
356
360
 
357
- if (searchTextInput) {
358
- searchTextInput.addEventListener('keydown', handleSearchTextKeydown);
361
+ if (searchTextElement) {
362
+ searchTextElement.addEventListener("keydown", handleKeyDown);
359
363
  }
360
364
  if (searchButton) {
361
- searchButton.addEventListener('click', handleSearchButtonClick);
365
+ searchButton.addEventListener("click", handleClick);
362
366
  }
363
367
 
364
368
  return () => {
365
- if (searchTextInput) {
366
- searchTextInput.removeEventListener('keydown', handleSearchTextKeydown);
369
+ if (searchTextElement) {
370
+ searchTextElement.removeEventListener("keydown", handleKeyDown);
367
371
  }
368
372
  if (searchButton) {
369
- searchButton.removeEventListener('click', handleSearchButtonClick);
373
+ searchButton.removeEventListener("click", handleClick);
370
374
  }
371
375
  };
372
376
  }, []);
@@ -378,19 +382,21 @@ const DocManager = () => {
378
382
  <nx-tab theme="theme-3" ref={tabRef}>
379
383
  <nx-tab-page caption="자연어 검색">
380
384
  <nx-form className="form1">
381
- <input type="text" id="searchText" name="searchText"
382
- placeholder="자연어 검색어를 입력하세요 (ex: 작성자가 홍길동인 데이타를 찾아줘)"/>
385
+ <input
386
+ type="text"
387
+ id="searchText"
388
+ name="searchText"
389
+ placeholder="자연어 검색어를 입력하세요 (ex: 작성자가 홍길동인 데이타를 찾아줘)"
390
+ />
383
391
  </nx-form>
384
392
  </nx-tab-page>
385
393
  <nx-tab-page caption="클래식 검색">
386
394
  <nx-form className="form2">
387
- <label>문서ID: <input type="text" name="docId"/></label>
388
- <label>문서명: <input type="text" name="docNm"/></label>
389
- <label>매출액: <input type="number" name="amt"/></label>
390
- <label>최초등록자: <input type="text" name="insertUser"/></label>
391
- <label>최초등록일: <input type="text" name="insertDt"/></label>
392
- <label>최종수정자: <input type="text" name="updateUser"/></label>
393
- <label>최종수정일: <input type="text" name="updateDt"/></label>
395
+ <label>문서명: <input type="text" name="docNm" /></label>
396
+ <label>매출액:
397
+ <input type="number" name="minAmt" placeholder="최소" /> ~
398
+ <input type="number" name="maxAmt" placeholder="최대" />
399
+ </label>
394
400
  </nx-form>
395
401
  <button className="search">검색</button>
396
402
  </nx-tab-page>
@@ -398,37 +404,56 @@ const DocManager = () => {
398
404
 
399
405
  <div className="grid-wrapper">
400
406
  <nine-grid
401
- ref={gridRef}
402
- caption="문서관리"
403
- select-type="row"
404
- show-title-bar="true"
405
- show-menu-icon="true"
406
- show-status-bar="true"
407
- enable-fixed-col="true"
408
- row-resizable="false"
409
- col-movable="true"
410
- >
407
+ ref={gridRef}
408
+ caption="매출 문서 관리"
409
+ select-type="row"
410
+ show-title-bar="true"
411
+ show-menu-icon="true"
412
+ show-status-bar="true"
413
+ enable-fixed-col="true"
414
+ row-resizable="false"
415
+ col-movable="true"
416
+ >
411
417
  <table>
412
418
  <colgroup>
413
- <col width="50" fixed="left" background-color="gray"/>
414
- {mainTableColumns.map((col) => (
415
- <col key={col.COLUMN_ID} width="150"/>
416
- ))}
419
+ <col width="50" fixed="left" background-color="gray" />
420
+ <col width="100" />
421
+ <col width="120" />
422
+ <col width="100" />
423
+ <col width="200" />
424
+ <col width="100" />
425
+ <col width="150" />
426
+ <col width="150" />
417
427
  </colgroup>
418
428
  <thead>
419
429
  <tr>
420
430
  <th>No.</th>
421
- {mainTableColumns.map((col) => (
422
- <th key={col.COLUMN_ID}>{col.COLUMN_COMMENT || col.COLUMN_NAME}</th>
423
- ))}
431
+ <th>문서ID</th>
432
+ <th>매출액</th>
433
+ <th>최종수정자</th>
434
+ <th>문서명</th>
435
+ <th>최초등록자</th>
436
+ <th>최초등록일</th>
437
+ <th>최종수정일</th>
424
438
  </tr>
425
439
  </thead>
426
440
  <tbody>
427
441
  <tr>
428
- <th><ng-row-indicator/></th>
429
- {mainTableColumns.map((col) => (
430
- <td key={col.COLUMN_ID} data-bind={toCamelCase(col.COLUMN_NAME)}></td>
431
- ))}
442
+ <th><ng-row-indicator /></th>
443
+ <td data-bind="docId" text-align="center"></td>
444
+ <td
445
+ data-bind="amt"
446
+ data-expr="data.amt.toLocaleString()"
447
+ text-align="right"
448
+ show-icon="true"
449
+ icon-type="sphere"
450
+ icon-color="data.amt >= 2000 ? 'red' : 'gray'"
451
+ ></td>
452
+ <td data-bind="updateUser" text-align="center"></td>
453
+ <td data-bind="docNm" text-align="left"></td>
454
+ <td data-bind="insertUser" text-align="center"></td>
455
+ <td data-bind="insertDt" text-align="center"></td>
456
+ <td data-bind="updateDt" text-align="center"></td>
432
457
  </tr>
433
458
  </tbody>
434
459
  </table>
@@ -442,9 +467,9 @@ const DocManager = () => {
442
467
  export default DocManager;
443
468
  `;
444
469
 
445
- //this.shadowRoot.querySelector("ide-diff-popup").popup(src1, src2);
470
+ this.shadowRoot.querySelector("ide-diff-popup").popup(src1, src2);
446
471
 
447
- //return;
472
+ return;
448
473
 
449
474
  const apply = {
450
475
  mybatis: this.shadowRoot.querySelector("#mybatis").checked,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ide-assi",
3
3
  "type": "module",
4
- "version": "0.354.0",
4
+ "version": "0.355.0",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {
@@ -124,7 +124,7 @@ export class IdeAssi extends HTMLElement
124
124
 
125
125
  //setTimeout(() => {
126
126
  const src1 = `
127
- import React, { useRef, useEffect } from "react";
127
+ import React, { useRef, useEffect } from "react";
128
128
  import { api, ai } from "ide-assi";
129
129
  import ninegrid from "ninegrid2";
130
130
 
@@ -162,6 +162,9 @@ const DocManager = () => {
162
162
  };
163
163
 
164
164
  const handleClassicSearch = () => {
165
+ if (!gridRef.current) return;
166
+ gridRef.current.classList.add("loading");
167
+
165
168
  const form2Element = ninegrid.querySelector(".form2", tabRef.current);
166
169
  const params = form2Element ? form2Element.getData() : {};
167
170
  selectList(params);
@@ -293,7 +296,7 @@ export default DocManager;
293
296
  `;
294
297
 
295
298
  const src2 = `
296
- import React, { useRef, useEffect } from 'react';
299
+ import React, { useRef, useEffect } from "react";
297
300
  import { api, ai } from "ide-assi";
298
301
  import ninegrid from "ninegrid2";
299
302
 
@@ -301,72 +304,73 @@ const DocManager = () => {
301
304
  const tabRef = useRef(null);
302
305
  const gridRef = useRef(null);
303
306
 
304
- const toCamelCase = (s) => {
305
- return s.toLowerCase().replace(/_([a-z])/g, (g) => g[1].toUpperCase());
307
+ const selectList = async (params) => {
308
+ if (!gridRef.current) return;
309
+ gridRef.current.classList.add("loading");
310
+ api.post(\`/api/tmpl-a/doc-manager/selectList\`, params).then((res) => {
311
+ gridRef.current.data.source = res.list;
312
+ });
306
313
  };
307
314
 
308
- const tableDefinitions = JSON.parse(\`{"list":[{"columns":[{"COLUMN_NAME":"doc_id","COLUMN_ID":1,"COLUMN_COMMENT":"문서ID"},{"COLUMN_NAME":"doc_nm","COLUMN_ID":2,"COLUMN_COMMENT":"문서명"},{"COLUMN_NAME":"amt","COLUMN_ID":3,"COLUMN_COMMENT":"매출액"},{"COLUMN_NAME":"insert_user","COLUMN_ID":4,"COLUMN_COMMENT":"최초등록자"},{"COLUMN_NAME":"insert_dt","COLUMN_ID":5,"COLUMN_COMMENT":"최초등록일"},{"COLUMN_NAME":"update_user","COLUMN_ID":6,"COLUMN_COMMENT":"최종수정자"},{"COLUMN_NAME":"update_dt","COLUMN_ID":7,"COLUMN_COMMENT":"최종수정일"}],"table":"t_doc"},{"columns":[{"COLUMN_NAME":"file_id","COLUMN_ID":1,"COLUMN_COMMENT":""},{"COLUMN_NAME":"doc_id","COLUMN_ID":2,"COLUMN_COMMENT":""},{"COLUMN_NAME":"download_cnt","COLUMN_ID":3,"COLUMN_COMMENT":""},{"COLUMN_NAME":"file_nm","COLUMN_ID":4,"COLUMN_COMMENT":""},{"COLUMN_NAME":"file_size","COLUMN_ID":5,"COLUMN_COMMENT":""},{"COLUMN_NAME":"file_contents","COLUMN_ID":6,"COLUMN_COMMENT":""},{"COLUMN_NAME":"insert_user","COLUMN_ID":7,"COLUMN_COMMENT":""},{"COLUMN_NAME":"insert_dt","COLUMN_ID":8,"COLUMN_COMMENT":""}],"table":"t_doc_file"},{"columns":[{"COLUMN_NAME":"file_id","COLUMN_ID":1,"COLUMN_COMMENT":""},{"COLUMN_NAME":"page","COLUMN_ID":2,"COLUMN_COMMENT":""},{"COLUMN_NAME":"text","COLUMN_ID":3,"COLUMN_COMMENT":""},{"COLUMN_NAME":"image","COLUMN_ID":4,"COLUMN_COMMENT":""},{"COLUMN_NAME":"vector_text","COLUMN_ID":5,"COLUMN_COMMENT":""},{"COLUMN_NAME":"vector_image","COLUMN_ID":6,"COLUMN_COMMENT":""}],"table":"t_doc_file_page"}]}\`);
309
- const mainTableColumns = tableDefinitions.list[0].columns;
315
+ const handleNaturalLanguageSearch = async () => {
316
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
317
+ const searchText = searchTextElement ? searchTextElement.value : "";
310
318
 
311
- const selectList = async (formData = {}) => {
312
319
  if (!gridRef.current) return;
313
-
314
320
  gridRef.current.classList.add("loading");
315
- /**
316
- const form1Data = ninegrid.querySelector(".form1", tabRef.current).getData();
317
- const form2Data = ninegrid.querySelector(".form2", tabRef.current).getData();
318
- const formData = { ...form1Data, ...form2Data };
319
321
 
320
- const formData1 = {
321
- "_whereClause": await getWhere(),
322
+ let params = {};
323
+ if (searchText) {
324
+ params = {
325
+ _whereClause: await ai.generateWhereCause(
326
+ "tmpla/DocManagerMapper.xml",
327
+ "selectList",
328
+ searchText,
329
+ import.meta.env.VITE_GEMINI_API_KEY
330
+ ),
331
+ };
322
332
  }
323
- console.log(formData1);
324
- */
325
-
326
- console.log(formData);
327
-
328
- api.post(\`/api/tmpl-a/doc-manager/selectList\`, formData).then((res) => {
329
- gridRef.current.data.source = res.list;
330
- });
333
+ selectList(params);
331
334
  };
332
335
 
333
- const getWhere = async () => {
334
- return await ai.generateWhereCause("tmpla/DocManagerMapper.xml", "selectList", ninegrid.querySelector("#searchText", tabRef.current).value, import.meta.env.VITE_GEMINI_API_KEY);
336
+ const handleClassicSearch = () => {
337
+ if (!gridRef.current) return;
338
+ gridRef.current.classList.add("loading");
339
+
340
+ const form2Element = ninegrid.querySelector(".form2", tabRef.current);
341
+ const params = form2Element ? form2Element.getData() : {};
342
+ selectList(params);
335
343
  };
336
344
 
337
345
  useEffect(() => {
338
- selectList();
346
+ selectList({});
339
347
 
340
- const searchTextInput = ninegrid.querySelector("#searchText", tabRef.current);
348
+ const searchTextElement = ninegrid.querySelector("#searchText", tabRef.current);
341
349
  const searchButton = ninegrid.querySelector(".search", tabRef.current);
342
350
 
343
- const handleSearchTextKeydown = (e) => {
344
- if (e.key === 'Enter' && !e.isComposing) {
345
-
346
- //getWhere();
347
- getWhere().then(res => {
348
- selectList({"_whereClause":res});
349
- });
351
+ const handleKeyDown = (e) => {
352
+ if (e.key === "Enter" && !e.isComposing) {
353
+ handleNaturalLanguageSearch();
350
354
  }
351
355
  };
352
356
 
353
- const handleSearchButtonClick = () => {
354
- selectList(ninegrid.querySelector(".form2", tabRef.current).getData());
357
+ const handleClick = () => {
358
+ handleClassicSearch();
355
359
  };
356
360
 
357
- if (searchTextInput) {
358
- searchTextInput.addEventListener('keydown', handleSearchTextKeydown);
361
+ if (searchTextElement) {
362
+ searchTextElement.addEventListener("keydown", handleKeyDown);
359
363
  }
360
364
  if (searchButton) {
361
- searchButton.addEventListener('click', handleSearchButtonClick);
365
+ searchButton.addEventListener("click", handleClick);
362
366
  }
363
367
 
364
368
  return () => {
365
- if (searchTextInput) {
366
- searchTextInput.removeEventListener('keydown', handleSearchTextKeydown);
369
+ if (searchTextElement) {
370
+ searchTextElement.removeEventListener("keydown", handleKeyDown);
367
371
  }
368
372
  if (searchButton) {
369
- searchButton.removeEventListener('click', handleSearchButtonClick);
373
+ searchButton.removeEventListener("click", handleClick);
370
374
  }
371
375
  };
372
376
  }, []);
@@ -378,19 +382,21 @@ const DocManager = () => {
378
382
  <nx-tab theme="theme-3" ref={tabRef}>
379
383
  <nx-tab-page caption="자연어 검색">
380
384
  <nx-form className="form1">
381
- <input type="text" id="searchText" name="searchText"
382
- placeholder="자연어 검색어를 입력하세요 (ex: 작성자가 홍길동인 데이타를 찾아줘)"/>
385
+ <input
386
+ type="text"
387
+ id="searchText"
388
+ name="searchText"
389
+ placeholder="자연어 검색어를 입력하세요 (ex: 작성자가 홍길동인 데이타를 찾아줘)"
390
+ />
383
391
  </nx-form>
384
392
  </nx-tab-page>
385
393
  <nx-tab-page caption="클래식 검색">
386
394
  <nx-form className="form2">
387
- <label>문서ID: <input type="text" name="docId"/></label>
388
- <label>문서명: <input type="text" name="docNm"/></label>
389
- <label>매출액: <input type="number" name="amt"/></label>
390
- <label>최초등록자: <input type="text" name="insertUser"/></label>
391
- <label>최초등록일: <input type="text" name="insertDt"/></label>
392
- <label>최종수정자: <input type="text" name="updateUser"/></label>
393
- <label>최종수정일: <input type="text" name="updateDt"/></label>
395
+ <label>문서명: <input type="text" name="docNm" /></label>
396
+ <label>매출액:
397
+ <input type="number" name="minAmt" placeholder="최소" /> ~
398
+ <input type="number" name="maxAmt" placeholder="최대" />
399
+ </label>
394
400
  </nx-form>
395
401
  <button className="search">검색</button>
396
402
  </nx-tab-page>
@@ -398,37 +404,56 @@ const DocManager = () => {
398
404
 
399
405
  <div className="grid-wrapper">
400
406
  <nine-grid
401
- ref={gridRef}
402
- caption="문서관리"
403
- select-type="row"
404
- show-title-bar="true"
405
- show-menu-icon="true"
406
- show-status-bar="true"
407
- enable-fixed-col="true"
408
- row-resizable="false"
409
- col-movable="true"
410
- >
407
+ ref={gridRef}
408
+ caption="매출 문서 관리"
409
+ select-type="row"
410
+ show-title-bar="true"
411
+ show-menu-icon="true"
412
+ show-status-bar="true"
413
+ enable-fixed-col="true"
414
+ row-resizable="false"
415
+ col-movable="true"
416
+ >
411
417
  <table>
412
418
  <colgroup>
413
- <col width="50" fixed="left" background-color="gray"/>
414
- {mainTableColumns.map((col) => (
415
- <col key={col.COLUMN_ID} width="150"/>
416
- ))}
419
+ <col width="50" fixed="left" background-color="gray" />
420
+ <col width="100" />
421
+ <col width="120" />
422
+ <col width="100" />
423
+ <col width="200" />
424
+ <col width="100" />
425
+ <col width="150" />
426
+ <col width="150" />
417
427
  </colgroup>
418
428
  <thead>
419
429
  <tr>
420
430
  <th>No.</th>
421
- {mainTableColumns.map((col) => (
422
- <th key={col.COLUMN_ID}>{col.COLUMN_COMMENT || col.COLUMN_NAME}</th>
423
- ))}
431
+ <th>문서ID</th>
432
+ <th>매출액</th>
433
+ <th>최종수정자</th>
434
+ <th>문서명</th>
435
+ <th>최초등록자</th>
436
+ <th>최초등록일</th>
437
+ <th>최종수정일</th>
424
438
  </tr>
425
439
  </thead>
426
440
  <tbody>
427
441
  <tr>
428
- <th><ng-row-indicator/></th>
429
- {mainTableColumns.map((col) => (
430
- <td key={col.COLUMN_ID} data-bind={toCamelCase(col.COLUMN_NAME)}></td>
431
- ))}
442
+ <th><ng-row-indicator /></th>
443
+ <td data-bind="docId" text-align="center"></td>
444
+ <td
445
+ data-bind="amt"
446
+ data-expr="data.amt.toLocaleString()"
447
+ text-align="right"
448
+ show-icon="true"
449
+ icon-type="sphere"
450
+ icon-color="data.amt >= 2000 ? 'red' : 'gray'"
451
+ ></td>
452
+ <td data-bind="updateUser" text-align="center"></td>
453
+ <td data-bind="docNm" text-align="left"></td>
454
+ <td data-bind="insertUser" text-align="center"></td>
455
+ <td data-bind="insertDt" text-align="center"></td>
456
+ <td data-bind="updateDt" text-align="center"></td>
432
457
  </tr>
433
458
  </tbody>
434
459
  </table>
@@ -442,9 +467,9 @@ const DocManager = () => {
442
467
  export default DocManager;
443
468
  `;
444
469
 
445
- //this.shadowRoot.querySelector("ide-diff-popup").popup(src1, src2);
470
+ this.shadowRoot.querySelector("ide-diff-popup").popup(src1, src2);
446
471
 
447
- //return;
472
+ return;
448
473
 
449
474
  const apply = {
450
475
  mybatis: this.shadowRoot.querySelector("#mybatis").checked,