Rename Brain to Upload material and Instruction to Brain and AI
Upload material (/upload) drops the metric cards for a larger upload box above the material list; Brain and AI moves to /brain. Old paths redirect. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@ import {
|
||||
type Source,
|
||||
} from '../api/engine'
|
||||
import { Icon } from '../components/Icon'
|
||||
import { Empty, PageHead, Skeleton, SkeletonLines, SkeletonRows } from '../components/Page'
|
||||
import { Empty, PageHead, SkeletonLines, SkeletonRows } from '../components/Page'
|
||||
import { toast } from '../components/Toast'
|
||||
import { locale, t } from '../i18n'
|
||||
|
||||
@@ -28,17 +28,10 @@ export function BrainPage() {
|
||||
// Poll quickly while anything is processing or building; slowly otherwise (colleagues may upload too).
|
||||
refetchInterval: q => (q.state.data?.some(d => phaseOf(d) === 'working') ? 3000 : 20_000),
|
||||
})
|
||||
const ready = docs.data?.filter(d => phaseOf(d) === 'ready').length ?? 0
|
||||
const waiting = docs.data?.filter(d => phaseOf(d) === 'answer').length ?? 0
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHead title={t('brain.title')} description={t('brain.description')} />
|
||||
<div className="metrics">
|
||||
<div className="metric"><span>{t('brain.metricMaterial')}</span>{docs.data ? <strong>{docs.data.length}</strong> : <Skeleton className="skel-num" />}<small>{t('brain.metricMaterialSub')}</small></div>
|
||||
<div className="metric"><span>{t('brain.metricReady')}</span>{docs.data ? <strong>{ready}</strong> : <Skeleton className="skel-num" />}<small>{t('brain.metricReadySub')}</small></div>
|
||||
<div className="metric"><span>{t('brain.metricAction')}</span>{docs.data ? <strong>{waiting}</strong> : <Skeleton className="skel-num" />}<small>{t('brain.metricActionSub')}</small></div>
|
||||
</div>
|
||||
<UploadBox />
|
||||
<div className="card">
|
||||
<div className="card-head"><h3>{t('brain.listTitle')}</h3><Icon name="brain" /></div>
|
||||
@@ -116,7 +109,7 @@ function UploadBox() {
|
||||
|
||||
const busy = items.some(i => i.state === 'uploading')
|
||||
return (
|
||||
<div className={`upload-box upload-compact${drag ? ' drag' : ''}`}>
|
||||
<div className={`upload-box upload-large${drag ? ' drag' : ''}`}>
|
||||
{drag && (
|
||||
<div className="drop-overlay" aria-hidden="true">
|
||||
<div><Icon name="upload" /><b>{t('brain.dropHere')}</b></div>
|
||||
|
||||
@@ -67,7 +67,7 @@ export function ProductionPage() {
|
||||
<div><small>{t('prod.links')}</small>{graph ? <b>{graph.links.filter(l => !l.hub).length}</b> : <b>-</b>}<span>{t('prod.linksSub')}</span></div>
|
||||
</div>
|
||||
<h3>{t('prod.scheduleTitle')}</h3>
|
||||
{schedules.data?.length === 0 && <p className="graph-empty">{t('prod.noSchedules')} <Link to="/instruction">{t('prod.giveInstruction')}</Link></p>}
|
||||
{schedules.data?.length === 0 && <p className="graph-empty">{t('prod.noSchedules')} <Link to="/brain">{t('prod.giveInstruction')}</Link></p>}
|
||||
<ul className="graph-list">
|
||||
{schedules.data?.slice(0, 4).map(s => (
|
||||
<li key={s.agent.id}>
|
||||
|
||||
@@ -105,7 +105,7 @@ function NoResults({ filtered, icon }: { filtered: boolean; icon: IconName }) {
|
||||
<span className="empty-icon"><Icon name={icon} /></span>
|
||||
<h3>{t('res.empty')}</h3>
|
||||
<p>{t('res.emptyCopy')}</p>
|
||||
<Link className="btn light" to="/instruction"><Icon name="plus" />{t('sch.newInstruction')}</Link>
|
||||
<Link className="btn light" to="/brain"><Icon name="plus" />{t('sch.newInstruction')}</Link>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -427,7 +427,7 @@ function SourceRow({ source: s }: { source: FoundSource }) {
|
||||
<div>
|
||||
<span className={`status ${tone}`}><i className="dot"></i>{label}</span>
|
||||
<h3>{s.url ? <a href={s.url} target="_blank" rel="noreferrer">{s.title}</a> : s.title}</h3>
|
||||
<p>{describeRule(s.rule)} · {fmt(s.createdAt)}{s.status === 'accepted' && <> · <Link to="/brain">{t('res.inBrain')}</Link></>}</p>
|
||||
<p>{describeRule(s.rule)} · {fmt(s.createdAt)}{s.status === 'accepted' && <> · <Link to="/upload">{t('res.inBrain')}</Link></>}</p>
|
||||
{s.preview && <p className="source-preview">{s.preview}</p>}
|
||||
{review.error && <span className="error">{review.error.message}</span>}
|
||||
</div>
|
||||
|
||||
@@ -24,7 +24,7 @@ export function SchedulePage() {
|
||||
return (
|
||||
<>
|
||||
<PageHead title={t('sch.title')} description={t('sch.description')}
|
||||
actions={<Link className="btn primary" to="/instruction"><Icon name="plus" />{t('sch.newInstruction')}</Link>} />
|
||||
actions={<Link className="btn primary" to="/brain"><Icon name="plus" />{t('sch.newInstruction')}</Link>} />
|
||||
<div className="card">
|
||||
<div className="card-head"><h3>{t('sch.cardTitle')}</h3><Icon name="calendar" /></div>
|
||||
{schedules.isPending && <SkeletonRows label={t('sch.loading')} />}
|
||||
|
||||
Reference in New Issue
Block a user