cleanup: wip 6.1
This commit is contained in:
parent
590ed9ce73
commit
d48d332c83
20
composer.lock
generated
20
composer.lock
generated
|
|
@ -5767,12 +5767,12 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bs-community/TwigBridge.git",
|
||||
"reference": "72d1481a08c145ca3b0020ee6c07c771bb2ca3bf"
|
||||
"reference": "61c2084d29bc63c3fa173fc631d8354fdf1c01fb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/bs-community/TwigBridge/zipball/72d1481a08c145ca3b0020ee6c07c771bb2ca3bf",
|
||||
"reference": "72d1481a08c145ca3b0020ee6c07c771bb2ca3bf",
|
||||
"url": "https://api.github.com/repos/bs-community/TwigBridge/zipball/61c2084d29bc63c3fa173fc631d8354fdf1c01fb",
|
||||
"reference": "61c2084d29bc63c3fa173fc631d8354fdf1c01fb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -5829,7 +5829,7 @@
|
|||
"support": {
|
||||
"source": "https://github.com/bs-community/TwigBridge/tree/blessing"
|
||||
},
|
||||
"time": "2025-01-18T08:54:48+00:00"
|
||||
"time": "2025-01-18T13:54:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sanmai/hoa-protocol",
|
||||
|
|
@ -9387,16 +9387,16 @@
|
|||
},
|
||||
{
|
||||
"name": "barryvdh/reflection-docblock",
|
||||
"version": "v2.3.0",
|
||||
"version": "v2.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/barryvdh/ReflectionDocBlock.git",
|
||||
"reference": "818be8de6af4d16ef3ad51ea9234b3d37026ee5f"
|
||||
"reference": "b6ff9f93603561f50e53b64310495d20b8dff5d8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/818be8de6af4d16ef3ad51ea9234b3d37026ee5f",
|
||||
"reference": "818be8de6af4d16ef3ad51ea9234b3d37026ee5f",
|
||||
"url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/b6ff9f93603561f50e53b64310495d20b8dff5d8",
|
||||
"reference": "b6ff9f93603561f50e53b64310495d20b8dff5d8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -9433,9 +9433,9 @@
|
|||
}
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.3.0"
|
||||
"source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.3.1"
|
||||
},
|
||||
"time": "2024-12-30T10:35:04+00:00"
|
||||
"time": "2025-01-18T19:26:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "clue/ndjson-react",
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ const icons = new Map<AlertType, string>([
|
|||
['danger', 'times-circle'],
|
||||
]);
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly type: AlertType;
|
||||
readonly children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const Alert: React.FC<Properties> = ({type, children}) => {
|
||||
const Alert: React.FC<Props> = ({type, children}) => {
|
||||
const icon = icons.get(type);
|
||||
|
||||
return children === ''
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
type Properties = {
|
||||
type Props = {
|
||||
readonly title?: string;
|
||||
readonly onClick: React.MouseEventHandler<HTMLAnchorElement>;
|
||||
};
|
||||
|
||||
const ButtonEdit: React.FC<Properties> = ({title, onClick}) => (
|
||||
const ButtonEdit: React.FC<Props> = ({title, onClick}) => (
|
||||
<a href='#' title={title} className='ml-2' onClick={onClick}>
|
||||
<i className='fas fa-edit'/>
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ class Captcha extends React.Component<Record<string, unknown>, State> {
|
|||
// eslint-disable-next-line ts/no-restricted-types
|
||||
ref: React.RefObject<Reaptcha | null>;
|
||||
|
||||
constructor(properties: Record<string, unknown>) {
|
||||
super(properties);
|
||||
constructor(props: Record<string, unknown>) {
|
||||
super(props);
|
||||
this.state = {
|
||||
value: '',
|
||||
time: Date.now(),
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import * as fetch from '@/scripts/net';
|
||||
import {useState} from 'react';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly initMode: boolean;
|
||||
};
|
||||
|
||||
const DarkModeButton: React.FC<Properties> = ({initMode}) => {
|
||||
const DarkModeButton: React.FC<Props> = ({initMode}) => {
|
||||
const [darkMode, setDarkMode] = useState(initMode);
|
||||
|
||||
const icon = darkMode ? 'moon' : 'sun';
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ const styles = css`
|
|||
|
||||
const domainNames = new Set(['qq.com', '163.com', 'gmail.com', 'hotmail.com']);
|
||||
|
||||
type Properties = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'> & {
|
||||
type Props = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'> & {
|
||||
onChange: (value: string) => void;
|
||||
};
|
||||
|
||||
const EmailSuggestion: React.FC<Properties> = props => {
|
||||
const EmailSuggestion: React.FC<Props> = props => {
|
||||
useEffect(() => {
|
||||
emit('emailDomainsSuggestion', domainNames);
|
||||
}, []);
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ const hideRawBrowseButton = css`
|
|||
}
|
||||
`;
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
file: File | undefined;
|
||||
accept?: string;
|
||||
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
};
|
||||
|
||||
const FileInput: React.FC<Properties> = properties => {
|
||||
const FileInput: React.FC<Props> = props => {
|
||||
const reference = useRef<HTMLInputElement>(null);
|
||||
|
||||
const handleClick = () => {
|
||||
|
|
@ -31,12 +31,12 @@ const FileInput: React.FC<Properties> = properties => {
|
|||
type='file'
|
||||
className='custom-file-input'
|
||||
id='select-file'
|
||||
accept={properties.accept}
|
||||
accept={props.accept}
|
||||
title={t('skinlib.upload.select-file')}
|
||||
onChange={properties.onChange}
|
||||
onChange={props.onChange}
|
||||
/>
|
||||
<label className='custom-file-label' css={hideRawBrowseButton}>
|
||||
{properties.file?.name}
|
||||
{props.file?.name}
|
||||
</label>
|
||||
</div>
|
||||
<div className='input-group-append'>
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ import {Modal as BootstrapModal} from 'bootstrap';
|
|||
import clsx from 'clsx';
|
||||
import {useEffect, useRef, useState} from 'react';
|
||||
import {t} from '../scripts/i18n';
|
||||
import ModalBody, {type Props as BodyProperties} from './ModalBody';
|
||||
import ModalFooter, {type Props as FooterProperties} from './ModalFooter';
|
||||
import ModalHeader, {type Props as HeaderProperties} from './ModalHeader';
|
||||
import ModalBody, {type Props as BodyProps} from './ModalBody';
|
||||
import ModalFooter, {type Props as FooterProps} from './ModalFooter';
|
||||
import ModalHeader, {type Props as HeaderProps} from './ModalHeader';
|
||||
|
||||
type BasicOptions = {
|
||||
readonly mode?: 'alert' | 'confirm' | 'prompt';
|
||||
|
|
@ -17,9 +17,9 @@ type BasicOptions = {
|
|||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
export type ModalOptions = BasicOptions & HeaderProperties & BodyProperties & FooterProperties;
|
||||
export type ModalOptions = BasicOptions & HeaderProps & BodyProps & FooterProps;
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly id?: string;
|
||||
readonly children?: React.ReactNode;
|
||||
readonly footer?: React.ReactNode;
|
||||
|
|
@ -32,7 +32,7 @@ export type ModalResult = {
|
|||
value: string;
|
||||
};
|
||||
|
||||
const Modal: React.FC<ModalOptions & Properties> = properties => {
|
||||
const Modal: React.FC<ModalOptions & Props> = props => {
|
||||
const {
|
||||
mode = 'confirm',
|
||||
title = t('general.tip'),
|
||||
|
|
@ -59,7 +59,7 @@ const Modal: React.FC<ModalOptions & Properties> = properties => {
|
|||
children,
|
||||
choices,
|
||||
dangerousHTML: html,
|
||||
} = properties;
|
||||
} = props;
|
||||
|
||||
const [value, setValue] = useState(input);
|
||||
const [valid, setValid] = useState(true);
|
||||
|
|
|
|||
|
|
@ -1,24 +1,24 @@
|
|||
|
||||
import ModalContent, {type Props as ContentProperties} from './ModalContent';
|
||||
import ModalContent, {type Props as ContentProps} from './ModalContent';
|
||||
import ModalInput, {
|
||||
type
|
||||
InternalProps as InputInteralProperties,
|
||||
InternalProps as InputInteralProps,
|
||||
type
|
||||
Props as InputProperties,
|
||||
Props as InputProps,
|
||||
} from './ModalInput';
|
||||
|
||||
type InternalProperties = {
|
||||
type InternalProps = {
|
||||
readonly showInput: boolean;
|
||||
};
|
||||
|
||||
export type Props = ContentProperties & InputProperties;
|
||||
export type Props = ContentProps & InputProps;
|
||||
|
||||
const ModalBody: React.FC<InternalProperties & InputInteralProperties & Props> = properties => (
|
||||
const ModalBody: React.FC<InternalProps & InputInteralProps & Props> = props => (
|
||||
<div className='modal-body'>
|
||||
<ModalContent text={properties.text} dangerousHTML={properties.dangerousHTML}>
|
||||
{properties.children}
|
||||
<ModalContent text={props.text} dangerousHTML={props.dangerousHTML}>
|
||||
{props.children}
|
||||
</ModalContent>
|
||||
{properties.showInput && <ModalInput {...properties}/>}
|
||||
{props.showInput && <ModalInput {...props}/>}
|
||||
</div>
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,22 +5,22 @@ export type Props = {
|
|||
readonly children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const ModalContent: React.FC<Props> = properties => {
|
||||
if (properties.children) {
|
||||
return <>{properties.children}</>;
|
||||
const ModalContent: React.FC<Props> = props => {
|
||||
if (props.children) {
|
||||
return <>{props.children}</>;
|
||||
}
|
||||
|
||||
if (properties.text) {
|
||||
if (props.text) {
|
||||
return (
|
||||
<>
|
||||
{properties.text.split(/\r?\n/).map((line, i) =>
|
||||
{props.text.split(/\r?\n/).map((line, i) =>
|
||||
<p key={i}>{line}</p>)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (properties.dangerousHTML) {
|
||||
return <div dangerouslySetInnerHTML={{__html: properties.dangerousHTML}}/>;
|
||||
if (props.dangerousHTML) {
|
||||
return <div dangerouslySetInnerHTML={{__html: props.dangerousHTML}}/>;
|
||||
}
|
||||
|
||||
return <></>;
|
||||
|
|
|
|||
|
|
@ -8,40 +8,40 @@ export type Props = {
|
|||
readonly children?: React.ReactNode;
|
||||
};
|
||||
|
||||
type InternalProperties = {
|
||||
type InternalProps = {
|
||||
readonly showCancelButton: boolean;
|
||||
onConfirm?: () => void;
|
||||
onDismiss?: () => void;
|
||||
};
|
||||
|
||||
const ModalFooter: React.FC<InternalProperties & Props> = properties => {
|
||||
const ModalFooter: React.FC<InternalProps & Props> = props => {
|
||||
const classes = ['modal-footer'];
|
||||
if (properties.flexFooter) {
|
||||
if (props.flexFooter) {
|
||||
classes.push('d-flex', 'justify-content-between');
|
||||
}
|
||||
|
||||
const footerClass = classes.join(' ');
|
||||
|
||||
return properties.children
|
||||
? <div className={footerClass}>{properties.children}</div>
|
||||
return props.children
|
||||
? <div className={footerClass}>{props.children}</div>
|
||||
: (
|
||||
<div className={footerClass}>
|
||||
{properties.showCancelButton && (
|
||||
{props.showCancelButton && (
|
||||
<button
|
||||
type='button'
|
||||
className={`btn btn-${properties.cancelButtonType}`}
|
||||
className={`btn btn-${props.cancelButtonType}`}
|
||||
data-dismiss='modal'
|
||||
onClick={properties.onDismiss}
|
||||
onClick={props.onDismiss}
|
||||
>
|
||||
{properties.cancelButtonText}
|
||||
{props.cancelButtonText}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
type='button'
|
||||
className={`btn btn-${properties.okButtonType}`}
|
||||
onClick={properties.onConfirm}
|
||||
className={`btn btn-${props.okButtonType}`}
|
||||
onClick={props.onConfirm}
|
||||
>
|
||||
{properties.okButtonText}
|
||||
{props.okButtonText}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ export type Props = {
|
|||
readonly title?: string;
|
||||
};
|
||||
|
||||
type InternalProperties = {
|
||||
type InternalProps = {
|
||||
onDismiss?: () => void;
|
||||
readonly show?: boolean;
|
||||
};
|
||||
|
||||
const ModalHeader: React.FC<Props & InternalProperties> = ({show, title, onDismiss}) =>
|
||||
const ModalHeader: React.FC<Props & InternalProps> = ({show, title, onDismiss}) =>
|
||||
show
|
||||
? (
|
||||
<div className='modal-header'>
|
||||
|
|
|
|||
|
|
@ -13,20 +13,20 @@ export type InternalProps = {
|
|||
readonly onChange?: React.ChangeEventHandler<HTMLInputElement>;
|
||||
};
|
||||
|
||||
const ModalInput: React.FC<InternalProps & Props> = properties => (
|
||||
const ModalInput: React.FC<InternalProps & Props> = props => (
|
||||
<>
|
||||
{properties.inputType === 'radios' && properties.choices
|
||||
{props.inputType === 'radios' && props.choices
|
||||
? (
|
||||
<>
|
||||
{properties.choices.map(choice => (
|
||||
{props.choices.map(choice => (
|
||||
<div key={choice.value}>
|
||||
<input
|
||||
type='radio'
|
||||
name='modal-radios'
|
||||
id={`modal-radio-${choice.value}`}
|
||||
value={choice.value}
|
||||
checked={choice.value === properties.value}
|
||||
onChange={properties.onChange}
|
||||
checked={choice.value === props.value}
|
||||
onChange={props.onChange}
|
||||
/>
|
||||
<label htmlFor={`modal-radio-${choice.value}`} className='ml-1'>
|
||||
{choice.text}
|
||||
|
|
@ -38,19 +38,19 @@ const ModalInput: React.FC<InternalProps & Props> = properties => (
|
|||
: (
|
||||
<div className='form-group'>
|
||||
<input
|
||||
value={properties.value}
|
||||
type={properties.inputType}
|
||||
inputMode={properties.inputMode}
|
||||
value={props.value}
|
||||
type={props.inputType}
|
||||
inputMode={props.inputMode}
|
||||
className='form-control'
|
||||
placeholder={properties.placeholder}
|
||||
onChange={properties.onChange}
|
||||
placeholder={props.placeholder}
|
||||
onChange={props.onChange}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{properties.invalid && (
|
||||
{props.invalid && (
|
||||
<div className='alert alert-danger'>
|
||||
<i className='icon far fa-times-circle'/>
|
||||
<span className='ml-1'>{properties.validatorMessage}</span>
|
||||
<span className='ml-1'>{props.validatorMessage}</span>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import {t} from '@/scripts/i18n';
|
||||
import PaginationItem from './PaginationItem';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly page: number;
|
||||
readonly totalPages: number;
|
||||
onChange: (page: number) => void | Promise<void>;
|
||||
|
|
@ -13,8 +13,8 @@ const labels = {
|
|||
next: '›',
|
||||
};
|
||||
|
||||
const Pagination: React.FC<Properties> = properties => {
|
||||
const {page, totalPages, onChange} = properties;
|
||||
const Pagination: React.FC<Props> = props => {
|
||||
const {page, totalPages, onChange} = props;
|
||||
|
||||
if (totalPages < 1) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly disabled?: boolean;
|
||||
readonly active?: boolean;
|
||||
readonly title?: string;
|
||||
|
|
@ -8,31 +8,31 @@ type Properties = {
|
|||
readonly children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const PaginationItem: React.FC<Properties> = properties => {
|
||||
const PaginationItem: React.FC<Props> = props => {
|
||||
const classes = ['page-item'];
|
||||
if (properties.active) {
|
||||
if (props.active) {
|
||||
classes.push('active');
|
||||
}
|
||||
|
||||
if (properties.disabled) {
|
||||
if (props.disabled) {
|
||||
classes.push('disabled');
|
||||
}
|
||||
|
||||
if (properties.className) {
|
||||
classes.push(properties.className);
|
||||
if (props.className) {
|
||||
classes.push(props.className);
|
||||
}
|
||||
|
||||
const handleClick = (event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
if (!properties.disabled && properties.onClick) {
|
||||
properties.onClick();
|
||||
if (!props.disabled && props.onClick) {
|
||||
props.onClick();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<li className={classes.join(' ')} title={properties.title} onClick={handleClick}>
|
||||
<a href='#' className='page-link' aria-disabled={properties.disabled}>
|
||||
{properties.children}
|
||||
<li className={classes.join(' ')} title={props.title} onClick={handleClick}>
|
||||
<a href='#' className='page-link' aria-disabled={props.disabled}>
|
||||
{props.children}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import {useEffect, useState} from 'react';
|
|||
|
||||
export type ToastType = 'success' | 'info' | 'warning' | 'error';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly type: ToastType;
|
||||
readonly distance: number;
|
||||
onClose: () => void | Promise<void>;
|
||||
|
|
@ -29,7 +29,7 @@ const shadow = css`
|
|||
box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1);
|
||||
`;
|
||||
|
||||
const Toast: React.FC<Properties> = properties => {
|
||||
const Toast: React.FC<Props> = props => {
|
||||
const [show, setShow] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -40,9 +40,9 @@ const Toast: React.FC<Properties> = properties => {
|
|||
return () => {
|
||||
clearTimeout(timer);
|
||||
};
|
||||
}, [properties.onClose]);
|
||||
}, [props.onClose]);
|
||||
|
||||
const type = properties.type === 'error' ? 'danger' : properties.type;
|
||||
const type = props.type === 'error' ? 'danger' : props.type;
|
||||
|
||||
const classes = [
|
||||
`alert alert-${type}`,
|
||||
|
|
@ -56,16 +56,16 @@ const Toast: React.FC<Properties> = properties => {
|
|||
const role = type === 'success' || type === 'info' ? 'status' : 'alert';
|
||||
|
||||
return (
|
||||
<div css={wrapper} style={{top: `${properties.distance}px`}}>
|
||||
<div css={wrapper} style={{top: `${props.distance}px`}}>
|
||||
<div className={classes.join(' ')} css={shadow} role={role}>
|
||||
<span className='mr-1 d-flex align-items-center'>
|
||||
<i className={`icon fas fa-${icons.get(properties.type)}`}/>
|
||||
<i className={`icon fas fa-${icons.get(props.type)}`}/>
|
||||
</span>
|
||||
<span>{properties.children}</span>
|
||||
<span>{props.children}</span>
|
||||
<button
|
||||
type='button'
|
||||
className='mr-2 ml-1 close'
|
||||
onClick={properties.onClose}
|
||||
onClick={props.onClose}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import SkinSteve from '../../../misc/textures/steve.png';
|
|||
const backgrounds = [bg1, bg2, bg3, bg4, bg5, bg6, bg7];
|
||||
export const PICTURES_COUNT = backgrounds.length;
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly skin?: string;
|
||||
readonly cape?: string;
|
||||
readonly children?: React.ReactNode;
|
||||
|
|
@ -58,8 +58,8 @@ const cssViewer = css`
|
|||
}
|
||||
`;
|
||||
|
||||
const Viewer: React.FC<Properties> = properties => {
|
||||
const {initPositionZ = 70} = properties;
|
||||
const Viewer: React.FC<Props> = props => {
|
||||
const {initPositionZ = 70} = props;
|
||||
|
||||
const viewReference: React.MutableRefObject<skinview3d.SkinViewer> = useRef(null!);
|
||||
const containerReference = useRef<HTMLCanvasElement>(null);
|
||||
|
|
@ -69,7 +69,7 @@ const Viewer: React.FC<Properties> = properties => {
|
|||
const [bgPicture, setBgPicture] = useState(-1);
|
||||
|
||||
const indicator = (() => {
|
||||
const {skin, cape} = properties;
|
||||
const {skin, cape} = props;
|
||||
if (skin && cape) {
|
||||
return `${t('general.skin')} & ${t('general.cape')}`;
|
||||
}
|
||||
|
|
@ -91,9 +91,9 @@ const Viewer: React.FC<Properties> = properties => {
|
|||
canvas: container,
|
||||
width: container.clientWidth,
|
||||
height: container.clientHeight,
|
||||
skin: properties.skin || SkinSteve,
|
||||
cape: properties.cape || undefined,
|
||||
model: properties.isAlex ? 'slim' : 'default',
|
||||
skin: props.skin || SkinSteve,
|
||||
cape: props.cape || undefined,
|
||||
model: props.isAlex ? 'slim' : 'default',
|
||||
zoom: initPositionZ / 100,
|
||||
});
|
||||
viewer.autoRotate = true;
|
||||
|
|
@ -117,19 +117,19 @@ const Viewer: React.FC<Properties> = properties => {
|
|||
|
||||
useEffect(() => {
|
||||
const viewer = viewReference.current;
|
||||
viewer.loadSkin(properties.skin || SkinSteve, {
|
||||
model: properties.isAlex ? 'slim' : 'default',
|
||||
viewer.loadSkin(props.skin || SkinSteve, {
|
||||
model: props.isAlex ? 'slim' : 'default',
|
||||
});
|
||||
}, [properties.skin, properties.isAlex]);
|
||||
}, [props.skin, props.isAlex]);
|
||||
|
||||
useEffect(() => {
|
||||
const viewer = viewReference.current;
|
||||
if (properties.cape) {
|
||||
viewer.loadCape(properties.cape);
|
||||
if (props.cape) {
|
||||
viewer.loadCape(props.cape);
|
||||
} else {
|
||||
viewer.resetCape();
|
||||
}
|
||||
}, [properties.cape]);
|
||||
}, [props.cape]);
|
||||
|
||||
useEffect(() => {
|
||||
const viewer = viewReference.current;
|
||||
|
|
@ -225,12 +225,12 @@ const Viewer: React.FC<Properties> = properties => {
|
|||
<div className='d-flex justify-content-between'>
|
||||
<h3 className='card-title'>
|
||||
<span>{t('general.texturePreview')}</span>
|
||||
{properties.showIndicator
|
||||
{props.showIndicator
|
||||
&& <span className='badge bg-olive ml-1'>{indicator}</span>}
|
||||
</h3>
|
||||
<div>
|
||||
<ActionButton
|
||||
className={`fas fa-tablet ${properties.cape ? '' : 'd-none'}`}
|
||||
className={`fas fa-tablet ${props.cape ? '' : 'd-none'}`}
|
||||
data-toggle='tooltip'
|
||||
data-placement='bottom'
|
||||
title={t('general.switchCapeElytra')}
|
||||
|
|
@ -301,7 +301,7 @@ const Viewer: React.FC<Properties> = properties => {
|
|||
<i className='fas fa-arrow-right'/>
|
||||
</div>
|
||||
</div>
|
||||
{properties.children}
|
||||
{props.children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -26,10 +26,9 @@ if (route) {
|
|||
const root = createRoot(container!);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<React.Suspense fallback={route.frame?.() ?? ''}>
|
||||
<Component/>
|
||||
</React.Suspense>
|
||||
</React.StrictMode>
|
||||
);
|
||||
<React.Suspense fallback={route.frame?.() ?? ''}>
|
||||
<Component/>
|
||||
</React.Suspense>
|
||||
</React.StrictMode>,);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import {showModal} from '@/scripts/notify';
|
|||
import clsx from 'clsx';
|
||||
import {Box} from './styles';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly player: Player;
|
||||
onUpdateName: () => void;
|
||||
onUpdateOwner: () => void;
|
||||
|
|
@ -13,8 +13,8 @@ type Properties = {
|
|||
onDelete: () => void;
|
||||
};
|
||||
|
||||
const Card: React.FC<Properties> = properties => {
|
||||
const {player} = properties;
|
||||
const Card: React.FC<Props> = props => {
|
||||
const {player} = props;
|
||||
|
||||
const handlePreviewTextures = () => {
|
||||
const skinPreview = `${blessing.base_url}/preview/${player.tid_skin}`;
|
||||
|
|
@ -109,7 +109,7 @@ const Card: React.FC<Properties> = properties => {
|
|||
<a
|
||||
href='#'
|
||||
className='dropdown-item'
|
||||
onClick={properties.onUpdateName}
|
||||
onClick={props.onUpdateName}
|
||||
>
|
||||
<i className='fas fa-signature mr-2'/>
|
||||
{t('admin.changePlayerName')}
|
||||
|
|
@ -117,7 +117,7 @@ const Card: React.FC<Properties> = properties => {
|
|||
<a
|
||||
href='#'
|
||||
className='dropdown-item'
|
||||
onClick={properties.onUpdateOwner}
|
||||
onClick={props.onUpdateOwner}
|
||||
>
|
||||
<i className='fas fa-user-edit mr-2'/>
|
||||
{t('admin.changeOwner')}
|
||||
|
|
@ -125,7 +125,7 @@ const Card: React.FC<Properties> = properties => {
|
|||
<a
|
||||
href='#'
|
||||
className='dropdown-item'
|
||||
onClick={properties.onUpdateTexture}
|
||||
onClick={props.onUpdateTexture}
|
||||
>
|
||||
<i className='fas fa-tshirt mr-2'/>
|
||||
{t('admin.changeTexture')}
|
||||
|
|
@ -134,7 +134,7 @@ const Card: React.FC<Properties> = properties => {
|
|||
<a
|
||||
href='#'
|
||||
className='dropdown-item dropdown-item-danger'
|
||||
onClick={properties.onDelete}
|
||||
onClick={props.onDelete}
|
||||
>
|
||||
<i className='fas fa-trash mr-2'/>
|
||||
{t('admin.deletePlayer')}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import {Box} from './styles';
|
|||
const isDarkMode = document.body.classList.contains('dark-mode');
|
||||
|
||||
const ShrinkedSkeleton = styled(Skeleton)<{width?: string}>`
|
||||
width: ${properties => properties.width};
|
||||
width: ${props => props.width};
|
||||
`;
|
||||
|
||||
export default function LoadingCard() {
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ import {t} from '@/scripts/i18n';
|
|||
import {TextureType} from '@/scripts/types';
|
||||
import {useState} from 'react';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly open: boolean;
|
||||
onSubmit: (type: 'skin' | 'cape', tid: number) => void;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const ModalUpdateTexture: React.FC<Properties> = properties => {
|
||||
const ModalUpdateTexture: React.FC<Props> = props => {
|
||||
const [type, setType] = useState<'skin' | 'cape'>('skin');
|
||||
const [tid, setTid] = useState('');
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ const ModalUpdateTexture: React.FC<Properties> = properties => {
|
|||
};
|
||||
|
||||
const handleConfirm = () => {
|
||||
properties.onSubmit(type, Number.parseInt(tid));
|
||||
props.onSubmit(type, Number.parseInt(tid));
|
||||
setType('skin');
|
||||
setTid('');
|
||||
};
|
||||
|
|
@ -30,13 +30,13 @@ const ModalUpdateTexture: React.FC<Properties> = properties => {
|
|||
const handleClose = () => {
|
||||
setType('skin');
|
||||
setTid('');
|
||||
properties.onClose();
|
||||
props.onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
center
|
||||
show={properties.open}
|
||||
show={props.open}
|
||||
title={t('admin.changeTexture')}
|
||||
onConfirm={handleConfirm}
|
||||
onClose={handleClose}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import type {Player} from '@/scripts/types';
|
|||
import ButtonEdit from '@/components/ButtonEdit';
|
||||
import {t} from '@/scripts/i18n';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly player: Player;
|
||||
onUpdateName: () => void;
|
||||
onUpdateOwner: () => void;
|
||||
|
|
@ -11,8 +11,8 @@ type Properties = {
|
|||
onDelete: () => void;
|
||||
};
|
||||
|
||||
const Row: React.FC<Properties> = properties => {
|
||||
const {player} = properties;
|
||||
const Row: React.FC<Props> = props => {
|
||||
const {player} = props;
|
||||
|
||||
return (
|
||||
<tr>
|
||||
|
|
@ -22,7 +22,7 @@ const Row: React.FC<Properties> = properties => {
|
|||
<span className='ml-1'>
|
||||
<ButtonEdit
|
||||
title={t('admin.changePlayerName')}
|
||||
onClick={properties.onUpdateName}
|
||||
onClick={props.onUpdateName}
|
||||
/>
|
||||
</span>
|
||||
</td>
|
||||
|
|
@ -31,7 +31,7 @@ const Row: React.FC<Properties> = properties => {
|
|||
<span className='ml-1'>
|
||||
<ButtonEdit
|
||||
title={t('admin.changeOwner')}
|
||||
onClick={properties.onUpdateOwner}
|
||||
onClick={props.onUpdateOwner}
|
||||
/>
|
||||
</span>
|
||||
</td>
|
||||
|
|
@ -68,11 +68,11 @@ const Row: React.FC<Properties> = properties => {
|
|||
<td className='d-flex flex-wrap'>
|
||||
<button
|
||||
className='btn btn-default mr-2'
|
||||
onClick={properties.onUpdateTexture}
|
||||
onClick={props.onUpdateTexture}
|
||||
>
|
||||
{t('admin.changeTexture')}
|
||||
</button>
|
||||
<button className='btn btn-danger' onClick={properties.onDelete}>
|
||||
<button className='btn btn-danger' onClick={props.onDelete}>
|
||||
{t('admin.deletePlayer')}
|
||||
</button>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ const Description = styled.div`
|
|||
font-size: 14px;
|
||||
`;
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly plugin: Plugin;
|
||||
onEnable: (plugin: Plugin) => void;
|
||||
onDisable: (plugin: Plugin) => void;
|
||||
|
|
@ -47,21 +47,21 @@ type Properties = {
|
|||
readonly baseUrl: string;
|
||||
};
|
||||
|
||||
const InfoBox: React.FC<Properties> = properties => {
|
||||
const {plugin} = properties;
|
||||
const InfoBox: React.FC<Props> = props => {
|
||||
const {plugin} = props;
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (event.target.checked) {
|
||||
properties.onEnable(plugin);
|
||||
props.onEnable(plugin);
|
||||
} else {
|
||||
properties.onDisable(plugin);
|
||||
props.onDisable(plugin);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = () => {
|
||||
properties.onDelete(plugin);
|
||||
props.onDelete(plugin);
|
||||
};
|
||||
|
||||
const isDarkMode = document.body.classList.contains('dark-mode');
|
||||
|
|
@ -96,7 +96,7 @@ const InfoBox: React.FC<Properties> = properties => {
|
|||
<div>
|
||||
{plugin.readme && (
|
||||
<ActionButton
|
||||
href={`${properties.baseUrl}/admin/plugins/readme/${plugin.name}`}
|
||||
href={`${props.baseUrl}/admin/plugins/readme/${plugin.name}`}
|
||||
title={t('admin.pluginReadme')}
|
||||
>
|
||||
<i className='fas fa-question'/>
|
||||
|
|
@ -104,7 +104,7 @@ const InfoBox: React.FC<Properties> = properties => {
|
|||
)}
|
||||
{plugin.enabled && plugin.config && (
|
||||
<ActionButton
|
||||
href={`${properties.baseUrl}/admin/plugins/config/${plugin.name}`}
|
||||
href={`${props.baseUrl}/admin/plugins/config/${plugin.name}`}
|
||||
title={t('admin.configurePlugin')}
|
||||
>
|
||||
<i className='fas fa-cog'/>
|
||||
|
|
|
|||
|
|
@ -2,15 +2,15 @@
|
|||
import type {Plugin} from './types';
|
||||
import {t} from '@/scripts/i18n';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly plugin: Plugin;
|
||||
readonly isInstalling: boolean;
|
||||
onInstall: () => void;
|
||||
onUpdate: () => void;
|
||||
};
|
||||
|
||||
const Row: React.FC<Properties> = properties => {
|
||||
const {plugin, isInstalling} = properties;
|
||||
const Row: React.FC<Props> = props => {
|
||||
const {plugin, isInstalling} = props;
|
||||
|
||||
const allDeps = Object.entries(plugin.dependencies.all);
|
||||
const unsatisfied = Object.keys(plugin.dependencies.unsatisfied);
|
||||
|
|
@ -54,7 +54,7 @@ const Row: React.FC<Properties> = properties => {
|
|||
<button
|
||||
className='btn btn-success'
|
||||
disabled={isInstalling}
|
||||
onClick={properties.onUpdate}
|
||||
onClick={props.onUpdate}
|
||||
>
|
||||
{isInstalling
|
||||
? (
|
||||
|
|
@ -74,8 +74,8 @@ const Row: React.FC<Properties> = properties => {
|
|||
: (
|
||||
<button
|
||||
className='btn btn-default'
|
||||
disabled={properties.isInstalling || Boolean(plugin.installed)}
|
||||
onClick={properties.onInstall}
|
||||
disabled={props.isInstalling || Boolean(plugin.installed)}
|
||||
onClick={props.onInstall}
|
||||
>
|
||||
{isInstalling
|
||||
? (
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ const Card = styled.div`
|
|||
}
|
||||
`;
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly report: Report;
|
||||
onClick: (texture: Texture | undefined) => void;
|
||||
onBan: () => void;
|
||||
|
|
@ -37,13 +37,13 @@ type Properties = {
|
|||
onReject: () => void;
|
||||
};
|
||||
|
||||
const ImageBox: React.FC<Properties> = properties => {
|
||||
const {report} = properties;
|
||||
const ImageBox: React.FC<Props> = props => {
|
||||
const {report} = props;
|
||||
const preview = `${blessing.base_url}/preview/${report.tid}?height=150`;
|
||||
const previewPNG = `${preview}&png`;
|
||||
|
||||
const handleImageClick = () => {
|
||||
properties.onClick(report.texture);
|
||||
props.onClick(report.texture);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -102,19 +102,19 @@ const ImageBox: React.FC<Properties> = properties => {
|
|||
<i className='fas fa-share-square mr-2'/>
|
||||
{t('user.viewInSkinlib')}
|
||||
</a>
|
||||
<a href='#' className='dropdown-item' onClick={properties.onBan}>
|
||||
<a href='#' className='dropdown-item' onClick={props.onBan}>
|
||||
<i className='fas fa-user-slash mr-2'/>
|
||||
{t('report.ban')}
|
||||
</a>
|
||||
<a
|
||||
href='#'
|
||||
className='dropdown-item dropdown-item-danger'
|
||||
onClick={properties.onDelete}
|
||||
onClick={props.onDelete}
|
||||
>
|
||||
<i className='fas fa-trash mr-2'/>
|
||||
{t('skinlib.show.delete-texture')}
|
||||
</a>
|
||||
<a href='#' className='dropdown-item' onClick={properties.onReject}>
|
||||
<a href='#' className='dropdown-item' onClick={props.onReject}>
|
||||
<i className='fas fa-thumbs-down mr-2'/>
|
||||
{t('report.reject')}
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -12,14 +12,14 @@ const Operations = styled.td`
|
|||
width: 25%;
|
||||
`;
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly line: Line;
|
||||
onEdit: (line: Line) => void;
|
||||
onRemove: (line: Line) => void;
|
||||
};
|
||||
|
||||
const Row: React.FC<Properties> = properties => {
|
||||
const {line, onEdit, onRemove} = properties;
|
||||
const Row: React.FC<Props> = props => {
|
||||
const {line, onEdit, onRemove} = props;
|
||||
const text = line.text[blessing.locale];
|
||||
|
||||
const handleEditClick = () => {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import {
|
|||
verificationStatusText,
|
||||
} from './utils';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly user: User;
|
||||
readonly currentUser: User;
|
||||
onEmailChange: () => void;
|
||||
|
|
@ -22,8 +22,8 @@ type Properties = {
|
|||
onDelete: () => void;
|
||||
};
|
||||
|
||||
const Card: React.FC<Properties> = properties => {
|
||||
const {user, currentUser} = properties;
|
||||
const Card: React.FC<Props> = props => {
|
||||
const {user, currentUser} = props;
|
||||
|
||||
const isDarkMode = document.body.classList.contains('dark-mode');
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ const Card: React.FC<Properties> = properties => {
|
|||
<a
|
||||
href='#'
|
||||
className='dropdown-item'
|
||||
onClick={properties.onEmailChange}
|
||||
onClick={props.onEmailChange}
|
||||
>
|
||||
<i className='fas fa-at mr-2'/>
|
||||
{t('admin.changeEmail')}
|
||||
|
|
@ -67,7 +67,7 @@ const Card: React.FC<Properties> = properties => {
|
|||
<a
|
||||
href='#'
|
||||
className='dropdown-item'
|
||||
onClick={properties.onNicknameChange}
|
||||
onClick={props.onNicknameChange}
|
||||
>
|
||||
<i className='fas fa-signature mr-2'/>
|
||||
{t('admin.changeNickName')}
|
||||
|
|
@ -75,7 +75,7 @@ const Card: React.FC<Properties> = properties => {
|
|||
<a
|
||||
href='#'
|
||||
className='dropdown-item'
|
||||
onClick={properties.onPasswordChange}
|
||||
onClick={props.onPasswordChange}
|
||||
>
|
||||
<i className='fas fa-asterisk mr-2'/>
|
||||
{t('admin.changePassword')}
|
||||
|
|
@ -84,7 +84,7 @@ const Card: React.FC<Properties> = properties => {
|
|||
<a
|
||||
href='#'
|
||||
className='dropdown-item'
|
||||
onClick={properties.onScoreChange}
|
||||
onClick={props.onScoreChange}
|
||||
>
|
||||
<i className='fas fa-coins mr-2'/>
|
||||
{t('admin.changeScore')}
|
||||
|
|
@ -93,7 +93,7 @@ const Card: React.FC<Properties> = properties => {
|
|||
<a
|
||||
href='#'
|
||||
className='dropdown-item'
|
||||
onClick={properties.onPermissionChange}
|
||||
onClick={props.onPermissionChange}
|
||||
>
|
||||
<i className='fas fa-user-secret mr-2'/>
|
||||
{t('admin.changePermission')}
|
||||
|
|
@ -102,7 +102,7 @@ const Card: React.FC<Properties> = properties => {
|
|||
<a
|
||||
href='#'
|
||||
className='dropdown-item'
|
||||
onClick={properties.onVerificationToggle}
|
||||
onClick={props.onVerificationToggle}
|
||||
>
|
||||
<i className='fas fa-user-check mr-2'/>
|
||||
{t('admin.toggleVerification')}
|
||||
|
|
@ -112,7 +112,7 @@ const Card: React.FC<Properties> = properties => {
|
|||
<a
|
||||
href='#'
|
||||
className='dropdown-item dropdown-item-danger'
|
||||
onClick={properties.onDelete}
|
||||
onClick={props.onDelete}
|
||||
>
|
||||
<i className='fas fa-trash mr-2'/>
|
||||
{t('admin.deleteUser')}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import Skeleton from 'react-loading-skeleton';
|
|||
import {Box, Icon, InfoTable} from './styles';
|
||||
|
||||
const ShrinkedSkeleton = styled(Skeleton)<{width?: string}>`
|
||||
width: ${properties => properties.width};
|
||||
width: ${props => props.width};
|
||||
`;
|
||||
|
||||
const isDarkMode = document.body.classList.contains('dark-mode');
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
verificationStatusText,
|
||||
} from './utils';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly user: User;
|
||||
readonly currentUser: User;
|
||||
onEmailChange: () => void;
|
||||
|
|
@ -21,8 +21,8 @@ type Properties = {
|
|||
onDelete: () => void;
|
||||
};
|
||||
|
||||
const Row: React.FC<Properties> = properties => {
|
||||
const {user, currentUser} = properties;
|
||||
const Row: React.FC<Props> = props => {
|
||||
const {user, currentUser} = props;
|
||||
|
||||
const canModify = canModifyUser(user, currentUser);
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ const Row: React.FC<Properties> = properties => {
|
|||
<span className='ml-1'>
|
||||
<ButtonEdit
|
||||
title={t('admin.changeEmail')}
|
||||
onClick={properties.onEmailChange}
|
||||
onClick={props.onEmailChange}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
|
|
@ -46,7 +46,7 @@ const Row: React.FC<Properties> = properties => {
|
|||
<span className='ml-1'>
|
||||
<ButtonEdit
|
||||
title={t('admin.changeNickName')}
|
||||
onClick={properties.onNicknameChange}
|
||||
onClick={props.onNicknameChange}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
|
|
@ -57,7 +57,7 @@ const Row: React.FC<Properties> = properties => {
|
|||
<span className='ml-1'>
|
||||
<ButtonEdit
|
||||
title={t('admin.changeScore')}
|
||||
onClick={properties.onScoreChange}
|
||||
onClick={props.onScoreChange}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
|
|
@ -68,7 +68,7 @@ const Row: React.FC<Properties> = properties => {
|
|||
<span className='ml-1'>
|
||||
<ButtonEdit
|
||||
title={t('admin.changePermission')}
|
||||
onClick={properties.onPermissionChange}
|
||||
onClick={props.onPermissionChange}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
|
|
@ -80,7 +80,7 @@ const Row: React.FC<Properties> = properties => {
|
|||
className='ml-1'
|
||||
href='#'
|
||||
title={t('admin.toggleVerification')}
|
||||
onClick={properties.onVerificationToggle}
|
||||
onClick={props.onVerificationToggle}
|
||||
>
|
||||
{user.verified
|
||||
? <i className='fas fa-toggle-on'/>
|
||||
|
|
@ -93,14 +93,14 @@ const Row: React.FC<Properties> = properties => {
|
|||
<button
|
||||
className='btn btn-default mr-2'
|
||||
disabled={!canModify}
|
||||
onClick={properties.onPasswordChange}
|
||||
onClick={props.onPasswordChange}
|
||||
>
|
||||
{t('admin.changePassword')}
|
||||
</button>
|
||||
<button
|
||||
className='btn btn-danger'
|
||||
disabled={!canModify || user.uid === currentUser.uid}
|
||||
onClick={properties.onDelete}
|
||||
onClick={props.onDelete}
|
||||
>
|
||||
{t('admin.deleteUser')}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type {Props as ModalInputProperties} from '@/components/ModalInput';
|
||||
import type {Props as ModalInputProps} from '@/components/ModalInput';
|
||||
import Pagination from '@/components/Pagination';
|
||||
import useBlessingExtra from '@/scripts/hooks/useBlessingExtra';
|
||||
import useIsLargeScreen from '@/scripts/hooks/useIsLargeScreen';
|
||||
|
|
@ -159,7 +159,7 @@ function UsersManagement() {
|
|||
};
|
||||
|
||||
const handlePermissionChange = async (user: User, index: number) => {
|
||||
const permissions: ModalInputProperties['choices'] = [
|
||||
const permissions: ModalInputProps['choices'] = [
|
||||
{text: t('admin.banned'), value: '-1'},
|
||||
{text: t('admin.normal'), value: '0'},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly active?: boolean;
|
||||
readonly bg?: string;
|
||||
};
|
||||
|
|
@ -9,21 +9,21 @@ type Attributes = React.DetailedHTMLProps<
|
|||
HTMLButtonElement
|
||||
>;
|
||||
|
||||
const Button: React.FC<Properties & Attributes> = properties => {
|
||||
const classes = [properties.className ?? ''];
|
||||
if (properties.bg) {
|
||||
classes.push('btn', `bg-${properties.bg}`);
|
||||
const Button: React.FC<Props & Attributes> = props => {
|
||||
const classes = [props.className ?? ''];
|
||||
if (props.bg) {
|
||||
classes.push('btn', `bg-${props.bg}`);
|
||||
}
|
||||
|
||||
if (properties.active) {
|
||||
if (props.active) {
|
||||
classes.push('active');
|
||||
}
|
||||
|
||||
const rest = {...properties, active: undefined, bg: undefined};
|
||||
const rest = {...props, active: undefined, bg: undefined};
|
||||
|
||||
return (
|
||||
<button {...rest} className={classes.join(' ')}>
|
||||
{properties.children}
|
||||
{props.children}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ import {TextureType} from '@/scripts/types';
|
|||
import Button from './Button';
|
||||
import {humanizeType} from './utils';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly filter: Filter;
|
||||
onChange: (filter: Filter) => void;
|
||||
};
|
||||
|
||||
const FilterSelector: React.FC<Properties> = properties => {
|
||||
const {filter, onChange} = properties;
|
||||
const FilterSelector: React.FC<Props> = props => {
|
||||
const {filter, onChange} = props;
|
||||
|
||||
const handleSkinClick = () => {
|
||||
onChange('skin');
|
||||
|
|
|
|||
|
|
@ -35,21 +35,21 @@ const NickNameBadge = styled(Badge)`
|
|||
max-width: 100px;
|
||||
`;
|
||||
|
||||
type ButtonLikeProperties = {
|
||||
type ButtonLikeProps = {
|
||||
liked: boolean;
|
||||
};
|
||||
const ButtonLike = styled.a<ButtonLikeProperties>`
|
||||
const ButtonLike = styled.a<ButtonLikeProps>`
|
||||
${cssUtils.pointerCursor}
|
||||
|
||||
i, span {
|
||||
color: ${properties => properties.liked ? '#dc3545' : '#6c757d'};
|
||||
color: ${props => props.liked ? '#dc3545' : '#6c757d'};
|
||||
&:hover {
|
||||
color: ${properties => properties.liked ? '#dc3545' : '#343a40'};
|
||||
color: ${props => props.liked ? '#dc3545' : '#343a40'};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly item: LibraryItem;
|
||||
readonly liked: boolean;
|
||||
onAdd: (texture: LibraryItem) => Promise<void>;
|
||||
|
|
@ -57,8 +57,8 @@ type Properties = {
|
|||
onUploaderClick: (uploader: number) => void;
|
||||
};
|
||||
|
||||
const Item: React.FC<Properties> = properties => {
|
||||
const {item} = properties;
|
||||
const Item: React.FC<Props> = props => {
|
||||
const {item} = props;
|
||||
|
||||
const link = `${blessing.base_url}/skinlib/show/${item.tid}`;
|
||||
const preview = `${blessing.base_url}/preview/${item.tid}?height=150`;
|
||||
|
|
@ -66,12 +66,12 @@ const Item: React.FC<Properties> = properties => {
|
|||
|
||||
const handleUploaderClick = (event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
properties.onUploaderClick(item.uploader);
|
||||
props.onUploaderClick(item.uploader);
|
||||
};
|
||||
|
||||
const handleHeartClick = (event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
properties.liked ? properties.onRemove(item) : properties.onAdd(item);
|
||||
props.liked ? props.onRemove(item) : props.onAdd(item);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -111,7 +111,7 @@ const Item: React.FC<Properties> = properties => {
|
|||
</NickNameBadge>
|
||||
</div>
|
||||
<ButtonLike
|
||||
liked={properties.liked}
|
||||
liked={props.liked}
|
||||
tabIndex={-1}
|
||||
onClick={handleHeartClick}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import {t} from '@/scripts/i18n';
|
|||
import setAsAvatar from './setAsAvatar';
|
||||
import {Card, DropdownButton} from './styles';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly item: ClosetItemType;
|
||||
readonly selected: boolean;
|
||||
onClick: (item: ClosetItemType) => void;
|
||||
|
|
@ -12,19 +12,19 @@ type Properties = {
|
|||
onRemove: () => void;
|
||||
};
|
||||
|
||||
const ClosetItem: React.FC<Properties> = properties => {
|
||||
const {item} = properties;
|
||||
const ClosetItem: React.FC<Props> = props => {
|
||||
const {item} = props;
|
||||
const preview = `${blessing.base_url}/preview/${item.tid}?height=150`;
|
||||
const previewPNG = `${preview}&png`;
|
||||
|
||||
const handleItemClick = () => {
|
||||
properties.onClick(item);
|
||||
props.onClick(item);
|
||||
};
|
||||
|
||||
const handleSetAsAvatar = async () => setAsAvatar(item.tid);
|
||||
|
||||
return (
|
||||
<Card className={`card mr-3 mb-3 ${properties.selected ? 'shadow' : ''}`}>
|
||||
<Card className={`card mr-3 mb-3 ${props.selected ? 'shadow' : ''}`}>
|
||||
<div className='card-body' onClick={handleItemClick}>
|
||||
<picture>
|
||||
<source srcSet={preview} type='image/webp'/>
|
||||
|
|
@ -49,10 +49,10 @@ const ClosetItem: React.FC<Properties> = properties => {
|
|||
<i className='fas fa-cog'/>
|
||||
</DropdownButton>
|
||||
<div className='dropdown-menu'>
|
||||
<a href='#' className='dropdown-item' onClick={properties.onRename}>
|
||||
<a href='#' className='dropdown-item' onClick={props.onRename}>
|
||||
{t('user.renameItem')}
|
||||
</a>
|
||||
<a href='#' className='dropdown-item' onClick={properties.onRemove}>
|
||||
<a href='#' className='dropdown-item' onClick={props.onRemove}>
|
||||
{t('user.removeItem')}
|
||||
</a>
|
||||
<a
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import {useEffect, useState} from 'react';
|
|||
|
||||
const baseUrl = blessing.base_url;
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly show: boolean;
|
||||
readonly canAdd: boolean;
|
||||
readonly skin?: number;
|
||||
|
|
@ -18,13 +18,13 @@ type Properties = {
|
|||
onClose: () => void;
|
||||
};
|
||||
|
||||
const ModalApply: React.FC<Properties> = properties => {
|
||||
const ModalApply: React.FC<Props> = props => {
|
||||
const [players, setPlayers] = useState<Player[]>([]);
|
||||
const [search, setSearch] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!properties.show) {
|
||||
if (!props.show) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ const ModalApply: React.FC<Properties> = properties => {
|
|||
};
|
||||
|
||||
getPlayers();
|
||||
}, [properties.show]);
|
||||
}, [props.show]);
|
||||
|
||||
const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSearch(event.target.value);
|
||||
|
|
@ -46,8 +46,8 @@ const ModalApply: React.FC<Properties> = properties => {
|
|||
const {code, message} = await fetch.put<fetch.ResponseBody>(
|
||||
urls.user.player.set(player.pid),
|
||||
{
|
||||
skin: properties.skin,
|
||||
cape: properties.cape,
|
||||
skin: props.skin,
|
||||
cape: props.cape,
|
||||
},
|
||||
);
|
||||
if (code === 0) {
|
||||
|
|
@ -61,11 +61,11 @@ const ModalApply: React.FC<Properties> = properties => {
|
|||
return (
|
||||
<Modal
|
||||
flexFooter
|
||||
show={properties.show}
|
||||
show={props.show}
|
||||
id='modal-apply'
|
||||
title={t('user.closet.use-as.title')}
|
||||
footer={<></>}
|
||||
onClose={properties.onClose}
|
||||
onClose={props.onClose}
|
||||
>
|
||||
{isLoading
|
||||
? <Loading/>
|
||||
|
|
|
|||
|
|
@ -5,25 +5,25 @@ import ReactDOM from 'react-dom';
|
|||
|
||||
const Viewer = React.lazy(async () => import('@/components/Viewer'));
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
skin?: string;
|
||||
cape?: string;
|
||||
children: React.ReactNode;
|
||||
isAlex: boolean;
|
||||
};
|
||||
|
||||
const Previewer: React.FC<Properties> = properties => {
|
||||
const Previewer: React.FC<Props> = props => {
|
||||
const container = useMount('#previewer');
|
||||
|
||||
const skin = properties.skin ? `${blessing.base_url}/textures/${properties.skin}` : '';
|
||||
const cape = properties.cape ? `${blessing.base_url}/textures/${properties.cape}` : '';
|
||||
const skin = props.skin ? `${blessing.base_url}/textures/${props.skin}` : '';
|
||||
const cape = props.cape ? `${blessing.base_url}/textures/${props.cape}` : '';
|
||||
|
||||
return (
|
||||
container
|
||||
&& ReactDOM.createPortal(
|
||||
<React.Suspense fallback={<ViewerSkeleton/>}>
|
||||
<Viewer showIndicator skin={skin} cape={cape} isAlex={properties.isAlex}>
|
||||
{properties.children}
|
||||
<Viewer showIndicator skin={skin} cape={cape} isAlex={props.isAlex}>
|
||||
{props.children}
|
||||
</Viewer>
|
||||
</React.Suspense>,
|
||||
container,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly name: string;
|
||||
readonly icon: string;
|
||||
readonly color: string;
|
||||
|
|
@ -9,24 +9,24 @@ type Properties = {
|
|||
readonly unit: string;
|
||||
};
|
||||
|
||||
const InfoBox: React.FC<Properties> = properties => {
|
||||
const total = Math.trunc(properties.used + properties.unused);
|
||||
const percentage = (properties.used / total) * 100;
|
||||
const InfoBox: React.FC<Props> = props => {
|
||||
const total = Math.trunc(props.used + props.unused);
|
||||
const percentage = (props.used / total) * 100;
|
||||
|
||||
return (
|
||||
<div className={`info-box bg-${properties.color}`}>
|
||||
<div className={`info-box bg-${props.color}`}>
|
||||
<span className='info-box-icon'>
|
||||
<i className={`fas fa-${properties.icon}`}/>
|
||||
<i className={`fas fa-${props.icon}`}/>
|
||||
</span>
|
||||
<div className='info-box-content'>
|
||||
<span className='info-box-text'>{properties.name}</span>
|
||||
<span className='info-box-text'>{props.name}</span>
|
||||
<span className='info-box-number'>
|
||||
<b>{properties.used}</b>
|
||||
<b>{props.used}</b>
|
||||
{' '}
|
||||
/
|
||||
{total}
|
||||
{' '}
|
||||
{properties.unit}
|
||||
{props.unit}
|
||||
</span>
|
||||
<div className='progress'>
|
||||
<div className='progress-bar' style={{width: `${percentage}%`}}/>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import {t} from '@/scripts/i18n';
|
|||
import React from 'react';
|
||||
import * as scoreUtils from './scoreUtils';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly isLoading: boolean;
|
||||
readonly lastSign: Date;
|
||||
readonly canSignAfterZero: boolean;
|
||||
|
|
@ -10,8 +10,8 @@ type Properties = {
|
|||
readonly onClick: React.MouseEventHandler<HTMLButtonElement>;
|
||||
};
|
||||
|
||||
const SignButton: React.FC<Properties> = properties => {
|
||||
const {lastSign, signGap, canSignAfterZero} = properties;
|
||||
const SignButton: React.FC<Props> = props => {
|
||||
const {lastSign, signGap, canSignAfterZero} = props;
|
||||
const remainingTime = scoreUtils.remainingTime(
|
||||
lastSign,
|
||||
signGap,
|
||||
|
|
@ -24,8 +24,8 @@ const SignButton: React.FC<Properties> = properties => {
|
|||
<button
|
||||
className='btn bg-gradient-primary pl-4 pr-4'
|
||||
role='button'
|
||||
disabled={!canSign || properties.isLoading}
|
||||
onClick={properties.onClick}
|
||||
disabled={!canSign || props.isLoading}
|
||||
onClick={props.onClick}
|
||||
>
|
||||
<i className='far fa-calendar-check' aria-hidden='true'/>
|
||||
{' '}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ import Modal from '@/components/Modal';
|
|||
import {t} from '@/scripts/i18n';
|
||||
import {useState} from 'react';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly show: boolean;
|
||||
onCreate: (name: string, redirect: string) => Promise<void>;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const ModalCreate: React.FC<Properties> = properties => {
|
||||
const ModalCreate: React.FC<Props> = props => {
|
||||
const [name, setName] = useState('');
|
||||
const [url, setUrl] = useState('');
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ const ModalCreate: React.FC<Properties> = properties => {
|
|||
};
|
||||
|
||||
const handleComplete = () => {
|
||||
properties.onCreate(name, url);
|
||||
props.onCreate(name, url);
|
||||
};
|
||||
|
||||
const handleDismiss = () => {
|
||||
|
|
@ -31,10 +31,10 @@ const ModalCreate: React.FC<Properties> = properties => {
|
|||
|
||||
return (
|
||||
<Modal
|
||||
show={properties.show}
|
||||
show={props.show}
|
||||
onConfirm={handleComplete}
|
||||
onDismiss={handleDismiss}
|
||||
onClose={properties.onClose}
|
||||
onClose={props.onClose}
|
||||
>
|
||||
<div className='form-group'>
|
||||
<label htmlFor='new-app-name'>{t('user.oauth.name')}</label>
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@ import type {App} from './types';
|
|||
import ButtonEdit from '@/components/ButtonEdit';
|
||||
import {t} from '@/scripts/i18n';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly app: App;
|
||||
readonly onEditName: React.MouseEventHandler<HTMLAnchorElement>;
|
||||
readonly onEditRedirect: React.MouseEventHandler<HTMLAnchorElement>;
|
||||
readonly onDelete: React.MouseEventHandler<HTMLButtonElement>;
|
||||
};
|
||||
|
||||
const Row: React.FC<Properties> = properties => {
|
||||
const {app} = properties;
|
||||
const Row: React.FC<Props> = props => {
|
||||
const {app} = props;
|
||||
|
||||
return (
|
||||
<tr>
|
||||
|
|
@ -20,7 +20,7 @@ const Row: React.FC<Properties> = properties => {
|
|||
<span>{app.name}</span>
|
||||
<ButtonEdit
|
||||
title={t('user.oauth.modifyName')}
|
||||
onClick={properties.onEditName}
|
||||
onClick={props.onEditName}
|
||||
/>
|
||||
</td>
|
||||
<td>{app.secret}</td>
|
||||
|
|
@ -28,11 +28,11 @@ const Row: React.FC<Properties> = properties => {
|
|||
<span>{app.redirect}</span>
|
||||
<ButtonEdit
|
||||
title={t('user.oauth.modifyUrl')}
|
||||
onClick={properties.onEditRedirect}
|
||||
onClick={props.onEditRedirect}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<button className='btn btn-danger' onClick={properties.onDelete}>
|
||||
<button className='btn btn-danger' onClick={props.onDelete}>
|
||||
{t('report.delete')}
|
||||
</button>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -13,13 +13,13 @@ type Extra = {
|
|||
length: string;
|
||||
};
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly show: boolean;
|
||||
onAdd: (player: Player) => void;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const ModalAddPlayer: React.FC<Properties> = properties => {
|
||||
const ModalAddPlayer: React.FC<Props> = props => {
|
||||
const [name, setName] = useState('');
|
||||
|
||||
const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
|
|
@ -36,7 +36,7 @@ const ModalAddPlayer: React.FC<Properties> = properties => {
|
|||
});
|
||||
if (code === 0) {
|
||||
toast.success(message);
|
||||
properties.onAdd(player);
|
||||
props.onAdd(player);
|
||||
} else {
|
||||
toast.error(message);
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ const ModalAddPlayer: React.FC<Properties> = properties => {
|
|||
|
||||
const handleClose = () => {
|
||||
setName('');
|
||||
properties.onClose();
|
||||
props.onClose();
|
||||
};
|
||||
|
||||
const {score, cost, rule, length} = blessing.extra as Extra;
|
||||
|
|
@ -52,7 +52,7 @@ const ModalAddPlayer: React.FC<Properties> = properties => {
|
|||
|
||||
return (
|
||||
<Modal
|
||||
show={properties.show}
|
||||
show={props.show}
|
||||
title={t('user.player.add-player')}
|
||||
onConfirm={handleConfirm}
|
||||
onClose={handleClose}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ import Modal from '@/components/Modal';
|
|||
import {t} from '@/scripts/i18n';
|
||||
import {useState} from 'react';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly show: boolean;
|
||||
onSubmit: (skin: boolean, cape: boolean) => Promise<void>;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const ModalReset: React.FC<Properties> = properties => {
|
||||
const ModalReset: React.FC<Props> = props => {
|
||||
const [skin, setSkin] = useState(false);
|
||||
const [cape, setCape] = useState(false);
|
||||
|
||||
|
|
@ -21,18 +21,18 @@ const ModalReset: React.FC<Properties> = properties => {
|
|||
};
|
||||
|
||||
const handleConfirm = () => {
|
||||
properties.onSubmit(skin, cape);
|
||||
props.onSubmit(skin, cape);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setSkin(false);
|
||||
setCape(false);
|
||||
properties.onClose();
|
||||
props.onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
show={properties.show}
|
||||
show={props.show}
|
||||
title={t('user.chooseClearTexture')}
|
||||
onConfirm={handleConfirm}
|
||||
onClose={handleClose}
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@ import Viewer2d from './Viewer2d';
|
|||
|
||||
const Viewer3d = React.lazy(async () => import('@/components/Viewer'));
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
skin: string;
|
||||
cape: string;
|
||||
isAlex: boolean;
|
||||
};
|
||||
|
||||
const Previewer: React.FC<Properties> = properties => {
|
||||
const Previewer: React.FC<Props> = props => {
|
||||
const [is3d, setIs3d] = useState(true);
|
||||
|
||||
const container = useMount('#previewer');
|
||||
|
|
@ -28,7 +28,7 @@ const Previewer: React.FC<Properties> = properties => {
|
|||
</button>
|
||||
);
|
||||
|
||||
const {skin, cape, isAlex} = properties;
|
||||
const {skin, cape, isAlex} = props;
|
||||
|
||||
return (
|
||||
container
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import {t} from '@/scripts/i18n';
|
|||
import * as cssUtils from '@/styles/utils';
|
||||
import {css} from '@emotion/react';
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
player: Player;
|
||||
selected: boolean;
|
||||
onClick: React.MouseEventHandler;
|
||||
|
|
@ -13,19 +13,19 @@ type Properties = {
|
|||
onDelete: (player: Player) => Promise<void>;
|
||||
};
|
||||
|
||||
const Row: React.FC<Properties> = properties => {
|
||||
const {player} = properties;
|
||||
const Row: React.FC<Props> = props => {
|
||||
const {player} = props;
|
||||
|
||||
const handleEdit = () => {
|
||||
properties.onEditName(player);
|
||||
props.onEditName(player);
|
||||
};
|
||||
|
||||
const handleDelete = () => {
|
||||
properties.onDelete(player);
|
||||
props.onDelete(player);
|
||||
};
|
||||
|
||||
const selected
|
||||
= properties.selected
|
||||
= props.selected
|
||||
&& css`
|
||||
background: #efefef;
|
||||
.dark-mode & {
|
||||
|
|
@ -34,14 +34,14 @@ const Row: React.FC<Properties> = properties => {
|
|||
`;
|
||||
|
||||
return (
|
||||
<tr css={[cssUtils.pointerCursor, selected]} onClick={properties.onClick}>
|
||||
<tr css={[cssUtils.pointerCursor, selected]} onClick={props.onClick}>
|
||||
<td>{player.pid}</td>
|
||||
<td>
|
||||
<span>{player.name}</span>
|
||||
<ButtonEdit title={t('user.player.edit-pname')} onClick={handleEdit}/>
|
||||
</td>
|
||||
<td className='d-flex'>
|
||||
<button className='btn btn-warning' onClick={properties.onReset}>
|
||||
<button className='btn btn-warning' onClick={props.onReset}>
|
||||
{t('user.player.delete-texture')}
|
||||
</button>
|
||||
<button className='btn btn-danger ml-2' onClick={handleDelete}>
|
||||
|
|
|
|||
|
|
@ -13,13 +13,13 @@ const TexturePreview = styled.div`
|
|||
}
|
||||
`;
|
||||
|
||||
type Properties = {
|
||||
type Props = {
|
||||
readonly skin: string;
|
||||
readonly cape: string;
|
||||
readonly children: React.ReactNode;
|
||||
};
|
||||
|
||||
const Viewer2d: React.FC<Properties> = properties => (
|
||||
const Viewer2d: React.FC<Props> = props => (
|
||||
<div className='card'>
|
||||
<div className='card-header'>
|
||||
<h3 className='card-title'>{t('general.texturePreview')}</h3>
|
||||
|
|
@ -27,18 +27,18 @@ const Viewer2d: React.FC<Properties> = properties => (
|
|||
<div className='card-body'>
|
||||
<TexturePreview className='mb-5'>
|
||||
<span>{t('general.skin')}</span>
|
||||
{properties.skin
|
||||
? <img src={properties.skin} alt={t('general.skin')}/>
|
||||
{props.skin
|
||||
? <img src={props.skin} alt={t('general.skin')}/>
|
||||
: <span>{t('user.player.texture-empty')}</span>}
|
||||
</TexturePreview>
|
||||
<TexturePreview className='mt-5'>
|
||||
<span>{t('general.cape')}</span>
|
||||
{properties.cape
|
||||
? <img src={properties.cape} alt={t('general.cape')}/>
|
||||
{props.cape
|
||||
? <img src={props.cape} alt={t('general.cape')}/>
|
||||
: <span>{t('user.player.texture-empty')}</span>}
|
||||
</TexturePreview>
|
||||
</div>
|
||||
<div className='card-footer'>{properties.children}</div>
|
||||
<div className='card-footer'>{props.children}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,11 @@ import {expect} from 'vitest';
|
|||
it('click to select file', () => {
|
||||
const {getAllByText} = render(
|
||||
<FileInput
|
||||
file={null}
|
||||
onChange={() => {
|
||||
file={null}
|
||||
onChange={() => {
|
||||
/* */
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>,);
|
||||
|
||||
fireEvent.click(getAllByText(t('skinlib.upload.select-file'))[1]);
|
||||
});
|
||||
|
|
@ -20,12 +19,11 @@ it('display file name', () => {
|
|||
const file = new File([], 'f.txt');
|
||||
const {queryByText} = render(
|
||||
<FileInput
|
||||
file={file}
|
||||
onChange={() => {
|
||||
file={file}
|
||||
onChange={() => {
|
||||
/* */
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>,);
|
||||
expect(queryByText('f.txt')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -85,12 +85,11 @@ describe('modal body', () => {
|
|||
it('input control type', () => {
|
||||
const {getByPlaceholderText} = render(
|
||||
<Modal
|
||||
show
|
||||
mode='prompt'
|
||||
placeholder='password'
|
||||
inputType='password'
|
||||
/>
|
||||
);
|
||||
show
|
||||
mode='prompt'
|
||||
placeholder='password'
|
||||
inputType='password'
|
||||
/>,);
|
||||
expect(getByPlaceholderText('password')).toHaveAttribute(
|
||||
'type',
|
||||
'password',
|
||||
|
|
@ -169,13 +168,12 @@ describe('"prompt" mode', () => {
|
|||
const reject = vi.fn();
|
||||
const {getByPlaceholderText, getByText} = render(
|
||||
<Modal
|
||||
show
|
||||
mode='prompt'
|
||||
placeholder='hint'
|
||||
onConfirm={resolve}
|
||||
onDismiss={reject}
|
||||
/>
|
||||
);
|
||||
show
|
||||
mode='prompt'
|
||||
placeholder='hint'
|
||||
onConfirm={resolve}
|
||||
onDismiss={reject}
|
||||
/>,);
|
||||
fireEvent.change(getByPlaceholderText('hint'), {
|
||||
target: {value: 'my'},
|
||||
});
|
||||
|
|
@ -201,13 +199,12 @@ describe('"prompt" mode', () => {
|
|||
const resolve = vi.fn();
|
||||
const {getByText, getByLabelText} = render(
|
||||
<Modal
|
||||
show
|
||||
mode='prompt'
|
||||
inputType='radios'
|
||||
choices={choices}
|
||||
onConfirm={resolve}
|
||||
/>
|
||||
);
|
||||
show
|
||||
mode='prompt'
|
||||
inputType='radios'
|
||||
choices={choices}
|
||||
onConfirm={resolve}
|
||||
/>,);
|
||||
fireEvent.click(getByLabelText('B'));
|
||||
fireEvent.click(getByText(t('general.confirm')));
|
||||
expect(resolve).toBeCalledWith({value: 'b'});
|
||||
|
|
@ -219,14 +216,13 @@ describe('"prompt" mode', () => {
|
|||
const validator = vi.fn().mockReturnValue(true);
|
||||
const {getByText} = render(
|
||||
<Modal
|
||||
show
|
||||
mode='prompt'
|
||||
input='val'
|
||||
validator={validator}
|
||||
onConfirm={resolve}
|
||||
onDismiss={reject}
|
||||
/>
|
||||
);
|
||||
show
|
||||
mode='prompt'
|
||||
input='val'
|
||||
validator={validator}
|
||||
onConfirm={resolve}
|
||||
onDismiss={reject}
|
||||
/>,);
|
||||
fireEvent.click(getByText(t('general.confirm')));
|
||||
expect(resolve).toBeCalledWith({value: 'val'});
|
||||
expect(reject).not.toBeCalled();
|
||||
|
|
@ -239,14 +235,13 @@ describe('"prompt" mode', () => {
|
|||
const validator = vi.fn().mockReturnValue(message);
|
||||
const {getByText, queryByText} = render(
|
||||
<Modal
|
||||
show
|
||||
mode='prompt'
|
||||
input='val'
|
||||
validator={validator}
|
||||
onConfirm={resolve}
|
||||
onDismiss={reject}
|
||||
/>
|
||||
);
|
||||
show
|
||||
mode='prompt'
|
||||
input='val'
|
||||
validator={validator}
|
||||
onConfirm={resolve}
|
||||
onDismiss={reject}
|
||||
/>,);
|
||||
expect(queryByText(message)).not.toBeInTheDocument();
|
||||
|
||||
fireEvent.click(getByText(t('general.confirm')));
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<div class="card card-primary">
|
||||
<div class="card card-primary mb-4">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">{{ trans('admin.index.overview') }}</h3>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,27 +1,27 @@
|
|||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="small-box bg-info">
|
||||
<div class="small-box text-bg-info">
|
||||
<div class="inner">
|
||||
<h3 class="stats">{{ sum.users }}</h3>
|
||||
<p>{{ trans('admin.index.total-users') }}</p>
|
||||
</div>
|
||||
<div class="icon"><i class="fas fa-users"></i></div>
|
||||
<a href="{{ url('admin/users') }}" class="small-box-footer">
|
||||
{{ trans('general.user-manage') }}
|
||||
<div class="small-box-icon"><i class="fas fa-users"></i></div>
|
||||
<a href="{{ url('admin/users') }}" class="small-box-footer link-light link-underline-opacity-0 link-underline-opacity-50-hover">
|
||||
{{ trans('general.user-manage') }}
|
||||
<i class="fa fa-arrow-circle-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="small-box bg-green">
|
||||
<div class="small-box text-bg-success">
|
||||
<div class="inner">
|
||||
<h3 class="stats">{{ sum.players }}</h3>
|
||||
<p>{{ trans('admin.index.total-players') }}</p>
|
||||
</div>
|
||||
<div class="icon"><i class="fas fa-gamepad"></i></div>
|
||||
<a href="{{ url('admin/players') }}" class="small-box-footer">
|
||||
{{ trans('general.player-manage') }}
|
||||
<div class="small-box-icon"><i class="fas fa-gamepad"></i></div>
|
||||
<a href="{{ url('admin/players') }}" class="small-box-footer link-light link-underline-opacity-0 link-underline-opacity-50-hover">
|
||||
{{ trans('general.player-manage') }}
|
||||
<i class="fa fa-arrow-circle-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -30,17 +30,17 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="small-box bg-purple">
|
||||
<div class="small-box text-bg-warning">
|
||||
<div class="inner">
|
||||
<h3 class="stats">{{ sum.textures }}</h3>
|
||||
<p>{{ trans('admin.index.total-textures') }}</p>
|
||||
</div>
|
||||
<div class="icon"><i class="fas fa-file"></i></div>
|
||||
<div class="small-box-icon"><i class="fas fa-file"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="small-box bg-yellow">
|
||||
<div class="small-box text-bg-danger">
|
||||
<div class="inner">
|
||||
{% if sum.storage > 1024 %}
|
||||
<h3 class="stats">{{ (sum.storage / 1024)|round(1) }}MB</h3>
|
||||
|
|
@ -49,7 +49,7 @@
|
|||
{% endif %}
|
||||
<p>{{ trans('admin.index.disk-usage') }}</p>
|
||||
</div>
|
||||
<div class="icon"><i class="fas fa-hdd"></i></div>
|
||||
<div class="small-box-icon"><i class="fas fa-hdd"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<a class="nav-link {{ item.active ? 'active' }}" href="#">
|
||||
<i class="nav-icon fas {{ item.icon }}"></i>
|
||||
<p class="ml-1">{{ trans(item.title) }}</p>
|
||||
<i class="right fas fa-angle-left"></i>
|
||||
<i class="nav-arrow right fas fa-angle-right"></i>
|
||||
</a>
|
||||
<ul class="nav nav-treeview">
|
||||
{% for child in item.children %}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<aside class="app-sidebar bg-body shadow elevation-3 layout-fixed" data-bs-theme="{{ color_mode }}">
|
||||
<aside class="app-sidebar bg-body shadow elevation-3 sidebar-expand-lg" data-bs-theme="{{ color_mode }}">
|
||||
<a href="{{ url('/') }}" class="brand-link text-center">
|
||||
<span class="sidebar-brand brand-text font-weight-light">{{ site_name }}</span>
|
||||
</a>
|
||||
|
|
@ -7,8 +7,9 @@
|
|||
<nav class="mt-2">
|
||||
<ul
|
||||
class="nav nav-pills nav-sidebar flex-column nav-child-indent sidebar-menu"
|
||||
data-widget="treeview"
|
||||
data-lte-toggle="treeview"
|
||||
role="menu"
|
||||
data-accordion="false"
|
||||
>
|
||||
|
||||
{% if scope == 'user' %}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<body class="{{ dark_mode ? 'dark-mode' : '' }} hold-transition layout-top-nav">
|
||||
<div class="wrapper">
|
||||
<nav class="main-header navbar navbar-expand navbar-{{ navbar_color }} navbar-{{ color_mode }} ml-0">
|
||||
<nav class="app-header navbar navbar-expand bg-primary-subtle ml-0" data-bs-theme="{{ color_mode }}">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="{{ url('/') }}" class="navbar-brand">{{ site_name }}</a>
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@
|
|||
<title>{% block title %}{% endblock %} - {{ site_name }}</title>
|
||||
</head>
|
||||
|
||||
<body class="{{ dark_mode ? 'dark-mode' : '' }} hold-transition">
|
||||
<body class="{{ dark_mode ? 'dark-mode' : '' }} hold-transition layout-fixed">
|
||||
<div class="app-wrapper">
|
||||
{{ include('shared.header') }}
|
||||
{{ include('shared.sidebar', {scope: 'user'}) }}
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header">
|
||||
<main class="app-main">
|
||||
<div class="app-content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="d-flex justify-content-between flex-wrap">
|
||||
<div>
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="app-footer">
|
||||
{{ include('shared.copyright') }}
|
||||
</footer>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<div class="card card-primary">
|
||||
<div class="card card-primary mb-4">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
{{ trans('user.profile.avatar.title') }}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<div class="card card-danger">
|
||||
<div class="card card-danger mb-4">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
{{ trans('user.profile.delete.title') }}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<form class="card card-warning" method="post" id="change-email">
|
||||
<form class="card card-warning mb-4" method="post" id="change-email">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
{{ trans('user.profile.email.title') }}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<div class="form-group mb-3">
|
||||
<input type="email" class="form-control" name="email" required
|
||||
value="{{ user.email }}"
|
||||
placeholder="{{ trans('user.profile.email.new') }}">
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<form class="card card-primary" method="post" id="change-nickname">
|
||||
<form class="card card-primary mb-4" method="post" id="change-nickname">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
{{ trans('user.profile.nickname.title') }}
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@
|
|||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<div class="form-group mb-3">
|
||||
<label>{{ trans('user.profile.password.old') }}</label>
|
||||
<input type="password" class="form-control" name="oldPassword"
|
||||
required autocomplete="current-password">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-group mb-3">
|
||||
<label>{{ trans('user.profile.password.new') }}</label>
|
||||
<input type="password" class="form-control" name="newPassword" required
|
||||
minlength="8" maxlength="32" autocomplete="new-password">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"extends": "@tsconfig/vite-react",
|
||||
"compilerOptions": {
|
||||
"jsxImportSource": "@emotion/react",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
|
|
@ -9,8 +10,7 @@
|
|||
},
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"skipLibCheck": false,
|
||||
"jsxImportSource": "@emotion/react"
|
||||
"skipLibCheck": false
|
||||
},
|
||||
"include": [
|
||||
"resources/assets/src",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import type {GetModuleInfo} from 'rollup';
|
||||
import {execSync} from 'node:child_process';
|
||||
import {env} from 'node:process';
|
||||
import react from '@vitejs/plugin-react-swc';
|
||||
import browserslistToEsbuild from 'browserslist-to-esbuild';
|
||||
import laravel from 'laravel-vite-plugin';
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user