Polish export and system mobile layout
This commit is contained in:
@@ -8,6 +8,8 @@ Data and Map workspaces include mobile-density CSS for file inputs, dataset acti
|
||||
|
||||
AI Labs uses the same mobile-density baseline for Detection and Segmentation model cards, run forms, QA/result summaries and scroll-safe result tables. This keeps long model ids, tile paths and artifact paths from widening the workbench on phones.
|
||||
|
||||
Exports and System provider capabilities now use compact, mobile-safe cards for handoff actions, artifact filters and provider metadata. Long provider limitations, export ids and artifact paths wrap inside their cards instead of widening the workbench.
|
||||
|
||||
## Scope implemented
|
||||
- API client layer (`src/services/api`)
|
||||
- Project and area list/create flows
|
||||
|
||||
@@ -14,25 +14,54 @@ export function ProviderPanel({
|
||||
onRefresh,
|
||||
}: ProviderPanelProps): JSX.Element {
|
||||
return (
|
||||
<section>
|
||||
<h2>Provider Capabilities</h2>
|
||||
<button type="button" onClick={onRefresh} disabled={loadingCapabilities}>
|
||||
Refresh providers
|
||||
</button>
|
||||
<section className="system-provider-panel">
|
||||
<div className="panel-title-row">
|
||||
<div>
|
||||
<h2>Provider Capabilities</h2>
|
||||
<p className="muted">Review configured local providers and honest not-configured external sources.</p>
|
||||
</div>
|
||||
<button type="button" className="secondary-action" onClick={onRefresh} disabled={loadingCapabilities}>
|
||||
Refresh providers
|
||||
</button>
|
||||
</div>
|
||||
{loadingCapabilities ? <p>Loading provider capabilities...</p> : null}
|
||||
{capabilitiesError ? <p className="error">{capabilitiesError}</p> : null}
|
||||
{providers.length === 0 && !loadingCapabilities ? <p>No providers reported by backend</p> : null}
|
||||
<ul>
|
||||
<ul className="system-provider-list">
|
||||
{providers.map((provider) => (
|
||||
<li key={provider.provider_name}>
|
||||
<strong>{provider.display_name}</strong>
|
||||
<div>provider: {provider.provider_name}</div>
|
||||
<div>authority: {provider.authority_level}</div>
|
||||
<div>status: {provider.status}</div>
|
||||
<div>configured: {provider.configured ? 'yes' : 'no'}</div>
|
||||
<div>layers: {provider.supported_layers.join(', ')}</div>
|
||||
<div>geometry: {provider.supported_geometry_types.join(', ')}</div>
|
||||
<div>query modes: {provider.supported_query_modes.join(', ')}</div>
|
||||
<li className="system-provider-card" key={provider.provider_name}>
|
||||
<div className="system-provider-header">
|
||||
<div>
|
||||
<strong>{provider.display_name}</strong>
|
||||
<span>{provider.provider_name}</span>
|
||||
</div>
|
||||
<span className={provider.configured ? 'status-badge status-badge-ready' : 'status-badge'}>{provider.status}</span>
|
||||
</div>
|
||||
<div className="system-provider-grid">
|
||||
<div>
|
||||
<span>Authority</span>
|
||||
<strong>{provider.authority_level}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>Configured</span>
|
||||
<strong>{provider.configured ? 'yes' : 'no'}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>Geometry</span>
|
||||
<strong>{provider.supported_geometry_types.join(', ')}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>Query modes</span>
|
||||
<strong>{provider.supported_query_modes.join(', ')}</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div className="provider-layer-list" aria-label={`${provider.provider_name} supported layers`}>
|
||||
{provider.supported_layers.map((layer) => (
|
||||
<span className="provider-layer-chip" key={layer}>
|
||||
{layer}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
<div>limitation: {provider.limitation_message}</div>
|
||||
<div>attribution: {provider.attribution}</div>
|
||||
<div>license: {provider.license_note}</div>
|
||||
|
||||
@@ -1493,6 +1493,12 @@ button.entity-card {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.export-history-controls input,
|
||||
.export-history-controls select {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.handoff-summary-card {
|
||||
display: grid;
|
||||
gap: 0.72rem;
|
||||
@@ -1575,6 +1581,7 @@ button.entity-card {
|
||||
color: var(--muted);
|
||||
font-size: 0.84rem;
|
||||
line-height: 1.36;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.handoff-action-card button {
|
||||
@@ -1671,6 +1678,95 @@ button.entity-card {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.system-provider-list {
|
||||
display: grid;
|
||||
gap: 0.72rem;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.system-provider-card {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
gap: 0.62rem;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 0.85rem;
|
||||
background: var(--panel-soft);
|
||||
}
|
||||
|
||||
.system-provider-card div {
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.system-provider-header {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 0.65rem;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.system-provider-header strong,
|
||||
.system-provider-header span {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.system-provider-header span:not(.status-badge) {
|
||||
margin-top: 0.16rem;
|
||||
color: var(--muted);
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
|
||||
.system-provider-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.system-provider-grid > div {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 7px;
|
||||
padding: 0.55rem;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.system-provider-grid span {
|
||||
display: block;
|
||||
color: var(--muted);
|
||||
font-size: 0.68rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.system-provider-grid strong {
|
||||
display: block;
|
||||
margin-top: 0.18rem;
|
||||
font-size: 0.88rem;
|
||||
line-height: 1.25;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.provider-layer-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.provider-layer-chip {
|
||||
display: inline-flex;
|
||||
min-height: 1.45rem;
|
||||
align-items: center;
|
||||
border: 1px solid rgba(15, 118, 110, 0.2);
|
||||
border-radius: 999px;
|
||||
padding: 0.16rem 0.5rem;
|
||||
background: var(--accent-soft);
|
||||
color: var(--accent-strong);
|
||||
font-size: 0.74rem;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.export-preview-panel .job-result {
|
||||
max-height: 38rem;
|
||||
}
|
||||
@@ -2114,6 +2210,22 @@ button.entity-card {
|
||||
min-width: 36rem;
|
||||
}
|
||||
|
||||
.export-action-grid,
|
||||
.handoff-action-grid,
|
||||
.system-provider-grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
|
||||
}
|
||||
|
||||
.handoff-action-card,
|
||||
.system-provider-card {
|
||||
padding: 0.68rem;
|
||||
}
|
||||
|
||||
.system-provider-header,
|
||||
.export-card-header {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.dataset-action-button,
|
||||
.map-empty-action-grid button {
|
||||
min-height: 3rem;
|
||||
|
||||
Reference in New Issue
Block a user