You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Hydro/packages/ui-default/pages/contest_balloon.page.tsx

124 lines
4.0 KiB
TypeScript

import $ from 'jquery';
import yaml from 'js-yaml';
import React from 'react';
import { HexColorInput, HexColorPicker } from 'react-colorful';
import { createRoot } from 'react-dom/client';
import { ActionDialog } from 'vj/components/dialog';
import Notification from 'vj/components/notification';
import { NamedPage } from 'vj/misc/Page';
import {
i18n, pjax, request, tpl,
} from 'vj/utils';
function Balloon({ tdoc, val }) {
const [color, setColor] = React.useState('');
const [now, setNow] = React.useState('');
return (
<div className="row">
<div className="medium-12 columns">
<table className="data-table">
<thead>
<tr>
<th>{i18n('Problem')}</th>
<th>{i18n('Color')}</th>
<th>{i18n('Name')}</th>
<th><span className="icon icon-wrench"></span></th>
</tr>
</thead>
<tbody>
{tdoc.pids.map((pid) => {
const { color: c, name } = val[+pid];
return (
<tr key={pid}>
<td>
{now === pid
? (<b>{String.fromCharCode(65 + tdoc.pids.indexOf(+pid))}</b>)
: (<span>{String.fromCharCode(65 + tdoc.pids.indexOf(+pid))}</span>)}
</td>
<td>
<HexColorInput
className='textbox'
color={c}
onFocus={() => { setNow(pid); setColor(c); }}
onChange={(e) => { val[+pid].color = e; setColor(e); }}
/>
</td>
<td>
<input
type="text"
className="textbox"
defaultValue={name}
onFocus={() => { setNow(pid); setColor(c); }}
onChange={(e) => { val[+pid].name = e.target.value; }}
/>
</td>
{tdoc.pids.indexOf(+pid) === 0 && <td rowSpan={0}>
{now && <HexColorPicker color={color} onChange={(e) => { val[+now].color = e; setColor(e); }} style={{ padding: '1rem' }} />}
</td>}
</tr>
);
})}
</tbody>
</table>
</div>
</div>
);
}
async function handleSetColor(tdoc) {
let val = tdoc.balloon;
if (!val) {
val = {};
for (const pid of tdoc.pids) val[+pid] = { color: '#ffffff', name: '' };
}
Notification.info(i18n('Loading...'));
const promise = new ActionDialog({
$body: tpl`
<div className="row"><div className="columns">
<h1>${i18n('Set Color')}</h1>
</div></div>
<div id="balloon"></div>`,
}).open();
createRoot($('#balloon').get(0)).render(
<Balloon tdoc={tdoc} val={val} />,
);
const action = await promise;
if (action !== 'ok') return;
Notification.info(i18n('Updating...'));
try {
await request.post('', { operation: 'set_color', color: yaml.dump(val) });
} catch (e) {
Notification.error(`${e.message} ${e.params?.[0]}`);
}
Notification.info(i18n('Successfully updated.'));
pjax.request({ url: '', push: false });
}
const page = new NamedPage('contest_balloon', () => {
const { tdoc } = UiContext;
const beginAt = new Date(tdoc.beginAt).getTime();
const endAt = new Date(tdoc.endAt).getTime();
function update() {
const now = Date.now();
if (beginAt <= now && now <= endAt) pjax.request({ url: '', push: false });
}
$('[name="set_color"]').on('click', () => handleSetColor(tdoc));
setInterval(update, 60000);
$(document).on('click', '[value="done"]', async (ev) => {
ev.preventDefault();
const balloon = $(ev.currentTarget).data('balloon');
try {
await request.post('', { balloon, operation: 'done' });
} catch (e) {
Notification.error(`${e.message} ${e.params?.[0]}`);
}
Notification.info(i18n('Successfully updated.'));
pjax.request({ url: '', push: false });
});
});
export default page;