ui: drop blueprintjs 6 (#1073)

This commit is contained in:
undefined authored and GitHub committed 2025-11-04 09:08:20 +00:00
1 parent 40114323e4
commit 3996f6f2ef
27 files changed
+764 -652

No files matched your search

@@ -1,8 +1,9 @@
import {
Button, Dialog, DialogBody, DialogFooter, Tab, Tabs,
} from '@blueprintjs/core';
import { Button, Tabs } from '@mantine/core';
import { Allotment } from 'allotment';
import { ContextMenuProvider } from 'mantine-contextmenu';
import React from 'react';
import { useSelector } from 'react-redux';
import { useSelector, useStore } from 'react-redux';
import { confirm } from 'vj/components/dialog/index';
import { i18n } from 'vj/utils';
import ProblemConfigEditor from './ProblemConfigEditor';
import ProblemConfigForm from './ProblemConfigForm';
@@ -15,40 +16,74 @@ interface Props {
export default function ProblemConfig(props: Props) {
const [selected, setSelected] = React.useState('basic');
const [open, setOpen] = React.useState(false);
const [container, setContainer] = React.useState<HTMLDivElement | null>(null);
const [tabs, setTabs] = React.useState<HTMLDivElement | null>(null);
const [editor, setEditor] = React.useState<any>(null);
const store = useStore<RootState>();
const valid = useSelector((state: RootState) => state.config.__valid);
const errors = useSelector((state: RootState) => state.config.__errors, (a, b) => JSON.stringify(a) === JSON.stringify(b));
React.useEffect(() => {
if (valid) setOpen(false);
}, [valid]);
return (<>
<div className="row">
<div className="medium-4 columns">
<ProblemConfigEditor />
</div>
<div className="medium-8 columns">
<Tabs onChange={(t) => (t !== 'errors' && setSelected(t.toString()))} selectedTabId={valid ? selected : 'errors'}>
<Tab id="basic" disabled={!valid} title={i18n('Basic')} panel={<ProblemConfigForm />} />
<Tab id="subtasks" disabled={!valid} title={i18n('Subtasks')} panel={<ProblemConfigTree />} />
<Tab
id="errors"
disabled={valid}
title={errors.length ? `Errors(${errors.length})` : 'No Errors'}
panel={<div>{errors.map((i) => (<pre key={i}>{i}</pre>))}</div>}
/>
</Tabs>
</div>
const handleSave = React.useCallback(async () => {
if (valid) props.onSave();
else if (await confirm(i18n('Errors detected in the config. Confirm save?'))) props.onSave();
}, [valid, props.onSave]);
React.useEffect(() => {
if (!container) return () => { };
container.style.height ||= '600px';
const callback = () => {
setTimeout(() => {
const target = Math.max(container.clientHeight, tabs?.clientHeight || 0);
container.style.height = `${target}px`;
if (editor) editor.layout();
}, 50);
};
const dispose = store.subscribe(callback);
window.addEventListener('resize', callback);
return () => {
dispose();
window.removeEventListener('resize', callback);
};
}, [container, tabs, store]);
return <ContextMenuProvider>
<div ref={setContainer}>
<Allotment defaultSizes={[2, 3]}>
<Allotment.Pane>
<div style={{ height: '100%', overflow: 'auto' }}>
<ProblemConfigEditor ref={setEditor} />
</div>
</Allotment.Pane>
<Allotment.Pane>
<Tabs
ref={setTabs}
value={valid ? selected : 'errors'}
keepMounted={false}
style={{ paddingLeft: 20 }}
onChange={(t) => (t !== 'errors' && t && setSelected(t.toString()))}
>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<Tabs.List>
<Tabs.Tab value="basic" disabled={!valid}>{i18n('Basic')}</Tabs.Tab>
<Tabs.Tab value="subtasks" disabled={!valid}>{i18n('Subtasks')}</Tabs.Tab>
<Tabs.Tab value="errors" disabled={valid}>{errors.length ? `Errors(${errors.length})` : 'No Errors'}</Tabs.Tab>
</Tabs.List>
<Button onClick={handleSave}>
{i18n('Save')}
</Button>
</div>
<Tabs.Panel value="basic">
<ProblemConfigForm />
</Tabs.Panel>
<Tabs.Panel value="subtasks">
<ProblemConfigTree />
</Tabs.Panel>
<Tabs.Panel value="errors">
<div>{errors.map((i) => (<pre key={i}>{i}</pre>))}</div>
</Tabs.Panel>
</Tabs>
</Allotment.Pane>
</Allotment>
</div>
<Dialog isOpen={open && !valid} onClose={() => setOpen(false)}>
<DialogBody>
<p>{i18n('Errors detected in the config. Confirm save?')}</p>
</DialogBody>
<DialogFooter actions={<>
<Button onClick={() => setOpen(false)}>{i18n('Cancel')}</Button>
<Button intent="warning" onClick={props.onSave}>{i18n('Save')}</Button>
</>} />
</Dialog>
<button className="rounded primary button" onClick={valid ? props.onSave : () => setOpen(true)}>{i18n('Save')}</button>
</>);
</ContextMenuProvider>;
}