5htp-core 0.0.8-2 → 0.0.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "5htp-core",
3
3
  "description": "5-HTP, scientifically called 5-Hydroxytryptophan, is the precursor of happiness neurotransmitter.",
4
- "version": "0.0.8-2",
4
+ "version": "0.0.9",
5
5
  "author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
6
6
  "repository": "git://github.com/gaetanlegac/5htp-core.git",
7
7
  "license": "MIT",
@@ -85,13 +85,6 @@ iframe {
85
85
  border: none;
86
86
  }
87
87
 
88
- header.card {
89
- > i {
90
- font-size: 3em;
91
- line-height: 1em;
92
- }
93
- }
94
-
95
88
  .dropArea {
96
89
  padding: @spacing;
97
90
  border-radius: @radius;
@@ -217,6 +217,7 @@
217
217
  Déclarer une grid: grid x-3
218
218
  Placer un element: x1-3
219
219
  */
220
+ @gridUnit: 6.66rem;
220
221
  .zones(@nb, @i: 1) when (@i <= @nb) {
221
222
  /*----------------------------------
222
223
  - ZONES DE LA GRILLE
@@ -287,23 +288,23 @@
287
288
  // Automatique
288
289
  .taille-auto(@min, @max) when (@min <= @max) {
289
290
  &.xa@{min}-@{max} {
290
- grid-template-columns: repeat(auto-fit, minmax(@min * 100px, @max * 100px))
291
+ grid-template-columns: repeat(auto-fit, minmax(@min * @gridUnit, @max * @gridUnit))
291
292
  }
292
293
  &.ya@{min}-@{max} {
293
- grid-template-rows: repeat(auto-fit, minmax(@min * 100px, @max * 100px))
294
+ grid-template-rows: repeat(auto-fit, minmax(@min * @gridUnit, @max * @gridUnit))
294
295
  }
295
296
  .taille-auto(@min + 1, @max);
296
297
  }
297
298
  &.xa@{i} {
298
- grid-template-columns: repeat(auto-fit, minmax(@i * 100px, 1fr));
299
+ grid-template-columns: repeat(auto-fit, minmax(@i * @gridUnit, 1fr));
299
300
  &5 {
300
- grid-template-columns: repeat(auto-fit, minmax(@i * 100px + 4.15rem, 1fr));
301
+ grid-template-columns: repeat(auto-fit, minmax(@i * @gridUnit + 4.15rem, 1fr));
301
302
  }
302
303
  }
303
304
  &.ya@{i} {
304
- grid-template-rows: repeat(auto-fit, minmax(@i * 100px, 1fr));
305
+ grid-template-rows: repeat(auto-fit, minmax(@i * @gridUnit, 1fr));
305
306
  &5 {
306
- grid-template-rows: repeat(auto-fit, minmax(@i * 100px + 4.15rem, 1fr));
307
+ grid-template-rows: repeat(auto-fit, minmax(@i * @gridUnit + 4.15rem, 1fr));
307
308
  }
308
309
  }
309
310
  .taille-auto(1, @i);
@@ -347,10 +348,10 @@
347
348
  break-inside: avoid;
348
349
  }
349
350
 
350
- &.xa1 { column-width: 100px; }
351
- &.xa2 { column-width: 200px; }
351
+ &.xa1 { column-width: @gridUnit; }
352
+ &.xa2 { column-width: @gridUnit * 2; }
352
353
  &,
353
- &.xa3 { column-width: 300px; }
354
- &.xa4 { column-width: 400px; }
354
+ &.xa3 { column-width: @gridUnit * 3; }
355
+ &.xa4 { column-width: @gridUnit * 4; }
355
356
 
356
357
  }
File without changes
@@ -5,6 +5,7 @@ a {
5
5
  color: inherit;
6
6
  cursor: pointer;
7
7
  text-decoration: underline;
8
+ text-decoration: none;
8
9
 
9
10
  &:not([disabled]):hover,
10
11
  &.active {
@@ -12,12 +13,16 @@ a {
12
13
  }
13
14
 
14
15
  &.super {
15
- position: absolute;
16
- top: 0; left: 0; right: 0; bottom: 0;
17
- z-index: 5;
18
-
19
- ~ a, ~ * a, ~ button, ~ * button {
20
- z-index: 6;
16
+ text-decoration: none;
17
+ &::after {
18
+ content: ' ';
19
+ position: absolute;
20
+ top: 0; left: 0; right: 0; bottom: 0;
21
+ z-index: 5;
22
+
23
+ ~ a, ~ * a, ~ button, ~ * button {
24
+ z-index: 6;
25
+ }
21
26
  }
22
27
  }
23
28
  }
@@ -0,0 +1,58 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+ import React from 'react';
7
+
8
+ // Core
9
+ import Button from '@client/components/button';
10
+ import Dropdown, { TDialogControls, Props as DropdownProps } from '@client/components/dropdown';
11
+
12
+ /*----------------------------------
13
+ - CONST
14
+ ----------------------------------*/
15
+
16
+ /*----------------------------------
17
+ - TYPES
18
+ ----------------------------------*/
19
+
20
+ type Choices = string[]
21
+
22
+ type SearchResultsFunction = (keywords: string) => Choices
23
+
24
+ export type Props = DropdownProps & {
25
+ title: string,
26
+ choices: Choices,
27
+ value?: string,
28
+ onChange: (value: string) => void,
29
+ search?: true | SearchResultsFunction
30
+ }
31
+
32
+ /*----------------------------------
33
+ - COMONENT
34
+ ----------------------------------*/
35
+
36
+ export default ({ title, choices, value, onChange, ...dropDownProps }: Props) => {
37
+ const refModal = React.useRef<TDialogControls>(null);
38
+ return (
39
+ <Dropdown {...dropDownProps} content={(
40
+ <ul class="card col menu">
41
+ {choices.map( jt => (
42
+ <li>
43
+ <Button active={jt === value} onClick={() => {
44
+ onChange(jt);
45
+ refModal.current?.close();
46
+ }}>
47
+ {jt}
48
+ </Button>
49
+ </li>
50
+ ))}
51
+ </ul>
52
+ )} iconR="chevron-down" refModal={refModal}>
53
+
54
+ {value || title}
55
+
56
+ </Dropdown>
57
+ )
58
+ }
@@ -33,7 +33,7 @@ export default ({
33
33
  ratioCercle = 1,
34
34
  className,
35
35
  style = {},
36
- epaisseur = 5,
36
+ epaisseur = 10,
37
37
  rotation,
38
38
  etapes,
39
39
  taille,
@@ -99,8 +99,8 @@ div.progressbar_old {
99
99
  .progressbar-svg {
100
100
 
101
101
  position: relative;
102
- min-width: 100px;
103
- min-height: 100px;
102
+ width: @sizeComponent;
103
+ height: @sizeComponent;
104
104
 
105
105
  > svg {
106
106
 
@@ -142,6 +142,8 @@ div.progressbar_old {
142
142
  left: 0;
143
143
  right: 0;
144
144
  bottom: 0;
145
+ // Text should fit inside the progressbar
146
+ font-size: 0.8em;
145
147
 
146
148
  > i,
147
149
  > img {
@@ -4,10 +4,12 @@
4
4
 
5
5
  // Npm
6
6
  import React from 'react';
7
- import { ComponentChild } from 'preact';
7
+ import { ComponentChild, RefObject } from 'preact';
8
8
 
9
9
  // Core
10
10
  import Button, { Props as ButtonProps } from '../button';
11
+ import { TDialogControls } from '../Dialog/Manager';
12
+ export type { TDialogControls } from '../Dialog/Manager';
11
13
 
12
14
  // Libs
13
15
  import useContexte from '@client/context';
@@ -17,23 +19,8 @@ import useContexte from '@client/context';
17
19
  ----------------------------------*/
18
20
 
19
21
  export type Props = ButtonProps & {
20
- content: ComponentChild
21
- }
22
-
23
- export type TAction<TDonnee> = {
24
- icone?: TIcons,
25
- label: ComponentChild,
26
- multi?: boolean,
27
-
28
- onClick?: (donnees: TDonnee, index: number) => void,
29
- lien?: (donnees: TDonnee, index: number) => string,
30
- bouton?: (donnees: TDonnee, index: number) => ButtonProps
31
- }
32
-
33
- export type TActionsPopover = {
34
- show: () => void,
35
- hide: () => void,
36
- toggle: () => void
22
+ content: ComponentChild,
23
+ refModal?: RefObject<TDialogControls>
37
24
  }
38
25
 
39
26
  /*----------------------------------
@@ -45,15 +32,19 @@ export default (props: Props) => {
45
32
 
46
33
  let {
47
34
  content,
48
- immutable,
35
+ refModal,
49
36
  ...buttonProps
50
37
  } = props;
51
38
 
52
39
  const refButton = React.useRef<HTMLElement>(null);
53
40
 
54
- const open = () => modal.show(() => content);
41
+ const open = () => {
42
+ const modalInstance = modal.show(() => content);
43
+ if (refModal)
44
+ refModal.current = modalInstance;
45
+ }
55
46
 
56
47
  return (
57
- <Button {...buttonProps} onClick={open} refElem={refButton} />
48
+ <Button {...buttonProps} onClick={(open)} refElem={refButton} />
58
49
  )
59
50
  }
@@ -57,8 +57,10 @@ export function useInput<TValue>(
57
57
  // External value change
58
58
  React.useEffect(() => {
59
59
 
60
- console.log("External value change", externalValue);
61
- setState({ value: externalValue, valueSource: 'external' })
60
+ if (externalValue !== undefined && externalValue !== state.value) {
61
+ console.log("External value change", externalValue);
62
+ setState({ value: externalValue, valueSource: 'external' })
63
+ }
62
64
 
63
65
  }, [externalValue]);
64
66
 
@@ -112,42 +112,6 @@ export class ClientContext {
112
112
  this.request = request;
113
113
  this.user = this.request.user || { ...GuestUser };
114
114
 
115
- this.api.reload = (ids?: string | string[], params?: TObjetDonnees) => {
116
-
117
- if (this.page === undefined)
118
- throw new Error("context.page is missing");
119
-
120
- if (ids === undefined)
121
- ids = Object.keys(this.page.fetchers);
122
- else if (typeof ids === 'string')
123
- ids = [ids];
124
-
125
- console.log("[api] Reload data", ids, params, this.page.fetchers);
126
-
127
- for (const id of ids) {
128
-
129
- const fetcher = this.page.fetchers[id];
130
- if (fetcher === undefined)
131
- return console.error(`Unable to reload ${id}: Request not found in fetchers list.`);
132
-
133
- if (params !== undefined)
134
- fetcher.data = { ...(fetcher.data || {}), ...params };
135
-
136
- console.log("[api][reload]", id, fetcher.method, fetcher.path, fetcher.data);
137
- const indicator = this.toast.loading("Loading ...");
138
-
139
- this.request.fetchAsync(fetcher.method, fetcher.path, fetcher.data).then((data) => {
140
-
141
- this.api.set({ [id]: data });
142
-
143
- }).finally(() => {
144
-
145
- indicator.close(true);
146
-
147
- })
148
- }
149
- }
150
-
151
115
  }
152
116
 
153
117
  // Is overwrote by the native app
@@ -194,10 +158,51 @@ export class ClientContext {
194
158
 
195
159
  // fetch doit appartenir à response, et non clientcontxt
196
160
  // car la méthode varie selon client (http) ou serveur (router.resolve)
197
- public api = this.request.api as this["request"]["api"] & {
198
- reload: (id?: string, params?: TObjetDonnees) => void,
199
- set: (data: TObjetDonnees) => void
200
- };
161
+ public api = {
162
+ ...this.request.api,
163
+ set: (newData: TObjetDonnees) => {
164
+
165
+ console.log("[api] Update page data", newData);
166
+ if (this.page)
167
+ this.page.setAllData(curData => ({ ...curData, ...newData }));
168
+
169
+ },
170
+ reload: (ids?: string | string[], params?: TObjetDonnees) => {
171
+
172
+ if (this.page === undefined)
173
+ throw new Error("context.page is missing");
174
+
175
+ if (ids === undefined)
176
+ ids = Object.keys(this.page.fetchers);
177
+ else if (typeof ids === 'string')
178
+ ids = [ids];
179
+
180
+ console.log("[api] Reload data", ids, params, this.page.fetchers);
181
+
182
+ for (const id of ids) {
183
+
184
+ const fetcher = this.page.fetchers[id];
185
+ if (fetcher === undefined)
186
+ return console.error(`Unable to reload ${id}: Request not found in fetchers list.`);
187
+
188
+ if (params !== undefined)
189
+ fetcher.data = { ...(fetcher.data || {}), ...params };
190
+
191
+ console.log("[api][reload]", id, fetcher.method, fetcher.path, fetcher.data);
192
+ const indicator = this.toast.loading("Loading ...");
193
+
194
+ this.request.fetchAsync(fetcher.method, fetcher.path, fetcher.data).then((data) => {
195
+
196
+ this.api.set({ [id]: data });
197
+
198
+ }).finally(() => {
199
+
200
+ indicator.close(true);
201
+
202
+ })
203
+ }
204
+ }
205
+ }
201
206
 
202
207
  public handleError(e: Error) {
203
208
  switch (e.http) {
@@ -50,6 +50,7 @@ const Page = ({ page, isCurrent }: { page: PageResponse, isCurrent?: boolean })
50
50
  id={page.id === undefined ? undefined : 'page_' + page.id}
51
51
  >
52
52
 
53
+ {/* Make request parameters and api data accessible from the page component */}
53
54
  {page.component ? (
54
55
 
55
56
  <page.component {...gui.request.data} {...data} />
File without changes
@@ -11,11 +11,13 @@ export type TVariation = {
11
11
  color: string,
12
12
  }
13
13
 
14
- export const variationStr = (value: number, reference: number, lowerIsBetter: boolean = false): TVariation => {
14
+ export const variationStr = (value: number, reference: number, options: {
15
+ lowerIsBetter?: boolean
16
+ } = {}): TVariation => {
15
17
  const pc = variation(value, reference);
16
18
  const pcStr = pc.toFixed(2);
17
19
  return {
18
20
  txt: ((pc > 0) ? '+' + pcStr : pcStr) + '%',
19
- color: (lowerIsBetter ? pc > 0 : pc < 0) ? 'ea3943' : '16c784'
21
+ color: (options.lowerIsBetter ? pc > 0 : pc < 0) ? 'ea3943' : '16c784'
20
22
  }
21
23
  }
@@ -35,7 +35,7 @@ const getLayout = (routePath: string | undefined): Layout | undefined => {
35
35
  if (routePath === layoutPath || routePath.startsWith( layoutPath + '/' ))
36
36
  layout = { path: layoutPath, Component: layouts[layoutPath] };
37
37
  }
38
- layout && console.log(`Using Layout: ${layout.path}`);
38
+ //layout && console.log(`${routePath}: Using Layout: ${layout.path}`);
39
39
  return layout;
40
40
  }
41
41
 
@@ -14,6 +14,12 @@ import app from '@server/app';
14
14
 
15
15
  // Libs
16
16
 
17
+ /*----------------------------------
18
+ - CONFIG
19
+ ----------------------------------*/
20
+
21
+ const debug = false;
22
+
17
23
  /*----------------------------------
18
24
  - TYPES
19
25
  ----------------------------------*/
@@ -50,7 +56,7 @@ class Cache {
50
56
 
51
57
  private cleanMem() {
52
58
 
53
- console.log("[cache] Clean memory");
59
+ debug && console.log("[cache] Clean memory");
54
60
 
55
61
  const now = Date.now();
56
62
  for (const key in this.data) {
@@ -88,11 +94,11 @@ class Cache {
88
94
 
89
95
  let retour: CacheEntry | undefined = this.data[cle];
90
96
 
91
- console.log(`[cache] Get "${cle}".`);
97
+ debug && console.log(`[cache] Get "${cle}".`);
92
98
 
93
99
  // Expired
94
100
  if (retour?.expiration && retour.expiration < Date.now()){
95
- console.log(`[cache] Key ${cle} expired.`);
101
+ debug && console.log(`[cache] Key ${cle} expired.`);
96
102
  retour = undefined;
97
103
  }
98
104
 
@@ -133,7 +139,7 @@ class Cache {
133
139
  */
134
140
  public set( cle: string, val: TPrimitiveValue, expiration: TExpirationDelay = null ): void {
135
141
 
136
- console.log("[cache] Updating cache " + cle);
142
+ debug && console.log("[cache] Updating cache " + cle);
137
143
  this.data[ cle ] = {
138
144
  value: val,
139
145
  expiration: this.delayToTimestamp(expiration)