@schukai/monster 3.92.3 → 3.94.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/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/source/components/datatable/datasource/rest.mjs +17 -0
- package/source/components/state/log/entry.mjs +4 -4
- package/source/components/state/log.mjs +195 -167
- package/source/components/state/style/log.pcss +31 -79
- package/source/components/state/stylesheet/log.mjs +7 -14
- package/source/data/transformer.mjs +806 -789
- package/source/i18n/time-ago.mjs +671 -0
- package/source/types/validate.mjs +1 -0
- package/test/cases/i18n/time-ago.mjs +33 -0
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,22 @@
|
|
2
2
|
|
3
3
|
|
4
4
|
|
5
|
+
## [3.94.0] - 2024-12-22
|
6
|
+
|
7
|
+
### Add Features
|
8
|
+
|
9
|
+
- **log:** auto update timestamp [#270](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/270)
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
## [3.93.0] - 2024-12-22
|
14
|
+
|
15
|
+
### Add Features
|
16
|
+
|
17
|
+
- **log:** update the apearance of the log [#270](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/270)
|
18
|
+
|
19
|
+
|
20
|
+
|
5
21
|
## [3.92.3] - 2024-12-20
|
6
22
|
|
7
23
|
### Bug Fixes
|
package/package.json
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.12","@popperjs/core":"^2.11.8"},"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.12","@popperjs/core":"^2.11.8"},"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.94.0"}
|
@@ -81,6 +81,9 @@ const filterObserverSymbol = Symbol("filterObserver");
|
|
81
81
|
* @copyright schukai GmbH
|
82
82
|
* @summary A rest api datasource
|
83
83
|
*/
|
84
|
+
|
85
|
+
|
86
|
+
|
84
87
|
class Rest extends Datasource {
|
85
88
|
/**
|
86
89
|
* the constructor of the class
|
@@ -453,6 +456,13 @@ function initFilter() {
|
|
453
456
|
filterControl.attachObserver(this[filterObserverSymbol]);
|
454
457
|
}
|
455
458
|
|
459
|
+
/**
|
460
|
+
* @private
|
461
|
+
* @param json
|
462
|
+
* @param response
|
463
|
+
* @param filterControl
|
464
|
+
* @returns {Promise<never>|Promise<Awaited<unknown>>}
|
465
|
+
*/
|
456
466
|
function handleIntersectionObserver(json, response, filterControl) {
|
457
467
|
const path = new Pathfinder(json);
|
458
468
|
|
@@ -495,6 +505,9 @@ function initAutoInit() {
|
|
495
505
|
});
|
496
506
|
}
|
497
507
|
|
508
|
+
/**
|
509
|
+
* @private
|
510
|
+
*/
|
498
511
|
function initEventHandler() {
|
499
512
|
this[intersectionObserverHandlerSymbol] = (entries) => {
|
500
513
|
entries.forEach((entry) => {
|
@@ -515,6 +528,9 @@ function initEventHandler() {
|
|
515
528
|
};
|
516
529
|
}
|
517
530
|
|
531
|
+
/**
|
532
|
+
* @private
|
533
|
+
*/
|
518
534
|
function initIntersectionObserver() {
|
519
535
|
this.classList.add("intersection-observer");
|
520
536
|
|
@@ -528,6 +544,7 @@ function initIntersectionObserver() {
|
|
528
544
|
this[intersectionObserverHandlerSymbol],
|
529
545
|
options,
|
530
546
|
);
|
547
|
+
|
531
548
|
this[intersectionObserverObserverSymbol].observe(this);
|
532
549
|
}
|
533
550
|
|
@@ -12,19 +12,20 @@
|
|
12
12
|
* SPDX-License-Identifier: AGPL-3.0
|
13
13
|
*/
|
14
14
|
|
15
|
-
import {
|
15
|
+
import {instanceSymbol} from "../../constants.mjs";
|
16
16
|
import {
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
assembleMethodSymbol,
|
18
|
+
CustomElement,
|
19
|
+
getSlottedElements,
|
20
|
+
registerCustomElement,
|
21
21
|
} from "../../dom/customelement.mjs";
|
22
|
-
import {
|
23
|
-
import {
|
24
|
-
import {
|
22
|
+
import {LogStyleSheet} from "./stylesheet/log.mjs";
|
23
|
+
import {Entry} from "./log/entry.mjs";
|
24
|
+
import {validateInstance, validateString} from "../../types/validate.mjs";
|
25
25
|
import "./state.mjs";
|
26
|
+
import {getWindow} from "../../dom/util.mjs";
|
26
27
|
|
27
|
-
export {
|
28
|
+
export {Log};
|
28
29
|
|
29
30
|
/**
|
30
31
|
* @private
|
@@ -39,133 +40,154 @@ const logElementSymbol = Symbol("logElement");
|
|
39
40
|
const emptyStateElementSymbol = Symbol("emptyStateElement");
|
40
41
|
|
41
42
|
/**
|
42
|
-
* A
|
43
|
+
* A log entry
|
43
44
|
*
|
44
|
-
* @fragments /fragments/components/
|
45
|
+
* @fragments /fragments/components/state/log
|
46
|
+
*
|
47
|
+
* @example /examples/components/state/log-simple
|
48
|
+
*
|
49
|
+
* @issue https://localhost.alvine.dev:8444/development/issues/closed/270.html
|
45
50
|
*
|
46
51
|
* @since 3.74.0
|
47
52
|
* @copyright schukai GmbH
|
48
|
-
* @summary
|
49
|
-
|
53
|
+
* @summary The log entry is a single entry in the log.
|
54
|
+
**/
|
50
55
|
class Log extends CustomElement {
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
56
|
+
/**
|
57
|
+
* @return {void}
|
58
|
+
*/
|
59
|
+
[assembleMethodSymbol]() {
|
60
|
+
super[assembleMethodSymbol]();
|
61
|
+
|
62
|
+
initControlReferences.call(this);
|
63
|
+
initEventHandler.call(this);
|
64
|
+
}
|
65
|
+
|
66
|
+
/**
|
67
|
+
* This method is called by the `instanceof` operator.
|
68
|
+
* @return {symbol}
|
69
|
+
*/
|
70
|
+
static get [instanceSymbol]() {
|
71
|
+
return Symbol.for("@schukai/monster/components/state/log@@instance");
|
72
|
+
}
|
73
|
+
|
74
|
+
/**
|
75
|
+
* To set the options via the HTML tag, the attribute `data-monster-options` must be used.
|
76
|
+
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
|
77
|
+
*
|
78
|
+
* The individual configuration values can be found in the table.
|
79
|
+
*
|
80
|
+
* @property {Object} templates Template definitions
|
81
|
+
* @property {string} templates.main Main template
|
82
|
+
* @property {Object} labels Labels
|
83
|
+
* @property {string} labels.nothingToReport Label for empty state
|
84
|
+
* @property {number} updateFrequency Update frequency in milliseconds for the timestamp
|
85
|
+
*/
|
86
|
+
get defaults() {
|
87
|
+
return Object.assign({}, super.defaults, {
|
88
|
+
templates: {
|
89
|
+
main: getTemplate(),
|
90
|
+
},
|
91
|
+
|
92
|
+
labels: {
|
93
|
+
nothingToReport: "There is nothing to report yet.",
|
94
|
+
},
|
95
|
+
|
96
|
+
classes: {
|
97
|
+
direction: "vertical",
|
98
|
+
},
|
99
|
+
|
100
|
+
updateFrequency: 10000,
|
101
|
+
|
102
|
+
entries: [],
|
103
|
+
|
104
|
+
timestamp: 0,
|
105
|
+
});
|
106
|
+
}
|
107
|
+
|
108
|
+
/**
|
109
|
+
* @return {void}
|
110
|
+
*/
|
111
|
+
connectedCallback() {
|
112
|
+
super.connectedCallback();
|
113
|
+
|
114
|
+
const slottedElements = getSlottedElements.call(this);
|
115
|
+
if (slottedElements.size > 0) {
|
116
|
+
this[emptyStateElementSymbol].style.display = "none";
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
/**
|
121
|
+
* Clear the log
|
122
|
+
*
|
123
|
+
* @return {Log}
|
124
|
+
*/
|
125
|
+
clear() {
|
126
|
+
this[logElementSymbol].innerHTML = "";
|
127
|
+
this[emptyStateElementSymbol].style.display = "block";
|
128
|
+
return this;
|
129
|
+
}
|
130
|
+
|
131
|
+
/**
|
132
|
+
* Add an entry to the log
|
133
|
+
* @param {Entry} entry
|
134
|
+
* @return {Log}
|
135
|
+
*/
|
136
|
+
addEntry(entry) {
|
137
|
+
validateInstance(entry, Entry);
|
138
|
+
|
139
|
+
if (entry.date === undefined || entry.date === null) {
|
140
|
+
entry.date = new Date();
|
141
|
+
}
|
142
|
+
|
143
|
+
const entries = this.getOption("entries");
|
144
|
+
entries.push(entry);
|
145
|
+
|
146
|
+
/** this field is not used, but triggers a change event */
|
147
|
+
this.setOption("length", entries.length - 1);
|
148
|
+
|
149
|
+
return this;
|
150
|
+
}
|
151
|
+
|
152
|
+
/**
|
153
|
+
* Add a log message
|
154
|
+
*
|
155
|
+
* @param {string} message
|
156
|
+
* @param {Date} date
|
157
|
+
* @return {Log}
|
158
|
+
* @throws {TypeError} message is not a string
|
159
|
+
*/
|
160
|
+
addMessage(message, date) {
|
161
|
+
if (!date) {
|
162
|
+
date = new Date();
|
163
|
+
}
|
164
|
+
|
165
|
+
validateString(message);
|
166
|
+
|
167
|
+
this.addEntry(
|
168
|
+
new Entry({
|
169
|
+
message: message,
|
170
|
+
date: date,
|
171
|
+
}),
|
172
|
+
);
|
173
|
+
|
174
|
+
return this;
|
175
|
+
}
|
176
|
+
|
177
|
+
/**
|
178
|
+
*
|
179
|
+
* @return {string}
|
180
|
+
*/
|
181
|
+
static getTag() {
|
182
|
+
return "monster-log";
|
183
|
+
}
|
184
|
+
|
185
|
+
/**
|
186
|
+
* @return {CSSStyleSheet[]}
|
187
|
+
*/
|
188
|
+
static getCSSStyleSheet() {
|
189
|
+
return [LogStyleSheet];
|
190
|
+
}
|
169
191
|
}
|
170
192
|
|
171
193
|
/**
|
@@ -174,37 +196,44 @@ class Log extends CustomElement {
|
|
174
196
|
* @throws {Error} no shadow-root is defined
|
175
197
|
*/
|
176
198
|
function initControlReferences() {
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
199
|
+
if (!this.shadowRoot) {
|
200
|
+
throw new Error("no shadow-root is defined");
|
201
|
+
}
|
202
|
+
|
203
|
+
this[logElementSymbol] = this.shadowRoot.querySelector(
|
204
|
+
"[data-monster-role=control]",
|
205
|
+
);
|
206
|
+
this[emptyStateElementSymbol] = this.shadowRoot.querySelector(
|
207
|
+
"[data-monster-role=empty-state]",
|
208
|
+
);
|
187
209
|
}
|
188
210
|
|
189
211
|
/**
|
190
212
|
* @private
|
191
213
|
*/
|
192
214
|
function initEventHandler() {
|
193
|
-
|
194
|
-
|
195
|
-
|
215
|
+
if (!this.shadowRoot) {
|
216
|
+
throw new Error("no shadow-root is defined");
|
217
|
+
}
|
196
218
|
|
197
|
-
|
198
|
-
|
219
|
+
this.shadowRoot.addEventListener("slotchange", (event) => {
|
220
|
+
const slottedElements = getSlottedElements.call(this);
|
199
221
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
222
|
+
if (slottedElements.size > 0) {
|
223
|
+
this[emptyStateElementSymbol].style.display = "none";
|
224
|
+
} else {
|
225
|
+
this[emptyStateElementSymbol].style.display = "block";
|
226
|
+
}
|
227
|
+
});
|
206
228
|
|
207
|
-
|
229
|
+
setInterval(() => {
|
230
|
+
getWindow().requestAnimationFrame(() => {
|
231
|
+
const timestamp = (new Date()).toTimeString();
|
232
|
+
this.setOption("timestamp", timestamp);
|
233
|
+
});
|
234
|
+
}, this.getOption("updateFrequency"));
|
235
|
+
|
236
|
+
return this;
|
208
237
|
}
|
209
238
|
|
210
239
|
/**
|
@@ -212,23 +241,22 @@ function initEventHandler() {
|
|
212
241
|
* @return {string}
|
213
242
|
*/
|
214
243
|
function getTemplate() {
|
215
|
-
|
216
|
-
|
244
|
+
// language=HTML
|
245
|
+
return `
|
217
246
|
<template id="entry">
|
218
247
|
<li data-monster-role="entry">
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
<span data-monster-replace="path:entry.date | time"></span>
|
229
|
-
</div>
|
248
|
+
<span data-monster-replace="path:entry.user"
|
249
|
+
data-monster-attributes="class path:entry.user | ?:user:hidden"></span>
|
250
|
+
<span data-monster-replace="path:entry.title"
|
251
|
+
data-monster-attributes="class path:entry.title | ?:title:hidden"></span>
|
252
|
+
<span data-monster-replace="path:entry.message"
|
253
|
+
data-monster-attributes="class path:entry.message | ?:message:hidden"></span>
|
254
|
+
<span data-monster-replace="path:entry.date | time-ago"
|
255
|
+
data-monster-attributes="title path:entry.date | datetime"></span>
|
256
|
+
|
230
257
|
</li>
|
231
258
|
</template>
|
259
|
+
|
232
260
|
<div part="control" data-monster-role="control">
|
233
261
|
<div data-monster-role="empty-state" data-monster-attributes="class path:entries | has-entries | ?:hidden:">
|
234
262
|
<monster-state>
|
@@ -240,7 +268,7 @@ function getTemplate() {
|
|
240
268
|
<path d="m256 314.925781c-2.628906 0-5.210938 1.066407-7.070312 2.929688-1.859376 1.867187-2.929688 4.4375-2.929688 7.070312 0 2.636719 1.070312 5.207031 2.929688 7.078125 1.859374 1.859375 4.441406 2.921875 7.070312 2.921875s5.210938-1.0625 7.070312-2.921875c1.859376-1.871094 2.929688-4.441406 2.929688-7.078125 0-2.632812-1.070312-5.203125-2.929688-7.070312-1.859374-1.863281-4.441406-2.929688-7.070312-2.929688zm0 0"/>
|
241
269
|
</svg>
|
242
270
|
</div>
|
243
|
-
<div part="content" monster-replace="path:labels.nothingToReport">
|
271
|
+
<div part="content" data-monster-replace="path:labels.nothingToReport">
|
244
272
|
There is nothing to report yet.
|
245
273
|
</div>
|
246
274
|
</monster-state>
|
@@ -8,104 +8,56 @@
|
|
8
8
|
@import "../../style/mixin/hover.pcss";
|
9
9
|
|
10
10
|
[data-monster-role=entries] {
|
11
|
-
|
12
|
-
|
11
|
+
display: flex;
|
12
|
+
flex-direction: column;
|
13
|
+
align-items: flex-start;
|
14
|
+
border: 0;
|
15
|
+
padding: 0;
|
16
|
+
margin: 0;
|
17
|
+
box-sizing: border-box;
|
18
|
+
position: relative;
|
13
19
|
|
14
20
|
& ul {
|
15
21
|
list-style-type: none;
|
16
22
|
margin: 0;
|
17
|
-
padding: 0;
|
18
|
-
|
19
|
-
top: 0
|
20
|
-
}
|
21
|
-
|
22
|
-
& ul:last-of-type {
|
23
|
-
top: 2rem;
|
23
|
+
padding: 0 0 0 1.8rem; /* Abstand links behalten */
|
24
|
+
width: 100%; /* Flex-Container-Anpassung */
|
24
25
|
}
|
25
26
|
|
26
27
|
& ul:before {
|
27
28
|
content: "";
|
28
29
|
display: block;
|
29
|
-
width:
|
30
|
+
width: 2px;
|
30
31
|
height: 100%;
|
31
|
-
|
32
|
+
|
33
|
+
border-left-color: var(--monster-bg-color-primary-3);
|
34
|
+
border-left-style: dotted;
|
35
|
+
border-left-width: 1px;
|
32
36
|
position: absolute;
|
37
|
+
left: 1rem;
|
38
|
+
bottom: 0;
|
33
39
|
top: 0;
|
34
|
-
left: 30px
|
35
40
|
}
|
36
41
|
|
37
42
|
& ul li {
|
38
|
-
margin:
|
39
|
-
|
40
|
-
|
41
|
-
color: var(--monster-color-primary-
|
42
|
-
background-color: var(--monster-bg-color-primary-2);
|
43
|
+
margin: 0;
|
44
|
+
padding: 0.1rem 0.3rem;
|
45
|
+
color: var(--monster-color-primary-1);
|
46
|
+
background-color: var(--monster-bg-color-primary-1);
|
43
47
|
border-radius: 5px;
|
48
|
+
position: relative;
|
44
49
|
}
|
45
50
|
|
46
|
-
|
47
|
-
& ul li > span {
|
48
|
-
content: "";
|
49
|
-
display: block;
|
50
|
-
width: 0;
|
51
|
-
height: 100%;
|
52
|
-
border: 1px solid var(--monster-color-primary-2);
|
53
|
-
position: absolute;
|
54
|
-
top: 0;
|
55
|
-
left: -30px
|
56
|
-
}
|
57
|
-
|
58
|
-
& ul li > span:before, & ul li > span:after {
|
51
|
+
& ul li:before {
|
59
52
|
content: "";
|
60
|
-
|
61
|
-
|
62
|
-
|
53
|
+
width: 6px;
|
54
|
+
height: 6px;
|
55
|
+
box-sizing: border-box;
|
63
56
|
border-radius: 50%;
|
64
|
-
background: var(--monster-bg-color-primary-
|
65
|
-
border:
|
66
|
-
position: absolute;
|
67
|
-
left: -7.5px
|
68
|
-
}
|
69
|
-
|
70
|
-
& ul li > span:before {
|
71
|
-
top: -10px
|
72
|
-
}
|
73
|
-
|
74
|
-
& ul li > span:after {
|
75
|
-
top: 95%
|
76
|
-
}
|
77
|
-
|
78
|
-
& .title {
|
79
|
-
text-transform: uppercase;
|
80
|
-
margin-bottom: 5px
|
81
|
-
}
|
82
|
-
|
83
|
-
& .message:first-letter {
|
84
|
-
}
|
85
|
-
|
86
|
-
& .user {
|
87
|
-
margin-top: 10px;
|
88
|
-
font-style: italic;
|
89
|
-
text-align: right;
|
90
|
-
margin-right: 20px;
|
91
|
-
font-size: 0.8rem;
|
92
|
-
}
|
93
|
-
|
94
|
-
& .datetime span {
|
57
|
+
background: var(--monster-bg-color-primary-3);
|
58
|
+
border: 1px solid var(--monster-color-primary-2);
|
95
59
|
position: absolute;
|
96
|
-
left: -
|
97
|
-
|
98
|
-
background-color: var(--monster-bg-color-primary-1);
|
99
|
-
font-size: 0.5rem;
|
100
|
-
}
|
101
|
-
|
102
|
-
& .datetime span:first-child {
|
103
|
-
top: -16px
|
104
|
-
}
|
105
|
-
|
106
|
-
& .datetime span:last-child {
|
107
|
-
top: 94%
|
60
|
+
left: calc(-1rem + (5px / 4));
|
61
|
+
top: 0.6rem;
|
108
62
|
}
|
109
|
-
|
110
|
-
|
111
|
-
}
|
63
|
+
}
|