@andersonalmeidax0/webcomponents 0.1.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.
@@ -0,0 +1,271 @@
1
+ import React from "react";
2
+ import {XButton} from "../XButton.jsx"
3
+ import {XInputExternal} from "../XInput.jsx"
4
+ import {XSelect3} from "../XSelect"
5
+ import {XTextArea} from "../XTextArea"
6
+ import {XCheckbox} from "../XCheckbox.jsx"
7
+ import {XDateSelect} from "../XDateSelect.jsx"
8
+
9
+ const DEBUG_ID=false;
10
+ const DEBUG_ID2=DEBUG_ID;
11
+ const DEBUG_ID3=false;
12
+
13
+
14
+ /**
15
+ * View 2 model => number digitado com fmt para numero interno
16
+ */
17
+ function NumberView2Model(n) {
18
+ var nStr = n+'';
19
+ nStr = nStr.replaceAll('.','@');
20
+ nStr = nStr.replaceAll(',','.');
21
+ nStr = nStr.replaceAll('@',',');
22
+ var nOk = nStr;// Number.parseFloat(nStr);
23
+ return nOk;
24
+ }
25
+ /**
26
+ * Mode 2 view => number interno para fmt
27
+ */
28
+ function NumberModel2View(n) {
29
+ var nStr = n+'';
30
+ //nStr = nStr.replace('.','');
31
+ nStr = nStr.replaceAll('.','@');
32
+ nStr = nStr.replaceAll(',','.');
33
+ nStr = nStr.replaceAll('@',',');
34
+ var nOk = (nStr);
35
+ return nOk;
36
+ }
37
+
38
+ function isNumeric(n) {
39
+ return !isNaN(n);
40
+ }
41
+
42
+ function nfmt(n) {
43
+ //alert("n:["+n+']'+new Error().stack);
44
+ if(isNumeric(n))
45
+ n = parseFloat(n).toFixed(0);
46
+ else
47
+ n=" - - - ";
48
+ // n="Num inv1("+n+")";
49
+
50
+ return NumberModel2View(n);
51
+ }
52
+
53
+ function nfmt2(n) {
54
+ if(isNumeric(n))
55
+ n = parseFloat(n).toFixed(2);
56
+ else
57
+ n=" - - - ";//+'['+n+']';
58
+ return NumberModel2View(n);
59
+ }
60
+
61
+ function nfmtM(n) {
62
+ if(isNumeric(n))
63
+ n = parseFloat(n).toFixed(2);
64
+ else
65
+ n=" - - - ";
66
+ return NumberModel2View(n);
67
+ }
68
+
69
+
70
+
71
+
72
+ /** *********************************************************
73
+ * XTableRead: metadata, list, onAction, onActionDelete
74
+ * Tabela readonly, permite chamar eventos de del e edit
75
+ * Nao renderiza elementos com atributo "isDeleted"
76
+ * =======================
77
+ * Faz inPlace edit se tiver isEditSelect ou edit
78
+ * renderHTML, renderFn, isButton, ==> custom CELL rendering
79
+ * NOVA FUNCIONALIDADE: para Edits, força o update
80
+ * ********************************************************* */
81
+ class XTableRead extends React.Component {
82
+ constructor(props) {
83
+ super(props)
84
+ //this.evt = this.evt.bind(this);
85
+ this.state={vi:0}
86
+ //this.renderListItem = this.renderListItem.bind(this);
87
+ }
88
+
89
+ evtRefresh = () => {
90
+ //alert('UPD');
91
+ var vi = this.state.vi;
92
+ this.setState({vi:vi+1});
93
+ this.forceUpdate();
94
+ }
95
+
96
+
97
+ cellChanged = () => {
98
+ console.log('u.xtable.cellchanged');
99
+ this.evtRefresh();
100
+ }
101
+
102
+ render () {
103
+ return (
104
+ <React.Fragment>
105
+ <h6>{DEBUG_ID&&'['+this.props.id+']'}</h6>
106
+ {/* div para scroll vertical */}
107
+ <div xstyle={{maxHeight:'400px',overflow: 'auto'}} >
108
+ <table className="hoverable" xwidth={'99%'} xstyle={{border:1}} >
109
+ <thead>
110
+ <tr key={'header'+this.props.id} className="table-header">
111
+ <th key={'0'+this.props.id}></th>
112
+ {this.props.metadata.fields.filter((item)=>{return(item.show)}).map((v)=> {
113
+ return <th key={v.label+this.props.id} x='center' align={v.align} className={v.className} >&nbsp; <b>{v.label}</b></th>
114
+ })}
115
+ <th key={'actions'} align='center'><b></b></th>
116
+ </tr>
117
+ </thead>
118
+ <tbody>
119
+ {this.props.list.map((item,index,arr)=> {
120
+ return <XTableCell key={index} item={item} index={index} lastIndex={arr.length} {...this.props} notifyChangeFn={this.cellChanged} /> })}
121
+ </tbody>
122
+ </table>
123
+ </div>
124
+ <p >{DEBUG_ID2&&'Total_'+this.props.id}</p>
125
+ <p style={{visibility: 'hidden'}} id={'Total_'+this.props.id}>{this.props.list.length}</p>
126
+ {this.props.metadata.dynamicTotalFN&&this.props.metadata.dynamicTotalFN(this.props.list)}
127
+ </React.Fragment>
128
+ );
129
+ }
130
+
131
+ }
132
+
133
+
134
+ //var XTableCell_ID=0;
135
+
136
+ /**
137
+ *
138
+ */
139
+ class XTableCell extends React.Component {
140
+ constructor(props) {
141
+ super(props)
142
+ this.state={vi:0}
143
+ this.renderListItem = this.renderListItem.bind(this);
144
+ //this.inputChange = this.inputChange.bind(this);
145
+ //this.select3Change = this.select3Change.bind(this);
146
+ }
147
+
148
+ evtRefresh = () => {
149
+ //alert('UPD');
150
+ var vi = this.state.vi;
151
+ this.setState({vi:vi+1});
152
+ this.forceUpdate();
153
+ }
154
+
155
+ render () {
156
+ var item = this.props.item;
157
+ var index = this.props.index;
158
+ var lastIndex = this.props.lastIndex;
159
+ return this.renderListItem(item,index,lastIndex);
160
+ }
161
+ //Map args: o valor do elemento corrente, o índice do elemento corrente e o array original que está sendo percorrido.
162
+ //map(v,i,arr)
163
+
164
+ //para XDate e XCheck
165
+ inputChange = (ev,item,v) => {
166
+ //item[v.attr]=ev.target.value;
167
+ //item[v.attr]=ev;
168
+ //this.evtRefresh();
169
+ //this.props.notifyChangeFn();
170
+ }
171
+
172
+ //new: recebe context para XInputExternal
173
+ inputChangeNew = (value,context) => {
174
+ console.log("u.xtableCell.inputChgNew.context"+context);
175
+ var v=context.v;
176
+ var item=context.item;
177
+ console.log("u.xtableCell.inputChgNew.value"+value);
178
+ item[v.attr]=value;
179
+ this.evtRefresh();
180
+ this.props.notifyChangeFn();
181
+ }
182
+
183
+ select3Change = (ev,item,v) => {
184
+ item[v.attr]=ev.target.value;
185
+ this.evtRefresh();
186
+ this.props.notifyChangeFn();
187
+ }
188
+
189
+ renderListItem(item,p1,lastIndex) {
190
+ //var kk='ASD'+(p1+1234);
191
+ //XTableCell_ID=XTableCell_ID+1;
192
+ if(item.isDeleted)
193
+ return null
194
+ else /* <td>{XTableCell_ID}</td> */
195
+ return (
196
+ <tr key={'TR_'+p1} >
197
+ <td key={(p1+1)+'_H_'+this.props.id} align='center' className="nudge--left "> {(p1+1)}.{DEBUG_ID3&&'['+(this.props.id)+'_R'+p1+']'} </td>
198
+ {this.props.metadata.fields.filter((item)=>{return(item.show)}).map((v,i,arr)=> {
199
+ if(item[v.attr]==null)
200
+ return <td key={i} align={v.align} className={v.className} >NAtr:{v.attr}</td>
201
+ else
202
+ //Se for editável
203
+ if(v.edit)
204
+ return <td key={i} align={v.align} className={v.className}><XInputExternal type={(v.type=='n'||v.type=='f')?'number':''} id={this.props.id+'_R'+p1+'_C'+i} width={v.width} cellStyle={1} value={item[v.attr]} onXG={(ev)=>{this.inputChange(ev)}} onChangeNew={this.inputChangeNew} context={{item:item,v:v}} />{DEBUG_ID2&&this.props.id+'_R'+p1+'_C'+i}</td>
205
+ else
206
+ if(v.isEditSelect) {
207
+ if(!v.lov)
208
+ v.lov=[{id:0,descr:"ERR: NULL"}];
209
+ else
210
+ if(v.lov.length==0)
211
+ v.lov=[{id:0,descr:"ERR:EMPTY"}];
212
+ //var selIdx = Number.parseInt(item[v.attr]);
213
+ //selIdx=isNaN(selIdx)?0:selIdx;
214
+ //var readValueDescr=v.lov[selIdx].descr;
215
+ //var readValueDescr='DEB:idx:'+selIdx+' item.v.atr:'+item[v.attr]+' JSON:'+JSON.stringify(v.lov);
216
+ //if(v.readOnly)
217
+ // return <td key={i} align={v.align} className={v.className} >{readValueDescr}</td>
218
+ //else
219
+ return <td key={i} align={v.align} className={v.className} ><XSelect3 id={this.props.id+'_R'+p1+'_C'+i} width={v.width} list={v.lov} value={item[v.attr]} disabled={v.readOnly} onChange={(ev)=>{this.select3Change(ev,item,v)}} onChange_xxx={(ev)=>item[v.attr]=ev.target.value} /></td>
220
+ }
221
+ else
222
+ if(v.renderHTML) {
223
+ //console.log("!!!!RENDER: HTML");
224
+ return <td key={i} align={v.align} className={v.className} ><div dangerouslySetInnerHTML={item[v.attr]} /></td>
225
+ }
226
+ else
227
+ if(v.renderFn)
228
+ {
229
+ //console.log("!!!!RENDER: fn");//]}
230
+ //chama a funcao custom de render, passando o valor como parametro!!!!!!!
231
+ return <td key={i} align={v.align} className={v.className}>{v.renderFn(item[v.attr],v,i,item,p1)}</td>
232
+ }
233
+ else
234
+ if(v.isButton)
235
+ return <td key={i} align={v.align} className={v.className}><XButton label={v.isButton} onClick={()=>v.isButtonEvt(item)}/></td>
236
+ else
237
+ if(v.isLink)
238
+ return <td key={i} align={v.align} className={v.className}><a href={v.isLink.href} > {item[v.attr]} </a> </td>
239
+ else {
240
+ //Renderização "NORMAL"
241
+ var cellFmt = item[v.attr];
242
+ if(v.type=='n')
243
+ cellFmt= nfmt(cellFmt);
244
+ if(v.type=='f')
245
+ cellFmt= nfmt2(cellFmt);
246
+ if(v.type=='m')
247
+ cellFmt= nfmtM(cellFmt);
248
+
249
+ if(v.type=='d'){
250
+ return <td key={i} align={v.align} className={v.className}><XDateSelect disabled={v.readOnly} id={this.props.id+'_R'+p1+'_C'+i} defaultValue={item[v.attr]} onChange={(ev)=>{this.inputChange(ev,item,v)}} xonChange={this.inputChangeNew} />{DEBUG_ID2&&this.props.id+'_R'+p1+'_C'+i}</td>
251
+ }
252
+ if(v.type=='c'){
253
+ return <td key={i} align={v.align} className={v.className}><XCheckbox disabled={v.readOnly} id={this.props.id+'_R'+p1+'_C'+i} defaultValue={item[v.attr]} onChange={(ev)=>{this.inputChange(ev,item,v)}} xonChange={this.inputChangeNew} />{DEBUG_ID2&&this.props.id+'_R'+p1+'_C'+i}</td>
254
+ }
255
+
256
+ return <td key={i} align={v.align} className={v.className} id={this.props.id+'_R'+p1+'_C'+i}>{cellFmt}&nbsp;{DEBUG_ID2&&'['+this.props.id+'_R'+p1+'_C'+i+']'}</td>
257
+ }
258
+ })}
259
+
260
+ <td key={lastIndex+1} align='left'>
261
+ {!this.props.inPlaceEdit&&this.props.metadata.hasEditFn&&this.props.metadata.hasEditFn(item)&&<button id={'Edt_'+p1+'_'+this.props.id} onClick={()=>this.props.onAction(p1,item)} className="btn--flat nudge--right"><i className="fa fa-pencil"></i>{DEBUG_ID&&'Edt_'+p1+'_'+this.props.id}{this.props.textlabels?"Edit":""}</button>}
262
+ {this.props.metadata.hasDeleteFn&&this.props.metadata.hasDeleteFn(item)&&<button id={'Del_'+p1+'_'+this.props.id} onClick={()=>this.props.onDelete(p1,item)} className="btn--flat nudge--right"><i className="fa fa-trash"></i>{DEBUG_ID&&'Del_'+p1+'_'+this.props.id}{this.props.textlabels?"Delete":""}</button>}
263
+ </td>
264
+
265
+ </tr>
266
+ );
267
+ }
268
+ }
269
+
270
+
271
+ export {XTableRead,nfmt,nfmt2,nfmtM};
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@andersonalmeidax0/webcomponents",
3
+ "version": "0.1.0",
4
+ "description": "webcomponents",
5
+ "main": "webcomponents",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/andersonalmeidax0/webcomponents.git"
12
+ },
13
+ "author": "aax0",
14
+ "license": "ISC",
15
+ "bugs": {
16
+ "url": "https://github.com/andersonalmeidax0/webcomponents/issues"
17
+ },
18
+ "homepage": "https://github.com/andersonalmeidax0/webcomponents#readme"
19
+ }
@@ -0,0 +1,37 @@
1
+ 0.1.0: beta
2
+ 0.1.1: add all components
3
+ 0.1.2: with text labels for buttons
4
+
5
+ TODO
6
+ -change "Errors" => string contants
7
+ -add "textIcon=true" option para JZEditTable ==> OK
8
+ -create NPM
9
+ -test
10
+
11
+ -readme: document capacities
12
+ JZ read and form: format specs, types
13
+ JZEdit: api spec, inplace, triggerUpdate cols, links, renders, totalRenders,
14
+ "Tester Friendly" hiden info (ex: last combo item), ID-based components
15
+
16
+ =====
17
+ TODO:
18
+ Exepctions de erros, criador para a)evitar tratar StatusCodesHttp e b)permitir "try catch" de erros "subindo" no stack
19
+ Expection "genericas" assim é só import de constantes, e tratar em qualquer camada com "Error.message==xxxx"
20
+ Package separado, assim dá para usar na aplicação "Error.message==xxxx", em npms, e também no server, com imports redundantes
21
+ 1-criar test cases para PlatAPIError
22
+ 2-criar uma classe com constantes string de error APIErrors
23
+ 3-Incluir APIAdapter no código de JZComponents
24
+ 4-Tratar erros vendo se e.message==APIErrors.API<messageCode>
25
+ -"Throw" erros com constructor == APIErrors.API<messageCode> (vai ficar no atributo message)
26
+ ==>Alterar APIAdapter para dar "throw" de new Error(APIErrors.API<messageCode>)
27
+
28
+
29
+ //Auth
30
+ PlatAPIAuthError
31
+ PlatAPIForbidden
32
+ //DB
33
+ PlatAPIDBNotFound
34
+ PlatAPIDBIntegrityConstraint
35
+ //Internal
36
+ PlatAPIError ==> PlatAPIPayloadError
37
+ PlatAPIReturnCodeError ==> PlatAPIServerError