5htp-core 0.3.6 → 0.3.7
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 +1 -1
- package/src/client/assets/css/components/button.less +6 -1
- package/src/client/assets/css/components/table.less +6 -0
- package/src/client/assets/css/core.less +2 -0
- package/src/client/assets/css/utils/layouts.less +21 -3
- package/src/client/components/Form.ts +4 -1
- package/src/client/components/Table/index.tsx +8 -6
- package/src/client/services/router/index.tsx +13 -5
- package/src/client/services/router/request/api.ts +2 -2
- package/src/common/errors/index.ts +2 -1
- package/src/common/validation/schema.ts +3 -0
- package/src/common/validation/validators.ts +7 -8
- package/src/server/services/database/index.ts +8 -3
- package/src/server/services/fetch/index.ts +64 -2
- package/src/server/services/users/index.ts +10 -2
- package/src/client/pages/_messages/400.tsx +0 -37
- package/src/client/pages/_messages/401.tsx +0 -49
- package/src/client/pages/_messages/403.tsx +0 -37
- package/src/client/pages/_messages/404.tsx +0 -37
- package/src/client/pages/_messages/500.tsx +0 -37
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.3.
|
|
4
|
+
"version": "0.3.7",
|
|
5
5
|
"author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
|
|
6
6
|
"repository": "git://github.com/gaetanlegac/5htp-core.git",
|
|
7
7
|
"license": "MIT",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
// Layout
|
|
13
13
|
position: relative;
|
|
14
14
|
gap: @spacing;
|
|
15
|
+
min-width: 0/*fit-content*/; // Fit content, even when flexbox parent width < content width
|
|
15
16
|
|
|
16
17
|
// Dimensions
|
|
17
18
|
font-size: 1em;
|
|
@@ -62,12 +63,16 @@
|
|
|
62
63
|
|
|
63
64
|
> .label {
|
|
64
65
|
text-align: left;
|
|
65
|
-
white-space: nowrap; // Autrement, si plusieurs mots, affiché sur plusieurs ligne
|
|
66
66
|
gap: @spacing / 2;
|
|
67
67
|
font-size: 1rem;
|
|
68
68
|
line-height: 1.5em;
|
|
69
69
|
z-index: 1; // Make the label on top of ::before for example
|
|
70
70
|
|
|
71
|
+
// Handle overflow
|
|
72
|
+
white-space: nowrap;
|
|
73
|
+
text-overflow: ellipsis;
|
|
74
|
+
overflow: hidden;
|
|
75
|
+
|
|
71
76
|
li > & {
|
|
72
77
|
flex: 1;
|
|
73
78
|
}
|
|
@@ -30,9 +30,13 @@
|
|
|
30
30
|
display: flex;
|
|
31
31
|
flex-wrap: nowrap;
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
&.scrollable {
|
|
34
|
+
|
|
35
|
+
overflow: auto;
|
|
36
|
+
|
|
37
|
+
> * {
|
|
38
|
+
min-width: fit-content;
|
|
39
|
+
}
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
// Avec justify-content: center, les premiers élements sont cachés
|
|
@@ -126,6 +130,20 @@
|
|
|
126
130
|
&.sep-1 > * + * { border-top: solid 1px var(--cLine); }
|
|
127
131
|
|
|
128
132
|
> .col-1 { align-self: stretch; }
|
|
133
|
+
|
|
134
|
+
&.unibody {
|
|
135
|
+
|
|
136
|
+
gap: 0;
|
|
137
|
+
|
|
138
|
+
> :not(:first-child) {
|
|
139
|
+
border-top-left-radius: 0;
|
|
140
|
+
border-top-right-radius: 0;
|
|
141
|
+
}
|
|
142
|
+
> :not(:last-child) {
|
|
143
|
+
border-bottom-left-radius: 0;
|
|
144
|
+
border-bottom-right-radius: 0;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
129
147
|
}
|
|
130
148
|
|
|
131
149
|
.row,
|
|
@@ -11,6 +11,9 @@ import type { Schema } from '@common/validation';
|
|
|
11
11
|
import type { TValidationResult } from '@common/validation/schema';
|
|
12
12
|
import useContext from '@/client/context';
|
|
13
13
|
|
|
14
|
+
// Exports
|
|
15
|
+
export type { TValidationResult, TSchemaData } from '@common/validation/schema';
|
|
16
|
+
|
|
14
17
|
/*----------------------------------
|
|
15
18
|
- TYPES
|
|
16
19
|
----------------------------------*/
|
|
@@ -23,7 +26,7 @@ type TFormOptions<TFormData extends {}> = {
|
|
|
23
26
|
}
|
|
24
27
|
}
|
|
25
28
|
|
|
26
|
-
type FieldsAttrs<TFormData extends {}> = {
|
|
29
|
+
export type FieldsAttrs<TFormData extends {}> = {
|
|
27
30
|
[fieldName in keyof TFormData]: {}
|
|
28
31
|
}
|
|
29
32
|
|
|
@@ -23,7 +23,7 @@ export type Props<TRow> = {
|
|
|
23
23
|
columns: (row: TRow, rows: TRow[], index: number) => TColumn[];
|
|
24
24
|
|
|
25
25
|
setData?: (rows: TRow[]) => void,
|
|
26
|
-
empty?: ComponentChild,
|
|
26
|
+
empty?: ComponentChild | false,
|
|
27
27
|
className?: string,
|
|
28
28
|
|
|
29
29
|
actions?: TAction<TRow>[]
|
|
@@ -40,15 +40,17 @@ export type TColumn = {
|
|
|
40
40
|
- COMPOSANTS
|
|
41
41
|
----------------------------------*/
|
|
42
42
|
export default function Liste<TRow extends TDonneeInconnue>({
|
|
43
|
-
data: rows, setData, empty
|
|
43
|
+
data: rows, setData, empty,
|
|
44
44
|
columns, actions, ...props
|
|
45
45
|
}: Props<TRow>) {
|
|
46
46
|
|
|
47
47
|
if (rows.length === 0)
|
|
48
|
-
return (
|
|
49
|
-
<div class="
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
return empty === false ? null : (
|
|
49
|
+
<div class="pd-2 col al-center">
|
|
50
|
+
{empty || <>
|
|
51
|
+
<i src="meh-rolling-eyes" class="xl" />
|
|
52
|
+
Uh ... No rows here.
|
|
53
|
+
</>}
|
|
52
54
|
</div>
|
|
53
55
|
);
|
|
54
56
|
|
|
@@ -159,16 +159,20 @@ export default class ClientRouter<
|
|
|
159
159
|
public url = (path: string, params: {} = {}, absolute: boolean = true) =>
|
|
160
160
|
buildUrl(path, params, this.config.domains, absolute);
|
|
161
161
|
|
|
162
|
-
public go( url: string
|
|
162
|
+
public go( url: string, opt: {
|
|
163
|
+
newTab?: boolean
|
|
164
|
+
} = {}) {
|
|
163
165
|
|
|
164
166
|
url = this.url(url, {}, false);
|
|
165
167
|
|
|
168
|
+
if (opt.newTab)
|
|
169
|
+
window.open(url)
|
|
166
170
|
// Same domain = history url replacement
|
|
167
|
-
if (url[0] === '/')
|
|
171
|
+
else if (url[0] === '/')
|
|
168
172
|
history?.replace( url );
|
|
169
173
|
// Different domain = hard navigation
|
|
170
174
|
else
|
|
171
|
-
|
|
175
|
+
window.location.href = url;
|
|
172
176
|
}
|
|
173
177
|
|
|
174
178
|
/*----------------------------------
|
|
@@ -274,7 +278,11 @@ export default class ClientRouter<
|
|
|
274
278
|
return route;
|
|
275
279
|
}
|
|
276
280
|
|
|
277
|
-
public error(
|
|
281
|
+
public error(
|
|
282
|
+
code: number,
|
|
283
|
+
options: Partial<TRoute["options"]>,
|
|
284
|
+
renderer: TFrontRenderer<{}, { message: string }>
|
|
285
|
+
) {
|
|
278
286
|
|
|
279
287
|
// Automatic layout form the nearest _layout folder
|
|
280
288
|
const layout = getLayout('Error ' + code, options);
|
|
@@ -345,7 +353,7 @@ export default class ClientRouter<
|
|
|
345
353
|
|
|
346
354
|
} catch (e) {
|
|
347
355
|
console.error(`Failed to fetch the route ${route.chunk}`, e);
|
|
348
|
-
this.app.handleError(new Error("Failed to load content. Please
|
|
356
|
+
this.app.handleError(new Error("Failed to load content. Please reload the page and try again."));
|
|
349
357
|
throw e;
|
|
350
358
|
}
|
|
351
359
|
|
|
@@ -12,7 +12,7 @@ import ApiClientService, {
|
|
|
12
12
|
TApiFetchOptions, TFetcherList, TFetcherArgs, TFetcher,
|
|
13
13
|
TDataReturnedByFetchers
|
|
14
14
|
} from '@common/router/request/api';
|
|
15
|
-
import {
|
|
15
|
+
import { viaHttpCode, NetworkError } from '@common/errors';
|
|
16
16
|
import type ClientApplication from '@client/app';
|
|
17
17
|
|
|
18
18
|
import { toMultipart } from './multipart';
|
|
@@ -233,7 +233,7 @@ export default class ApiClient implements ApiClientService {
|
|
|
233
233
|
if (e.response !== undefined) {
|
|
234
234
|
|
|
235
235
|
console.warn(`[api] Failure:`, e);
|
|
236
|
-
throw
|
|
236
|
+
throw viaHttpCode(
|
|
237
237
|
e.response.status || 500,
|
|
238
238
|
e.response.data
|
|
239
239
|
);
|
|
@@ -169,12 +169,13 @@ export class NetworkError extends Error {
|
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
|
|
172
|
-
export const
|
|
172
|
+
export const viaHttpCode = (
|
|
173
173
|
code: number,
|
|
174
174
|
message?: string | TListeErreursSaisie,
|
|
175
175
|
details?: TDetailsErreur
|
|
176
176
|
): CoreError => {
|
|
177
177
|
|
|
178
|
+
// TODO: more reliablme detection of form errors
|
|
178
179
|
if (typeof message === 'object')
|
|
179
180
|
return new InputErrorSchema(message, details);
|
|
180
181
|
|
|
@@ -33,6 +33,9 @@ export type TValidationResult<TFields extends TSchemaFields> = {
|
|
|
33
33
|
erreurs: TListeErreursSaisie
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
export type TSchemaData<TSchema extends Schema<{}>> =
|
|
37
|
+
TValidationResult<TSchema["fields"]>
|
|
38
|
+
|
|
36
39
|
export type TValidatedData<TFields extends TSchemaFields> = {
|
|
37
40
|
// For each field, the values returned by validator.validate()
|
|
38
41
|
[name in keyof TFields]: ReturnType<TFields[name]["validate"]>
|
|
@@ -22,7 +22,6 @@ import Validator, { TValidator } from './validator'
|
|
|
22
22
|
|
|
23
23
|
// Components
|
|
24
24
|
import NumberInput from '@client/components/input/Number';
|
|
25
|
-
import Dropdown from '@client/components/dropdown.old';
|
|
26
25
|
|
|
27
26
|
/*----------------------------------
|
|
28
27
|
- TYPES
|
|
@@ -146,11 +145,13 @@ export default class SchemaValidators {
|
|
|
146
145
|
/*----------------------------------
|
|
147
146
|
- CHAINES
|
|
148
147
|
----------------------------------*/
|
|
149
|
-
public string = ({ min, max, ...opts }: TValidator<string> & {
|
|
148
|
+
public string = ({ min, max, include, ...opts }: TValidator<string> & {
|
|
150
149
|
min?: number,
|
|
151
|
-
max?: number
|
|
150
|
+
max?: number,
|
|
151
|
+
include?: string
|
|
152
152
|
} = {}) => new Validator<string>('string', (val, input, output, corriger?: boolean) => {
|
|
153
153
|
|
|
154
|
+
// Check type
|
|
154
155
|
if (val === '')
|
|
155
156
|
return undefined;
|
|
156
157
|
else if (typeof val === 'number')
|
|
@@ -158,14 +159,14 @@ export default class SchemaValidators {
|
|
|
158
159
|
else if (typeof val !== 'string')
|
|
159
160
|
throw new InputError("This value must be a string.");
|
|
160
161
|
|
|
161
|
-
//
|
|
162
|
+
// Whitespace
|
|
162
163
|
val = trim(val);
|
|
163
164
|
|
|
164
|
-
//
|
|
165
|
+
// Min size
|
|
165
166
|
if (min !== undefined && val.length < min)
|
|
166
167
|
throw new InputError(`Must be at least ` + min + ' characters');
|
|
167
168
|
|
|
168
|
-
//
|
|
169
|
+
// Max size
|
|
169
170
|
if (max !== undefined && val.length > max)
|
|
170
171
|
if (corriger)
|
|
171
172
|
val = val.substring(0, max);
|
|
@@ -193,8 +194,6 @@ export default class SchemaValidators {
|
|
|
193
194
|
if (opts.normalize !== undefined)
|
|
194
195
|
val = normalizeUrl(val, opts.normalize);
|
|
195
196
|
|
|
196
|
-
console.log("@@@@@@@@@@@@@NORMALISZE URL", opts.normalize, val);
|
|
197
|
-
|
|
198
197
|
return val;
|
|
199
198
|
}, opts)
|
|
200
199
|
|
|
@@ -170,14 +170,19 @@ export default class SQL extends Service<Config, Hooks, Application, Services> {
|
|
|
170
170
|
return query;
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
public esc(data: any) {
|
|
173
|
+
public esc( data: any, forStorage: boolean = false ) {
|
|
174
174
|
|
|
175
175
|
// JSON object
|
|
176
176
|
// TODO: do it via datatypes.ts
|
|
177
177
|
if (typeof data === 'object' && data !== null) {
|
|
178
178
|
|
|
179
|
+
// Object: stringify in JSON
|
|
179
180
|
if (data.constructor.name === "Object")
|
|
180
181
|
data = safeStringify(data);
|
|
182
|
+
// Array: if for storage, reparate items with a comma
|
|
183
|
+
else if (forStorage && Array.isArray( data )) {
|
|
184
|
+
data = data.join(',')
|
|
185
|
+
}
|
|
181
186
|
}
|
|
182
187
|
|
|
183
188
|
return mysql.escape(data);
|
|
@@ -474,7 +479,7 @@ export default class SQL extends Service<Config, Hooks, Application, Services> {
|
|
|
474
479
|
const values: string[] = [];
|
|
475
480
|
for (const col of colNames)
|
|
476
481
|
if (col in entry)
|
|
477
|
-
values.push( this.esc( entry[col] ));
|
|
482
|
+
values.push( this.esc( entry[col], true));
|
|
478
483
|
else
|
|
479
484
|
values.push("DEFAULT");
|
|
480
485
|
|
|
@@ -528,7 +533,7 @@ export default class SQL extends Service<Config, Hooks, Application, Services> {
|
|
|
528
533
|
const { '*': updateAll, ...customValuesToUpdate } = colsToUpdate;
|
|
529
534
|
|
|
530
535
|
for (const colKey in customValuesToUpdate)
|
|
531
|
-
valuesToUpdate[ colKey ] = this.esc(customValuesToUpdate[ colKey ]);
|
|
536
|
+
valuesToUpdate[ colKey ] = this.esc(customValuesToUpdate[ colKey ], true);
|
|
532
537
|
|
|
533
538
|
if (updateAll)
|
|
534
539
|
valuesNamesToUpdate = Object.keys(table.colonnes);//table.columnNamesButPk;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// Npm
|
|
6
6
|
import sharp from 'sharp';
|
|
7
7
|
import fs from 'fs-extra';
|
|
8
|
+
import got, { Method, Options } from 'got';
|
|
8
9
|
|
|
9
10
|
// Node
|
|
10
11
|
import request from 'request';
|
|
@@ -12,6 +13,10 @@ import request from 'request';
|
|
|
12
13
|
// Core: general
|
|
13
14
|
import type { Application } from '@server/app';
|
|
14
15
|
import Service, { AnyService } from '@server/app/service';
|
|
16
|
+
import { viaHttpCode } from '@common/errors';
|
|
17
|
+
|
|
18
|
+
// Local
|
|
19
|
+
import type RouterService from '../router';
|
|
15
20
|
import type DisksManager from '../disks';
|
|
16
21
|
import type FsDriver from '../disks/driver';
|
|
17
22
|
|
|
@@ -29,7 +34,8 @@ export type Hooks = {
|
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
export type Services = {
|
|
32
|
-
disks: DisksManager
|
|
37
|
+
disks: DisksManager,
|
|
38
|
+
router?: RouterService
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
/*----------------------------------
|
|
@@ -89,7 +95,63 @@ export default class FetchService extends Service<Config, Hooks, Application, Se
|
|
|
89
95
|
}
|
|
90
96
|
|
|
91
97
|
/*----------------------------------
|
|
92
|
-
-
|
|
98
|
+
- EXTERNAL API REQUESTS
|
|
99
|
+
----------------------------------*/
|
|
100
|
+
|
|
101
|
+
public post(
|
|
102
|
+
url: string,
|
|
103
|
+
data: {[k: string]: any},
|
|
104
|
+
options: {} = {}
|
|
105
|
+
) {
|
|
106
|
+
|
|
107
|
+
return this.request('POST', url, data, options);
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public async request(
|
|
112
|
+
method: Method,
|
|
113
|
+
url: string,
|
|
114
|
+
data: {[k: string]: any},
|
|
115
|
+
options: Options = {}
|
|
116
|
+
) {
|
|
117
|
+
|
|
118
|
+
// Parse url if router service is provided
|
|
119
|
+
if (this.services.router !== undefined)
|
|
120
|
+
url = this.services.router.url(url);
|
|
121
|
+
|
|
122
|
+
// Send request
|
|
123
|
+
const res = await got(url, {
|
|
124
|
+
throwHttpErrors: false,
|
|
125
|
+
headers: {
|
|
126
|
+
'Accept': 'application/json',
|
|
127
|
+
},
|
|
128
|
+
method,
|
|
129
|
+
...(method === 'GET' ? {
|
|
130
|
+
searchParams: data
|
|
131
|
+
} : {
|
|
132
|
+
json: data
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
// Handle errors
|
|
137
|
+
if (res.statusCode !== 200) {
|
|
138
|
+
|
|
139
|
+
// Instanciate error from HTTP code
|
|
140
|
+
const error = viaHttpCode( res.statusCode, res.body );
|
|
141
|
+
if (error)
|
|
142
|
+
throw error;
|
|
143
|
+
|
|
144
|
+
// Not catched via viaHttpCode
|
|
145
|
+
console.log("RESPONSE", res.body);
|
|
146
|
+
throw new Error("Error while contacting the API");
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Format & return response
|
|
150
|
+
return JSON.parse( res.body );
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/*----------------------------------
|
|
154
|
+
- IMAGES
|
|
93
155
|
----------------------------------*/
|
|
94
156
|
|
|
95
157
|
public toBuffer( uri: string ): Promise<Buffer> {
|
|
@@ -93,7 +93,7 @@ export default abstract class UsersManagementService<
|
|
|
93
93
|
----------------------------------*/
|
|
94
94
|
|
|
95
95
|
public abstract login( ...args: any[] ): Promise<{ user: TUser, token: string }>;
|
|
96
|
-
public abstract decodeSession( jwt: TJwtSession, req: THttpRequest ): Promise<TUser>;
|
|
96
|
+
public abstract decodeSession( jwt: TJwtSession, req: THttpRequest ): Promise<TUser | null>;
|
|
97
97
|
|
|
98
98
|
protected abstract displayName(user?: TUser | null): string;
|
|
99
99
|
protected abstract displaySessionName(session: TJwtSession): string;
|
|
@@ -134,9 +134,17 @@ export default abstract class UsersManagementService<
|
|
|
134
134
|
// Deserialize full user data
|
|
135
135
|
this.config.debug && console.log(LogPrefix, `Deserialize user ${sessionName}`);
|
|
136
136
|
const user = await this.decodeSession(session, req);
|
|
137
|
+
|
|
138
|
+
// User not found
|
|
139
|
+
if (user === null)
|
|
140
|
+
return null;
|
|
141
|
+
|
|
137
142
|
this.config.debug && console.log(LogPrefix, `Deserialized user ${sessionName}:`, this.displayName(user));
|
|
138
143
|
|
|
139
|
-
return
|
|
144
|
+
return {
|
|
145
|
+
...user,
|
|
146
|
+
_token: token
|
|
147
|
+
};
|
|
140
148
|
}
|
|
141
149
|
|
|
142
150
|
public unauthorized( req: THttpRequest ) {
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/*----------------------------------
|
|
2
|
-
- DEPENDANCES
|
|
3
|
-
----------------------------------*/
|
|
4
|
-
|
|
5
|
-
// Npm
|
|
6
|
-
import React from 'react';
|
|
7
|
-
|
|
8
|
-
// Core
|
|
9
|
-
import { Router } from '@app';
|
|
10
|
-
import { Button } from '@client/components';
|
|
11
|
-
|
|
12
|
-
// App
|
|
13
|
-
import useHeader from '@client/pages/useHeader';
|
|
14
|
-
|
|
15
|
-
/*----------------------------------
|
|
16
|
-
- CONTROLEUR
|
|
17
|
-
----------------------------------*/
|
|
18
|
-
Router.error( 400, ({ message, modal }) => {
|
|
19
|
-
|
|
20
|
-
useHeader({
|
|
21
|
-
title: 'Bad request',
|
|
22
|
-
subtitle: message
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<div class="card w-3-4 col al-center pd-2">
|
|
27
|
-
|
|
28
|
-
<i src="times-circle" class="fg error xxl" />
|
|
29
|
-
|
|
30
|
-
<h1>Bad Request</h1>
|
|
31
|
-
|
|
32
|
-
<p>{message}</p>
|
|
33
|
-
|
|
34
|
-
<Button type="primary" link="/">Go Home</Button>
|
|
35
|
-
</div>
|
|
36
|
-
)
|
|
37
|
-
});
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/*----------------------------------
|
|
2
|
-
- DEPENDANCES
|
|
3
|
-
----------------------------------*/
|
|
4
|
-
|
|
5
|
-
// Npm
|
|
6
|
-
import React from 'react';
|
|
7
|
-
|
|
8
|
-
// Core
|
|
9
|
-
import { Router } from '@app';
|
|
10
|
-
import { Button } from '@client/components';
|
|
11
|
-
|
|
12
|
-
// App
|
|
13
|
-
import useHeader from '@client/pages/useHeader';
|
|
14
|
-
|
|
15
|
-
/*----------------------------------
|
|
16
|
-
- RESSOURCES
|
|
17
|
-
----------------------------------*/
|
|
18
|
-
|
|
19
|
-
/*----------------------------------
|
|
20
|
-
- CONTROLEUR
|
|
21
|
-
----------------------------------*/
|
|
22
|
-
Router.error( 401, ({ message, request, page }) => {
|
|
23
|
-
|
|
24
|
-
request.response?.redirect('https://becrosspath.com');
|
|
25
|
-
|
|
26
|
-
useHeader({
|
|
27
|
-
title: 'Authentication Required',
|
|
28
|
-
subtitle: message
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
React.useEffect(() => {
|
|
32
|
-
|
|
33
|
-
page?.go('/');
|
|
34
|
-
|
|
35
|
-
}, []);
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<div class="card w-3-4 col al-center pd-2">
|
|
39
|
-
|
|
40
|
-
<i src="times-circle" class="fg error xxl" />
|
|
41
|
-
|
|
42
|
-
<h1>Authentication Required</h1>
|
|
43
|
-
|
|
44
|
-
<p>{message}</p>
|
|
45
|
-
|
|
46
|
-
<Button type="primary" link="/">Go Home</Button>
|
|
47
|
-
</div>
|
|
48
|
-
)
|
|
49
|
-
});
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/*----------------------------------
|
|
2
|
-
- DEPENDANCES
|
|
3
|
-
----------------------------------*/
|
|
4
|
-
|
|
5
|
-
// Npm
|
|
6
|
-
import React from 'react';
|
|
7
|
-
|
|
8
|
-
// Core
|
|
9
|
-
import { Router } from '@app';
|
|
10
|
-
import { Button } from '@client/components';
|
|
11
|
-
|
|
12
|
-
// App
|
|
13
|
-
import useHeader from '@client/pages/useHeader';
|
|
14
|
-
|
|
15
|
-
/*----------------------------------
|
|
16
|
-
- CONTROLEUR
|
|
17
|
-
----------------------------------*/
|
|
18
|
-
Router.error( 403, ({ message, modal }) => {
|
|
19
|
-
|
|
20
|
-
useHeader({
|
|
21
|
-
title: 'Access Denied.',
|
|
22
|
-
subtitle: message
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<div class="card w-3-4 col al-center pd-2">
|
|
27
|
-
|
|
28
|
-
<i src="times-circle" class="fg error xxl" />
|
|
29
|
-
|
|
30
|
-
<h1>Access Denied.</h1>
|
|
31
|
-
|
|
32
|
-
<p>{message}</p>
|
|
33
|
-
|
|
34
|
-
<Button type="primary" link="/">Go Home</Button>
|
|
35
|
-
</div>
|
|
36
|
-
)
|
|
37
|
-
});
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/*----------------------------------
|
|
2
|
-
- DEPENDANCES
|
|
3
|
-
----------------------------------*/
|
|
4
|
-
|
|
5
|
-
// Npm
|
|
6
|
-
import React from 'react';
|
|
7
|
-
|
|
8
|
-
// Core
|
|
9
|
-
import { Router } from '@app';
|
|
10
|
-
import { Button } from '@client/components';
|
|
11
|
-
|
|
12
|
-
// App
|
|
13
|
-
import useHeader from '@client/pages/useHeader';
|
|
14
|
-
|
|
15
|
-
/*----------------------------------
|
|
16
|
-
- CONTROLEUR
|
|
17
|
-
----------------------------------*/
|
|
18
|
-
Router.error( 404, ({ message, modal }) => {
|
|
19
|
-
|
|
20
|
-
useHeader({
|
|
21
|
-
title: 'Page Not Found',
|
|
22
|
-
subtitle: message
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<div class="card w-3-4 col al-center pd-2">
|
|
27
|
-
|
|
28
|
-
<i src="times-circle" class="fg error xxl" />
|
|
29
|
-
|
|
30
|
-
<h1>Page Not Found</h1>
|
|
31
|
-
|
|
32
|
-
<p>{message}</p>
|
|
33
|
-
|
|
34
|
-
<Button type="primary" link="/">Go Home</Button>
|
|
35
|
-
</div>
|
|
36
|
-
)
|
|
37
|
-
});
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/*----------------------------------
|
|
2
|
-
- DEPENDANCES
|
|
3
|
-
----------------------------------*/
|
|
4
|
-
|
|
5
|
-
// Npm
|
|
6
|
-
import React from 'react';
|
|
7
|
-
|
|
8
|
-
// Core
|
|
9
|
-
import { Router } from '@app';
|
|
10
|
-
import { Button } from '@client/components';
|
|
11
|
-
|
|
12
|
-
// App
|
|
13
|
-
import useHeader from '@client/pages/useHeader';
|
|
14
|
-
|
|
15
|
-
/*----------------------------------
|
|
16
|
-
- CONTROLEUR
|
|
17
|
-
----------------------------------*/
|
|
18
|
-
Router.error( 500, ({ message }) => {
|
|
19
|
-
|
|
20
|
-
useHeader({
|
|
21
|
-
title: 'Technical Error',
|
|
22
|
-
subtitle: message
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<div class="card w-3-4 col al-center pd-2">
|
|
27
|
-
|
|
28
|
-
<i src="times-circle" class="fg error xxl" />
|
|
29
|
-
|
|
30
|
-
<h1>Technical Error</h1>
|
|
31
|
-
|
|
32
|
-
<p>{message}</p>
|
|
33
|
-
|
|
34
|
-
<Button type="primary" link="/">Go Home</Button>
|
|
35
|
-
</div>
|
|
36
|
-
)
|
|
37
|
-
});
|