@schukai/monster 3.109.0 → 3.110.1
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/CHANGELOG.md
CHANGED
@@ -2,6 +2,22 @@
|
|
2
2
|
|
3
3
|
|
4
4
|
|
5
|
+
## [3.110.1] - 2025-02-19
|
6
|
+
|
7
|
+
### Bug Fixes
|
8
|
+
|
9
|
+
- optimize rest errors
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
## [3.110.0] - 2025-02-18
|
14
|
+
|
15
|
+
### Add Features
|
16
|
+
|
17
|
+
- **datatable-status:** add callbacks.onError
|
18
|
+
|
19
|
+
|
20
|
+
|
5
21
|
## [3.109.0] - 2025-02-18
|
6
22
|
|
7
23
|
### Add Features
|
package/package.json
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.13","@popperjs/core":"^2.11.8","buffer":"^6.0.3"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"3.
|
1
|
+
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.13","@popperjs/core":"^2.11.8","buffer":"^6.0.3"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"3.110.1"}
|
@@ -13,25 +13,26 @@
|
|
13
13
|
*/
|
14
14
|
|
15
15
|
import {
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
assembleMethodSymbol,
|
17
|
+
CustomElement,
|
18
|
+
registerCustomElement,
|
19
19
|
} from "../../dom/customelement.mjs";
|
20
|
-
import {
|
21
|
-
import {
|
22
|
-
import {
|
23
|
-
import {
|
24
|
-
import {
|
25
|
-
import {
|
20
|
+
import {findElementWithSelectorUpwards} from "../../dom/util.mjs";
|
21
|
+
import {ThemeStyleSheet} from "../stylesheet/theme.mjs";
|
22
|
+
import {Datasource} from "./datasource.mjs";
|
23
|
+
import {SpinnerStyleSheet} from "../stylesheet/spinner.mjs";
|
24
|
+
import {isString} from "../../types/is.mjs";
|
25
|
+
import {instanceSymbol} from "../../constants.mjs";
|
26
26
|
import "../form/select.mjs";
|
27
27
|
|
28
28
|
import "./datasource/dom.mjs";
|
29
29
|
import "./datasource/rest.mjs";
|
30
30
|
import "../form/popper.mjs";
|
31
31
|
import "../form/context-error.mjs";
|
32
|
-
import {
|
32
|
+
import {StatusStyleSheet} from "./stylesheet/status.mjs";
|
33
|
+
import {Formatter} from "../../text/formatter.mjs";
|
33
34
|
|
34
|
-
export {
|
35
|
+
export {DatasourceStatus};
|
35
36
|
|
36
37
|
/**
|
37
38
|
* @private
|
@@ -58,76 +59,97 @@ const datasourceLinkedElementSymbol = Symbol("datasourceLinkedElement");
|
|
58
59
|
* @summary The Status component is used to show the current status of a datasource.
|
59
60
|
*/
|
60
61
|
class DatasourceStatus extends CustomElement {
|
61
|
-
|
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
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
62
|
+
/**
|
63
|
+
*/
|
64
|
+
constructor() {
|
65
|
+
super();
|
66
|
+
}
|
67
|
+
|
68
|
+
/**
|
69
|
+
* This method is called by the `instanceof` operator.
|
70
|
+
* @return {symbol}
|
71
|
+
*/
|
72
|
+
static get [instanceSymbol]() {
|
73
|
+
return Symbol.for("@schukai/monster/components/datatable/status@@instance");
|
74
|
+
}
|
75
|
+
|
76
|
+
/**
|
77
|
+
* To set the options via the HTML tag, the attribute `data-monster-options` must be used.
|
78
|
+
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
|
79
|
+
*
|
80
|
+
* The individual configuration values can be found in the table.
|
81
|
+
*
|
82
|
+
* @property {Object} templates Template definitions
|
83
|
+
* @property {string} templates.main Main template
|
84
|
+
* @property {Object} datasource Datasource configuration
|
85
|
+
* @property {string} datasource.selector The selector of the datasource
|
86
|
+
* @property {Object} callbacks Callbacks
|
87
|
+
* @property {Function} callbacks.onError Callback function for error handling <code>function(message: string, event: Event): string</code>
|
88
|
+
* @property {Object} timeouts Timeouts
|
89
|
+
* @property {number} timeouts.message Timeout for the message
|
90
|
+
* @property {Object} state State
|
91
|
+
*/
|
92
|
+
get defaults() {
|
93
|
+
return Object.assign({}, super.defaults, {
|
94
|
+
templates: {
|
95
|
+
main: getTemplate(),
|
96
|
+
},
|
97
|
+
|
98
|
+
datasource: {
|
99
|
+
selector: null,
|
100
|
+
},
|
101
|
+
|
102
|
+
callbacks: {
|
103
|
+
onError: null
|
104
|
+
},
|
105
|
+
|
106
|
+
|
107
|
+
timeouts: {
|
108
|
+
message: 4000,
|
109
|
+
},
|
110
|
+
|
111
|
+
state: {
|
112
|
+
spinner: "hide",
|
113
|
+
},
|
114
|
+
});
|
115
|
+
}
|
116
|
+
|
117
|
+
/**
|
118
|
+
*
|
119
|
+
* @return {string}
|
120
|
+
*/
|
121
|
+
static getTag() {
|
122
|
+
return "monster-datasource-status";
|
123
|
+
}
|
124
|
+
|
125
|
+
/**
|
126
|
+
* @private
|
127
|
+
*/
|
128
|
+
[assembleMethodSymbol]() {
|
129
|
+
super[assembleMethodSymbol]();
|
130
|
+
|
131
|
+
initControlReferences.call(this);
|
132
|
+
initEventHandler.call(this);
|
133
|
+
}
|
134
|
+
|
135
|
+
/**
|
136
|
+
*
|
137
|
+
* @param message
|
138
|
+
* @param timeout
|
139
|
+
* @returns {DatasourceStatus}
|
140
|
+
*/
|
141
|
+
setErrorMessage(message, timeout) {
|
142
|
+
this[errorElementSymbol].setErrorMessage(message, timeout);
|
143
|
+
return this;
|
144
|
+
}
|
145
|
+
|
146
|
+
/**
|
147
|
+
*
|
148
|
+
* @return [CSSStyleSheet]
|
149
|
+
*/
|
150
|
+
static getCSSStyleSheet() {
|
151
|
+
return [StatusStyleSheet, SpinnerStyleSheet, ThemeStyleSheet];
|
152
|
+
}
|
131
153
|
}
|
132
154
|
|
133
155
|
/**
|
@@ -136,79 +158,85 @@ class DatasourceStatus extends CustomElement {
|
|
136
158
|
* @throws {Error} no shadow-root is defined
|
137
159
|
*/
|
138
160
|
function initControlReferences() {
|
139
|
-
|
140
|
-
|
141
|
-
|
161
|
+
if (!this.shadowRoot) {
|
162
|
+
throw new Error("no shadow-root is defined");
|
163
|
+
}
|
142
164
|
|
143
|
-
|
144
|
-
|
145
|
-
|
165
|
+
this[errorElementSymbol] = this.shadowRoot.querySelector(
|
166
|
+
"monster-context-error",
|
167
|
+
);
|
146
168
|
}
|
147
169
|
|
148
170
|
/**
|
149
171
|
* @private
|
150
172
|
*/
|
151
173
|
function initEventHandler() {
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
174
|
+
const selector = this.getOption("datasource.selector", "");
|
175
|
+
const self = this;
|
176
|
+
|
177
|
+
if (isString(selector)) {
|
178
|
+
const element = findElementWithSelectorUpwards(this, selector);
|
179
|
+
if (element === null) {
|
180
|
+
throw new Error("the selector must match exactly one element");
|
181
|
+
}
|
182
|
+
|
183
|
+
if (!(element instanceof Datasource)) {
|
184
|
+
throw new TypeError("the element must be a datasource");
|
185
|
+
}
|
186
|
+
|
187
|
+
let fadeOutTimer = null;
|
188
|
+
|
189
|
+
this[datasourceLinkedElementSymbol] = element;
|
190
|
+
element.addEventListener("monster-datasource-fetched", function () {
|
191
|
+
fadeOutTimer = setTimeout(() => {
|
192
|
+
self.setOption("state.spinner", "hide");
|
193
|
+
}, 800);
|
194
|
+
});
|
195
|
+
|
196
|
+
element.addEventListener("monster-datasource-fetch", function () {
|
197
|
+
if (fadeOutTimer) {
|
198
|
+
clearTimeout(fadeOutTimer);
|
199
|
+
fadeOutTimer = null;
|
200
|
+
}
|
201
|
+
|
202
|
+
self.setOption("state.spinner", "show");
|
203
|
+
});
|
204
|
+
|
205
|
+
element.addEventListener("monster-datasource-error", function (event) {
|
206
|
+
if (fadeOutTimer) {
|
207
|
+
clearTimeout(fadeOutTimer);
|
208
|
+
fadeOutTimer = null;
|
209
|
+
}
|
210
|
+
|
211
|
+
self.setOption("state.spinner", "hide");
|
212
|
+
|
213
|
+
const timeout = self.getOption("timeouts.message", 4000);
|
214
|
+
let msg = "Cannot load data";
|
215
|
+
|
216
|
+
try {
|
217
|
+
if (event.detail.error instanceof Error) {
|
218
|
+
msg = event.detail.error.message;
|
219
|
+
} else if (event.detail.error instanceof Object) {
|
220
|
+
msg = JSON.stringify(event.detail.error);
|
221
|
+
} else if (event.detail.error instanceof String) {
|
222
|
+
msg = event.detail.error;
|
223
|
+
} else if (event.detail.error instanceof Number) {
|
224
|
+
msg = event.detail.error.toString();
|
225
|
+
} else {
|
226
|
+
msg = event.detail.error;
|
227
|
+
}
|
228
|
+
} catch (e) {
|
229
|
+
} finally {
|
230
|
+
|
231
|
+
const callback = self.getOption("callbacks.onError", null);
|
232
|
+
if (callback) {
|
233
|
+
callback.call(self, msg, event);
|
234
|
+
} else {
|
235
|
+
self[errorElementSymbol].setErrorMessage(msg, timeout);
|
236
|
+
}
|
237
|
+
}
|
238
|
+
});
|
239
|
+
}
|
212
240
|
}
|
213
241
|
|
214
242
|
/**
|
@@ -216,13 +244,13 @@ function initEventHandler() {
|
|
216
244
|
* @return {string}
|
217
245
|
*/
|
218
246
|
function getTemplate() {
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
247
|
+
// language=HTML
|
248
|
+
return `
|
249
|
+
<div data-monster-role="control" part="control"
|
250
|
+
data-monster-attributes="disabled path:disabled | if:true">
|
223
251
|
<monster-context-error
|
224
252
|
data-monster-option-classes-button="monster-theme-error-2 monster-theme-background-inherit"></monster-context-error>
|
225
|
-
<div class="monster-spinner"
|
253
|
+
<div class="monster-spinner"
|
226
254
|
data-monster-attributes="data-monster-state-loader path:state.spinner"></div>
|
227
255
|
</div>
|
228
256
|
`;
|
@@ -32,8 +32,20 @@ class DataFetchError extends Error {
|
|
32
32
|
*/
|
33
33
|
constructor(message, response) {
|
34
34
|
super(message);
|
35
|
+
|
36
|
+
let body = null
|
37
|
+
|
38
|
+
if (response instanceof Response) {
|
39
|
+
body = response.text();
|
40
|
+
}
|
41
|
+
|
42
|
+
if(!(body instanceof Promise)) {
|
43
|
+
body = Promise.resolve(body);
|
44
|
+
}
|
45
|
+
|
35
46
|
this[internalSymbol] = {
|
36
47
|
response: response,
|
48
|
+
body : body
|
37
49
|
};
|
38
50
|
}
|
39
51
|
|
@@ -47,10 +59,17 @@ class DataFetchError extends Error {
|
|
47
59
|
);
|
48
60
|
}
|
49
61
|
|
62
|
+
/**
|
63
|
+
* @return {string|Object}
|
64
|
+
*/
|
65
|
+
getBody() {
|
66
|
+
return this[internalSymbol]?.["body"];
|
67
|
+
}
|
68
|
+
|
50
69
|
/**
|
51
70
|
* @return {Response}
|
52
71
|
*/
|
53
72
|
getResponse() {
|
54
|
-
return this[internalSymbol]["response"];
|
73
|
+
return this[internalSymbol]?.["response"];
|
55
74
|
}
|
56
75
|
}
|
@@ -245,7 +245,7 @@ function fetchData(init, key, callback) {
|
|
245
245
|
if (body.length > 100) {
|
246
246
|
body = `${body.substring(0, 97)}...`;
|
247
247
|
}
|
248
|
-
|
248
|
+
|
249
249
|
throw new DataFetchError(
|
250
250
|
getInternalLocalizationMessage(
|
251
251
|
`i18n{the-response-does-not-contain-a-valid-json::actual=${body}}`,
|
@@ -257,6 +257,7 @@ function fetchData(init, key, callback) {
|
|
257
257
|
if (callback && isFunction(callback)) {
|
258
258
|
callback(obj);
|
259
259
|
}
|
260
|
+
|
260
261
|
return response;
|
261
262
|
})
|
262
263
|
.catch((e) => {
|