@jinntec/fore 2.1.1 → 2.3.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.
- package/README.md +2 -2
- package/dist/fore-dev.js +2 -2
- package/dist/fore-dev.js.map +1 -1
- package/dist/fore.js +2 -2
- package/dist/fore.js.map +1 -1
- package/index.js +4 -2
- package/package.json +10 -38
- package/resources/fore.css +263 -262
- package/resources/vars.css +8 -0
- package/src/DependencyNotifyingDomFacade.js +1 -0
- package/src/ForeElementMixin.js +243 -228
- package/src/actions/abstract-action.js +407 -398
- package/src/actions/fx-action.js +6 -6
- package/src/actions/fx-append.js +1 -1
- package/src/actions/fx-call.js +63 -62
- package/src/actions/fx-confirm.js +11 -11
- package/src/actions/fx-construct-done.js +4 -4
- package/src/actions/fx-copy.js +36 -36
- package/src/actions/fx-delete.js +77 -79
- package/src/actions/fx-dispatch.js +14 -14
- package/src/actions/fx-hide.js +15 -15
- package/src/actions/fx-insert.js +9 -12
- package/src/actions/fx-insertchild.js +88 -0
- package/src/actions/fx-load.js +188 -185
- package/src/actions/fx-message.js +18 -19
- package/src/actions/fx-refresh.js +10 -10
- package/src/actions/fx-reload.js +16 -14
- package/src/actions/fx-replace.js +0 -1
- package/src/actions/fx-reset.js +31 -31
- package/src/actions/fx-send.js +59 -52
- package/src/actions/fx-setattribute.js +48 -49
- package/src/actions/fx-setfocus.js +54 -58
- package/src/actions/fx-setvalue.js +85 -81
- package/src/actions/fx-show.js +11 -11
- package/src/actions/fx-toggle.js +2 -2
- package/src/actions/fx-toggleboolean.js +38 -39
- package/src/actions/fx-unmodified.js +27 -0
- package/src/actions/fx-update.js +6 -6
- package/src/dep_graph.js +1 -1
- package/src/drawdown.js +23 -30
- package/src/events.js +19 -19
- package/src/fore.js +143 -125
- package/src/functions/common-function.js +24 -25
- package/src/functions/fx-function.js +6 -99
- package/src/functions/fx-functionlib.js +56 -0
- package/src/functions/registerFunction.js +112 -0
- package/src/fx-bind.js +19 -24
- package/src/fx-connection.js +226 -0
- package/src/fx-fore.js +844 -815
- package/src/fx-header.js +4 -4
- package/src/fx-instance.js +25 -29
- package/src/fx-model.js +405 -380
- package/src/fx-submission.js +399 -397
- package/src/fx-var.js +13 -12
- package/src/getInScopeContext.js +102 -89
- package/src/json-util.js +24 -24
- package/src/lab/fore-component.js +48 -52
- package/src/lab/instance-inspector.js +13 -16
- package/src/modelitem.js +48 -10
- package/src/relevance.js +12 -16
- package/src/tools/adi.js +858 -812
- package/src/tools/fx-action-log.js +377 -295
- package/src/tools/fx-devtools.js +210 -210
- package/src/tools/fx-dom-inspector.js +123 -122
- package/src/tools/fx-json-instance.js +262 -253
- package/src/tools/fx-log-item.js +6 -11
- package/src/tools/fx-log-settings.js +358 -301
- package/src/tools/fx-minimap.js +186 -177
- package/src/tools/helpers.js +1 -1
- package/src/ui/abstract-control.js +73 -53
- package/src/ui/fx-case.js +59 -7
- package/src/ui/fx-container.js +13 -14
- package/src/ui/fx-control.js +572 -538
- package/src/ui/fx-dialog.js +3 -3
- package/src/ui/fx-droptarget.js +3 -4
- package/src/ui/fx-group.js +4 -2
- package/src/ui/fx-hint.js +3 -0
- package/src/ui/fx-inspector.js +5 -5
- package/src/ui/fx-items.js +11 -11
- package/src/ui/fx-output.js +10 -12
- package/src/ui/fx-repeat-attributes.js +23 -27
- package/src/ui/fx-repeat.js +347 -344
- package/src/ui/fx-repeatitem.js +75 -68
- package/src/ui/fx-switch.js +39 -14
- package/src/ui/fx-trigger.js +4 -4
- package/src/withDraggability.js +193 -191
- package/src/xpath-evaluation.js +969 -958
- package/src/xpath-util.js +161 -134
package/src/fx-submission.js
CHANGED
|
@@ -1,142 +1,144 @@
|
|
|
1
|
-
import {Fore} from './fore.js';
|
|
2
|
-
import {Relevance} from './relevance.js';
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import getInScopeContext from './getInScopeContext.js';
|
|
6
|
-
import {XPathUtil} from "./xpath-util.js";
|
|
1
|
+
import { Fore } from './fore.js';
|
|
2
|
+
import { Relevance } from './relevance.js';
|
|
3
|
+
import { evaluateXPath } from './xpath-evaluation.js';
|
|
4
|
+
import ForeElementMixin from './ForeElementMixin.js';
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* todo: validate='false'
|
|
10
8
|
*/
|
|
11
|
-
export class FxSubmission extends
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
export class FxSubmission extends ForeElementMixin {
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
this.attachShadow({ mode: 'open' });
|
|
13
|
+
this.credentials = '';
|
|
14
|
+
this.parameters = new Map();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
connectedCallback() {
|
|
18
|
+
// this.style.display = 'none';
|
|
19
|
+
this.methods = ['get', 'put', 'post', 'delete', 'head', 'urlencoded-post'];
|
|
20
|
+
|
|
21
|
+
this.model = this.parentNode;
|
|
22
|
+
|
|
23
|
+
// ### initialize properties with defaults
|
|
24
|
+
// if (!this.hasAttribute('id')) throw new Error('id is required');
|
|
25
|
+
if (!this.hasAttribute('id')) console.warn('id is required');
|
|
26
|
+
this.id = this.getAttribute('id');
|
|
27
|
+
|
|
28
|
+
/** if present should be a existing instance id */
|
|
29
|
+
this.instance = this.hasAttribute('instance') ? this.getAttribute('instance') : null;
|
|
30
|
+
|
|
31
|
+
/** if present will determine XPath where to insert a response into when mode is 'replace' */
|
|
32
|
+
this.into = this.hasAttribute('into') ? this.getAttribute('into') : null;
|
|
33
|
+
|
|
34
|
+
/** http method */
|
|
35
|
+
this.method = this.hasAttribute('method') ? this.getAttribute('method') : 'get';
|
|
36
|
+
|
|
37
|
+
/** relevance processing - one of 'remove, keep or empty' */
|
|
38
|
+
this.nonrelevant = this.hasAttribute('nonrelevant')
|
|
39
|
+
? this.getAttribute('nonrelevant')
|
|
40
|
+
: 'remove';
|
|
41
|
+
|
|
42
|
+
/** replace might be 'all', 'instance' or 'none' */
|
|
43
|
+
this.replace = this.hasAttribute('replace') ? this.getAttribute('replace') : 'all';
|
|
44
|
+
|
|
45
|
+
this.serialization = this.hasAttribute('serialization')
|
|
46
|
+
? this.getAttribute('serialization')
|
|
47
|
+
: 'xml';
|
|
48
|
+
|
|
49
|
+
this.mediatype = this.hasAttribute('mediatype')
|
|
50
|
+
? this.getAttribute('mediatype')
|
|
51
|
+
: 'application/xml';
|
|
52
|
+
|
|
53
|
+
this.responseMediatype = this.hasAttribute('response-mediatype')
|
|
54
|
+
? this.getAttribute('response-mediatype')
|
|
55
|
+
: this.mediatype;
|
|
56
|
+
this.url = this.hasAttribute('url') ? this.getAttribute('url') : null;
|
|
57
|
+
|
|
58
|
+
this.targetref = this.hasAttribute('targetref') ? this.getAttribute('targetref') : null;
|
|
59
|
+
|
|
60
|
+
this.validate = this.getAttribute('validate') ? this.getAttribute('validate') : 'true';
|
|
61
|
+
this.credentials = this.hasAttribute('credentials')
|
|
62
|
+
? this.getAttribute('credentials')
|
|
63
|
+
: 'same-origin';
|
|
64
|
+
if (!['same-origin', 'include', 'omit'].includes(this.credentials)) {
|
|
65
|
+
console.error(
|
|
66
|
+
`fx-submission: the value of credentials is not valid. Expected 'same-origin', 'include' or 'omit' but got '${this.credentials}'`,
|
|
67
|
+
this,
|
|
68
|
+
);
|
|
17
69
|
}
|
|
70
|
+
this.shadowRoot.innerHTML = this.renderHTML();
|
|
71
|
+
}
|
|
18
72
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
this.model = this.parentNode;
|
|
24
|
-
|
|
25
|
-
// ### initialize properties with defaults
|
|
26
|
-
// if (!this.hasAttribute('id')) throw new Error('id is required');
|
|
27
|
-
if (!this.hasAttribute('id')) console.warn('id is required');
|
|
28
|
-
this.id = this.getAttribute('id');
|
|
29
|
-
|
|
30
|
-
/** if present should be a existing instance id */
|
|
31
|
-
this.instance = this.hasAttribute('instance') ? this.getAttribute('instance') : null;
|
|
32
|
-
|
|
33
|
-
/** if present will determine XPath where to insert a response into when mode is 'replace' */
|
|
34
|
-
this.into = this.hasAttribute('into') ? this.getAttribute('into') : null;
|
|
35
|
-
|
|
36
|
-
/** http method */
|
|
37
|
-
this.method = this.hasAttribute('method') ? this.getAttribute('method') : 'get';
|
|
38
|
-
|
|
39
|
-
/** relevance processing - one of 'remove, keep or empty' */
|
|
40
|
-
this.nonrelevant = this.hasAttribute('nonrelevant')
|
|
41
|
-
? this.getAttribute('nonrelevant')
|
|
42
|
-
: 'remove';
|
|
43
|
-
|
|
44
|
-
/** replace might be 'all', 'instance' or 'none' */
|
|
45
|
-
this.replace = this.hasAttribute('replace') ? this.getAttribute('replace') : 'all';
|
|
46
|
-
|
|
47
|
-
this.serialization = this.hasAttribute('serialization')
|
|
48
|
-
? this.getAttribute('serialization')
|
|
49
|
-
: 'xml';
|
|
50
|
-
|
|
51
|
-
this.mediatype = this.hasAttribute('mediatype')
|
|
52
|
-
? this.getAttribute('mediatype')
|
|
53
|
-
: 'application/xml';
|
|
54
|
-
|
|
55
|
-
this.responseMediatype = this.hasAttribute('response-mediatype') ? this.getAttribute('response-mediatype') : this.mediatype;
|
|
56
|
-
this.url = this.hasAttribute('url') ? this.getAttribute('url') : null;
|
|
57
|
-
|
|
58
|
-
this.targetref = this.hasAttribute('targetref') ? this.getAttribute('targetref') : null;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
this.validate = this.getAttribute('validate') ? this.getAttribute('validate') : 'true';
|
|
62
|
-
this.credentials = this.hasAttribute('credentials')
|
|
63
|
-
? this.getAttribute('credentials')
|
|
64
|
-
: 'same-origin';
|
|
65
|
-
if (!['same-origin', 'include', 'omit'].includes(this.credentials)) {
|
|
66
|
-
console.error(`fx-submission: the value of credentials is not valid. Expected 'same-origin', 'include' or 'omit' but got '${this.credentials}'`, this);
|
|
67
|
-
}
|
|
68
|
-
this.shadowRoot.innerHTML = this.renderHTML();
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// eslint-disable-next-line class-methods-use-this
|
|
72
|
-
renderHTML() {
|
|
73
|
-
return `
|
|
73
|
+
// eslint-disable-next-line class-methods-use-this
|
|
74
|
+
renderHTML() {
|
|
75
|
+
return `
|
|
74
76
|
<slot></slot>
|
|
75
77
|
`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async submit() {
|
|
81
|
+
await Fore.dispatch(this, 'submit', { submission: this });
|
|
82
|
+
await this._submit();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async _submit() {
|
|
86
|
+
// console.log('submitting....', this.getAttribute('id'));
|
|
87
|
+
this.evalInContext();
|
|
88
|
+
const model = this.getModel();
|
|
89
|
+
|
|
90
|
+
model.recalculate();
|
|
91
|
+
|
|
92
|
+
if (this.validate === 'true' && this.method !== 'get') {
|
|
93
|
+
const valid = model.revalidate();
|
|
94
|
+
if (!valid) {
|
|
95
|
+
console.log('validation failed. Submission stopped');
|
|
96
|
+
this.getOwnerForm().classList.add('submit-validation-failed');
|
|
97
|
+
// ### allow alerts to pop up
|
|
98
|
+
// this.dispatch('submit-error', {});
|
|
99
|
+
Fore.dispatch(this, 'submit-error', {});
|
|
100
|
+
this.getModel().parentNode.refresh(true);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
76
103
|
}
|
|
104
|
+
await this._serializeAndSend();
|
|
105
|
+
}
|
|
77
106
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
107
|
+
_getProperty(attrName) {
|
|
108
|
+
if (this.parameters.has(attrName)) {
|
|
109
|
+
return this.parameters.get(attrName);
|
|
81
110
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
Fore.dispatch(this, 'submit-error', {});
|
|
98
|
-
this.getModel().parentNode.refresh(true);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
await this._serializeAndSend();
|
|
111
|
+
return this.getAttribute(attrName);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* sends the data after evaluating
|
|
116
|
+
*
|
|
117
|
+
* @private
|
|
118
|
+
*/
|
|
119
|
+
async _serializeAndSend() {
|
|
120
|
+
const url = this._getProperty('url');
|
|
121
|
+
const resolvedUrl = this.evaluateAttributeTemplateExpression(url, this);
|
|
122
|
+
// console.log('resolvedUrl', resolvedUrl);
|
|
123
|
+
const instance = this.getInstance();
|
|
124
|
+
if (!instance) {
|
|
125
|
+
Fore.dispatch(this, 'warn', { message: `instance not found ${instance.getAttribute('id')}` });
|
|
103
126
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
127
|
+
const instType = instance.getAttribute('type');
|
|
128
|
+
// console.log('instance type', instance.type);
|
|
129
|
+
|
|
130
|
+
let serialized;
|
|
131
|
+
if (this.serialization === 'none') {
|
|
132
|
+
serialized = undefined;
|
|
133
|
+
} else {
|
|
134
|
+
// const relevant = this.selectRelevant(instance.type);
|
|
135
|
+
const relevant = Relevance.selectRelevant(this, instType);
|
|
136
|
+
serialized = this._serialize(instType, relevant);
|
|
110
137
|
}
|
|
111
138
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
* @private
|
|
116
|
-
*/
|
|
117
|
-
async _serializeAndSend() {
|
|
118
|
-
const url = this._getProperty('url');
|
|
119
|
-
const resolvedUrl = this.evaluateAttributeTemplateExpression(url,this);
|
|
120
|
-
console.log('resolvedUrl',resolvedUrl);
|
|
121
|
-
const instance = this.getInstance();
|
|
122
|
-
if (!instance) {
|
|
123
|
-
Fore.dispatch(this, 'warn', {message: `instance not found ${instance.getAttribute('id')}`})
|
|
124
|
-
}
|
|
125
|
-
const instType = instance.getAttribute('type');
|
|
126
|
-
// console.log('instance type', instance.type);
|
|
127
|
-
|
|
128
|
-
let serialized;
|
|
129
|
-
if (this.serialization === 'none') {
|
|
130
|
-
serialized = undefined;
|
|
131
|
-
} else {
|
|
132
|
-
// const relevant = this.selectRelevant(instance.type);
|
|
133
|
-
const relevant = Relevance.selectRelevant(this, instType);
|
|
134
|
-
serialized = this._serialize(instType, relevant);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// let serialized = serializer.serializeToString(relevant);
|
|
138
|
-
if (this.method.toLowerCase() === 'get') {
|
|
139
|
-
/*
|
|
139
|
+
// let serialized = serializer.serializeToString(relevant);
|
|
140
|
+
if (this.method.toLowerCase() === 'get') {
|
|
141
|
+
/*
|
|
140
142
|
todo: serialize the bound instance element names as get parameters and using their text values
|
|
141
143
|
as param values. leave out empty params and create querystring from the result.Elements may
|
|
142
144
|
have exactly level deep or are otherwise ignored.
|
|
@@ -153,216 +155,215 @@ export class FxSubmission extends foreElementMixin(HTMLElement) {
|
|
|
153
155
|
|
|
154
156
|
*/
|
|
155
157
|
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
// console.log('data being send', serialized);
|
|
159
|
-
// console.log('submitting data',serialized);
|
|
160
|
-
|
|
161
|
-
// if (resolvedUrl === '#echo') {
|
|
162
|
-
if (resolvedUrl.startsWith('#echo')) {
|
|
163
|
-
const data = this._parse(serialized, instance);
|
|
164
|
-
this._handleResponse(data);
|
|
165
|
-
// this.dispatch('submit-done', {});
|
|
166
|
-
console.log('### <<<<< submit-done >>>>>');
|
|
167
|
-
Fore.dispatch(this, 'submit-done', {});
|
|
168
|
-
this.parameters.clear();
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (resolvedUrl.startsWith('localStore:')) {
|
|
173
|
-
|
|
174
|
-
if (this.method === 'get' || this.method === 'consume') {
|
|
175
|
-
// let data = this._parse(serialized, instance);
|
|
176
|
-
this.replace = 'instance';
|
|
177
|
-
const key = resolvedUrl.substring(resolvedUrl.indexOf(':') + 1);
|
|
178
|
-
const serialized = localStorage.getItem(key);
|
|
179
|
-
if (!serialized) {
|
|
180
|
-
Fore.dispatch(this, 'submit-error', {message: `Error reading key ${key} from localstorage`});
|
|
181
|
-
this.parameters.clear();
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
const data = this._parse(serialized, instance);
|
|
185
|
-
this._handleResponse(data);
|
|
186
|
-
if (this.method === 'consume') {
|
|
187
|
-
localStorage.removeItem(key);
|
|
188
|
-
}
|
|
189
|
-
console.log('### <<<<< submit-done >>>>>');
|
|
190
|
-
Fore.dispatch(this, 'submit-done', {});
|
|
191
|
-
}
|
|
192
|
-
if (this.method === 'post') {
|
|
193
|
-
// let data = this._parse(serialized, instance);
|
|
194
|
-
const key = resolvedUrl.substring(resolvedUrl.indexOf(':') + 1);
|
|
195
|
-
localStorage.setItem(key, serialized);
|
|
196
|
-
this._handleResponse(instance.instanceData);
|
|
197
|
-
console.log('### <<<<< submit-done >>>>>');
|
|
198
|
-
Fore.dispatch(this, 'submit-done', {});
|
|
199
|
-
}
|
|
200
|
-
if (this.method === 'delete') {
|
|
201
|
-
const key = resolvedUrl.substring(resolvedUrl.indexOf(':') + 1);
|
|
202
|
-
localStorage.removeItem(key);
|
|
203
|
-
const newInst = new DOMParser().parseFromString('<data></data>', 'application/xml');
|
|
204
|
-
this.replace = 'instance';
|
|
205
|
-
this._handleResponse(newInst);
|
|
206
|
-
console.log('### <<<<< submit-done >>>>>');
|
|
207
|
-
Fore.dispatch(this, 'submit-done', {});
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// ### setting headers
|
|
214
|
-
const headers = this._getHeaders();
|
|
215
|
-
|
|
216
|
-
if (!this.methods.includes(this.method.toLowerCase())) {
|
|
217
|
-
// this.dispatch('error', { message: `Unknown method ${this.method}` });
|
|
218
|
-
Fore.dispatch(this, 'error', {message: `Unknown method ${this.method}`});
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
try {
|
|
222
|
-
const response = await fetch(resolvedUrl, {
|
|
223
|
-
method: this.method,
|
|
224
|
-
credentials: this.credentials,
|
|
225
|
-
mode:'cors',
|
|
226
|
-
headers,
|
|
227
|
-
body: serialized,
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
if (!response.ok || response.status > 400) {
|
|
231
|
-
// this.dispatch('submit-error', { message: `Error while submitting ${this.id}` });
|
|
232
|
-
Fore.dispatch(this, 'submit-error', {message: `Error while submitting ${this.id}`});
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
const contentType = response.headers.get('content-type').toLowerCase();
|
|
237
|
-
if (
|
|
238
|
-
contentType.startsWith('text/')
|
|
239
|
-
) {
|
|
240
|
-
const text = await response.text();
|
|
241
|
-
this._handleResponse(text, resolvedUrl,contentType);
|
|
242
|
-
} else if (contentType.startsWith('application/json')) {
|
|
243
|
-
const json = await response.json();
|
|
244
|
-
this._handleResponse(json, resolvedUrl,contentType);
|
|
245
|
-
} else if (contentType.startsWith('application/xml')) {
|
|
246
|
-
const text = await response.text();
|
|
247
|
-
const xml = new DOMParser().parseFromString(text, 'application/xml');
|
|
248
|
-
this._handleResponse(xml, resolvedUrl,contentType);
|
|
249
|
-
} else {
|
|
250
|
-
const blob = await response.blob();
|
|
251
|
-
this._handleResponse(blob, resolvedUrl,contentType);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// this.dispatch('submit-done', {});
|
|
255
|
-
console.log(`### <<<<< ${this.id} submit-done >>>>>`);
|
|
256
|
-
Fore.dispatch(this, 'submit-done', {});
|
|
257
|
-
} catch (error) {
|
|
258
|
-
Fore.dispatch(this, 'submit-error', {error: error.message});
|
|
259
|
-
} finally {
|
|
260
|
-
this.parameters.clear();
|
|
261
|
-
const download = document.querySelector('[download]');
|
|
262
|
-
if(download){
|
|
263
|
-
document.body.removeChild(download);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
158
|
+
serialized = undefined;
|
|
266
159
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
return data;
|
|
160
|
+
// console.log('data being send', serialized);
|
|
161
|
+
// console.log('submitting data',serialized);
|
|
162
|
+
|
|
163
|
+
// if (resolvedUrl === '#echo') {
|
|
164
|
+
if (resolvedUrl.startsWith('#echo')) {
|
|
165
|
+
const data = this._parse(serialized, instance);
|
|
166
|
+
this._handleResponse(data);
|
|
167
|
+
// this.dispatch('submit-done', {});
|
|
168
|
+
console.log('### <<<<< submit-done >>>>>');
|
|
169
|
+
Fore.dispatch(this, 'submit-done', {});
|
|
170
|
+
this.parameters.clear();
|
|
171
|
+
return;
|
|
280
172
|
}
|
|
281
173
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
174
|
+
if (resolvedUrl.startsWith('localStore:')) {
|
|
175
|
+
if (this.method === 'get' || this.method === 'consume') {
|
|
176
|
+
// let data = this._parse(serialized, instance);
|
|
177
|
+
this.replace = 'instance';
|
|
178
|
+
const key = resolvedUrl.substring(resolvedUrl.indexOf(':') + 1);
|
|
179
|
+
const serialized = localStorage.getItem(key);
|
|
180
|
+
if (!serialized) {
|
|
181
|
+
Fore.dispatch(this, 'submit-error', {
|
|
182
|
+
message: `Error reading key ${key} from localstorage`,
|
|
183
|
+
});
|
|
184
|
+
this.parameters.clear();
|
|
185
|
+
return;
|
|
291
186
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
187
|
+
const data = this._parse(serialized, instance);
|
|
188
|
+
this._handleResponse(data);
|
|
189
|
+
if (this.method === 'consume') {
|
|
190
|
+
localStorage.removeItem(key);
|
|
295
191
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
192
|
+
console.log('### <<<<< submit-done >>>>>');
|
|
193
|
+
Fore.dispatch(this, 'submit-done', {});
|
|
194
|
+
}
|
|
195
|
+
if (this.method === 'post') {
|
|
196
|
+
// let data = this._parse(serialized, instance);
|
|
197
|
+
const key = resolvedUrl.substring(resolvedUrl.indexOf(':') + 1);
|
|
198
|
+
localStorage.setItem(key, serialized);
|
|
199
|
+
this._handleResponse(instance.instanceData);
|
|
200
|
+
console.log('### <<<<< submit-done >>>>>');
|
|
201
|
+
Fore.dispatch(this, 'submit-done', {});
|
|
202
|
+
}
|
|
203
|
+
if (this.method === 'delete') {
|
|
204
|
+
const key = resolvedUrl.substring(resolvedUrl.indexOf(':') + 1);
|
|
205
|
+
localStorage.removeItem(key);
|
|
206
|
+
const newInst = new DOMParser().parseFromString('<data></data>', 'application/xml');
|
|
207
|
+
this.replace = 'instance';
|
|
208
|
+
this._handleResponse(newInst);
|
|
209
|
+
console.log('### <<<<< submit-done >>>>>');
|
|
210
|
+
Fore.dispatch(this, 'submit-done', {});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return;
|
|
304
214
|
}
|
|
305
215
|
|
|
306
|
-
|
|
307
|
-
|
|
216
|
+
// ### setting headers
|
|
217
|
+
const headers = this._getHeaders();
|
|
308
218
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
// ### needed to overwrite browsers' setting of 'Accept' header
|
|
314
|
-
if (headers.has('Accept')) {
|
|
315
|
-
headers.delete('Accept');
|
|
316
|
-
}
|
|
317
|
-
// headers.append('Accept', 'application/xml');
|
|
318
|
-
|
|
319
|
-
// ### add header defined by fx-header elements
|
|
320
|
-
const headerElems = this.querySelectorAll('fx-header');
|
|
321
|
-
Array.from(headerElems).forEach(header => {
|
|
322
|
-
const {name} = header;
|
|
323
|
-
const val = header.getValue();
|
|
324
|
-
headers.append(name, val);
|
|
325
|
-
});
|
|
326
|
-
return headers;
|
|
219
|
+
if (!this.methods.includes(this.method.toLowerCase())) {
|
|
220
|
+
// this.dispatch('error', { message: `Unknown method ${this.method}` });
|
|
221
|
+
Fore.dispatch(this, 'error', { message: `Unknown method ${this.method}` });
|
|
222
|
+
return;
|
|
327
223
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
224
|
+
try {
|
|
225
|
+
const response = await fetch(resolvedUrl, {
|
|
226
|
+
method: this.method,
|
|
227
|
+
credentials: this.credentials,
|
|
228
|
+
mode: 'cors',
|
|
229
|
+
headers,
|
|
230
|
+
body: serialized,
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
if (!response.ok || response.status > 400) {
|
|
234
|
+
// this.dispatch('submit-error', { message: `Error while submitting ${this.id}` });
|
|
235
|
+
Fore.dispatch(this, 'submit-error', { message: `Error while submitting ${this.id}` });
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const contentType = response.headers.get('content-type').toLowerCase();
|
|
240
|
+
if (contentType.startsWith('text/')) {
|
|
241
|
+
const text = await response.text();
|
|
242
|
+
this._handleResponse(text, resolvedUrl, contentType);
|
|
243
|
+
} else if (contentType.startsWith('application/json')) {
|
|
244
|
+
const json = await response.json();
|
|
245
|
+
this._handleResponse(json, resolvedUrl, contentType);
|
|
246
|
+
} else if (contentType.startsWith('application/xml')) {
|
|
247
|
+
const text = await response.text();
|
|
248
|
+
const xml = new DOMParser().parseFromString(text, 'application/xml');
|
|
249
|
+
this._handleResponse(xml, resolvedUrl, contentType);
|
|
250
|
+
} else {
|
|
251
|
+
const blob = await response.blob();
|
|
252
|
+
this._handleResponse(blob, resolvedUrl, contentType);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// this.dispatch('submit-done', {});
|
|
256
|
+
// console.log(`### <<<<< ${this.id} submit-done >>>>>`);
|
|
257
|
+
Fore.dispatch(this, 'submit-done', {});
|
|
258
|
+
} catch (error) {
|
|
259
|
+
Fore.dispatch(this, 'submit-error', { error: error.message });
|
|
260
|
+
} finally {
|
|
261
|
+
this.parameters.clear();
|
|
262
|
+
const download = document.querySelector('[download]');
|
|
263
|
+
if (download) {
|
|
264
|
+
document.body.removeChild(download);
|
|
265
|
+
}
|
|
331
266
|
}
|
|
267
|
+
}
|
|
332
268
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
if (!targetInstance) {
|
|
341
|
-
throw new Error(`target instance not found: ${targetInstance}`);
|
|
342
|
-
}
|
|
343
|
-
return targetInstance;
|
|
269
|
+
_parse(serialized, instance) {
|
|
270
|
+
let data = null;
|
|
271
|
+
if (serialized && instance.getAttribute('type') === 'xml') {
|
|
272
|
+
data = new DOMParser().parseFromString(serialized, 'application/xml');
|
|
273
|
+
}
|
|
274
|
+
if (serialized && instance.getAttribute('type') === 'json') {
|
|
275
|
+
data = JSON.parse(serialized);
|
|
344
276
|
}
|
|
277
|
+
if (serialized && instance.getAttribute('type') === 'text') {
|
|
278
|
+
data = serialized;
|
|
279
|
+
}
|
|
280
|
+
return data;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
_serialize(instanceType, relevantNodes) {
|
|
284
|
+
if (this.serialization === 'application/x-www-form-urlencoded') {
|
|
285
|
+
// this.method = 'post';
|
|
286
|
+
const params = new URLSearchParams();
|
|
287
|
+
// console.log('nodes to serialize', relevantNodes);
|
|
288
|
+
Array.from(relevantNodes.children).forEach(child => {
|
|
289
|
+
params.append(child.nodeName, child.textContent);
|
|
290
|
+
});
|
|
291
|
+
return params;
|
|
292
|
+
}
|
|
293
|
+
if (instanceType === 'xml') {
|
|
294
|
+
const serializer = new XMLSerializer();
|
|
295
|
+
return serializer.serializeToString(relevantNodes);
|
|
296
|
+
}
|
|
297
|
+
if (instanceType === 'json') {
|
|
298
|
+
// console.warn('JSON serialization is not yet supported')
|
|
299
|
+
return JSON.stringify(relevantNodes);
|
|
300
|
+
}
|
|
301
|
+
if (instanceType === 'text') {
|
|
302
|
+
return relevantNodes;
|
|
303
|
+
}
|
|
304
|
+
throw new Error('unknown instance type ', instanceType);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
_getHeaders() {
|
|
308
|
+
const headers = new Headers();
|
|
309
|
+
|
|
310
|
+
// ### set content-type header according to type of instance
|
|
311
|
+
const instance = this.getInstance();
|
|
312
|
+
const contentType = Fore.getContentType(instance, this.serialization);
|
|
313
|
+
headers.append('Content-Type', contentType);
|
|
314
|
+
// ### needed to overwrite browsers' setting of 'Accept' header
|
|
315
|
+
if (headers.has('Accept')) {
|
|
316
|
+
headers.delete('Accept');
|
|
317
|
+
}
|
|
318
|
+
// headers.append('Accept', 'application/xml');
|
|
319
|
+
|
|
320
|
+
// ### add header defined by fx-header elements
|
|
321
|
+
const headerElems = this.querySelectorAll('fx-header');
|
|
322
|
+
Array.from(headerElems).forEach(header => {
|
|
323
|
+
const { name } = header;
|
|
324
|
+
const val = header.getValue();
|
|
325
|
+
headers.append(name, val);
|
|
326
|
+
});
|
|
327
|
+
return headers;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
_getUrlExpr() {
|
|
331
|
+
return this.storedTemplateExpressions.find(stored => stored.node.nodeName === 'url');
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
_getTargetInstance() {
|
|
335
|
+
let targetInstance;
|
|
336
|
+
if (this.instance) {
|
|
337
|
+
targetInstance = this.model.getInstance(this.instance);
|
|
338
|
+
} else {
|
|
339
|
+
targetInstance = this.model.getInstance('default');
|
|
340
|
+
}
|
|
341
|
+
if (!targetInstance) {
|
|
342
|
+
throw new Error(`target instance not found: ${targetInstance}`);
|
|
343
|
+
}
|
|
344
|
+
return targetInstance;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* handles replacement of instance data from response data.
|
|
349
|
+
*
|
|
350
|
+
* Please note that data might be
|
|
351
|
+
* @param data
|
|
352
|
+
* @private
|
|
353
|
+
*/
|
|
354
|
+
_handleResponse(data, resolvedUrl, contentType) {
|
|
355
|
+
// console.log('_handleResponse ', data);
|
|
345
356
|
|
|
346
|
-
|
|
347
|
-
* handles replacement of instance data from response data.
|
|
348
|
-
*
|
|
349
|
-
* Please note that data might be
|
|
350
|
-
* @param data
|
|
351
|
-
* @private
|
|
352
|
-
*/
|
|
353
|
-
_handleResponse(data, resolvedUrl, contentType) {
|
|
354
|
-
// console.log('_handleResponse ', data);
|
|
355
|
-
|
|
356
|
-
/*
|
|
357
|
+
/*
|
|
357
358
|
// ### responses need to be handled depending on their type.
|
|
358
359
|
if(this.type === 'json'){
|
|
359
360
|
|
|
360
361
|
}
|
|
361
362
|
*/
|
|
362
363
|
|
|
363
|
-
|
|
364
|
+
const targetInstance = this._getTargetInstance();
|
|
364
365
|
|
|
365
|
-
/*
|
|
366
|
+
/*
|
|
366
367
|
if(this.replace === 'merge'){
|
|
367
368
|
if(targetInstance.type !== 'xml') {
|
|
368
369
|
Fore.dispatch(this, "warn", {'message': 'merging of instances only work for type xml'});
|
|
@@ -382,89 +383,91 @@ export class FxSubmission extends foreElementMixin(HTMLElement) {
|
|
|
382
383
|
}
|
|
383
384
|
*/
|
|
384
385
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
// Skip any refreshes if the model is not yet inited
|
|
418
|
-
if (this.model.inited) {
|
|
419
|
-
this.model.updateModel(); // force update
|
|
420
|
-
this.getOwnerForm().refresh(true);
|
|
421
|
-
}
|
|
422
|
-
} else {
|
|
423
|
-
throw new Error(`target instance not found: ${targetInstance}`);
|
|
424
|
-
}
|
|
386
|
+
if (this.replace === 'instance') {
|
|
387
|
+
if (targetInstance) {
|
|
388
|
+
if (this.targetref) {
|
|
389
|
+
const [theTarget] = evaluateXPath(
|
|
390
|
+
this.targetref,
|
|
391
|
+
targetInstance.instanceData.firstElementChild,
|
|
392
|
+
this,
|
|
393
|
+
);
|
|
394
|
+
console.log('theTarget', theTarget);
|
|
395
|
+
const clone = data.firstElementChild;
|
|
396
|
+
const parent = theTarget.parentNode;
|
|
397
|
+
parent.replaceChild(clone, theTarget);
|
|
398
|
+
console.log('finally ', parent);
|
|
399
|
+
} else if (this.into) {
|
|
400
|
+
const [theTarget] = evaluateXPath(
|
|
401
|
+
this.into,
|
|
402
|
+
targetInstance.instanceData.firstElementChild,
|
|
403
|
+
this,
|
|
404
|
+
);
|
|
405
|
+
console.log('theTarget', theTarget);
|
|
406
|
+
if (data.nodeType === Node.DOCUMENT_NODE) {
|
|
407
|
+
theTarget.appendChild(data.firstElementChild);
|
|
408
|
+
} else {
|
|
409
|
+
theTarget.innerHTML = data;
|
|
410
|
+
}
|
|
411
|
+
} else {
|
|
412
|
+
const instanceData = data;
|
|
413
|
+
targetInstance.instanceData = instanceData;
|
|
414
|
+
// console.log('### replaced instance ', this.getModel().instances);
|
|
415
|
+
// console.log('### replaced instance ', targetInstance.instanceData);
|
|
425
416
|
}
|
|
426
417
|
|
|
427
|
-
if
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
downloadLink.setAttribute('href',`data:${contentType},${data}`);
|
|
432
|
-
document.body.appendChild(downloadLink);
|
|
433
|
-
downloadLink.click();
|
|
434
|
-
}
|
|
435
|
-
if (this.replace === 'all') {
|
|
436
|
-
const target = this._getProperty('target');
|
|
437
|
-
if(target && target === '_blank'){
|
|
438
|
-
const win = window.open("", "_blank");
|
|
439
|
-
win.document.write(`<pre>${data}</pre>`);
|
|
440
|
-
win.document.close();
|
|
441
|
-
}else{
|
|
442
|
-
document.open();
|
|
443
|
-
document.write(data);
|
|
444
|
-
document.close();
|
|
445
|
-
window.location.href = resolvedUrl;
|
|
446
|
-
}
|
|
447
|
-
// document.getElementsByTagName('html')[0].innerHTML = data;
|
|
448
|
-
}
|
|
449
|
-
if (this.replace === 'target' && contentType.startsWith('text/html')) {
|
|
450
|
-
// const target = this.getAttribute('target');
|
|
451
|
-
const target = this._getProperty('target');
|
|
452
|
-
const targetNode = document.querySelector(target);
|
|
453
|
-
if(targetNode){
|
|
454
|
-
targetNode.innerHTML = data;
|
|
455
|
-
}else{
|
|
456
|
-
Fore.dispatch(this, 'submit-error', {message:`targetNode for selector ${target} not found`});
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
if (this.replace === 'redirect') {
|
|
460
|
-
window.location.href = data;
|
|
418
|
+
// Skip any refreshes if the model is not yet inited
|
|
419
|
+
if (this.model.inited) {
|
|
420
|
+
this.model.updateModel(); // force update
|
|
421
|
+
this.getOwnerForm().refresh(true);
|
|
461
422
|
}
|
|
423
|
+
} else {
|
|
424
|
+
throw new Error(`target instance not found: ${targetInstance}`);
|
|
425
|
+
}
|
|
462
426
|
}
|
|
463
427
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
428
|
+
if (this.replace === 'download') {
|
|
429
|
+
const target = this._getProperty('target');
|
|
430
|
+
const downloadLink = document.createElement('a');
|
|
431
|
+
downloadLink.setAttribute('download', target);
|
|
432
|
+
downloadLink.setAttribute('href', `data:${contentType},${data}`);
|
|
433
|
+
document.body.appendChild(downloadLink);
|
|
434
|
+
downloadLink.click();
|
|
435
|
+
}
|
|
436
|
+
if (this.replace === 'all') {
|
|
437
|
+
const target = this._getProperty('target');
|
|
438
|
+
if (target && target === '_blank') {
|
|
439
|
+
const win = window.open('', '_blank');
|
|
440
|
+
win.document.write(`<pre>${data}</pre>`);
|
|
441
|
+
win.document.close();
|
|
442
|
+
} else {
|
|
443
|
+
document.open();
|
|
444
|
+
document.write(data);
|
|
445
|
+
document.close();
|
|
446
|
+
window.location.href = resolvedUrl;
|
|
447
|
+
}
|
|
448
|
+
// document.getElementsByTagName('html')[0].innerHTML = data;
|
|
449
|
+
}
|
|
450
|
+
if (this.replace === 'target' && contentType.startsWith('text/html')) {
|
|
451
|
+
// const target = this.getAttribute('target');
|
|
452
|
+
const target = this._getProperty('target');
|
|
453
|
+
const targetNode = document.querySelector(target);
|
|
454
|
+
if (targetNode) {
|
|
455
|
+
targetNode.innerHTML = data;
|
|
456
|
+
} else {
|
|
457
|
+
Fore.dispatch(this, 'submit-error', {
|
|
458
|
+
message: `targetNode for selector ${target} not found`,
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
if (this.replace === 'redirect') {
|
|
463
|
+
window.location.href = data;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
_handleError() {
|
|
468
|
+
// this.dispatch('submit-error', {});
|
|
469
|
+
Fore.dispatch(this, 'submit-error', {});
|
|
470
|
+
/*
|
|
468
471
|
console.log('ERRRORRRRR');
|
|
469
472
|
this.dispatchEvent(
|
|
470
473
|
new CustomEvent('submit-error', {
|
|
@@ -474,9 +477,9 @@ export class FxSubmission extends foreElementMixin(HTMLElement) {
|
|
|
474
477
|
}),
|
|
475
478
|
);
|
|
476
479
|
*/
|
|
477
|
-
|
|
480
|
+
}
|
|
478
481
|
|
|
479
|
-
|
|
482
|
+
/*
|
|
480
483
|
mergeNodes(node1, node2) {
|
|
481
484
|
// Overwrite attributes in node1 with values from node2
|
|
482
485
|
for (const { name, value } of node2.attributes) {
|
|
@@ -507,9 +510,8 @@ export class FxSubmission extends foreElementMixin(HTMLElement) {
|
|
|
507
510
|
});
|
|
508
511
|
}
|
|
509
512
|
*/
|
|
510
|
-
|
|
511
513
|
}
|
|
512
514
|
|
|
513
515
|
if (!customElements.get('fx-submission')) {
|
|
514
|
-
|
|
516
|
+
customElements.define('fx-submission', FxSubmission);
|
|
515
517
|
}
|