mirror of
https://github.com/TronoSfera/Law.git
synced 2026-05-18 10:03:45 +03:00
fix ui data 2
This commit is contained in:
parent
cd3bcf29c2
commit
a9704d77b0
3 changed files with 167 additions and 33 deletions
|
|
@ -275,6 +275,25 @@
|
|||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.config-head-actions {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn-icon-only {
|
||||
width: 40px;
|
||||
min-width: 40px;
|
||||
height: 40px;
|
||||
min-height: 40px;
|
||||
padding: 0;
|
||||
display: inline-grid;
|
||||
place-items: center;
|
||||
font-size: 1.06rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.muted {
|
||||
color: var(--muted);
|
||||
margin: 0.45rem 0 0;
|
||||
|
|
@ -1229,18 +1248,56 @@
|
|||
background: transparent;
|
||||
}
|
||||
|
||||
.config-actions-row {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.config-panel-flat .config-content .table-wrap table {
|
||||
min-width: 640px;
|
||||
}
|
||||
|
||||
.config-controls-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.config-controls-summary {
|
||||
color: var(--muted);
|
||||
font-size: 0.86rem;
|
||||
}
|
||||
|
||||
.config-controls-actions {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.45rem;
|
||||
flex-wrap: wrap;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.config-control-btn {
|
||||
width: 40px;
|
||||
min-width: 40px;
|
||||
height: 40px;
|
||||
min-height: 40px;
|
||||
padding: 0;
|
||||
display: inline-grid;
|
||||
place-items: center;
|
||||
font-size: 1.05rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.config-control-btn-loadall {
|
||||
width: auto;
|
||||
min-width: 58px;
|
||||
padding: 0 0.62rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.33rem;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
|
||||
.block {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 12px;
|
||||
|
|
@ -2918,6 +2975,13 @@
|
|||
.filter-action {
|
||||
margin-left: 0;
|
||||
}
|
||||
.config-controls-summary {
|
||||
width: 100%;
|
||||
}
|
||||
.config-controls-actions {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
}
|
||||
.topbar {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ const NEW_REQUEST_CLIENT_OPTION = "__new_client__";
|
|||
);
|
||||
}
|
||||
|
||||
function FilterToolbar({ filters, onOpen, onRemove, onEdit, getChipLabel }) {
|
||||
function FilterToolbar({ filters, onOpen, onRemove, onEdit, getChipLabel, hideAction = false }) {
|
||||
return (
|
||||
<div className="filter-toolbar">
|
||||
<div className="filter-chips">
|
||||
|
|
@ -190,11 +190,13 @@ const NEW_REQUEST_CLIENT_OPTION = "__new_client__";
|
|||
<span className="chip-placeholder">Фильтры не заданы</span>
|
||||
)}
|
||||
</div>
|
||||
{!hideAction ? (
|
||||
<div className="filter-action">
|
||||
<button className="btn secondary" type="button" onClick={onOpen}>
|
||||
Фильтр
|
||||
</button>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { KNOWN_CONFIG_TABLE_KEYS, OPERATOR_LABELS, TABLE_SERVER_CONFIG } from "../../shared/constants.js";
|
||||
import { KNOWN_CONFIG_TABLE_KEYS, OPERATOR_LABELS, PAGE_SIZE, TABLE_SERVER_CONFIG } from "../../shared/constants.js";
|
||||
import { boolLabel, fmtDate, listPreview, normalizeReferenceMeta, roleLabel, statusKindLabel, statusLabel } from "../../shared/utils.js";
|
||||
|
||||
function fmtBalance(value) {
|
||||
|
|
@ -57,7 +57,6 @@ export function ConfigSection(props) {
|
|||
loadAllRows,
|
||||
FilterToolbarComponent,
|
||||
DataTableComponent,
|
||||
TablePagerComponent,
|
||||
StatusLineComponent,
|
||||
IconButtonComponent,
|
||||
UserAvatarComponent,
|
||||
|
|
@ -65,10 +64,24 @@ export function ConfigSection(props) {
|
|||
|
||||
const FilterToolbar = FilterToolbarComponent;
|
||||
const DataTable = DataTableComponent;
|
||||
const TablePager = TablePagerComponent;
|
||||
const StatusLine = StatusLineComponent;
|
||||
const IconButton = IconButtonComponent;
|
||||
const UserAvatar = UserAvatarComponent;
|
||||
const canOpenFilter = Boolean(configActiveKey);
|
||||
const canRefresh = Boolean(configActiveKey);
|
||||
const canCreateRecord = Boolean(canCreateInConfig && configActiveKey);
|
||||
const canLoadAllRows = Boolean(
|
||||
configActiveKey &&
|
||||
activeConfigTableState.total > 0 &&
|
||||
!activeConfigTableState.showAll &&
|
||||
activeConfigTableState.rows.length < activeConfigTableState.total
|
||||
);
|
||||
const canLoadPrev = Boolean(configActiveKey && !activeConfigTableState.showAll && activeConfigTableState.offset > 0);
|
||||
const canLoadNext = Boolean(
|
||||
configActiveKey &&
|
||||
!activeConfigTableState.showAll &&
|
||||
activeConfigTableState.offset + PAGE_SIZE < activeConfigTableState.total
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -83,32 +96,33 @@ export function ConfigSection(props) {
|
|||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: "0.5rem", flexWrap: "wrap" }}>
|
||||
<div className="config-head-actions">
|
||||
{configActiveKey === "otp_sessions" ? (
|
||||
<button className="btn secondary" type="button" onClick={onRefreshSmsProviderHealth}>
|
||||
Баланс
|
||||
</button>
|
||||
) : null}
|
||||
<button className="btn secondary" type="button" onClick={() => loadCurrentConfigTable(true)}>
|
||||
Обновить
|
||||
<button
|
||||
className="btn secondary btn-icon-only"
|
||||
type="button"
|
||||
onClick={() => openFilterModal(configActiveKey)}
|
||||
disabled={!canOpenFilter}
|
||||
title="Фильтр"
|
||||
aria-label="Фильтр"
|
||||
>
|
||||
⚲
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="config-layout">
|
||||
<div className="config-panel config-panel-flat">
|
||||
<div className="config-content">
|
||||
{canCreateInConfig && configActiveKey ? (
|
||||
<div className="config-actions-row">
|
||||
<button className="btn" type="button" onClick={() => openCreateRecordModal(configActiveKey)}>
|
||||
Добавить
|
||||
</button>
|
||||
</div>
|
||||
) : null}
|
||||
<FilterToolbar
|
||||
filters={activeConfigTableState.filters}
|
||||
onOpen={() => openFilterModal(configActiveKey)}
|
||||
onRemove={(index) => removeFilterChip(configActiveKey, index)}
|
||||
onEdit={(index) => openFilterEditModal(configActiveKey, index)}
|
||||
hideAction
|
||||
getChipLabel={(clause) => {
|
||||
const fieldDef = getFieldDef(configActiveKey, clause.field);
|
||||
return (
|
||||
|
|
@ -584,12 +598,66 @@ export function ConfigSection(props) {
|
|||
)}
|
||||
/>
|
||||
) : null}
|
||||
<TablePager
|
||||
tableState={activeConfigTableState}
|
||||
onPrev={() => loadPrevPage(configActiveKey)}
|
||||
onNext={() => loadNextPage(configActiveKey)}
|
||||
onLoadAll={() => loadAllRows(configActiveKey)}
|
||||
/>
|
||||
<div className="pager table-footer-bar config-controls-bar">
|
||||
<div className="config-controls-summary">
|
||||
{activeConfigTableState.showAll
|
||||
? "Всего: " + activeConfigTableState.total + " • показаны все записи"
|
||||
: "Всего: " + activeConfigTableState.total + " • смещение: " + activeConfigTableState.offset}
|
||||
</div>
|
||||
<div className="config-controls-actions">
|
||||
<button
|
||||
className="btn secondary config-control-btn config-control-btn-loadall"
|
||||
type="button"
|
||||
onClick={() => loadAllRows(configActiveKey)}
|
||||
disabled={!canLoadAllRows}
|
||||
title={"Загрузить все " + activeConfigTableState.total}
|
||||
aria-label={"Загрузить все " + activeConfigTableState.total}
|
||||
>
|
||||
<span aria-hidden="true">⤓</span>
|
||||
<span>{activeConfigTableState.total}</span>
|
||||
</button>
|
||||
<button
|
||||
className="btn secondary btn-icon-only config-control-btn"
|
||||
type="button"
|
||||
onClick={() => loadCurrentConfigTable(true)}
|
||||
disabled={!canRefresh}
|
||||
title="Обновить"
|
||||
aria-label="Обновить"
|
||||
>
|
||||
↻
|
||||
</button>
|
||||
<button
|
||||
className="btn secondary btn-icon-only config-control-btn"
|
||||
type="button"
|
||||
onClick={() => openCreateRecordModal(configActiveKey)}
|
||||
disabled={!canCreateRecord}
|
||||
title="Добавить"
|
||||
aria-label="Добавить"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
<button
|
||||
className="btn secondary btn-icon-only config-control-btn"
|
||||
type="button"
|
||||
onClick={() => loadPrevPage(configActiveKey)}
|
||||
disabled={!canLoadPrev}
|
||||
title="Назад"
|
||||
aria-label="Назад"
|
||||
>
|
||||
←
|
||||
</button>
|
||||
<button
|
||||
className="btn secondary btn-icon-only config-control-btn"
|
||||
type="button"
|
||||
onClick={() => loadNextPage(configActiveKey)}
|
||||
disabled={!canLoadNext}
|
||||
title="Вперед"
|
||||
aria-label="Вперед"
|
||||
>
|
||||
→
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<StatusLine status={getStatus(configActiveKey)} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue