proteum 1.0.0-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/.dockerignore +10 -0
- package/Rte.zip +0 -0
- package/cli/app/config.ts +54 -0
- package/cli/app/index.ts +195 -0
- package/cli/bin.js +11 -0
- package/cli/commands/build.ts +34 -0
- package/cli/commands/deploy/app.ts +29 -0
- package/cli/commands/deploy/web.ts +60 -0
- package/cli/commands/dev.ts +109 -0
- package/cli/commands/init.ts +85 -0
- package/cli/compiler/client/identite.ts +72 -0
- package/cli/compiler/client/index.ts +334 -0
- package/cli/compiler/common/babel/index.ts +170 -0
- package/cli/compiler/common/babel/plugins/index.ts +0 -0
- package/cli/compiler/common/babel/plugins/services.ts +579 -0
- package/cli/compiler/common/babel/routes/imports.ts +127 -0
- package/cli/compiler/common/babel/routes/routes.ts +1130 -0
- package/cli/compiler/common/files/autres.ts +39 -0
- package/cli/compiler/common/files/images.ts +35 -0
- package/cli/compiler/common/files/style.ts +78 -0
- package/cli/compiler/common/index.ts +154 -0
- package/cli/compiler/index.ts +532 -0
- package/cli/compiler/server/index.ts +211 -0
- package/cli/index.ts +189 -0
- package/cli/paths.ts +165 -0
- package/cli/print.ts +12 -0
- package/cli/tsconfig.json +38 -0
- package/cli/utils/index.ts +22 -0
- package/cli/utils/keyboard.ts +78 -0
- package/client/app/component.tsx +54 -0
- package/client/app/index.ts +142 -0
- package/client/app/service.ts +34 -0
- package/client/app.tsconfig.json +28 -0
- package/client/components/Button.tsx +298 -0
- package/client/components/Dialog/Manager.tsx +309 -0
- package/client/components/Dialog/card.tsx +208 -0
- package/client/components/Dialog/index.less +151 -0
- package/client/components/Dialog/status.less +176 -0
- package/client/components/Dialog/status.tsx +48 -0
- package/client/components/index.ts +2 -0
- package/client/components/types.d.ts +3 -0
- package/client/data/input.ts +32 -0
- package/client/global.d.ts +5 -0
- package/client/hooks.ts +22 -0
- package/client/index.ts +6 -0
- package/client/pages/_layout/index.less +6 -0
- package/client/pages/_layout/index.tsx +43 -0
- package/client/pages/bug.tsx.old +60 -0
- package/client/pages/useHeader.tsx +50 -0
- package/client/services/captcha/index.ts +67 -0
- package/client/services/router/components/Link.tsx +46 -0
- package/client/services/router/components/Page.tsx +55 -0
- package/client/services/router/components/router.tsx +218 -0
- package/client/services/router/index.tsx +521 -0
- package/client/services/router/request/api.ts +267 -0
- package/client/services/router/request/history.ts +5 -0
- package/client/services/router/request/index.ts +53 -0
- package/client/services/router/request/multipart.ts +147 -0
- package/client/services/router/response/index.tsx +128 -0
- package/client/services/router/response/page.ts +86 -0
- package/client/services/socket/index.ts +147 -0
- package/client/utils/dom.ts +77 -0
- package/common/app/index.ts +9 -0
- package/common/data/chaines/index.ts +54 -0
- package/common/data/dates.ts +179 -0
- package/common/data/markdown.ts +73 -0
- package/common/data/rte/nodes.ts +83 -0
- package/common/data/stats.ts +90 -0
- package/common/errors/index.tsx +326 -0
- package/common/router/index.ts +213 -0
- package/common/router/layouts.ts +93 -0
- package/common/router/register.ts +55 -0
- package/common/router/request/api.ts +77 -0
- package/common/router/request/index.ts +35 -0
- package/common/router/response/index.ts +45 -0
- package/common/router/response/page.ts +128 -0
- package/common/utils/rte.ts +183 -0
- package/common/utils.ts +7 -0
- package/doc/TODO.md +71 -0
- package/doc/front/router.md +27 -0
- package/doc/workspace/workspace.png +0 -0
- package/doc/workspace/workspace2.png +0 -0
- package/doc/workspace/workspace_26.01.22.png +0 -0
- package/package.json +171 -0
- package/server/app/commands.ts +141 -0
- package/server/app/container/config.ts +203 -0
- package/server/app/container/console/index.ts +550 -0
- package/server/app/container/index.ts +137 -0
- package/server/app/index.ts +273 -0
- package/server/app/service/container.ts +88 -0
- package/server/app/service/index.ts +235 -0
- package/server/app.tsconfig.json +28 -0
- package/server/context.ts +4 -0
- package/server/index.ts +4 -0
- package/server/services/auth/index.ts +250 -0
- package/server/services/auth/old.ts +277 -0
- package/server/services/auth/router/index.ts +95 -0
- package/server/services/auth/router/request.ts +54 -0
- package/server/services/auth/router/service.json +6 -0
- package/server/services/auth/service.json +6 -0
- package/server/services/cache/commands.ts +41 -0
- package/server/services/cache/index.ts +297 -0
- package/server/services/cache/service.json +6 -0
- package/server/services/cron/CronTask.ts +86 -0
- package/server/services/cron/index.ts +112 -0
- package/server/services/cron/service.json +6 -0
- package/server/services/disks/driver.ts +103 -0
- package/server/services/disks/drivers/local/index.ts +188 -0
- package/server/services/disks/drivers/local/service.json +6 -0
- package/server/services/disks/drivers/s3/index.ts +301 -0
- package/server/services/disks/drivers/s3/service.json +6 -0
- package/server/services/disks/index.ts +90 -0
- package/server/services/disks/service.json +6 -0
- package/server/services/email/index.ts +188 -0
- package/server/services/email/utils.ts +53 -0
- package/server/services/fetch/index.ts +201 -0
- package/server/services/fetch/service.json +7 -0
- package/server/services/models.7z +0 -0
- package/server/services/prisma/Facet.ts +142 -0
- package/server/services/prisma/index.ts +201 -0
- package/server/services/prisma/service.json +6 -0
- package/server/services/router/http/index.ts +217 -0
- package/server/services/router/http/multipart.ts +102 -0
- package/server/services/router/http/session.ts.old +40 -0
- package/server/services/router/index.ts +801 -0
- package/server/services/router/request/api.ts +87 -0
- package/server/services/router/request/index.ts +184 -0
- package/server/services/router/request/service.ts +21 -0
- package/server/services/router/request/validation/zod.ts +180 -0
- package/server/services/router/response/index.ts +338 -0
- package/server/services/router/response/mask/Filter.ts +323 -0
- package/server/services/router/response/mask/index.ts +60 -0
- package/server/services/router/response/mask/selecteurs.ts +92 -0
- package/server/services/router/response/page/document.tsx +160 -0
- package/server/services/router/response/page/index.tsx +196 -0
- package/server/services/router/service.json +6 -0
- package/server/services/router/service.ts +36 -0
- package/server/services/schema/index.ts +44 -0
- package/server/services/schema/request.ts +49 -0
- package/server/services/schema/router/index.ts +28 -0
- package/server/services/schema/router/service.json +6 -0
- package/server/services/schema/service.json +6 -0
- package/server/services/security/encrypt/aes/index.ts +85 -0
- package/server/services/security/encrypt/aes/service.json +6 -0
- package/server/services/socket/index.ts +162 -0
- package/server/services/socket/scope.ts +226 -0
- package/server/services/socket/service.json +6 -0
- package/server/services_old/SocketClient.ts +92 -0
- package/server/services_old/Token.old.ts +97 -0
- package/server/utils/slug.ts +79 -0
- package/tsconfig.common.json +45 -0
- package/tsconfig.json +3 -0
- package/types/aliases.d.ts +54 -0
- package/types/global/modules.d.ts +49 -0
- package/types/global/utils.d.ts +103 -0
- package/types/icons.d.ts +1 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPENDANCES
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
|
|
5
|
+
// Npm
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { ComponentChild } from 'preact';
|
|
8
|
+
|
|
9
|
+
// Core
|
|
10
|
+
import useContext from '@/client/context';
|
|
11
|
+
import { blurable, deepContains, focusContent } from '@client/utils/dom';
|
|
12
|
+
|
|
13
|
+
// Specific
|
|
14
|
+
import type Application from '../../app';
|
|
15
|
+
import Card, { Props as CardInfos } from './card';
|
|
16
|
+
import Button from '../Button';
|
|
17
|
+
|
|
18
|
+
/*----------------------------------
|
|
19
|
+
- TYPES: IMPORTATIONS
|
|
20
|
+
----------------------------------*/
|
|
21
|
+
|
|
22
|
+
/*----------------------------------
|
|
23
|
+
- TYPES: DECLARATIONS
|
|
24
|
+
----------------------------------*/
|
|
25
|
+
|
|
26
|
+
type TParams = { [cle: string]: unknown }
|
|
27
|
+
|
|
28
|
+
type ComposantToast = React.FunctionComponent<{ close?: any }> & { data?: object };
|
|
29
|
+
|
|
30
|
+
type TOptsToast = (CardInfos & {
|
|
31
|
+
content?: ComponentChild,
|
|
32
|
+
data?: {},
|
|
33
|
+
className?: string,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
type TOnCloseCallback<TReturnType extends any> = (returnedValue: TReturnType) => void
|
|
37
|
+
|
|
38
|
+
type TToastShortcutArgs = [
|
|
39
|
+
title: TOptsToast["title"],
|
|
40
|
+
content?: TOptsToast["content"],
|
|
41
|
+
boutons?: TOptsToast["boutons"],
|
|
42
|
+
options?: TOptsToast,
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
export type TDialogControls = {
|
|
46
|
+
close: TOnCloseCallback<any>,
|
|
47
|
+
then: (cb: TOnCloseCallback<any>) => any
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
type TDialogContentArg = ComposantToast | Promise<{ default: ComposantToast }> | TOptsToast;
|
|
51
|
+
|
|
52
|
+
type TDialogShowArgs = [
|
|
53
|
+
// On utilise une fonction pour pouvoir accéder aux fonctions (close, ...) lors de la déclaration des infos de la toast
|
|
54
|
+
Content: TDialogContentArg,
|
|
55
|
+
paramsInit?: TParams
|
|
56
|
+
] | [
|
|
57
|
+
title: string,
|
|
58
|
+
// On utilise une fonction pour pouvoir accéder aux fonctions (close, ...) lors de la déclaration des infos de la toast
|
|
59
|
+
Content: TDialogContentArg,
|
|
60
|
+
paramsInit?: TParams
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
type DialogActions = {
|
|
64
|
+
|
|
65
|
+
setToasts: ( setter: (old: ComponentChild[]) => ComponentChild[]) => void,
|
|
66
|
+
setModals: ( setter: (old: ComponentChild[]) => ComponentChild[]) => void,
|
|
67
|
+
|
|
68
|
+
show: (...args: TDialogShowArgs ) => TDialogControls,
|
|
69
|
+
|
|
70
|
+
confirm: (title: string, content: string | ComponentChild, defaultBtn: 'Yes'|'No') => TDialogControls,
|
|
71
|
+
|
|
72
|
+
loading: (title: string) => TDialogControls,
|
|
73
|
+
|
|
74
|
+
info: (...[title, content, boutons, options]: TToastShortcutArgs) => TDialogControls,
|
|
75
|
+
|
|
76
|
+
success: (...[title, content, boutons, options]: TToastShortcutArgs) => TDialogControls,
|
|
77
|
+
|
|
78
|
+
warning: (...[title, content, boutons, options]: TToastShortcutArgs) => TDialogControls,
|
|
79
|
+
|
|
80
|
+
error: (...[title, content, boutons, options]: TToastShortcutArgs) => TDialogControls,
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/*----------------------------------
|
|
84
|
+
- SERVICE CONTEXTE
|
|
85
|
+
----------------------------------*/
|
|
86
|
+
let idA: number = 0;
|
|
87
|
+
export const createDialog = (app: Application, isToast: boolean): DialogActions => {
|
|
88
|
+
|
|
89
|
+
const show = <TReturnType extends any = true>( ...args: TDialogShowArgs ): TDialogControls => {
|
|
90
|
+
|
|
91
|
+
let onClose: TOnCloseCallback<TReturnType>;
|
|
92
|
+
const id = idA++;
|
|
93
|
+
|
|
94
|
+
// Parse args
|
|
95
|
+
let title: string | undefined;
|
|
96
|
+
let Content: TDialogContentArg;
|
|
97
|
+
let paramsInit: TParams = {};
|
|
98
|
+
if (typeof args[0] === 'string') {
|
|
99
|
+
[title, Content, paramsInit] = args;
|
|
100
|
+
} else {
|
|
101
|
+
[Content, paramsInit] = args;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Set instance management function
|
|
105
|
+
const setDialog = isToast
|
|
106
|
+
? instance.setToasts
|
|
107
|
+
: instance.setModals;
|
|
108
|
+
|
|
109
|
+
// Close function
|
|
110
|
+
const close = (retour: TReturnType) => {
|
|
111
|
+
|
|
112
|
+
setDialog(q => q.filter(m => m.id !== id))
|
|
113
|
+
|
|
114
|
+
if (onClose !== undefined)
|
|
115
|
+
onClose(retour);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const promise = new Promise(async (resolve: TOnCloseCallback<TReturnType>) => {
|
|
119
|
+
onClose = resolve
|
|
120
|
+
|
|
121
|
+
let render: ComponentChild;
|
|
122
|
+
let propsRendu: CardInfos = {
|
|
123
|
+
...paramsInit,
|
|
124
|
+
close: close
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// modal.show( import('./modalSupprimer') )
|
|
128
|
+
// -> Fetch component
|
|
129
|
+
if (Content.constructor === Promise)
|
|
130
|
+
Content = (await Content).default;
|
|
131
|
+
|
|
132
|
+
// modal.show('Supprimer', import('./modalSupprimer'))
|
|
133
|
+
// -> Shortcut for modal.show({ title: 'Suoorimer', content: <Component> })
|
|
134
|
+
if (title !== undefined) {
|
|
135
|
+
Content = {
|
|
136
|
+
title: title,
|
|
137
|
+
content: Content
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// modal.show({ title: 'supprimer', content: <>...</> })
|
|
142
|
+
if (Content.constructor === Object) {
|
|
143
|
+
|
|
144
|
+
const { content: CardContent, data = {}, ...propsToast } = Content as TOptsToast;
|
|
145
|
+
|
|
146
|
+
let cardContent: ComponentChild;
|
|
147
|
+
if (typeof CardContent === 'function') {
|
|
148
|
+
cardContent = <CardContent {...propsRendu} {...data} />
|
|
149
|
+
propsToast.boutons = null; // Component content = advanced content = should include buttons
|
|
150
|
+
} else {
|
|
151
|
+
cardContent = CardContent;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
render = (
|
|
155
|
+
<Card {...propsRendu} {...propsToast} isToast={isToast}>
|
|
156
|
+
{cardContent}
|
|
157
|
+
</Card>
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
// modal.show( ToastSupprimer )
|
|
161
|
+
// -> Content is a component rendering a Card
|
|
162
|
+
} else {
|
|
163
|
+
|
|
164
|
+
render = (
|
|
165
|
+
<Content {...propsRendu} isToast={isToast} />
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Chargeur de données
|
|
170
|
+
/*if (('data' in ComposantCharge) && typeof ComposantCharge.data === 'function') {
|
|
171
|
+
|
|
172
|
+
propsRendu.data = await ComposantCharge.data(app, paramsInit);
|
|
173
|
+
|
|
174
|
+
const { fetchersStateA } = initStateAsync(propsRendu.data, {}, false);
|
|
175
|
+
|
|
176
|
+
await execFetchersState(fetchersStateA);
|
|
177
|
+
|
|
178
|
+
}*/
|
|
179
|
+
|
|
180
|
+
if (!isToast)
|
|
181
|
+
render = (
|
|
182
|
+
<div class="modal">
|
|
183
|
+
{render}
|
|
184
|
+
</div>
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
render["id"] = id;
|
|
188
|
+
|
|
189
|
+
setDialog(q => [...q, render]);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
close,
|
|
194
|
+
then: (cb) => promise.then(cb)
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const instance: DialogActions = {
|
|
199
|
+
|
|
200
|
+
show: show,
|
|
201
|
+
|
|
202
|
+
setToasts: undefined as unknown as DialogActions["setToasts"],
|
|
203
|
+
setModals: undefined as unknown as DialogActions["setModals"],
|
|
204
|
+
|
|
205
|
+
confirm: (title: string, content: string | ComponentChild, defaultBtn: 'Yes'|'No' = 'No') => show<boolean>(({ close }) => (
|
|
206
|
+
<div class="card col">
|
|
207
|
+
<header>
|
|
208
|
+
<h2>{title}</h2>
|
|
209
|
+
</header>
|
|
210
|
+
{typeof content === 'string' ? <p>{content}</p> : content}
|
|
211
|
+
<footer class="row fill">
|
|
212
|
+
<Button type={defaultBtn === 'Yes' ? 'primary' : undefined}
|
|
213
|
+
onClick={() => close(true)}>
|
|
214
|
+
Yes
|
|
215
|
+
</Button>
|
|
216
|
+
<Button type={defaultBtn === 'No' ? 'primary' : undefined}
|
|
217
|
+
onClick={() => close(false)}>
|
|
218
|
+
No
|
|
219
|
+
</Button>
|
|
220
|
+
</footer>
|
|
221
|
+
</div>
|
|
222
|
+
)),
|
|
223
|
+
|
|
224
|
+
loading: (title: string) => show({
|
|
225
|
+
title: title,
|
|
226
|
+
type: 'loading'
|
|
227
|
+
}),
|
|
228
|
+
|
|
229
|
+
info: (...[title, content, boutons, options]: TToastShortcutArgs) => show({
|
|
230
|
+
title: title,
|
|
231
|
+
type: 'info',
|
|
232
|
+
content: content && <p>{content}</p>,
|
|
233
|
+
boutons,
|
|
234
|
+
...options
|
|
235
|
+
}),
|
|
236
|
+
|
|
237
|
+
success: (...[title, content, boutons, options]: TToastShortcutArgs) => show({
|
|
238
|
+
title: title,
|
|
239
|
+
type: 'success',
|
|
240
|
+
content: content && <p>{content}</p>,
|
|
241
|
+
boutons,
|
|
242
|
+
...options
|
|
243
|
+
}),
|
|
244
|
+
|
|
245
|
+
warning: (...[title, content, boutons, options]: TToastShortcutArgs) => show({
|
|
246
|
+
title: title,
|
|
247
|
+
type: 'warn',
|
|
248
|
+
content: content && <p>{content}</p>,
|
|
249
|
+
boutons,
|
|
250
|
+
...options
|
|
251
|
+
}),
|
|
252
|
+
|
|
253
|
+
error: (...[title, content, boutons, options]: TToastShortcutArgs) => show({
|
|
254
|
+
title: title,
|
|
255
|
+
type: 'error',
|
|
256
|
+
content: content && <p>{content}</p>,
|
|
257
|
+
boutons,
|
|
258
|
+
...options
|
|
259
|
+
}),
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return instance;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/*----------------------------------
|
|
266
|
+
- COMPOSANT
|
|
267
|
+
----------------------------------*/
|
|
268
|
+
import './index.less';
|
|
269
|
+
export default () => {
|
|
270
|
+
|
|
271
|
+
const app = useContext();
|
|
272
|
+
|
|
273
|
+
const [modals, setModals] = React.useState<ComponentChild[]>([]);
|
|
274
|
+
const [toasts, setToasts] = React.useState<ComponentChild[]>([]);
|
|
275
|
+
|
|
276
|
+
if (app.side === 'client') {
|
|
277
|
+
app.modal.setModals = setModals;
|
|
278
|
+
app.toast.setToasts = setToasts;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
React.useEffect(() => {
|
|
282
|
+
|
|
283
|
+
console.log('Updated toast list');
|
|
284
|
+
|
|
285
|
+
const modals = document.querySelectorAll("#modals > .modal");
|
|
286
|
+
if (modals.length === 0)
|
|
287
|
+
return;
|
|
288
|
+
|
|
289
|
+
// Focus
|
|
290
|
+
const lastToast = modals[ modals.length - 1 ];
|
|
291
|
+
focusContent( lastToast );
|
|
292
|
+
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
return <>
|
|
296
|
+
{modals.length !== 0 ? (
|
|
297
|
+
<div id="modals">
|
|
298
|
+
{modals}
|
|
299
|
+
</div>
|
|
300
|
+
) : null}
|
|
301
|
+
|
|
302
|
+
{toasts.length !== 0 ? (
|
|
303
|
+
<div id="toasts">
|
|
304
|
+
{toasts}
|
|
305
|
+
</div>
|
|
306
|
+
) : null}
|
|
307
|
+
</>
|
|
308
|
+
|
|
309
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPENDANCES
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
|
|
5
|
+
// Npm
|
|
6
|
+
import React from 'react';
|
|
7
|
+
|
|
8
|
+
// Composants globaux
|
|
9
|
+
import Button from '@client/components/Button';
|
|
10
|
+
|
|
11
|
+
/*----------------------------------
|
|
12
|
+
- TYPES
|
|
13
|
+
----------------------------------*/
|
|
14
|
+
import { ComponentChild } from 'preact';
|
|
15
|
+
|
|
16
|
+
type funcBtns = () => void
|
|
17
|
+
|
|
18
|
+
type Boutons = { [label: string]: funcBtns }
|
|
19
|
+
|
|
20
|
+
/*----------------------------------
|
|
21
|
+
- CONTENU
|
|
22
|
+
----------------------------------*/
|
|
23
|
+
export type Props = {
|
|
24
|
+
|
|
25
|
+
// Informations modale
|
|
26
|
+
type?: 'primary' | 'success' | 'warning' | 'error' | 'loading' | 'info',
|
|
27
|
+
cover?: string,
|
|
28
|
+
icon?: ComponentChild,
|
|
29
|
+
title?: string | ComponentChild,
|
|
30
|
+
className?: string,
|
|
31
|
+
|
|
32
|
+
children?: ComponentChild,
|
|
33
|
+
isToast?: boolean,
|
|
34
|
+
width?: number,
|
|
35
|
+
|
|
36
|
+
footer?: ComponentChild,
|
|
37
|
+
boutons?: Boutons | null, // nul = pas de footer
|
|
38
|
+
defaultBtn?: string,
|
|
39
|
+
|
|
40
|
+
prison?: boolean,
|
|
41
|
+
/* Hide after x seconds */autohide?: number | false,
|
|
42
|
+
close?: funcBtns,
|
|
43
|
+
onClose?: () => Promise<any>,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default ({
|
|
47
|
+
|
|
48
|
+
// Content
|
|
49
|
+
type,
|
|
50
|
+
cover,
|
|
51
|
+
icon,
|
|
52
|
+
title,
|
|
53
|
+
className = '',
|
|
54
|
+
|
|
55
|
+
children,
|
|
56
|
+
isToast,
|
|
57
|
+
width,
|
|
58
|
+
|
|
59
|
+
footer,
|
|
60
|
+
boutons,
|
|
61
|
+
defaultBtn,
|
|
62
|
+
|
|
63
|
+
onClose,
|
|
64
|
+
close,
|
|
65
|
+
autohide,
|
|
66
|
+
prison,
|
|
67
|
+
|
|
68
|
+
}: Props) => {
|
|
69
|
+
|
|
70
|
+
// Boutons
|
|
71
|
+
if (footer === undefined && boutons !== null) {
|
|
72
|
+
|
|
73
|
+
// Default buttons
|
|
74
|
+
if (boutons === undefined || !Object.keys(boutons).length) {
|
|
75
|
+
|
|
76
|
+
// Toast: by default, if no buttons, we autohide after 3 seconds
|
|
77
|
+
if (autohide === undefined)
|
|
78
|
+
autohide = 3;
|
|
79
|
+
|
|
80
|
+
// If isToast, we show a default OK button
|
|
81
|
+
if (close && !isToast)
|
|
82
|
+
boutons = { 'Ok': () => close(true) };
|
|
83
|
+
else
|
|
84
|
+
boutons = null;
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (boutons !== null) {
|
|
89
|
+
|
|
90
|
+
const nbBtns = Object.keys(boutons).length;
|
|
91
|
+
|
|
92
|
+
footer = Object.entries(boutons).map(([texte, action]: [string, Function], index: number) => {
|
|
93
|
+
const dernier = nbBtns > 1 && index === nbBtns - 1;
|
|
94
|
+
return (
|
|
95
|
+
<Button
|
|
96
|
+
async
|
|
97
|
+
onClick={() => action()}
|
|
98
|
+
type={(defaultBtn === undefined ? dernier : (defaultBtn === texte)) ? 'primary' : undefined}
|
|
99
|
+
>
|
|
100
|
+
{texte}
|
|
101
|
+
</Button>
|
|
102
|
+
)
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (typeof icon === 'string')
|
|
108
|
+
icon = <i class={"svg-" + icon} />
|
|
109
|
+
else if (icon === undefined)
|
|
110
|
+
switch (type) {
|
|
111
|
+
case 'info':
|
|
112
|
+
icon = <i src="info-circle" />
|
|
113
|
+
break;
|
|
114
|
+
case 'success':
|
|
115
|
+
icon = <i src="check-circle" />
|
|
116
|
+
break;
|
|
117
|
+
case 'warning':
|
|
118
|
+
icon = <i src="exclamation-circle" />
|
|
119
|
+
break;
|
|
120
|
+
case 'error':
|
|
121
|
+
icon = <i src="times-circle" />
|
|
122
|
+
break;
|
|
123
|
+
case 'loading':
|
|
124
|
+
icon = <i src="spin" />
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Autohide
|
|
129
|
+
if (isToast)
|
|
130
|
+
React.useEffect(() => {
|
|
131
|
+
if (autohide) {
|
|
132
|
+
const timeout = setTimeout(() => close(true), autohide * 1000);
|
|
133
|
+
return () => clearTimeout(timeout);
|
|
134
|
+
}
|
|
135
|
+
}, []);
|
|
136
|
+
|
|
137
|
+
let render = isToast ? (
|
|
138
|
+
<div class="card row bg dark" onClick={() => isToast && !prison && close(true)}>
|
|
139
|
+
|
|
140
|
+
{icon}
|
|
141
|
+
|
|
142
|
+
<div>
|
|
143
|
+
|
|
144
|
+
{typeof title === "string" ? (
|
|
145
|
+
<strong>{title}</strong>
|
|
146
|
+
) : title}
|
|
147
|
+
|
|
148
|
+
{children}
|
|
149
|
+
|
|
150
|
+
</div>
|
|
151
|
+
|
|
152
|
+
</div>
|
|
153
|
+
) : (
|
|
154
|
+
<div class={"card pd-2 col al-top " + className} style={width === undefined
|
|
155
|
+
? {}
|
|
156
|
+
: { minWidth: width + "px", maxWidth: width + "px" }
|
|
157
|
+
}>
|
|
158
|
+
|
|
159
|
+
{(title || icon) && (
|
|
160
|
+
<header {...{
|
|
161
|
+
class: ('col ' + type),
|
|
162
|
+
style: cover ? {
|
|
163
|
+
backgroundImage: 'url(' + cover + ')'
|
|
164
|
+
} : undefined
|
|
165
|
+
}}>
|
|
166
|
+
|
|
167
|
+
{icon}
|
|
168
|
+
|
|
169
|
+
{typeof title === "string" ? (
|
|
170
|
+
<strong>{title}</strong>
|
|
171
|
+
) : title}
|
|
172
|
+
|
|
173
|
+
{(!prison && close) && (
|
|
174
|
+
<Button class="close" icon="times" size="s" shape="pill" onClick={async () => {
|
|
175
|
+
if (typeof close === "function") {
|
|
176
|
+
|
|
177
|
+
if (onClose !== undefined)
|
|
178
|
+
onClose(false);
|
|
179
|
+
else
|
|
180
|
+
close(false);
|
|
181
|
+
}
|
|
182
|
+
}} />
|
|
183
|
+
)}
|
|
184
|
+
|
|
185
|
+
</header>
|
|
186
|
+
)}
|
|
187
|
+
|
|
188
|
+
{children && (
|
|
189
|
+
<div class="col content">
|
|
190
|
+
|
|
191
|
+
{children}
|
|
192
|
+
|
|
193
|
+
</div>
|
|
194
|
+
)}
|
|
195
|
+
|
|
196
|
+
{footer && (
|
|
197
|
+
<footer class="row fill actions">
|
|
198
|
+
|
|
199
|
+
{footer}
|
|
200
|
+
|
|
201
|
+
</footer>
|
|
202
|
+
)}
|
|
203
|
+
|
|
204
|
+
</div>
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
return render;
|
|
208
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
|
|
2
|
+
@c1: #6c5dd3; // Should be darker than c1
|
|
3
|
+
@spacing: 1.2em;
|
|
4
|
+
@toast-zindex: 200;
|
|
5
|
+
@radius: 1rem;
|
|
6
|
+
|
|
7
|
+
#modals,
|
|
8
|
+
#toasts {
|
|
9
|
+
|
|
10
|
+
z-index: @toast-zindex;
|
|
11
|
+
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: column;
|
|
14
|
+
align-items: center;
|
|
15
|
+
justify-content: flex-end;
|
|
16
|
+
gap: @spacing;
|
|
17
|
+
padding: @spacing;
|
|
18
|
+
|
|
19
|
+
&,
|
|
20
|
+
> .modal {
|
|
21
|
+
position: fixed;
|
|
22
|
+
left: 0px;
|
|
23
|
+
right: 0px;
|
|
24
|
+
bottom: 0px;
|
|
25
|
+
max-height: 100vh;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Toast
|
|
29
|
+
> .card,
|
|
30
|
+
// Modal (pas forcément une card quand bcp de contenu. Ex: inventory)
|
|
31
|
+
> .modal > div {
|
|
32
|
+
|
|
33
|
+
.btn.close {
|
|
34
|
+
position: absolute;
|
|
35
|
+
top: @spacing;
|
|
36
|
+
right: @spacing;
|
|
37
|
+
|
|
38
|
+
// Vire le margin-top créé par .col > *
|
|
39
|
+
margin-top: 0;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#modals {
|
|
45
|
+
|
|
46
|
+
&,
|
|
47
|
+
> .modal {
|
|
48
|
+
top: 0px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
> .modal {
|
|
52
|
+
|
|
53
|
+
@modal-zindex: 9;
|
|
54
|
+
|
|
55
|
+
display: flex;
|
|
56
|
+
flex-direction: column;
|
|
57
|
+
align-items: center;
|
|
58
|
+
justify-content: center;
|
|
59
|
+
gap: @spacing;
|
|
60
|
+
z-index: @modal-zindex;
|
|
61
|
+
|
|
62
|
+
background: fade(#000, 20%);
|
|
63
|
+
border-radius: @radius;
|
|
64
|
+
|
|
65
|
+
// Pour les animations (ex: conffetis
|
|
66
|
+
> canvas {
|
|
67
|
+
position: absolute;
|
|
68
|
+
top: 0; left: 0;
|
|
69
|
+
width: 100%;
|
|
70
|
+
height: 100%;
|
|
71
|
+
z-index: 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
> .card {
|
|
75
|
+
|
|
76
|
+
position: relative;
|
|
77
|
+
min-width: 300px;
|
|
78
|
+
max-height: 99vh;
|
|
79
|
+
max-width: 99vw;
|
|
80
|
+
width: 400px; // Default width
|
|
81
|
+
box-shadow: none;
|
|
82
|
+
overflow-y: auto;
|
|
83
|
+
|
|
84
|
+
// Pas d'anim quand pas card,
|
|
85
|
+
// Car peut contenir bcp d'elemnts => performance
|
|
86
|
+
animation: aff-modale 0.1s ease;
|
|
87
|
+
@keyframes aff-modale {
|
|
88
|
+
0% {
|
|
89
|
+
opacity: 0;
|
|
90
|
+
transform: scale(0.8);
|
|
91
|
+
}
|
|
92
|
+
100% {
|
|
93
|
+
opacity: 1;
|
|
94
|
+
transform: scale(1);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
> header {
|
|
99
|
+
> i {
|
|
100
|
+
color: @c1;
|
|
101
|
+
font-size: 3em;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
z-index: 1; // Au dessus de l'animation canvas
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
#toasts {
|
|
111
|
+
// Toast
|
|
112
|
+
> .card {
|
|
113
|
+
|
|
114
|
+
text-align: left;
|
|
115
|
+
max-width: 450px;
|
|
116
|
+
z-index: 999;
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
padding-right: @spacing * 1.5;
|
|
119
|
+
|
|
120
|
+
animation: aff-toast 0.1s ease;
|
|
121
|
+
@keyframes aff-toast {
|
|
122
|
+
0% {
|
|
123
|
+
opacity: 0.5;
|
|
124
|
+
transform: scale(0.5);
|
|
125
|
+
}
|
|
126
|
+
100% {
|
|
127
|
+
opacity: 1;
|
|
128
|
+
transform: scale(1);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
> i {
|
|
133
|
+
color: @c1;
|
|
134
|
+
flex: 0 0 1em;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
h2 {
|
|
138
|
+
font-size: 1em;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
p {
|
|
142
|
+
text-align: left;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Selecteur moins profond pour que les clases utilitaires (w-a-x) soient prioritaires
|
|
148
|
+
.modal > .card {
|
|
149
|
+
// Modal content should always be whiteys adapt from content width
|
|
150
|
+
//max-width: 500px;
|
|
151
|
+
}
|