@andersonalmeidax0/webcomponents 0.1.12 → 0.1.14
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.
- package/RestAPIAdapter.js +58 -2
- package/jzcomponents/JZListComponent.jsx +1 -0
- package/jzcomponents/XFormEdit.jsx +81 -72
- package/jzcomponents/XTableRead.jsx +23 -3
- package/package.json +1 -1
- package/releasenotes.txt +3 -1
package/RestAPIAdapter.js
CHANGED
|
@@ -151,14 +151,70 @@ X-Colocar o MetalMarlek em outro server AWS ... com docker... com outra conta de
|
|
|
151
151
|
r=await this.getJSONResponse(response);
|
|
152
152
|
|
|
153
153
|
//tag de dados pode ser nada,result, data
|
|
154
|
-
if(this.tagData==null)
|
|
154
|
+
if(this.tagData==null){
|
|
155
|
+
if(vo.fileData)
|
|
156
|
+
await uploadFile(vo.fileData);
|
|
157
|
+
return r;
|
|
158
|
+
|
|
159
|
+
}
|
|
155
160
|
|
|
156
161
|
var respBlock=this.tagData;
|
|
157
162
|
if(r[respBlock])
|
|
158
163
|
r[respBlock].insertedId=r.insertedId;
|
|
159
|
-
if(r[respBlock])
|
|
164
|
+
if(r[respBlock]) {
|
|
165
|
+
if(vo.fileData)
|
|
166
|
+
await uploadFile(vo.fileData);
|
|
167
|
+
return r[respBlock];
|
|
168
|
+
}
|
|
160
169
|
throw new PlatAPIError('Invalid payload response');
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
161
173
|
};
|
|
174
|
+
|
|
175
|
+
/** ***********************
|
|
176
|
+
*
|
|
177
|
+
*********************** */
|
|
178
|
+
async uploadFile(fileData) {
|
|
179
|
+
alert('UPLOAD start');
|
|
180
|
+
let formData = new FormData();
|
|
181
|
+
formData.append('file', fileData);
|
|
182
|
+
const response = await fetch(urlAPI+'/api/upload', {
|
|
183
|
+
method: 'POST',
|
|
184
|
+
body: formData,
|
|
185
|
+
})
|
|
186
|
+
if (!response.ok) {
|
|
187
|
+
if(response.status===404)
|
|
188
|
+
throw new PlatAPIDBNotFound( `An error has occured: ${response.status}`);
|
|
189
|
+
if(response.status===403)
|
|
190
|
+
throw new PlatAPIForbidden( `An error has occured: ${response.status}`);
|
|
191
|
+
if(response.status===401)
|
|
192
|
+
throw new PlatAPIAuthError( `An error has occured: ${response.status}`);
|
|
193
|
+
throw new PlatAPIReturnCodeError();
|
|
194
|
+
}
|
|
195
|
+
r=await response.json();
|
|
196
|
+
alert("upload response:"+JSON.stringify(r));
|
|
197
|
+
return r;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
async downloadFile(f) {
|
|
202
|
+
var response=await fetch(urlAPI+'/api/download/'+f, {
|
|
203
|
+
method: 'GET'
|
|
204
|
+
})
|
|
205
|
+
if (!response.ok) {
|
|
206
|
+
if(response.status===404)
|
|
207
|
+
throw new PlatAPIDBNotFound( `An error has occured: ${response.status}`);
|
|
208
|
+
if(response.status===403)
|
|
209
|
+
throw new PlatAPIForbidden( `An error has occured: ${response.status}`);
|
|
210
|
+
if(response.status===401)
|
|
211
|
+
throw new PlatAPIAuthError( `An error has occured: ${response.status}`);
|
|
212
|
+
throw new PlatAPIReturnCodeError();
|
|
213
|
+
}
|
|
214
|
+
var blob = await response.blob();
|
|
215
|
+
return blob;
|
|
216
|
+
}
|
|
217
|
+
|
|
162
218
|
/** ***********************
|
|
163
219
|
*
|
|
164
220
|
*********************** */
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {XButton}
|
|
3
|
-
import {XInputExternal} from "../XInput.jsx"
|
|
4
|
-
import {XSelect3}
|
|
5
|
-
import {XTextArea}
|
|
6
|
-
import {XCheckbox}
|
|
7
|
-
import {XDateSelect}
|
|
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
8
|
|
|
9
9
|
import { JZInPlaceListComponent } from "./JZInPlaceListComponent.jsx";
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
const DEBUG_ID=false;
|
|
14
|
-
const DEBUG_ID2=DEBUG_ID;
|
|
15
|
-
const DEBUG_ID3=false;
|
|
13
|
+
const DEBUG_ID = false;
|
|
14
|
+
const DEBUG_ID2 = DEBUG_ID;
|
|
15
|
+
const DEBUG_ID3 = false;
|
|
16
16
|
|
|
17
17
|
//TODO: tirar debug de celulas (DEBUF_2)
|
|
18
18
|
//atualizar e refres
|
|
@@ -23,83 +23,92 @@ const DEBUG_ID3=false;
|
|
|
23
23
|
/** *********************************************************
|
|
24
24
|
* XFormEdit: metadata, formData, btn0, btn0.label, btn0.evt
|
|
25
25
|
* altera diretamente a prop, por isso nao tem estado (via input external)
|
|
26
|
-
* ********************************************************* */
|
|
26
|
+
* ********************************************************* */
|
|
27
27
|
class XFormEdit extends React.Component {
|
|
28
28
|
constructor(props) {
|
|
29
29
|
super(props)
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
inputChangeNew = (value,context) => {
|
|
33
|
-
console.log("u.XFormEdit.inputChgNew.context"+context);
|
|
34
|
-
var v=context.v;
|
|
35
|
-
var item=context.item;
|
|
36
|
-
console.log("u.XFormEdit.inputChgNew.value"+value);
|
|
37
|
-
item[v.attr]=value;
|
|
32
|
+
inputChangeNew = (value, context) => {
|
|
33
|
+
console.log("u.XFormEdit.inputChgNew.context" + context);
|
|
34
|
+
var v = context.v;
|
|
35
|
+
var item = context.item;
|
|
36
|
+
console.log("u.XFormEdit.inputChgNew.value" + value);
|
|
37
|
+
item[v.attr] = value;
|
|
38
38
|
//this.evtRefresh();
|
|
39
39
|
//this.props.notifyChangeFn();
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
render
|
|
44
|
-
if(!this.props.metadata.fields)
|
|
45
|
-
|
|
43
|
+
render() {
|
|
44
|
+
if (!this.props.metadata.fields)
|
|
45
|
+
return <h3>No metadata.fields on XFormEdit</h3>
|
|
46
46
|
else
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
47
|
+
return (
|
|
48
|
+
<React.Fragment>
|
|
49
|
+
<h6>{DEBUG_ID2 && '[' + this.props.id + ']'}</h6>
|
|
50
|
+
<h3>{this.props.metadata.title}</h3>
|
|
51
|
+
|
|
52
|
+
{this.props.metadata.fields.filter((item) => { return (item.show) }).map((v, i) => {
|
|
53
|
+
if (v.type === 'l') /*list*/ {
|
|
54
|
+
return <React.Fragment key={i}>
|
|
55
|
+
<div xclassName="card">
|
|
56
|
+
<div>{v.label}</div>
|
|
57
|
+
<XSelect3 list={v.lov} value={this.props.formData[v.attr]} disabled={v.readOnly} onChange={(ev) => this.props.formData[v.attr] = ev.target.value} />
|
|
58
|
+
<br />
|
|
59
|
+
<p> </p>
|
|
60
|
+
</div>
|
|
61
|
+
</React.Fragment>
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
if (v.type === 'a') /* array */ {
|
|
65
|
+
return (
|
|
66
|
+
<React.Fragment key={i}>
|
|
67
|
+
<div xclassName="card"><div>{v.label}</div>
|
|
68
|
+
<JZInPlaceListComponent _id={this.props.id + '_F' + i} textlabels={true} list={this.props.formData[v.attr]} listConfig={v.listConfig} newItemFN={v.newItemFN} />
|
|
69
|
+
</div>
|
|
70
|
+
</React.Fragment>)
|
|
71
|
+
}
|
|
72
|
+
else
|
|
73
|
+
if (v.type === 'd') /* date */ {
|
|
74
|
+
return (
|
|
75
|
+
<React.Fragment key={i}>
|
|
76
|
+
<div className=""><div>{v.label}</div>
|
|
77
|
+
<XDateSelect id={this.props.id + '_F' + i} width={v.width} label={v.label} disabled={v.readOnly} value={this.props.formData[v.attr]} onChange={(v) => this.props.formData[v.attr] = v} />
|
|
60
78
|
</div>
|
|
61
|
-
</React.Fragment>
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return (
|
|
92
|
-
<React.Fragment key={i} >{DEBUG_ID2&&'['+this.props.id+'_F'+i+']'}
|
|
93
|
-
<XInputExternal type={v.type=='n'?'number':''} id={this.props.id+'_F'+i} width={v.width} label = {v.label} readOnly={v.readOnly} value={this.props.formData[v.attr]} /*onChangeNew={(value)=>this.props.formData[v.attr]=ev.target.value}*/ onChangeNew={this.inputChangeNew} context={{item:this.props.formData,v:v}} />
|
|
94
|
-
</React.Fragment>)
|
|
95
|
-
}
|
|
96
|
-
})}
|
|
97
|
-
{this.props.btn0&& <XButton label = {this.props.btn0.label} onClick={this.props.btn0.evt} />}
|
|
98
|
-
</React.Fragment>
|
|
99
|
-
);
|
|
79
|
+
</React.Fragment>)
|
|
80
|
+
}
|
|
81
|
+
else
|
|
82
|
+
if (v.type === 'c') /* check */ {
|
|
83
|
+
return (
|
|
84
|
+
<React.Fragment key={i}>
|
|
85
|
+
<div className=""><div>{v.label}</div>
|
|
86
|
+
<XCheckbox id={this.props.id + '_F' + i} width={v.width} label={v.label} disabled={v.readOnly} value={this.props.formData[v.attr]} onChange={(v) => this.props.formData[v.attr] = v} />
|
|
87
|
+
</div>
|
|
88
|
+
</React.Fragment>)
|
|
89
|
+
}
|
|
90
|
+
else
|
|
91
|
+
if (v.type === 'file') /* file */ {
|
|
92
|
+
return (
|
|
93
|
+
<React.Fragment key={i}>
|
|
94
|
+
<div className=""><div>{v.label}</div>
|
|
95
|
+
<p>{this.props.formData[v.attr]?this.props.formData[v.attr]:"No file selected"}</p>
|
|
96
|
+
<XButton id={this.props.id + '_F' + i} attachFile={true} disabled={v.readOnly} onClick={(e)=>{this.props.formData[v.attr]=e.target.files[0].name;this.props.formData.filedata=e.target.files[0]}} textlabel='Select File'></XButton>
|
|
97
|
+
</div>
|
|
98
|
+
</React.Fragment>)
|
|
99
|
+
} else
|
|
100
|
+
return (
|
|
101
|
+
<React.Fragment key={i} >{DEBUG_ID2 && '[' + this.props.id + '_F' + i + ']'}
|
|
102
|
+
<XInputExternal type={v.type == 'n' ? 'number' : ''} id={this.props.id + '_F' + i} width={v.width} label={v.label} readOnly={v.readOnly} value={this.props.formData[v.attr]} /*onChangeNew={(value)=>this.props.formData[v.attr]=ev.target.value}*/ onChangeNew={this.inputChangeNew} context={{ item: this.props.formData, v: v }} />
|
|
103
|
+
</React.Fragment>)
|
|
104
|
+
}
|
|
105
|
+
})}
|
|
106
|
+
{this.props.btn0 && <XButton label={this.props.btn0.label} onClick={this.props.btn0.evt} />}
|
|
107
|
+
</React.Fragment>
|
|
108
|
+
);
|
|
100
109
|
}
|
|
101
110
|
|
|
102
111
|
}
|
|
103
112
|
|
|
104
113
|
|
|
105
|
-
export {XFormEdit};
|
|
114
|
+
export { XFormEdit };
|
|
@@ -117,7 +117,7 @@ function nfmtM(n) {
|
|
|
117
117
|
</thead>
|
|
118
118
|
<tbody>
|
|
119
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} /> })}
|
|
120
|
+
return <XTableCell key={index} item={item} index={index} lastIndex={arr.length} {...this.props} notifyChangeFn={this.cellChanged} api={this.props.api} /> })}
|
|
121
121
|
</tbody>
|
|
122
122
|
</table>
|
|
123
123
|
</div>
|
|
@@ -134,7 +134,7 @@ function nfmtM(n) {
|
|
|
134
134
|
//var XTableCell_ID=0;
|
|
135
135
|
|
|
136
136
|
/**
|
|
137
|
-
*
|
|
137
|
+
* recebe "api"> só quando chamado de JZlist vem preenchido. Usa para download.
|
|
138
138
|
*/
|
|
139
139
|
class XTableCell extends React.Component {
|
|
140
140
|
constructor(props) {
|
|
@@ -186,6 +186,24 @@ class XTableCell extends React.Component {
|
|
|
186
186
|
this.props.notifyChangeFn();
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
evtDownload = async(f) => {
|
|
190
|
+
alert(f)
|
|
191
|
+
if(this.props.api) {
|
|
192
|
+
var blob=await this.props.api.download(urlAPI+'/api/download/'+f)
|
|
193
|
+
// 2. Create blob link to download
|
|
194
|
+
const url = window.URL.createObjectURL(new Blob([blob]));
|
|
195
|
+
const link = document.createElement('a');
|
|
196
|
+
link.href = url;
|
|
197
|
+
link.setAttribute('download', `${f}`);
|
|
198
|
+
// 3. Append to html page
|
|
199
|
+
document.body.appendChild(link);
|
|
200
|
+
// 4. Force download
|
|
201
|
+
link.click();
|
|
202
|
+
// 5. Clean up and remove the link
|
|
203
|
+
link.parentNode.removeChild(link);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
189
207
|
renderListItem(item,p1,lastIndex) {
|
|
190
208
|
//var kk='ASD'+(p1+1234);
|
|
191
209
|
//XTableCell_ID=XTableCell_ID+1;
|
|
@@ -252,7 +270,9 @@ class XTableCell extends React.Component {
|
|
|
252
270
|
if(v.type=='c'){
|
|
253
271
|
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
272
|
}
|
|
255
|
-
|
|
273
|
+
if(v.type=='file'){
|
|
274
|
+
return <td key={i} align={v.align} className={v.className} id={this.props.id+'_R'+p1+'_C'+i}><a onClick={()=>{self.evtDownload(cellFmt)}}>{cellFmt}</a> {DEBUG_ID2&&'['+this.props.id+'_R'+p1+'_C'+i+']'}</td>
|
|
275
|
+
}
|
|
256
276
|
return <td key={i} align={v.align} className={v.className} id={this.props.id+'_R'+p1+'_C'+i}>{cellFmt} {DEBUG_ID2&&'['+this.props.id+'_R'+p1+'_C'+i+']'}</td>
|
|
257
277
|
}
|
|
258
278
|
})}
|
package/package.json
CHANGED
package/releasenotes.txt
CHANGED
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
0.1.9: doc fix
|
|
10
10
|
0.1.10: add css
|
|
11
11
|
0.0.11: no alert on update / XButton upload com text=true
|
|
12
|
-
0.1.12:
|
|
12
|
+
0.1.12: remove getStorage from APIAdapter
|
|
13
|
+
0.1.13: new form type: "f"=file upload (Part 1: UI CREATE)
|
|
14
|
+
0.1.14: RestAPIAdapter => (Part 2: CREATE: file upload REST API / Part3: show fileField on list with download link
|
|
13
15
|
|
|
14
16
|
npm login
|
|
15
17
|
npm publish --access public
|