ui: bug fix

This commit is contained in:
undefined committed 2023-03-19 04:29:55 +08:00
1 parent b681c1e840
commit 53e697dfb4
7 files changed
+33 -49

No files matched your search

@@ -34,7 +34,6 @@ export interface AutoCompleteProps<Item> {
allowEmptyQuery?: boolean;
freeSolo?: boolean;
freeSoloConverter?: (value: string) => string;
alwaysShowList?: boolean;
}
export interface AutoCompleteHandle<Item> {
@@ -83,22 +82,17 @@ function DraggableSelection({
// eslint-disable-next-line prefer-arrow-callback
const AutoComplete = forwardRef(function Impl<T>(props: AutoCompleteProps<T>, ref: React.Ref<AutoCompleteHandle<T>>) {
const width = props.width ?? '100%';
const height = props.height ?? 'auto';
const disabled = props.disabled ?? false;
const disabledHint = props.disabledHint ?? '';
const listStyle = props.listStyle ?? {};
const {
multi = false, width = '100%', height = 'auto',
freeSolo = false, allowEmptyQuery = false, listStyle = {},
disabled = false, disabledHint = '', draggable = multi,
} = props;
const queryItems = props.queryItems ?? (() => []);
const renderItem = props.renderItem ?? ((item) => item);
const itemText = props.itemText ?? ((item) => item.toString());
const itemKey = props.itemKey ?? itemText;
const onChange = props.onChange ?? (() => { });
const multi = props.multi ?? false;
const draggable = props.draggable ?? props.multi;
const allowEmptyQuery = props.allowEmptyQuery ?? false;
const freeSolo = props.freeSolo ?? false;
const freeSoloConverter = freeSolo ? props.freeSoloConverter ?? ((i) => i) : ((i) => i);
const alwaysShowList = props.alwaysShowList ?? false;
const [focused, setFocused] = useState(false); // is focused
const [selected, setSelected] = useState([]); // selected items
@@ -142,6 +136,7 @@ const AutoComplete = forwardRef(function Impl<T>(props: AutoCompleteProps<T>, re
useEffect(() => {
if (first) first = false;
else dispatchChange();
if (!multi) return; // Load pre-selected items only in multi mode
const ids = [];
for (const key of selectedKeys) if (!valueCache[key]) ids.push(key);
if (!ids.length) return;
@@ -154,7 +149,7 @@ const AutoComplete = forwardRef(function Impl<T>(props: AutoCompleteProps<T>, re
const handleInputChange = debounce((e?) => queryList(e ? e.target.value : ''), 300);
const toggleItem = (item: T, key = itemKey(item), preserve = false) => {
const shouldKeepOpen = (multi ? alwaysShowList : allowEmptyQuery) && inputRef.current.value === '';
const shouldKeepOpen = multi && allowEmptyQuery && inputRef.current.value === '';
if (multi) {
const idx = selectedKeys.indexOf(key);
if (idx !== -1) {
@@ -46,7 +46,6 @@ CustomSelectAutoComplete.defaultProps = {
selectedKeys: [],
freeSolo: false,
freeSoloConverter: (input) => input,
alwaysShowList: true,
};
export default CustomSelectAutoComplete;
@@ -46,7 +46,6 @@ FileSelectAutoComplete.defaultProps = {
selectedKeys: [],
freeSolo: false,
freeSoloConverter: (input) => input,
alwaysShowList: true,
};
export default FileSelectAutoComplete;
@@ -23,7 +23,7 @@ function FileIOConfig() {
rightElement={<Tag minimal>.in/.out</Tag>}
value={filename || ''}
onChange={(ev) => {
dispatch({ type: 'CONFIG_FORM_UPDATE', key: 'filename', value: ev.currentTarget.value });
dispatch({ type: 'problemconfig/updateFileIO', filename: ev.currentTarget.value });
}}
fill
/>
@@ -135,7 +135,7 @@ export function SubtaskConfigTree() {
{ids.map((id) => <SubtaskNode key={id} subtaskId={id} />)}
<li
className="bp4-tree-node"
onClick={() => dispatch({ type: 'CONFIG_SUBTASK_UPDATE', id: 0, key: 'add' })}
onClick={() => dispatch({ type: 'problemconfig/addSubtask' })}
>
<div className="bp4-tree-node-content bp4-tree-node-content-0">
<Icon icon="folder-new" />&nbsp;
@@ -15,15 +15,19 @@ const ajv = new Ajv();
const validate = ajv.compile(schema);
export default function reducer(state = {
type: 'default', __loaded: false, __valid: true, __errors: [], __cases: [], subtasks: [],
type: 'default', __loaded: false, __valid: false, __errors: [], __cases: [], subtasks: [],
} as State, action: any = {}): State {
switch (action.type) {
case 'CONFIG_LOAD_FULFILLED': {
const c = { ...state, __loaded: true };
try {
let data = yaml.load(action.payload.config) as any;
if (typeof data !== 'object') data = { subtasks: [] };
else data.subtasks ||= [];
if (!validate(data)) {
return { ...state, __valid: false, __errors: validate.errors.map((i) => `${i.instancePath}: ${i.message}`) };
Object.assign(c, data);
c.__errors = validate.errors.map((i) => `${i.instancePath}: ${i.message}`);
return c;
}
const subtasks = (data as any).subtasks;
for (const subtask of subtasks) {
@@ -36,12 +40,12 @@ export default function reducer(state = {
}
}
}
return {
...state, ...data as any, __valid: true, __errors: [], __loaded: true,
};
Object.assign(c, data);
c.__valid = true;
} catch (e) {
return { ...state, __valid: false, __errors: [e.message] };
c.__errors.push(e.message);
}
return c;
}
case 'CONFIG_FORM_UPDATE': {
const next = { ...state, [action.key]: action.value };
@@ -94,32 +98,10 @@ export default function reducer(state = {
}
return next;
}
case 'CONFIG_SUBTASK_UPDATE': {
const subtasks = cloneDeep(state.subtasks);
const subtask = state.subtasks.find((i) => i.id === action.id);
if (action.value !== '' && ['score', 'id'].includes(action.key)) action.value = +action.value;
if (action.key === 'if' && action.value.join('') !== '') action.value = action.value.map((i) => +i);
if (action.key.split('-')[0] === 'cases') {
if (action.key === 'cases-add') subtask.cases.push(action.value);
else if (action.key === 'cases-edit') {
if (action.value === '' && !['input', 'output'].includes(action.casesKey)) delete subtask.cases[action.casesId][action.casesKey];
else subtask.cases[action.casesId][action.casesKey] = action.value;
} else if (action.key === 'cases-delete') {
subtask.cases = subtask.cases.filter((k, v) => v !== action.value);
}
} else if (action.key === 'add') {
subtasks.push({
cases: [],
score: 0,
id: Object.keys(subtasks).map((i) => subtasks[i].id).reduce((a, b) => Math.max(+a, +b), 0) + 1,
});
return { ...state, subtasks };
} else if (action.key === 'delete') return { ...state, subtasks: subtasks.filter((k, v) => v !== action.id) };
else {
if (action.value === '' || (action.key === 'if' && action.value.join('') === '')) delete subtask[action.key];
else subtask[action.key] = action.value;
}
return { ...state, subtasks };
case 'problemconfig/updateFileIO': {
const n = { ...state, filename: action.filename };
if (!n.filename) delete n.filename;
return n;
}
case 'problemconfig/updateGlobalConfig': {
const n = { ...state, time: action.time, memory: action.memory };
@@ -127,6 +109,15 @@ export default function reducer(state = {
if (!n.memory) delete n.memory;
return n;
}
case 'problemconfig/addSubtask': {
const subtasks = cloneDeep(state.subtasks);
subtasks.push({
cases: [],
score: 0,
id: Object.keys(subtasks).map((i) => subtasks[i].id).reduce((a, b) => Math.max(+a, +b), 0) + 1,
});
return { ...state, subtasks };
}
case 'problemconfig/updateSubtaskConfig': {
if (!state.subtasks.find((i) => i.id === action.id)) return state;
const subtask = { ...state.subtasks.find((i) => i.id === action.id) };
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@hydrooj/ui-default",
"version": "4.48.6",
"version": "4.48.7",
"author": "undefined <i@undefined.moe>",
"license": "AGPL-3.0",
"main": "index.ts",