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.
Files changed (48) hide show
  1. package/package.json +4 -12
  2. package/src/client/app/component.tsx +11 -2
  3. package/src/client/assets/css/components/button.less +10 -10
  4. package/src/client/assets/css/components/other.less +0 -1
  5. package/src/client/assets/css/core.less +0 -4
  6. package/src/client/assets/css/text/text.less +1 -2
  7. package/src/client/assets/css/text/titres.less +0 -5
  8. package/src/client/assets/css/utils/layouts.less +5 -5
  9. package/src/client/assets/css/utils/sizing.less +6 -6
  10. package/src/client/components/Dialog/card.tsx +1 -1
  11. package/src/client/components/button.tsx +1 -1
  12. package/src/client/components/containers/Popover/index.tsx +2 -2
  13. package/src/client/components/index.ts +5 -16
  14. package/src/client/components/inputv3/index.tsx +2 -5
  15. package/src/client/services/router/components/Page.tsx +1 -2
  16. package/src/client/services/router/components/router.tsx +4 -8
  17. package/src/client/services/router/request/api.ts +31 -52
  18. package/src/client/services/router/response/index.tsx +2 -0
  19. package/src/common/data/dates.ts +50 -6
  20. package/src/common/router/layouts.ts +14 -5
  21. package/src/common/router/response/page.ts +12 -6
  22. package/src/common/validation/validators.ts +0 -4
  23. package/src/server/app/container/config.ts +2 -1
  24. package/src/server/services/router/http/index.ts +16 -22
  25. package/src/server/services/router/response/page/index.tsx +0 -0
  26. package/src/client/assets/fonts/Inter/index.less +0 -77
  27. package/src/client/assets/fonts/Inter/latin-500.woff2 +0 -0
  28. package/src/client/assets/fonts/Inter/latin-600.woff2 +0 -0
  29. package/src/client/assets/fonts/Inter/latin-800.woff2 +0 -0
  30. package/src/client/assets/fonts/Inter/latin-ext-500.woff2 +0 -0
  31. package/src/client/assets/fonts/Inter/latin-ext-600.woff2 +0 -0
  32. package/src/client/assets/fonts/Inter/latin-ext-800.woff2 +0 -0
  33. package/src/client/assets/fonts/Rubik/cyrillic-ext.woff2 +0 -0
  34. package/src/client/assets/fonts/Rubik/cyrillic.woff2 +0 -0
  35. package/src/client/assets/fonts/Rubik/hebrew.woff2 +0 -0
  36. package/src/client/assets/fonts/Rubik/index.less +0 -30
  37. package/src/client/assets/fonts/Rubik/latin-ext.woff2 +0 -0
  38. package/src/client/assets/fonts/Rubik/latin.woff2 +0 -0
  39. package/src/client/components/Amount.tsx +0 -38
  40. package/src/client/components/Form_old/index.tsx +0 -450
  41. package/src/client/components/Form_old/index.tsx.old +0 -436
  42. package/src/client/components/dropdown.old/Manager.tsx +0 -164
  43. package/src/client/components/dropdown.old/getPosition.ts +0 -137
  44. package/src/client/components/dropdown.old/index.tsx +0 -99
  45. package/src/client/components/dropdown.old/popover.less +0 -56
  46. package/src/client/components/input/Base/Choix.ts +0 -48
  47. package/src/client/components/input/Base/index.tsx +0 -432
  48. 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.2",
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.5.15",
66
- "preact-render-to-string": "^5.1.19",
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 context={context} />
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
- &.selected,
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).selected {
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
- &.selected,
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 + .menu,
284
- > .btn[disabled] + .menu {
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 + .menu {
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 + ul {
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 + .menu {
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 + .menu {
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 + .menu.pos-bottom {
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
@@ -19,7 +19,6 @@
19
19
  border-radius: @radius;
20
20
 
21
21
  line-height: 1.5;
22
- font-weight: 600;
23
22
  text-align: left;
24
23
 
25
24
  padding: 0.4em @spacing;
@@ -5,10 +5,6 @@
5
5
  @import './utils/spacing.less';
6
6
  @import (reference) "./theme.less";
7
7
 
8
- // Fonts
9
- @import '../fonts/Inter/index.less';
10
- @import '../fonts/Rubik/index.less';
11
-
12
8
  // Apply the theme class
13
9
  .bg {
14
10
  background: var(--cBg);
@@ -172,8 +172,7 @@ pre {
172
172
 
173
173
  &,
174
174
  p {
175
- font-family: 'Lato', sans-serif;
176
- font-size: 1.1rem;
175
+ font-size: 1.2rem;
177
176
  line-height: 2em;
178
177
  color: var(--cTxtBase);
179
178
  text-align: justify;
@@ -26,11 +26,6 @@ h3 {
26
26
  }
27
27
  }
28
28
 
29
- h1,
30
- h2 {
31
- font-family: "Rubik";
32
- }
33
-
34
29
  // sans input.h1, .h1 seul ne peut pas override le style par défaut des champs
35
30
  h1, .h1 {
36
31
  font-size: @h1Size;
@@ -69,7 +69,7 @@
69
69
  position: relative;
70
70
  }
71
71
 
72
- > a.selected {
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
- &, &.al-middle { justify-content: center; }
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
- &.bi-1 { // Bordure interne
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: 1em; }
2
- .s { font-size: 0.8em !important; line-height: 1em; }
3
- .m { font-size: 1em !important; line-height: 1em; }
4
- .l { font-size: 1.3em !important; line-height: 1em; }
5
- .xl { font-size: 2em !important; line-height: 1em; }
6
- .xxl { font-size: 2.5em !important; line-height: 1em; }
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 glass" onClick={() => isToast && !prison && close(true)}>
136
+ <div class="card row bg dark" onClick={() => isToast && !prison && close(true)}>
137
137
 
138
138
  {icon}
139
139
 
@@ -151,7 +151,7 @@ export default ({
151
151
  className += ' pressed';
152
152
 
153
153
  if (active || isActive === true)
154
- className += ' selected';
154
+ className += ' active';
155
155
 
156
156
  // Icon
157
157
  if (prefix === undefined && icon !== undefined)
@@ -4,7 +4,7 @@
4
4
 
5
5
  // Npm
6
6
  import React from 'react';
7
- import { JSX, ComponentChild, VNode } from 'preact';
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?: ComponentChild,
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 Number } from './input/Number';
17
- export { default as Slider } from './input/Slider';
18
- export { default as Radio } from './input/Radio';
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
- let className: string = 'input text';
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
  ----------------------------------*/
@@ -51,8 +51,7 @@ export default ({ page }: { page: Page }) => {
51
51
  ...apiData,
52
52
  ...context.request.data
53
53
  }}
54
- context={context}
55
54
  />
56
55
 
57
- ) : 'Renderer missing'
56
+ ) : <>Renderer missing</>
58
57
  }
@@ -36,11 +36,11 @@ const PageLoading = ({ clientRouter }: { clientRouter?: ClientRouter }) => {
36
36
  if (clientRouter)
37
37
  clientRouter.setLoading = setLoading;
38
38
 
39
- return isLoading ? (
40
- <div id="loading">
39
+ return (
40
+ <div id="loading" class={isLoading ? 'display' : ''}>
41
41
  <i src="spin" />
42
42
  </div>
43
- ) : null
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): AxiosRequestConfig => {
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
- debug && console.log(`[api] Sending request`, method, url, data);
193
+ const url = this.router.url(path, {}, false);
200
194
 
201
- // Create AXIOS config
202
- const config: AxiosRequestConfig = {
195
+ debug && console.log(`[api] Sending request`, method, url, data);
203
196
 
204
- url,
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
- config.params = data;
227
- // Post form data
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
- config.data = toMultipart(data);
231
- // Post JSON
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.data = data;
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
- const config = this.configure(...args);
243
-
244
- return axios.request(config)
245
- .then((res: AxiosResponse<TApiResponseData>) => {
246
-
247
- debug && console.log(`[api] Success:`, res);
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
- // Erreur réseau: l'utilisateur n'ets probablement plus connecté à internet
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;
@@ -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
  };