mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge 51c4070879
into 7d84185d0e
This commit is contained in:
commit
671e577689
5 changed files with 46 additions and 7 deletions
|
@ -149,9 +149,17 @@ const UserNew = () => {
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error('[usernew] failed to update user policy', err);
|
console.error('[usernew] failed to update user policy', err);
|
||||||
});
|
});
|
||||||
}, function () {
|
}, function (error) {
|
||||||
|
try {
|
||||||
|
console.error('[usernew] failed to create new user', error);
|
||||||
|
error.text().then((errorMessage: string) => {
|
||||||
|
toast(errorMessage);
|
||||||
|
loading.hide();
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
toast(globalize.translate('ErrorDefault'));
|
toast(globalize.translate('ErrorDefault'));
|
||||||
loading.hide();
|
loading.hide();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -198,6 +206,7 @@ const UserNew = () => {
|
||||||
type='text'
|
type='text'
|
||||||
id='txtUsername'
|
id='txtUsername'
|
||||||
label='LabelName'
|
label='LabelName'
|
||||||
|
validator={{ pattern: '^([\\w \\-\'._@+]*)([\\w\\-\'._@+])([\\w \\-\'._@+]*)$', errMessage: globalize.translate('MessageInvalidUsernameFormat') }}
|
||||||
options={'required'}
|
options={'required'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -230,7 +230,16 @@ const UserEdit = () => {
|
||||||
)).then(() => {
|
)).then(() => {
|
||||||
onSaveComplete();
|
onSaveComplete();
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
|
try {
|
||||||
console.error('[useredit] failed to update user', err);
|
console.error('[useredit] failed to update user', err);
|
||||||
|
err.text().then((errorMessage: string) => {
|
||||||
|
toast(errorMessage);
|
||||||
|
loading.hide();
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
toast(globalize.translate('ErrorDefault'));
|
||||||
|
loading.hide();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -318,6 +327,7 @@ const UserEdit = () => {
|
||||||
type='text'
|
type='text'
|
||||||
id='txtUserName'
|
id='txtUserName'
|
||||||
label='LabelName'
|
label='LabelName'
|
||||||
|
validator={{ pattern: '^([\\w \\-\'._@+]*)([\\w\\-\'._@+])([\\w \\-\'._@+]*)$', errMessage: globalize.translate('MessageInvalidUsernameFormat') }}
|
||||||
options={'required'}
|
options={'required'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,23 +2,30 @@ import React, { type FC, useCallback, useEffect, useMemo, useRef } from 'react';
|
||||||
|
|
||||||
import globalize from 'lib/globalize';
|
import globalize from 'lib/globalize';
|
||||||
|
|
||||||
|
import './InputElementInvalidMessage.scss';
|
||||||
|
|
||||||
interface CreateInputElementParams {
|
interface CreateInputElementParams {
|
||||||
type?: string
|
type?: string
|
||||||
id?: string
|
id?: string
|
||||||
label?: string
|
label?: string
|
||||||
initialValue?: string
|
initialValue?: string
|
||||||
|
validator?: { pattern: string, errMessage: string }
|
||||||
options?: string
|
options?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const createInputElement = ({ type, id, label, initialValue, options }: CreateInputElementParams) => ({
|
const createInputElement = ({ type, id, label, initialValue, validator, options }: CreateInputElementParams) => ({
|
||||||
__html: `<input
|
__html: `<input
|
||||||
is="emby-input"
|
is="emby-input"
|
||||||
type="${type}"
|
type="${type}"
|
||||||
id="${id}"
|
id="${id}"
|
||||||
label="${label}"
|
label="${label}"
|
||||||
value="${initialValue}"
|
value="${initialValue}"
|
||||||
|
${validator ? 'pattern="' + validator.pattern + '"' : ''}
|
||||||
${options}
|
${options}
|
||||||
/>`
|
/>
|
||||||
|
<div class="inputElementInvalidMessage">
|
||||||
|
${validator?.errMessage || ''}
|
||||||
|
</div>`
|
||||||
});
|
});
|
||||||
|
|
||||||
type InputElementProps = {
|
type InputElementProps = {
|
||||||
|
@ -33,7 +40,9 @@ const InputElement: FC<InputElementProps> = ({
|
||||||
type,
|
type,
|
||||||
id,
|
id,
|
||||||
label,
|
label,
|
||||||
|
validator,
|
||||||
options = ''
|
options = ''
|
||||||
|
|
||||||
}) => {
|
}) => {
|
||||||
const container = useRef<HTMLDivElement>(null);
|
const container = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
@ -44,14 +53,16 @@ const InputElement: FC<InputElementProps> = ({
|
||||||
id,
|
id,
|
||||||
label: globalize.translate(label),
|
label: globalize.translate(label),
|
||||||
initialValue,
|
initialValue,
|
||||||
|
validator,
|
||||||
options
|
options
|
||||||
})
|
})
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
), []);
|
), []);
|
||||||
|
|
||||||
const onInput = useCallback((e: Event) => {
|
const onInput = useCallback((e: Event) => {
|
||||||
|
if (validator) (e.target as HTMLElement).parentElement?.querySelector('.inputElementInvalidMessage')?.classList.add('inputReadyForValidation');
|
||||||
onChange((e.target as HTMLInputElement).value);
|
onChange((e.target as HTMLInputElement).value);
|
||||||
}, [ onChange ]);
|
}, [ onChange, validator ]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const inputElement = container?.current?.querySelector<HTMLInputElement>('input');
|
const inputElement = container?.current?.querySelector<HTMLInputElement>('input');
|
||||||
|
|
8
src/elements/InputElementInvalidMessage.scss
Normal file
8
src/elements/InputElementInvalidMessage.scss
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
.inputElementInvalidMessage {
|
||||||
|
color: red;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emby-input:invalid + .inputElementInvalidMessage.inputReadyForValidation {
|
||||||
|
display: block;
|
||||||
|
}
|
|
@ -1124,6 +1124,7 @@
|
||||||
"MessageImageTypeNotSelected": "Please select an image type from the drop-down menu.",
|
"MessageImageTypeNotSelected": "Please select an image type from the drop-down menu.",
|
||||||
"MessageInvalidForgotPasswordPin": "An invalid or expired PIN code was entered. Please try again.",
|
"MessageInvalidForgotPasswordPin": "An invalid or expired PIN code was entered. Please try again.",
|
||||||
"MessageInvalidUser": "Invalid username or password. Please try again.",
|
"MessageInvalidUser": "Invalid username or password. Please try again.",
|
||||||
|
"MessageInvalidUsernameFormat": "Username must not be empty and contain only numbers, letters, spaces, or the following symbols -'._@+",
|
||||||
"MessageItemsAdded": "Items added.",
|
"MessageItemsAdded": "Items added.",
|
||||||
"MessageItemSaved": "Item saved.",
|
"MessageItemSaved": "Item saved.",
|
||||||
"MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item or the global default value.",
|
"MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item or the global default value.",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue