5htp-core 0.4.2 → 0.4.3
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/package.json +4 -12
- package/src/client/app/component.tsx +11 -2
- package/src/client/assets/css/components/button.less +10 -10
- package/src/client/assets/css/components/other.less +0 -1
- package/src/client/assets/css/core.less +0 -4
- package/src/client/assets/css/text/text.less +1 -2
- package/src/client/assets/css/text/titres.less +0 -5
- package/src/client/assets/css/utils/layouts.less +5 -5
- package/src/client/assets/css/utils/sizing.less +6 -6
- package/src/client/components/Dialog/card.tsx +1 -1
- package/src/client/components/button.tsx +1 -1
- package/src/client/components/containers/Popover/index.tsx +2 -2
- package/src/client/components/index.ts +5 -16
- package/src/client/components/inputv3/index.tsx +2 -5
- package/src/client/services/router/components/Page.tsx +1 -2
- package/src/client/services/router/components/router.tsx +4 -8
- package/src/client/services/router/request/api.ts +31 -52
- package/src/client/services/router/response/index.tsx +2 -0
- package/src/common/data/dates.ts +50 -6
- package/src/common/router/layouts.ts +14 -5
- package/src/common/router/response/page.ts +12 -6
- package/src/common/validation/validators.ts +0 -4
- package/src/server/app/container/config.ts +2 -1
- package/src/server/services/router/http/index.ts +16 -22
- package/src/server/services/router/response/page/index.tsx +0 -0
- package/src/client/assets/fonts/Inter/index.less +0 -77
- package/src/client/assets/fonts/Inter/latin-500.woff2 +0 -0
- package/src/client/assets/fonts/Inter/latin-600.woff2 +0 -0
- package/src/client/assets/fonts/Inter/latin-800.woff2 +0 -0
- package/src/client/assets/fonts/Inter/latin-ext-500.woff2 +0 -0
- package/src/client/assets/fonts/Inter/latin-ext-600.woff2 +0 -0
- package/src/client/assets/fonts/Inter/latin-ext-800.woff2 +0 -0
- package/src/client/assets/fonts/Rubik/cyrillic-ext.woff2 +0 -0
- package/src/client/assets/fonts/Rubik/cyrillic.woff2 +0 -0
- package/src/client/assets/fonts/Rubik/hebrew.woff2 +0 -0
- package/src/client/assets/fonts/Rubik/index.less +0 -30
- package/src/client/assets/fonts/Rubik/latin-ext.woff2 +0 -0
- package/src/client/assets/fonts/Rubik/latin.woff2 +0 -0
- package/src/client/components/Amount.tsx +0 -38
- package/src/client/components/Form_old/index.tsx +0 -450
- package/src/client/components/Form_old/index.tsx.old +0 -436
- package/src/client/components/dropdown.old/Manager.tsx +0 -164
- package/src/client/components/dropdown.old/getPosition.ts +0 -137
- package/src/client/components/dropdown.old/index.tsx +0 -99
- package/src/client/components/dropdown.old/popover.less +0 -56
- package/src/client/components/input/Base/Choix.ts +0 -48
- package/src/client/components/input/Base/index.tsx +0 -432
- package/src/client/components/input/BaseV2/index.tsx +0 -72
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "5htp-core",
|
|
3
3
|
"description": "Convenient TypeScript framework designed for Performance and Productivity.",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.3",
|
|
5
5
|
"author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
|
|
6
6
|
"repository": "git://github.com/gaetanlegac/5htp-core.git",
|
|
7
7
|
"license": "MIT",
|
|
@@ -18,12 +18,10 @@
|
|
|
18
18
|
"ansi-to-html": "^0.7.1",
|
|
19
19
|
"array-move": "^3.0.1",
|
|
20
20
|
"aws-sdk": "^2.1415.0",
|
|
21
|
-
"axios": "^1.2.1",
|
|
22
21
|
"bowser": "^2.11.0",
|
|
23
22
|
"chart.js": "^3.6.2",
|
|
24
23
|
"cli-highlight": "^2.1.11",
|
|
25
24
|
"compression": "^1.7.4",
|
|
26
|
-
"connect-redis": "^6.0.0",
|
|
27
25
|
"cookie-parser": "^1.4.5",
|
|
28
26
|
"core-js": "^3.18.1",
|
|
29
27
|
"cors": "^2.8.5",
|
|
@@ -34,11 +32,9 @@
|
|
|
34
32
|
"express": "^4.17.1",
|
|
35
33
|
"express-csp-header": "^5.0.0",
|
|
36
34
|
"express-fileupload": "^1.2.1",
|
|
37
|
-
"express-static-gzip": "^2.1.1",
|
|
38
35
|
"fast-safe-stringify": "^2.1.1",
|
|
39
36
|
"formattor": "^0.0.2",
|
|
40
37
|
"fs-extra": "^10.1.0",
|
|
41
|
-
"google-auth-library": "^7.11.0",
|
|
42
38
|
"got": "^11.8.3",
|
|
43
39
|
"handlebars": "^4.7.7",
|
|
44
40
|
"helmet": "^4.6.0",
|
|
@@ -47,7 +43,6 @@
|
|
|
47
43
|
"human-interval": "^2.0.1",
|
|
48
44
|
"intl": "^1.2.5",
|
|
49
45
|
"iso-639-1": "^2.1.9",
|
|
50
|
-
"javascript-time-ago": "^2.3.9",
|
|
51
46
|
"js-cookie": "^3.0.1",
|
|
52
47
|
"jsonwebtoken": "^8.5.1",
|
|
53
48
|
"load-script": "^2.0.0",
|
|
@@ -58,17 +53,15 @@
|
|
|
58
53
|
"module-alias": "^2.2.2",
|
|
59
54
|
"morgan": "^1.10.0",
|
|
60
55
|
"mysql2": "^2.3.0",
|
|
61
|
-
"nodemailer": "^6.6.3",
|
|
62
56
|
"object-sizeof": "^1.6.3",
|
|
63
57
|
"path-to-regexp": "^6.2.0",
|
|
64
58
|
"picomatch": "^2.3.1",
|
|
65
|
-
"preact": "^10.
|
|
66
|
-
"preact-render-to-string": "^5.
|
|
59
|
+
"preact": "^10.22.1",
|
|
60
|
+
"preact-render-to-string": "^6.5.5",
|
|
67
61
|
"react-datetime-picker": "^5.6.0",
|
|
68
62
|
"react-scrollbars-custom": "^4.0.27",
|
|
69
63
|
"react-slider": "^2.0.1",
|
|
70
64
|
"react-textarea-autosize": "^8.3.3",
|
|
71
|
-
"redis": "^3.1.2",
|
|
72
65
|
"regenerator-runtime": "^0.13.9",
|
|
73
66
|
"request": "^2.88.2",
|
|
74
67
|
"sharp": "^0.29.1",
|
|
@@ -94,8 +87,7 @@
|
|
|
94
87
|
"@types/universal-analytics": "^0.4.5",
|
|
95
88
|
"@types/webpack-env": "^1.16.2",
|
|
96
89
|
"@types/ws": "^7.4.7",
|
|
97
|
-
"@types/yargs-parser": "^21.0.0"
|
|
98
|
-
"babel-plugin-glob-import": "^0.0.7"
|
|
90
|
+
"@types/yargs-parser": "^21.0.0"
|
|
99
91
|
},
|
|
100
92
|
"peerDependencies": {
|
|
101
93
|
"5htp": "0.3.9"
|
|
@@ -26,6 +26,7 @@ export default function App ({ context }: {
|
|
|
26
26
|
|
|
27
27
|
const curLayout = context.page?.layout;
|
|
28
28
|
const [layout, setLayout] = React.useState<Layout | false | undefined>(curLayout);
|
|
29
|
+
const [apiData, setApiData] = React.useState<{[k: string]: any} | null>( context.page?.data || {});
|
|
29
30
|
|
|
30
31
|
// TODO: context.page is always provided in the context on the client side
|
|
31
32
|
if (context.app.side === "client")
|
|
@@ -39,8 +40,16 @@ export default function App ({ context }: {
|
|
|
39
40
|
{!layout ? <>
|
|
40
41
|
{/* TODO: move to app, because here, we're not aware that the router service has been defined */}
|
|
41
42
|
<RouterComponent service={context.Router} />
|
|
42
|
-
</> : <>
|
|
43
|
-
<layout.Component
|
|
43
|
+
</> : <> {/* Same as router/components/Page.tsx */}
|
|
44
|
+
<layout.Component
|
|
45
|
+
// Services
|
|
46
|
+
{...context}
|
|
47
|
+
// API data & URL params
|
|
48
|
+
data={{
|
|
49
|
+
...apiData,
|
|
50
|
+
...context.request.data
|
|
51
|
+
}}
|
|
52
|
+
/>
|
|
44
53
|
</>}
|
|
45
54
|
|
|
46
55
|
</ReactClientContext.Provider>
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
// Hover
|
|
35
35
|
//transition: all .5s linear;
|
|
36
36
|
&:hover,
|
|
37
|
-
&.
|
|
37
|
+
&.active,
|
|
38
38
|
li:hover > & {
|
|
39
39
|
|
|
40
40
|
color: var(--cTxtImportant);
|
|
@@ -123,7 +123,7 @@
|
|
|
123
123
|
|
|
124
124
|
cursor: pointer;
|
|
125
125
|
|
|
126
|
-
&:not(.primary).
|
|
126
|
+
&:not(.primary).active {
|
|
127
127
|
|
|
128
128
|
&.col {
|
|
129
129
|
box-shadow: 0 0 0 0.2em @c2;
|
|
@@ -229,7 +229,7 @@ ul.row {
|
|
|
229
229
|
//width: 100%;
|
|
230
230
|
background: transparent;
|
|
231
231
|
|
|
232
|
-
&.
|
|
232
|
+
&.active,
|
|
233
233
|
&:hover {
|
|
234
234
|
background: var(--cBgActive);
|
|
235
235
|
color: var(--cTxtImportant);
|
|
@@ -280,8 +280,8 @@ ul.row {
|
|
|
280
280
|
position: relative;
|
|
281
281
|
|
|
282
282
|
// Submenu
|
|
283
|
-
&:not(.contPopover):not(:hover) > .btn + .
|
|
284
|
-
> .btn[disabled] + .
|
|
283
|
+
&:not(.contPopover):not(:hover) > .btn + .submenu,
|
|
284
|
+
> .btn[disabled] + .submenu {
|
|
285
285
|
visibility: hidden;
|
|
286
286
|
}
|
|
287
287
|
}
|
|
@@ -332,7 +332,7 @@ ul.col {
|
|
|
332
332
|
}
|
|
333
333
|
|
|
334
334
|
.btn.icon > .label,
|
|
335
|
-
> li > .btn + .
|
|
335
|
+
> li > .btn + .submenu {
|
|
336
336
|
left: 100%;
|
|
337
337
|
margin-left: @spacing;
|
|
338
338
|
}
|
|
@@ -340,7 +340,7 @@ ul.col {
|
|
|
340
340
|
> li {
|
|
341
341
|
|
|
342
342
|
// Sous le label quand bouton = icone seulement
|
|
343
|
-
> .btn +
|
|
343
|
+
> .btn + .menu {
|
|
344
344
|
|
|
345
345
|
top: @sizeComponent;
|
|
346
346
|
margin-top: @spacing / 2;
|
|
@@ -365,7 +365,7 @@ ul.col {
|
|
|
365
365
|
&.bubble-left {
|
|
366
366
|
|
|
367
367
|
.btn.icon > .label,
|
|
368
|
-
> li > .btn + .
|
|
368
|
+
> li > .btn + .submenu {
|
|
369
369
|
left: auto;
|
|
370
370
|
margin-left: 0;
|
|
371
371
|
right: 100%;
|
|
@@ -378,12 +378,12 @@ ul.col {
|
|
|
378
378
|
ul.row {
|
|
379
379
|
|
|
380
380
|
.btn.icon > .label,
|
|
381
|
-
> li > .btn + .
|
|
381
|
+
> li > .btn + .submenu {
|
|
382
382
|
bottom: 100%;
|
|
383
383
|
margin-bottom: 0; // User's mouse shouldnt go outside the li so the hover state is not lost
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
-
> li > .btn + .
|
|
386
|
+
> li > .btn + .submenu.pos-bottom {
|
|
387
387
|
bottom: auto;
|
|
388
388
|
top: 100%;
|
|
389
389
|
margin-top: 0; // User's mouse shouldnt go outside the li so the hover state is not lost
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
position: relative;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
> a.
|
|
72
|
+
> a.active {
|
|
73
73
|
color: var(--cTxtImportant );
|
|
74
74
|
|
|
75
75
|
@indicatorSize: 5px;
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
|
|
115
115
|
&.inline { display: inline-flex; }
|
|
116
116
|
|
|
117
|
-
&.al-left { justify-content: flex-start; }
|
|
117
|
+
&.wrap, &.al-left { justify-content: flex-start; }
|
|
118
118
|
&,
|
|
119
119
|
&.al-center { justify-content: center; }
|
|
120
120
|
&.al-right { justify-content: flex-end; }
|
|
@@ -137,8 +137,8 @@
|
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
&.al-top { justify-content: flex-start; }
|
|
141
|
-
|
|
140
|
+
&, &.al-top { justify-content: flex-start; }
|
|
141
|
+
&.al-middle { justify-content: center; }
|
|
142
142
|
&.al-bottom { justify-content: flex-end; }
|
|
143
143
|
|
|
144
144
|
&.al-left { align-items: flex-start; }
|
|
@@ -238,7 +238,7 @@
|
|
|
238
238
|
border-radius: @radius;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
&.
|
|
241
|
+
&.sep-1 { // Bordure interne
|
|
242
242
|
|
|
243
243
|
background-color: var(--cLine2);
|
|
244
244
|
gap: 1px;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
.xs { font-size: 0.6em !important; line-height:
|
|
2
|
-
.s { font-size: 0.8em !important; line-height:
|
|
3
|
-
.m { font-size: 1em !important; line-height:
|
|
4
|
-
.l { font-size: 1.
|
|
5
|
-
.xl { font-size: 2em !important; line-height:
|
|
6
|
-
.xxl { font-size: 2.5em !important; line-height:
|
|
1
|
+
.xs { font-size: 0.6em !important; line-height: 1.5em; }
|
|
2
|
+
.s { font-size: 0.8em !important; line-height: 1.5em; }
|
|
3
|
+
.m { font-size: 1em !important; line-height: 1.5em; }
|
|
4
|
+
.l { font-size: 1.25em !important; line-height: 1.5em; }
|
|
5
|
+
.xl { font-size: 2em !important; line-height: 1.5em; }
|
|
6
|
+
.xxl { font-size: 2.5em !important; line-height: 1.5em; }
|
|
7
7
|
|
|
8
8
|
/*----------------------------------
|
|
9
9
|
- FONCTIONS
|
|
@@ -133,7 +133,7 @@ export default ({
|
|
|
133
133
|
}, []);
|
|
134
134
|
|
|
135
135
|
let render = isToast ? (
|
|
136
|
-
<div class="card row bg dark
|
|
136
|
+
<div class="card row bg dark" onClick={() => isToast && !prison && close(true)}>
|
|
137
137
|
|
|
138
138
|
{icon}
|
|
139
139
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
// Npm
|
|
6
6
|
import React from 'react';
|
|
7
|
-
import { JSX, ComponentChild
|
|
7
|
+
import { JSX, ComponentChild } from 'preact';
|
|
8
8
|
import type { StateUpdater } from 'preact/hooks';
|
|
9
9
|
|
|
10
10
|
// Libs
|
|
@@ -20,7 +20,7 @@ export type Props = JSX.HTMLAttributes<HTMLDivElement> & {
|
|
|
20
20
|
id?: string,
|
|
21
21
|
|
|
22
22
|
// Display
|
|
23
|
-
content?:
|
|
23
|
+
content?: JSX.Element,
|
|
24
24
|
state?: [boolean, StateUpdater<boolean>],
|
|
25
25
|
width?: number | string,
|
|
26
26
|
disable?: boolean
|
|
@@ -12,14 +12,12 @@ export { default as Row } from './Row';
|
|
|
12
12
|
export { default as Logo } from './logo';
|
|
13
13
|
export { default as Video } from './Video';
|
|
14
14
|
|
|
15
|
-
// Input
|
|
16
|
-
export { default as
|
|
17
|
-
export { default as
|
|
18
|
-
export { default as
|
|
19
|
-
export { default as Checkbox } from './input/Checkbox';
|
|
15
|
+
// Input (OLD, TO ADAPT)
|
|
16
|
+
//export { default as Slider } from './input/Slider';
|
|
17
|
+
//export { default as Radio } from './input/Radio';
|
|
18
|
+
//export { default as Checkbox } from './input/Checkbox';
|
|
20
19
|
|
|
21
20
|
// Data
|
|
22
|
-
export { default as Amount } from './Amount';
|
|
23
21
|
export { default as Time } from './data/Time';
|
|
24
22
|
export { default as SpinText } from './data/spintext';
|
|
25
23
|
export { default as Progressbar } from './data/progressbar';
|
|
@@ -29,13 +27,4 @@ export { default as CircularProgressbar } from './data/progressbar/circular';
|
|
|
29
27
|
export { default as Select } from './Select';
|
|
30
28
|
export { default as Input } from './inputv3';
|
|
31
29
|
export { default as File } from './inputv3/file';
|
|
32
|
-
export { default as DateRangeInput } from './inputv3/date';
|
|
33
|
-
|
|
34
|
-
// TOD: fix popover component
|
|
35
|
-
//export { default as Date } from './input/Date';
|
|
36
|
-
//export { default as Periode } from './input/Periode';
|
|
37
|
-
|
|
38
|
-
// TODO: adapt
|
|
39
|
-
//export { default as Couleur } from './input/Couleur';
|
|
40
|
-
//export { default as Code } from './input/Code';
|
|
41
|
-
//export { default as Rte } from './input/Rte';
|
|
30
|
+
export { default as DateRangeInput } from './inputv3/date';
|
|
@@ -44,7 +44,7 @@ export type Props = {
|
|
|
44
44
|
----------------------------------*/
|
|
45
45
|
export default ({
|
|
46
46
|
// Decoration
|
|
47
|
-
icon, prefix, suffix, iconR, required, size,
|
|
47
|
+
icon, prefix, suffix, iconR, required, size, className = '',
|
|
48
48
|
// State
|
|
49
49
|
inputRef, errors,
|
|
50
50
|
// Behavior
|
|
@@ -103,7 +103,7 @@ export default ({
|
|
|
103
103
|
- ATTRIBUTES
|
|
104
104
|
----------------------------------*/
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
className += ' input text';
|
|
107
107
|
|
|
108
108
|
// Auto prefix
|
|
109
109
|
if (prefix === undefined && icon !== undefined)
|
|
@@ -147,9 +147,6 @@ export default ({
|
|
|
147
147
|
if (errors?.length)
|
|
148
148
|
className += ' error';
|
|
149
149
|
|
|
150
|
-
if (props.className !== undefined)
|
|
151
|
-
className += ' ' + props.className;
|
|
152
|
-
|
|
153
150
|
/*----------------------------------
|
|
154
151
|
- VALIDATION
|
|
155
152
|
----------------------------------*/
|
|
@@ -36,11 +36,11 @@ const PageLoading = ({ clientRouter }: { clientRouter?: ClientRouter }) => {
|
|
|
36
36
|
if (clientRouter)
|
|
37
37
|
clientRouter.setLoading = setLoading;
|
|
38
38
|
|
|
39
|
-
return
|
|
40
|
-
<div id="loading">
|
|
39
|
+
return (
|
|
40
|
+
<div id="loading" class={isLoading ? 'display' : ''}>
|
|
41
41
|
<i src="spin" />
|
|
42
42
|
</div>
|
|
43
|
-
)
|
|
43
|
+
)
|
|
44
44
|
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -85,7 +85,7 @@ export default ({ service: clientRouter }: { service?: ClientRouter }) => {
|
|
|
85
85
|
// WARNING: Don"t try to play with pages here, since the object will not be updated
|
|
86
86
|
// If needed to play with pages, do it in the setPages callback below
|
|
87
87
|
// Unchanged path
|
|
88
|
-
if (request.path === currentRequest.path && request.hash !== currentRequest.hash) {
|
|
88
|
+
if (request.path === currentRequest.path && request.hash !== currentRequest.hash && request.hash !== undefined) {
|
|
89
89
|
scrollToElement(request.hash);
|
|
90
90
|
return;
|
|
91
91
|
}
|
|
@@ -183,10 +183,6 @@ export default ({ service: clientRouter }: { service?: ClientRouter }) => {
|
|
|
183
183
|
----------------------------------*/
|
|
184
184
|
// Render the page component
|
|
185
185
|
return <>
|
|
186
|
-
{/*pages.previous && (
|
|
187
|
-
<Page page={pages.previous} key={pages.previous.id === undefined ? undefined : 'page_' + pages.previous.id} />
|
|
188
|
-
)*/}
|
|
189
|
-
|
|
190
186
|
{pages.current && (
|
|
191
187
|
<PageComponent page={pages.current}
|
|
192
188
|
/* Create a new instance of the Page component every time the page change
|
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
- DEPENDANCES
|
|
3
3
|
----------------------------------*/
|
|
4
4
|
|
|
5
|
-
// Npm
|
|
6
|
-
import axios, { AxiosResponse, AxiosError, AxiosRequestConfig } from 'axios';
|
|
7
|
-
|
|
8
5
|
// Core
|
|
9
6
|
import type { TApiResponseData } from '@server/services/router';
|
|
10
7
|
import ApiClientService, {
|
|
@@ -190,83 +187,65 @@ export default class ApiClient implements ApiClientService {
|
|
|
190
187
|
return { ...alreadyLoadedData, ...fetchedData }
|
|
191
188
|
}
|
|
192
189
|
|
|
193
|
-
public configure = (...[method, path, data, options]: TFetcherArgs)
|
|
194
|
-
|
|
190
|
+
public configure = (...[method, path, data, options]: TFetcherArgs) => {
|
|
195
191
|
const { onProgress, captcha } = options || {};
|
|
196
|
-
|
|
197
|
-
const url = this.router.url( path, {}, false );
|
|
198
192
|
|
|
199
|
-
|
|
193
|
+
const url = this.router.url(path, {}, false);
|
|
200
194
|
|
|
201
|
-
|
|
202
|
-
const config: AxiosRequestConfig = {
|
|
195
|
+
debug && console.log(`[api] Sending request`, method, url, data);
|
|
203
196
|
|
|
204
|
-
|
|
197
|
+
// Create Fetch config
|
|
198
|
+
const config = {
|
|
205
199
|
method: method,
|
|
206
200
|
headers: {
|
|
207
201
|
'Content-Type': "application/json",
|
|
208
202
|
'Accept': "application/json",
|
|
209
|
-
},
|
|
210
|
-
|
|
211
|
-
validateStatus: function (status: number) {
|
|
212
|
-
return status === 200;
|
|
213
|
-
},
|
|
214
|
-
|
|
215
|
-
onUploadProgress: onProgress === undefined ? undefined : (e) => {
|
|
216
|
-
const percentCompleted = Math.round((e.loaded * 100) / e.total);
|
|
217
|
-
onProgress(percentCompleted);
|
|
218
203
|
}
|
|
219
|
-
|
|
220
204
|
};
|
|
221
205
|
|
|
222
206
|
// Format request data
|
|
223
207
|
if (data) {
|
|
224
|
-
// URL params
|
|
225
208
|
if (method === "GET") {
|
|
226
|
-
|
|
227
|
-
|
|
209
|
+
const params = new URLSearchParams(data).toString();
|
|
210
|
+
config.url = `${url}?${params}`;
|
|
228
211
|
} else if (options?.encoding === 'multipart') {
|
|
229
212
|
config.headers["Content-Type"] = 'multipart/form-data';
|
|
230
|
-
|
|
231
|
-
|
|
213
|
+
const formData = new FormData();
|
|
214
|
+
Object.keys(data).forEach(key => formData.append(key, data[key]));
|
|
215
|
+
config.body = formData;
|
|
232
216
|
} else {
|
|
233
|
-
config.
|
|
217
|
+
config.body = JSON.stringify(data);
|
|
234
218
|
}
|
|
235
219
|
}
|
|
236
220
|
|
|
237
|
-
return config;
|
|
221
|
+
return { url, config };
|
|
238
222
|
}
|
|
239
223
|
|
|
240
224
|
public execute<TData = unknown>(...args: TFetcherArgs): Promise<TData> {
|
|
225
|
+
const { url, config } = this.configure(...args);
|
|
241
226
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
return res.data as TData;
|
|
249
|
-
|
|
250
|
-
})
|
|
251
|
-
.catch((e: AxiosError) => {
|
|
252
|
-
|
|
253
|
-
if (e.response !== undefined) {
|
|
254
|
-
|
|
255
|
-
// Transmiss error
|
|
256
|
-
console.warn(`[api] Failure:`, e);
|
|
257
|
-
const error = viaHttpCode(
|
|
258
|
-
e.response.status || 500,
|
|
259
|
-
e.response.data
|
|
260
|
-
);
|
|
261
|
-
|
|
227
|
+
return fetch(url, config)
|
|
228
|
+
.then(async (response) => {
|
|
229
|
+
if (!response.ok) {
|
|
230
|
+
const errorData = await response.json();
|
|
231
|
+
console.warn(`[api] Failure:`, response.status, errorData);
|
|
232
|
+
const error = viaHttpCode(response.status || 500, errorData);
|
|
262
233
|
throw error;
|
|
263
|
-
|
|
264
|
-
|
|
234
|
+
}
|
|
235
|
+
debug && console.log(`[api] Success:`, response);
|
|
236
|
+
return response.json() as Promise<TData>;
|
|
237
|
+
})
|
|
238
|
+
.catch((error) => {
|
|
239
|
+
if (error instanceof TypeError) {
|
|
240
|
+
// Network error
|
|
241
|
+
console.warn(`[api] Network Failure:`, error);
|
|
242
|
+
const networkError = new NetworkError(error.message);
|
|
243
|
+
this.app.handleError(networkError);
|
|
244
|
+
throw networkError;
|
|
265
245
|
} else {
|
|
266
|
-
const error = new NetworkError(e.message);
|
|
267
|
-
this.app.handleError(error);
|
|
268
246
|
throw error;
|
|
269
247
|
}
|
|
270
248
|
});
|
|
271
249
|
}
|
|
250
|
+
|
|
272
251
|
}
|
|
@@ -95,6 +95,8 @@ export default class ClientPageResponse<
|
|
|
95
95
|
...this.request.router.config.context( basicContext, this.request.router )
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
newContext.context = newContext;
|
|
99
|
+
|
|
98
100
|
// Update context object if already exists
|
|
99
101
|
// NOTE: we don't create a nex instance of context because we don't want to rereder the full page (inc layout) to update the context given by thr react context provider
|
|
100
102
|
const existingContext = this.request.router.context;
|
package/src/common/data/dates.ts
CHANGED
|
@@ -1,9 +1,53 @@
|
|
|
1
|
-
import TimeAgo from 'javascript-time-ago';
|
|
2
|
-
import en from 'javascript-time-ago/locale/en'
|
|
3
|
-
TimeAgo.addLocale(en)
|
|
4
|
-
const timeAgo = new TimeAgo('en-US')
|
|
5
|
-
|
|
6
1
|
import dayjs from 'dayjs';
|
|
2
|
+
/*
|
|
3
|
+
// Function to calculate the difference in the specified unit
|
|
4
|
+
function dateDiffInUnits(date1, date2) {
|
|
5
|
+
const msPerSecond = 1000;
|
|
6
|
+
const msPerMinute = msPerSecond * 60;
|
|
7
|
+
const msPerHour = msPerMinute * 60;
|
|
8
|
+
const msPerDay = msPerHour * 24;
|
|
9
|
+
const msPerMonth = msPerDay * 30; // Approximation
|
|
10
|
+
const msPerYear = msPerDay * 365; // Approximation
|
|
11
|
+
|
|
12
|
+
const diffInMs = date2 - date1;
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
years: diffInMs / msPerYear,
|
|
16
|
+
months: diffInMs / msPerMonth,
|
|
17
|
+
days: diffInMs / msPerDay,
|
|
18
|
+
hours: diffInMs / msPerHour,
|
|
19
|
+
minutes: diffInMs / msPerMinute,
|
|
20
|
+
seconds: diffInMs / msPerSecond,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Function to determine the best unit based on the differences
|
|
25
|
+
function chooseBestUnit(diffs) {
|
|
26
|
+
if (Math.abs(diffs.years) >= 1) return 'year';
|
|
27
|
+
if (Math.abs(diffs.months) >= 1) return 'month';
|
|
28
|
+
if (Math.abs(diffs.days) >= 1) return 'day';
|
|
29
|
+
if (Math.abs(diffs.hours) >= 1) return 'hour';
|
|
30
|
+
if (Math.abs(diffs.minutes) >= 1) return 'minute';
|
|
31
|
+
return 'second';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Function to format the relative time between two dates
|
|
35
|
+
function formatRelativeTime(date1, date2, locale = 'en') {
|
|
36
|
+
const diffs = dateDiffInUnits(date1, date2);
|
|
37
|
+
const bestUnit = chooseBestUnit(diffs);
|
|
38
|
+
const diff = diffs[bestUnit];
|
|
39
|
+
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
|
|
40
|
+
return rtf.format(Math.round(diff), bestUnit);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Example dates
|
|
44
|
+
const date1 = new Date('2023-07-01');
|
|
45
|
+
const date2 = new Date('2024-07-13');
|
|
46
|
+
|
|
47
|
+
// Format the relative time automatically choosing the best unit
|
|
48
|
+
console.log(formatRelativeTime(date1, date2)); // Output: "in 1 year"
|
|
49
|
+
|
|
50
|
+
*/
|
|
7
51
|
|
|
8
52
|
export type TDateInfo = {
|
|
9
53
|
isPast: boolean,
|
|
@@ -30,7 +74,7 @@ export const timeSince = (date: Date | number | string): TDateInfo | null => {
|
|
|
30
74
|
const isPast = now > timestamp;
|
|
31
75
|
|
|
32
76
|
return {
|
|
33
|
-
text: timeAgo.format(date),
|
|
77
|
+
text: date,//timeAgo.format(date),
|
|
34
78
|
isPast,
|
|
35
79
|
delta: deltaSeconds
|
|
36
80
|
};
|