5htp-core 0.5.1-4 → 0.5.1-5
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": "Convenient TypeScript framework designed for Performance and Productivity.",
|
|
4
|
-
"version": "0.5.1-
|
|
4
|
+
"version": "0.5.1-5",
|
|
5
5
|
"author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
|
|
6
6
|
"repository": "git://github.com/gaetanlegac/5htp-core.git",
|
|
7
7
|
"license": "MIT",
|
|
@@ -5,14 +5,16 @@
|
|
|
5
5
|
position: relative;
|
|
6
6
|
overflow: hidden;
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
&.box {
|
|
9
|
+
border-radius: @radius;
|
|
10
|
+
border: dashed 3px var(--cLine);
|
|
11
|
+
background: @cBgPage + #090909;
|
|
12
|
+
|
|
13
|
+
padding: @spacing;
|
|
14
|
+
width: 100%;
|
|
15
|
+
min-height: 200px;
|
|
16
|
+
height: 14.15rem;
|
|
17
|
+
}
|
|
16
18
|
|
|
17
19
|
.preview,
|
|
18
20
|
.indication,
|
|
@@ -6,7 +6,7 @@ import React from 'react';
|
|
|
6
6
|
import { ComponentChild } from 'preact';
|
|
7
7
|
|
|
8
8
|
// Composants généraux
|
|
9
|
-
import
|
|
9
|
+
import Button, { Props as BtnProps } from '@client/components/button';
|
|
10
10
|
|
|
11
11
|
// Core libs
|
|
12
12
|
import { InputWrapper } from '../base';
|
|
@@ -67,6 +67,7 @@ export type Props = {
|
|
|
67
67
|
emptyText?: ComponentChild,
|
|
68
68
|
className?: string,
|
|
69
69
|
previewUrl?: string,
|
|
70
|
+
button?: boolean | BtnProps,
|
|
70
71
|
|
|
71
72
|
// Actions
|
|
72
73
|
onChange: (file: FileToUpload | undefined) => void
|
|
@@ -85,11 +86,12 @@ export default (props: Props) => {
|
|
|
85
86
|
let {
|
|
86
87
|
// Input
|
|
87
88
|
value: file,
|
|
88
|
-
className,
|
|
89
|
+
className: customClassName,
|
|
89
90
|
|
|
90
91
|
// Display
|
|
91
92
|
emptyText = 'Click here to select a File',
|
|
92
93
|
previewUrl: previewUrlInit,
|
|
94
|
+
button,
|
|
93
95
|
|
|
94
96
|
// Actions
|
|
95
97
|
onChange
|
|
@@ -97,7 +99,13 @@ export default (props: Props) => {
|
|
|
97
99
|
|
|
98
100
|
const [previewUrl, setPreviewUrl] = React.useState<string | undefined>(previewUrlInit);
|
|
99
101
|
|
|
100
|
-
className = 'input upload
|
|
102
|
+
let className = 'input upload';
|
|
103
|
+
|
|
104
|
+
if (!button)
|
|
105
|
+
className += ' box';
|
|
106
|
+
|
|
107
|
+
if (customClassName !== undefined)
|
|
108
|
+
className += ' ' + customClassName;
|
|
101
109
|
|
|
102
110
|
/*----------------------------------
|
|
103
111
|
- ACTIONS
|
|
@@ -131,33 +139,49 @@ export default (props: Props) => {
|
|
|
131
139
|
|
|
132
140
|
<div class={className}>
|
|
133
141
|
|
|
134
|
-
{
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
{
|
|
138
|
-
|
|
139
|
-
|
|
142
|
+
{button ? <>
|
|
143
|
+
|
|
144
|
+
<Button type="secondary"
|
|
145
|
+
{...button === true ? {} : button}
|
|
146
|
+
>
|
|
147
|
+
{emptyText}
|
|
148
|
+
</Button>
|
|
149
|
+
|
|
150
|
+
</> : <>
|
|
151
|
+
|
|
152
|
+
{file && <>
|
|
153
|
+
<div class="preview">
|
|
154
|
+
|
|
155
|
+
{previewUrl ? (
|
|
156
|
+
<img src={previewUrl} />
|
|
157
|
+
) : typeof file === 'string' ? <>
|
|
158
|
+
<strong>A file has been selected</strong>
|
|
159
|
+
</> : file ? <>
|
|
160
|
+
<strong>{file.name}</strong>
|
|
161
|
+
</> : null}
|
|
162
|
+
</div>
|
|
163
|
+
|
|
164
|
+
<div class="row actions sp-05">
|
|
165
|
+
|
|
166
|
+
{typeof file === 'string' && <>
|
|
167
|
+
<Button type="secondary" icon="eye" shape="pill" size="s" link={file} />
|
|
168
|
+
</>}
|
|
169
|
+
|
|
170
|
+
<Button class='bg error' icon="trash" shape="pill" size="s"
|
|
171
|
+
async onClick={() => onChange(undefined)} />
|
|
172
|
+
</div>
|
|
173
|
+
</>}
|
|
174
|
+
|
|
175
|
+
<div class="indication col al-center">
|
|
176
|
+
{typeof file === 'string' ? <>
|
|
140
177
|
<strong>A file has been selected</strong>
|
|
141
178
|
</> : file ? <>
|
|
142
179
|
<strong>{file.name}</strong>
|
|
143
|
-
</> :
|
|
144
|
-
</div>
|
|
145
|
-
|
|
146
|
-
<div class="row actions sp-05">
|
|
147
|
-
|
|
148
|
-
{typeof file === 'string' && <>
|
|
149
|
-
<Bouton type="secondary" icon="eye" shape="pill" size="s" link={file} />
|
|
150
|
-
</>}
|
|
151
|
-
|
|
152
|
-
<Bouton class='bg error' icon="trash" shape="pill" size="s"
|
|
153
|
-
async onClick={() => onChange(undefined)} />
|
|
180
|
+
</> : emptyText}
|
|
154
181
|
</div>
|
|
182
|
+
|
|
155
183
|
</>}
|
|
156
184
|
|
|
157
|
-
<div class="indication col al-center">
|
|
158
|
-
{emptyText}
|
|
159
|
-
</div>
|
|
160
|
-
|
|
161
185
|
<input type="file" onChange={selectFile} />
|
|
162
186
|
</div>
|
|
163
187
|
</InputWrapper>
|
|
@@ -24,7 +24,21 @@ import ServerResponse from '../response';
|
|
|
24
24
|
- TYPES
|
|
25
25
|
----------------------------------*/
|
|
26
26
|
|
|
27
|
-
const localeFilter = (input: any) =>
|
|
27
|
+
const localeFilter = (input: any) => {
|
|
28
|
+
|
|
29
|
+
// Data type
|
|
30
|
+
if (typeof input !== 'string')
|
|
31
|
+
return;
|
|
32
|
+
|
|
33
|
+
// Extract ISO code
|
|
34
|
+
let lang = input.trim().split(/[-_]/)[0].toLowerCase();
|
|
35
|
+
|
|
36
|
+
// Check size
|
|
37
|
+
if (!ISO6391.validate(lang))
|
|
38
|
+
return;
|
|
39
|
+
|
|
40
|
+
return lang.toUpperCase();
|
|
41
|
+
}
|
|
28
42
|
|
|
29
43
|
export type UploadedFile = With<FileToUpload, 'md5'|'ext'>
|
|
30
44
|
|
|
@@ -132,6 +146,9 @@ export default class ServerRequest<
|
|
|
132
146
|
'EN'
|
|
133
147
|
)
|
|
134
148
|
|
|
149
|
+
console.log("locale", this.req.acceptsLanguages(), locale);
|
|
150
|
+
|
|
151
|
+
|
|
135
152
|
return locale ? locale.toUpperCase() : 'EN'
|
|
136
153
|
}
|
|
137
154
|
|
package/src/server/utils/rte.ts
CHANGED
package/src/server/utils/slug.ts
CHANGED
|
@@ -37,31 +37,43 @@ export class Slug {
|
|
|
37
37
|
|
|
38
38
|
// Check if already existing
|
|
39
39
|
if (SQL !== undefined) {
|
|
40
|
-
|
|
41
|
-
const escapedSlug = escapeStringRegexp(slug);
|
|
42
|
-
|
|
43
|
-
const duplicates = await SQL.selectVal<number>(`
|
|
44
|
-
SELECT
|
|
45
|
-
IF( ${column} LIKE ${SQL.esc(slug)},
|
|
46
|
-
1,
|
|
47
|
-
CAST(SUBSTRING_INDEX(slug, '-', -1) AS UNSIGNED)
|
|
48
|
-
) AS duplicates
|
|
49
|
-
FROM ${table}
|
|
50
|
-
WHERE
|
|
51
|
-
${column} LIKE ${SQL.esc(slug)}
|
|
52
|
-
OR
|
|
53
|
-
${column} REGEXP '^${escapedSlug}-[0-9]+$'
|
|
54
|
-
ORDER BY duplicates DESC
|
|
55
|
-
LIMIT 1
|
|
56
|
-
`);
|
|
57
|
-
|
|
58
|
-
if (duplicates && duplicates > 0)
|
|
59
|
-
slug += `-${duplicates + 1}`;
|
|
40
|
+
slug = await this.Correct(slug, SQL, table, column);
|
|
60
41
|
}
|
|
61
42
|
|
|
62
43
|
return slug;
|
|
63
44
|
}
|
|
64
45
|
|
|
46
|
+
public async Correct(
|
|
47
|
+
slug: string,
|
|
48
|
+
SQL: SQL,
|
|
49
|
+
table: string,
|
|
50
|
+
column: string
|
|
51
|
+
) {
|
|
52
|
+
|
|
53
|
+
const escapedSlug = escapeStringRegexp(slug);
|
|
54
|
+
|
|
55
|
+
const duplicates = await SQL.selectVal<number>(`
|
|
56
|
+
SELECT
|
|
57
|
+
IF( ${column} LIKE ${SQL.esc(slug)},
|
|
58
|
+
1,
|
|
59
|
+
CAST(SUBSTRING_INDEX(slug, '-', -1) AS UNSIGNED)
|
|
60
|
+
) AS duplicates
|
|
61
|
+
FROM ${table}
|
|
62
|
+
WHERE
|
|
63
|
+
${column} LIKE ${SQL.esc(slug)}
|
|
64
|
+
OR
|
|
65
|
+
${column} REGEXP '^${escapedSlug}-[0-9]+$'
|
|
66
|
+
ORDER BY duplicates DESC
|
|
67
|
+
LIMIT 1
|
|
68
|
+
`);
|
|
69
|
+
|
|
70
|
+
if (duplicates && duplicates > 0)
|
|
71
|
+
slug += `-${duplicates + 1}`;
|
|
72
|
+
|
|
73
|
+
return slug;
|
|
74
|
+
|
|
75
|
+
}
|
|
76
|
+
|
|
65
77
|
}
|
|
66
78
|
|
|
67
79
|
export default new Slug;
|