mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 17:46:28 +08:00
ui: bug fixes
This commit is contained in:
15 files changed
+76
-54
No files matched your search
@@ -85,7 +85,7 @@ function LangConfig() {
|
||||
<CustomSelectAutoComplete
|
||||
ref={ref}
|
||||
data={data}
|
||||
placeholder={i18n('Unlimited')}
|
||||
placeholder={!selectedKeys.length ? i18n('Unlimited') : i18n('Code language')}
|
||||
selectedKeys={selectedKeys}
|
||||
onChange={(val) => {
|
||||
const value = val.split(',');
|
||||
|
||||
@@ -79,7 +79,7 @@ export function SubtaskNode(props: { subtaskId: number }) {
|
||||
</span>
|
||||
</div>}
|
||||
<ul className="bp4-tree-node-list" ref={drop}>
|
||||
{subtaskId !== -1 && <SubtaskSettings subtaskId={subtaskId} time={time} memory={memory} />}
|
||||
{subtaskId !== -1 && <SubtaskSettings subtaskId={subtaskId} subtaskIds={subtaskIds} time={time} memory={memory} />}
|
||||
{expand
|
||||
? <SelectionManager subtaskId={subtaskId} subtaskIds={subtaskIds} />
|
||||
: <TreeNode
|
||||
|
||||
@@ -15,17 +15,18 @@ const ajv = new Ajv();
|
||||
const validate = ajv.compile(schema);
|
||||
|
||||
export default function reducer(state = {
|
||||
type: 'default', __loaded: false, __valid: true, __errors: [], __cases: [],
|
||||
type: 'default', __loaded: false, __valid: true, __errors: [], __cases: [], subtasks: [],
|
||||
} as State, action: any = {}): State {
|
||||
switch (action.type) {
|
||||
case 'CONFIG_LOAD_FULFILLED': {
|
||||
try {
|
||||
const data = yaml.load(action.payload.config) as any;
|
||||
let data = yaml.load(action.payload.config) as any;
|
||||
if (typeof data !== 'object') data = { subtasks: [] };
|
||||
if (!validate(data)) {
|
||||
return { ...state, __valid: false, __errors: validate.errors.map((i) => `${i.instancePath}: ${i.message}`) };
|
||||
}
|
||||
const subtasks = (data as any).subtasks;
|
||||
for (const subtask of subtasks || []) {
|
||||
for (const subtask of subtasks) {
|
||||
if (typeof subtask.id !== 'number') {
|
||||
for (let i = 1; ; i++) {
|
||||
if (!subtasks.find((s) => s.id === i)) {
|
||||
|
||||
@@ -13,31 +13,47 @@ export function AddTestcase() {
|
||||
const [input, setInput] = React.useState('');
|
||||
const [output, setOutput] = React.useState('');
|
||||
const [valid, setValid] = React.useState(false);
|
||||
const [autoInput, setAutoInput] = React.useState(true);
|
||||
const [autoOutput, setAutoOutput] = React.useState(true);
|
||||
const testdata = useSelector((state: RootState) => state.testdata);
|
||||
const store = useStore<RootState>();
|
||||
const refInput = useRef();
|
||||
const refOutput = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
setValid(testdata.find((i) => i.name === input) && testdata.find((i) => i.name === output));
|
||||
if (input && !output) {
|
||||
const inputValid = testdata.find((i) => i.name === input);
|
||||
if (input) setAutoInput(false);
|
||||
else setAutoInput(true);
|
||||
setValid(inputValid);
|
||||
if (inputValid && autoOutput) {
|
||||
const filename = input.substring(0, input.lastIndexOf('.'));
|
||||
let outputFile = '';
|
||||
if (testdata.find((i) => i.name === `${filename}.out`)) outputFile = `${filename}.out`;
|
||||
else if (testdata.find((i) => i.name === `${filename}.ans`)) outputFile = `${filename}.ans`;
|
||||
// @ts-ignore
|
||||
refOutput.current!.setSelectedItems([outputFile]);
|
||||
setOutput(outputFile);
|
||||
if (outputFile) {
|
||||
// @ts-ignore
|
||||
refOutput.current!.setSelectedItems([outputFile]);
|
||||
setOutput(outputFile);
|
||||
setAutoOutput(true);
|
||||
}
|
||||
}
|
||||
if (output && !input) {
|
||||
}, [input]);
|
||||
|
||||
useEffect(() => {
|
||||
const outputValid = testdata.find((i) => i.name === output);
|
||||
if (output) setAutoOutput(false);
|
||||
else setAutoOutput(true);
|
||||
setValid(outputValid);
|
||||
if (outputValid && autoInput) {
|
||||
const filename = output.substring(0, output.lastIndexOf('.'));
|
||||
if (testdata.find((i) => i.name === `${filename}.in`)) {
|
||||
// @ts-ignore
|
||||
refInput.current!.setSelectedItems([`${filename}.in`]);
|
||||
setInput(`${filename}.in`);
|
||||
setAutoInput(true);
|
||||
}
|
||||
}
|
||||
}, [input, output]);
|
||||
}, [output]);
|
||||
|
||||
function onConfirm() {
|
||||
store.dispatch({
|
||||
@@ -81,6 +97,8 @@ export function AddTestcase() {
|
||||
onClick={() => {
|
||||
setInput('');
|
||||
setOutput('');
|
||||
setAutoInput(true);
|
||||
setAutoOutput(true);
|
||||
setOpen(true);
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -8,9 +8,11 @@ import { isEqual } from 'lodash';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { i18n } from 'vj/utils';
|
||||
import CustomSelectAutoComplete from '../../autocomplete/components/CustomSelectAutoComplete';
|
||||
import { RootState } from '../reducer';
|
||||
|
||||
interface SubtaskSettingsProps {
|
||||
subtaskIds: number[];
|
||||
subtaskId: number;
|
||||
time: string;
|
||||
memory: string;
|
||||
@@ -19,6 +21,7 @@ interface SubtaskSettingsProps {
|
||||
export function SubtaskSettings(props: SubtaskSettingsProps) {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const [depsOpen, setDepsOpen] = React.useState(false);
|
||||
const subtaskIds = props.subtaskIds.filter((i) => i !== props.subtaskId);
|
||||
const score = useSelector((state: RootState) => state.config.subtasks.find((i) => i.id === props.subtaskId).score);
|
||||
const time = useSelector((state: RootState) => state.config.subtasks.find((i) => i.id === props.subtaskId).time);
|
||||
const memory = useSelector((state: RootState) => state.config.subtasks.find((i) => i.id === props.subtaskId).memory);
|
||||
@@ -88,14 +91,13 @@ export function SubtaskSettings(props: SubtaskSettingsProps) {
|
||||
</Dialog>
|
||||
<Dialog title={i18n('Set dependencies')} icon="cog" isOpen={depsOpen} onClose={() => setDepsOpen(false)}>
|
||||
<DialogBody>
|
||||
<ControlGroup fill={true} vertical={false}>
|
||||
<InputGroup
|
||||
leftElement={<Icon icon="diagram-tree" />}
|
||||
onChange={(ev) => setDeps(ev.currentTarget.value)}
|
||||
placeholder={'Dependencies'}
|
||||
value={cdeps || ''}
|
||||
/>
|
||||
</ControlGroup>
|
||||
<CustomSelectAutoComplete
|
||||
data={subtaskIds.map((i) => ({ _id: i, name: `${i18n('Subtask {0}', i)}` }))}
|
||||
setSelectItems={cdeps.split(',').map((i) => i.trim()).filter((i) => +i).map((i) => +i)}
|
||||
onChange={(items) => setDeps(items)}
|
||||
placeholder="dependencies"
|
||||
multi
|
||||
/>
|
||||
</DialogBody>
|
||||
<DialogFooter actions={<Button className="primary rounded button" onClick={onConfirm} intent="primary" text="Save" />} />
|
||||
</Dialog>
|
||||
|
||||
Reference in new issue
Block a user