From 4a5ae8baa18e4960cf70908d036ab74315f4551a Mon Sep 17 00:00:00 2001 From: Denozordec Date: Sun, 4 Oct 2026 16:12:22 +0700 Subject: [PATCH] =?UTF-8?q?fix(ui):=20=D0=BE=D0=B3=D1=80=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=87=D0=B8=D1=82=D1=8C=20=D1=81=D0=BF=D0=B8=D1=81=D0=BE=D0=BA?= =?UTF-8?q?=20Filters=20=D1=81=20=D1=81=D0=BE=D1=85=D1=80=D0=B0=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=D0=BC=20=D0=BF=D0=BE=D1=80=D1=8F=D0=B4?= =?UTF-8?q?=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/data-grids/filters-data-grid.tsx | 50 ++++++++++++++------ docs/ux-ui-performance.md | 7 +-- docs/ux-ui-plan.md | 2 +- docs/ux-ui-progress.md | 8 ++++ docs/ux-ui-stage-12.md | 9 ++++ docs/ux-ui/screens/large-filters-320.png | Bin 0 -> 64110 bytes tests/e2e/large-filters.spec.ts | 31 ++++++++++++ 7 files changed, 88 insertions(+), 19 deletions(-) create mode 100644 docs/ux-ui/screens/large-filters-320.png create mode 100644 tests/e2e/large-filters.spec.ts diff --git a/components/data-grids/filters-data-grid.tsx b/components/data-grids/filters-data-grid.tsx index 09e28bd4..bc1e4dfe 100644 --- a/components/data-grids/filters-data-grid.tsx +++ b/components/data-grids/filters-data-grid.tsx @@ -1,7 +1,7 @@ "use client" -import { useMemo } from "react" -import { dataGridFeatures, type DataGridFeatures } from "@/components/reui/data-grid" +import { useEffect, useMemo } from "react" +import { DataGridContainer, DataGridScrollArea, DataGridTable, dataGridFeatures, type DataGridFeatures } from "@/components/reui/data-grid" import { type ColumnDef, useTable, @@ -154,11 +154,12 @@ function FilterRowActions({ onDelete: () => void }) { return ( -
+
@@ -253,18 +256,19 @@ function FiltersDataGrid({ onClick={() => onMoveDown(row.original.id)} aria-label={`Опустить правило ${row.original.community}`} disabled={mutationsLocked || index < 0 || isLast} - className="text-muted-foreground/50 hover:text-foreground disabled:opacity-20" + className="size-11 shrink-0 inline-flex items-center justify-center rounded text-muted-foreground hover:bg-muted disabled:opacity-40" >
) }, - size: 28, + size: 104, meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD }, }, { id: "community", + size: 120, accessorKey: "community", header: ({ column }) => , enableSorting, @@ -301,6 +305,7 @@ function FiltersDataGrid({ }, { id: "gateway", + size: 192, accessorKey: "gateway", header: ({ column }) => , enableSorting, @@ -316,6 +321,7 @@ function FiltersDataGrid({ }, { id: "description", + size: 240, accessorKey: "description", header: ({ column }) => , enableSorting, @@ -335,13 +341,14 @@ function FiltersDataGrid({ onDelete={() => onDelete(row.original.id)} /> ), - size: 64, + size: 112, meta: { headerClassName: DATA_GRID_CELL_PAD_LAST, cellClassName: DATA_GRID_CELL_PAD_LAST }, }, ], [ communityNameMap, orderedRules, + orderedIndex, mutationsLocked, enableSorting, onDelete, @@ -356,12 +363,21 @@ function FiltersDataGrid({ const table = useTable({ features: dataGridFeatures, - manualPagination: true, + manualPagination: false, + autoResetPageIndex: false, + initialState: { pagination: { pageIndex: 0, pageSize: 50 }, columnPinning: { start: ["priority", "community"], end: [] } }, + manualSorting: !enableSorting, data: rules, columns, getRowId: (row) => row.id, }) + const { pageIndex, pageSize } = table.state.pagination + useEffect(() => { + const lastPage = Math.max(0, Math.ceil(rules.length / pageSize) - 1) + if (pageIndex > lastPage) table.setPageIndex(lastPage) + }, [rules.length, pageIndex, pageSize, table]) + if (rules.length === 0) { return ( - + 50 || pageSize !== 50} tableLayout={{ dense: true, columnsPinnable: true }}> + + + +
Последнее правило имеет наивысший приоритет в RouterOS diff --git a/docs/ux-ui-performance.md b/docs/ux-ui-performance.md index e46eb5d9..3f5268fd 100644 --- a/docs/ux-ui-performance.md +++ b/docs/ux-ui-performance.md @@ -15,12 +15,11 @@ ## Оставшиеся специализированные grids -Аудит12.3.36 от2026-10-04: точный поиск `manualPagination: true` в components/data-grids —13 файлов после12.3.40. Это не15 дефектов: есть фиксированный источник, demo, неподключённый компонент и ограниченные срезы. Файлы ниже сопоставлены с действующими JSX-потребителями; ограничения установлены чтением кода, не нагрузочной приёмкой API. +Аудит12.3.36 от2026-10-04: точный поиск `manualPagination: true` в components/data-grids —12 файлов после12.3.42. Это не12 доказанных дефектов: есть фиксированный источник, demo, неподключённый компонент и ограниченные срезы. Файлы ниже сопоставлены с действующими JSX-потребителями; ограничения установлены чтением кода, не нагрузочной приёмкой API. | Файл | Источник и необходимая проверка | | --- | --- | | [data-collection-scheduler-data-grid.tsx](../components/data-grids/data-collection-scheduler-data-grid.tsx) | 11 фиксированных SCHEDULER_JOB_KEYS (lib/scheduler-settings.ts); UI map этих ключей. Fixture1000 не соответствует источнику. | -| [filters-data-grid.tsx](../components/data-grids/filters-data-grid.tsx) | currentRules/filteredRules + orderedRules: move up/down относятся ко всему исходному порядку. Проверить границу страниц и точный target. | | [firewall-rules-data-grid.tsx](../components/data-grids/firewall-rules-data-grid.tsx) | filteredRules; reorderable отключает сортировку, DnD dataIds включает исходный массив. Ограничение DOM требует отдельной проверки cross-page порядка. | | [firewall-scenario-rules-data-grid.tsx](../components/data-grids/firewall-scenario-rules-data-grid.tsx) | Локальный редактор сценария, динамический массив; не путать с live правилами. Проверить сохранение/симуляцию всего сценария. | | [gre-pools-data-grid.tsx](../components/data-grids/gre-pools-data-grid.tsx) | В live displayPools=[]; только mockGrePools в demo. Приоритета live1000 нет. | @@ -33,7 +32,7 @@ | [subusers-data-grid.tsx](../components/data-grids/subusers-data-grid.tsx) | Поиск импортов/JSX в app/components не нашёл потребителя: компонент экспортируется, но не подключён. Не доказывает дефект экрана /users. | | [traffic-flows-data-grid.tsx](../components/data-grids/traffic-flows-data-grid.tsx) | FlowAnalyticsPanel/conversationsList: backend traffic-flow-analytics.ts top=min(50,max(10,settings.topN)), slice(0,top). Это top slice, не полный каталог/серверная pagination. Проверить сообщение об ограничении50 и связывание с графиками. | -Очередь: Filters порядок → Firewall/DnD → OSPF таблица+topology → optimizer preview/комбинаторика. Scheduler11, traffic cap50 и commRecs24 проверять на реальной границе, не искусственно подставлять1000 в недоступный DTO. Demo и неиспользуемый Subusers отделены от live приёмки. Все новые профили должны сохранять search/sort/refresh/clamp, точный target и права,320px и URL scope. +Очередь: Firewall/DnD → OSPF таблица+topology → optimizer preview/комбинаторика. Scheduler11, traffic cap50 и commRecs24 проверять на реальной границе, не искусственно подставлять1000 в недоступный DTO. Demo и неиспользуемый Subusers отделены от live приёмки. Все новые профили должны сохранять search/sort/refresh/clamp, точный target и права,320px и URL scope. Принятые после ранней карты: OSPF routes/BFD, WireGuard interfaces/peers/detail, VXLAN/GRE tunnels. Pagination сохраняет полный DTO в памяти и не доказывает серверную производительность. Текущий журнал: [ux-ui-progress.md](ux-ui-progress.md). @@ -82,3 +81,5 @@ Statistics pivot в backend/src/services/statistics-aggregate.ts огранич 12.3.40: recursive1000 групп→50 rows/2118 nodes/1457ms; одна группа1000 endpoints→50 cards/1126 nodes.35 browser/type/lint/build прошли; большой RouteSheet пока вне принятого performance scope.13 manualPagination:true остаются. 12.3.41: recursive RouteSheet1000 endpoints ×1000 gateways →10 cards/1569 modal nodes, максимум5 gateway choices на карточку; полный PUT1001 сохранён.22+1 browser/type/lint/build. Расчёт/валидация полного draft остаётся на клиенте. + +12.3.42: Filters1000/120894 JSON bytes →50 rows/2266 nodes/1880ms dev ready. Global order/граница страниц/полный PUT/403/поиск/сортировка/refresh/cache/clamp/320px/axe проверены;10+1 browser/type/lint/build прошли.12 manualPagination:true остаются. diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index 99e0717a..d2745fe5 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -4,7 +4,7 @@ ## Актуальная точка продолжения — 2026-10-04 -Этап 11Б завершён в границах локальной приёмки (11Б.7); внешний выпуск не проверен. 12.1 принят локально: доступность оболочки/клавиатура/health в описанных сценариях. 12.2.1 принят локально: strict BGP catalog/partial/nullable counters. 12.2.2 принят локально: strict traffic DTO и агрегация без выдуманных точек. 12.2.3 принят локально: observations для server traffic от backend до dashboard. 12.2.4 принят локально: strict servers/probes и unknown server status. 12.2.5 принят локально: реальные ping samples/unknown/ось RTT/Recharts. 12.2.6 принят локально: strict GRE/WireGuard/VXLAN и device failures. 12.2.7 принят локально: strict Internet path snapshot/fallback. 12.2.8 принят локально: подтверждение полного backend сбора. 12.2.9 принят локально: метрики участков и наблюдаемый WAN без эвристической подмены. 12.3.1 принят локально:1000 серверов/штатная пагинация. 12.3.2 принят локально: пагинация CompactDataGrid/1000 строк статистики. 12.3.3 принят локально: порционный DOM очереди проблем. 12.3.4 принят локально: большой BGP каталог/страница при обновлении. Production build и123 профильных browser приняты локально на3978976. 12.2.10 принят локально: обязательные RouterOS поля. 12.3.5 принят локально: страница CompactDataGrid сохраняется при опросе,89 browser и повторный production build прошли. 12.3.6 сохранён: baseline1000 speed probes (ограничение DOM пока не выполнено). 12.3.7 принят локально:50 строк speed-проб/сохранение страницы/глобальная сортировка/1000→1; каталог1001 устройства остаётся в DOM. 12.3.8 принят локально:50 строк ресурсов, URL/поиск/сохранение страницы/1000→1; исправлена pagination оболочки с children, production build и8 больших browser прошли. 12.3.9 принят локально:порционное раскрытие1000 предупреждений ресурсов/клавиатура/axe; исходная ошибка ESLint speedDraft подтверждена. 12.3.10 принят локально:недоступные интерфейсы очищаются в обработчиках,54 browser/полный ESLint/production build прошли. 12.3.11 принят локально:ServerTileRail50 устройств/URL/поиск/клавиатура/две площадки/mobile Sheet/axe обе темы;47 browser и production build прошли. 12.3.12 принят локально:BGP ручная страница при выбранной URL сессии/refresh/reload,16 browser/build прошли. 12.4.1 записан:main1091 сценарий/1088 passed/3 устаревших fixtures; оба исправленных файла6 passed. 12.4.2 принят локально:context205/24 файла и unit28 прошли. 12.3.13 принят локально:wide pivot51×16/ScrollArea/axe/24+2 browser/builds. 12.3.14 принят локально:history200/50 DOM/54+1 browser/build. 12.3.15 принят локально:live расписание1000/page20 error cache/15 browser. 12.3.16 принят локально:certificates1000/50 DOM/refresh деталей/19+3 browser/build. 12.3.17 принят локально:pinning идентификатора/видимость значений/29 browser/build. 12.3.18 принят локально:users1000/поиск всего списка/детали и ошибка refresh/32 browser/build. 12.3.19 принят локально:backups1000/все мобильные действия/возврат focus/39+4 browser/build. 12.3.20 принят локально:независимые speed GET/cache/freshness/58+4 browser/build. 12.3.21 принят локально:strict history DTO/null rates от DB до UI/60+5 browser/unit4/builds. 12.4.3 принят локально:users/backups delta context36 на a558412. 12.3.22 принят локально:shared speed-probes DTO/context8/60+6+47 browser/unit5/builds. 12.3.23 принят локально:strict write DTO/atomic replacement/confirmed scheduler warning/65 browser/HTTP DI JWT/builds. 12.3.24 принят локально:OSPF routes1000/50 DOM/page20/cache/320px/22+1 browser/build. 12.3.25 принят локально:BFD1000/50 DOM/cache/320px/12 browser/build. 12.4.4 принят локально:context213/25 файлов и unit36 прошли на5b2a291. 12.4.5 принят локально:main1110/171 прошли на21859be. 12.3.26 принят локально:strict atomic Ping write/подтверждение каталога и сохранения/история удаления/62 browser/context11/DI6/builds. 12.3.27 принят локально:WireGuard zero/missing counters/UI/backend mapper/29 browser/unit/builds. 12.3.28 принят локально:WireGuard interfaces1000/50 DOM/pinning/actions/cache/29+1 browser/build. 12.3.29 принят локально:WG peers1000/50 DOM/pinning/точный delete target/29+3 browser/build. 12.3.30 принят локально:WG detail1000/50 DOM/320px/клавиатура/31+1 browser/build. 12.3.31 принят локально:WG handshake без ложного online/unknown/7+1 browser/build. 12.3.32 принят локально:WG URL search/tab/status/reload/история/34+4 browser/unit/build. 12.3.33 принят локально:WG strict read/cache/freshness/unknown/40+7 browser/context8/build. 12.3.34 принят локально:VXLAN1000/50 DOM/pinning/export/22 browser/build. 12.3.35 принят локально:GRE1000/50 DOM/pinning/20+1 browser/build. 12.3.36 карта15 оставшихся источников обновлена. 12.3.37 top50 traffic/пустой локальный фильтр/перенос tabs принят в описанных границах. 12.3.38 Communities1000/50 DOM/19 browser/build принят локально. 12.3.39 clipboard ack/error/retry/unmount/5 browser/build принят локально. 12.3.40 recursive groups/endpoints1000/50 DOM/35 browser/build принят локально. 12.3.41 большая форма1000×1000/10 cards/полный PUT/22+1 browser/build принята локально. Следующий блок12.3.42: Filters pagination/порядок и полная main/context регрессия.12.5 отдельно. См. docs/ux-ui-stage-12.md. Внешние ограничения 11Б сохраняются. +Этап 11Б завершён в границах локальной приёмки (11Б.7); внешний выпуск не проверен. 12.1 принят локально: доступность оболочки/клавиатура/health в описанных сценариях. 12.2.1 принят локально: strict BGP catalog/partial/nullable counters. 12.2.2 принят локально: strict traffic DTO и агрегация без выдуманных точек. 12.2.3 принят локально: observations для server traffic от backend до dashboard. 12.2.4 принят локально: strict servers/probes и unknown server status. 12.2.5 принят локально: реальные ping samples/unknown/ось RTT/Recharts. 12.2.6 принят локально: strict GRE/WireGuard/VXLAN и device failures. 12.2.7 принят локально: strict Internet path snapshot/fallback. 12.2.8 принят локально: подтверждение полного backend сбора. 12.2.9 принят локально: метрики участков и наблюдаемый WAN без эвристической подмены. 12.3.1 принят локально:1000 серверов/штатная пагинация. 12.3.2 принят локально: пагинация CompactDataGrid/1000 строк статистики. 12.3.3 принят локально: порционный DOM очереди проблем. 12.3.4 принят локально: большой BGP каталог/страница при обновлении. Production build и123 профильных browser приняты локально на3978976. 12.2.10 принят локально: обязательные RouterOS поля. 12.3.5 принят локально: страница CompactDataGrid сохраняется при опросе,89 browser и повторный production build прошли. 12.3.6 сохранён: baseline1000 speed probes (ограничение DOM пока не выполнено). 12.3.7 принят локально:50 строк speed-проб/сохранение страницы/глобальная сортировка/1000→1; каталог1001 устройства остаётся в DOM. 12.3.8 принят локально:50 строк ресурсов, URL/поиск/сохранение страницы/1000→1; исправлена pagination оболочки с children, production build и8 больших browser прошли. 12.3.9 принят локально:порционное раскрытие1000 предупреждений ресурсов/клавиатура/axe; исходная ошибка ESLint speedDraft подтверждена. 12.3.10 принят локально:недоступные интерфейсы очищаются в обработчиках,54 browser/полный ESLint/production build прошли. 12.3.11 принят локально:ServerTileRail50 устройств/URL/поиск/клавиатура/две площадки/mobile Sheet/axe обе темы;47 browser и production build прошли. 12.3.12 принят локально:BGP ручная страница при выбранной URL сессии/refresh/reload,16 browser/build прошли. 12.4.1 записан:main1091 сценарий/1088 passed/3 устаревших fixtures; оба исправленных файла6 passed. 12.4.2 принят локально:context205/24 файла и unit28 прошли. 12.3.13 принят локально:wide pivot51×16/ScrollArea/axe/24+2 browser/builds. 12.3.14 принят локально:history200/50 DOM/54+1 browser/build. 12.3.15 принят локально:live расписание1000/page20 error cache/15 browser. 12.3.16 принят локально:certificates1000/50 DOM/refresh деталей/19+3 browser/build. 12.3.17 принят локально:pinning идентификатора/видимость значений/29 browser/build. 12.3.18 принят локально:users1000/поиск всего списка/детали и ошибка refresh/32 browser/build. 12.3.19 принят локально:backups1000/все мобильные действия/возврат focus/39+4 browser/build. 12.3.20 принят локально:независимые speed GET/cache/freshness/58+4 browser/build. 12.3.21 принят локально:strict history DTO/null rates от DB до UI/60+5 browser/unit4/builds. 12.4.3 принят локально:users/backups delta context36 на a558412. 12.3.22 принят локально:shared speed-probes DTO/context8/60+6+47 browser/unit5/builds. 12.3.23 принят локально:strict write DTO/atomic replacement/confirmed scheduler warning/65 browser/HTTP DI JWT/builds. 12.3.24 принят локально:OSPF routes1000/50 DOM/page20/cache/320px/22+1 browser/build. 12.3.25 принят локально:BFD1000/50 DOM/cache/320px/12 browser/build. 12.4.4 принят локально:context213/25 файлов и unit36 прошли на5b2a291. 12.4.5 принят локально:main1110/171 прошли на21859be. 12.3.26 принят локально:strict atomic Ping write/подтверждение каталога и сохранения/история удаления/62 browser/context11/DI6/builds. 12.3.27 принят локально:WireGuard zero/missing counters/UI/backend mapper/29 browser/unit/builds. 12.3.28 принят локально:WireGuard interfaces1000/50 DOM/pinning/actions/cache/29+1 browser/build. 12.3.29 принят локально:WG peers1000/50 DOM/pinning/точный delete target/29+3 browser/build. 12.3.30 принят локально:WG detail1000/50 DOM/320px/клавиатура/31+1 browser/build. 12.3.31 принят локально:WG handshake без ложного online/unknown/7+1 browser/build. 12.3.32 принят локально:WG URL search/tab/status/reload/история/34+4 browser/unit/build. 12.3.33 принят локально:WG strict read/cache/freshness/unknown/40+7 browser/context8/build. 12.3.34 принят локально:VXLAN1000/50 DOM/pinning/export/22 browser/build. 12.3.35 принят локально:GRE1000/50 DOM/pinning/20+1 browser/build. 12.3.36 карта15 оставшихся источников обновлена. 12.3.37 top50 traffic/пустой локальный фильтр/перенос tabs принят в описанных границах. 12.3.38 Communities1000/50 DOM/19 browser/build принят локально. 12.3.39 clipboard ack/error/retry/unmount/5 browser/build принят локально. 12.3.40 recursive groups/endpoints1000/50 DOM/35 browser/build принят локально. 12.3.41 большая форма1000×1000/10 cards/полный PUT/22+1 browser/build принята локально. 12.3.42 Filters1000/50 DOM/полный PUT/10+1 browser/build принят локально. Следующий блок12.3.43: Firewall pagination/DnD, затем полная main/context регрессия.12.5 отдельно. См. docs/ux-ui-stage-12.md. Внешние ограничения 11Б сохраняются. Реальные pg_dump/pg_restore, PG rollback и остановка UDP worker требуют внешней приёмки. Датированные продолжения ниже — история; точный следующий шаг также указан в начале [журнала](ux-ui-progress.md). diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index 8ad94727..1492ac1f 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -31,6 +31,14 @@ | 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 | | 12 | Итоговая доступность, адаптивность, производительность и регрессия | В работе;12.1/12.2.1–12.2.10 и12.3.1–12.3.5 и12.3.7–12.3.12 приняты в описанных локальных границах;12.4.1 main регрессия и профильный повтор записаны;12.4.2 context205 и unit28 прошли;12.3.13–12.3.25 приняты локально в описанных границах;12.4.4 context213 и12.4.5 main1110 прошли, 12.3.26–12.3.33 приняты локально; 12.3.34 VXLAN и12.3.35 GRE tunnels приняты; остаются network grids/общая регрессия после delta/внешняя приёмка | +## 12.3.42 — большой список Filters (2026-10-04) + +ReUI pagination50/clamp/закреплённые номер и community; доступные действия44px без hover. Индекс и крайние позиции берутся из полного orderedRules через Map. Поиск сортирует весь срез, очистка поиска возвращает исходный порядок (manualSorting), перемещение отправляет все правила. + +10 профильных browser и финальный large1/1 прошли:1000/120894 JSON bytes →50 rows/2266 nodes/1880ms dev ready. Проверены down r50 через границу страницы, keyboard up обратно, полный PUT1000/403 rollback, search1000/global sort/clear, refresh/page/cache503/блокировка действий/1000→1,320px/ScrollArea/axe. TypeScript без incremental/ESLint и production build прошли. [Filters320px](ux-ui/screens/large-filters-320.png) просмотрен. DTO целиком остаётся в памяти; реальные RouterOS операции не проверены. Старое уведомление ошибки перемещения сохраняется после refresh; это отдельное состояние операции, не успех чтения. + +Осталось12 manualPagination:true specialized grids. Следующий блок12.3.43: Firewall1000/pagination/порядок DnD и действия, точный RouterOS destination через границу страниц. Общая main/context после delta и внешняя12.5 отдельно. Коммит локальный без push. + ## 12.3.41 — большая форма рекурсивного маршрута (2026-10-04) RouteSheet показывает10 endpoints, но хранит весь draft. Предыдущая/следующая страница и прямой переход по номеру endpoint доступны с клавиатуры; add открывает страницу нового элемента, удаление корректирует индекс. Валидация ищет ошибки во всём draft и открывает страницу первого невалидного endpoint. RecursiveGatewayChoices сохраняет прежние карточки/семантику статуса; показывает5 вариантов (выбранный первым) и ищет по всему каталогу IP/name. Ручной gateway ввод сохранён. diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index a78a7c2f..a38de27b 100644 --- a/docs/ux-ui-stage-12.md +++ b/docs/ux-ui-stage-12.md @@ -524,3 +524,12 @@ RouteSheet показывает10 endpoints, но хранит весь draft. Следующий блок12.3.42: Filters1000/порядок через границу страниц/whole-catalog PUT/search/sort/refresh/cache/320px.13 manualPagination:true specialized grids остаются. Общая main/context после delta и внешняя12.5 отдельно. Коммит локальный без push. + +## 12.3.42 — большой список Filters (2026-10-04) + +ReUI pagination50/clamp/закреплённые номер и community; доступные действия44px без hover. Индекс и крайние позиции берутся из полного orderedRules через Map. Поиск сортирует весь срез, очистка поиска возвращает исходный порядок (manualSorting), перемещение отправляет все правила. + +10 профильных browser и финальный large1/1 прошли:1000/120894 JSON bytes →50 rows/2266 nodes/1880ms dev ready. Проверены down r50 через границу страницы, keyboard up обратно, полный PUT1000/403 rollback, search1000/global sort/clear, refresh/page/cache503/блокировка действий/1000→1,320px/ScrollArea/axe. TypeScript без incremental/ESLint и production build прошли. [Filters320px](ux-ui/screens/large-filters-320.png) просмотрен. DTO целиком остаётся в памяти; реальные RouterOS операции не проверены. Старое уведомление ошибки перемещения сохраняется после refresh; это отдельное состояние операции, не успех чтения. + +Осталось12 manualPagination:true specialized grids. Следующий блок12.3.43: Firewall1000/pagination/порядок DnD и действия, точный RouterOS destination через границу страниц. Общая main/context после delta и внешняя12.5 отдельно. Коммит локальный без push. + diff --git a/docs/ux-ui/screens/large-filters-320.png b/docs/ux-ui/screens/large-filters-320.png new file mode 100644 index 0000000000000000000000000000000000000000..fdf0c4b61651ffd1ebc99cf6d09eb759f9a286ff GIT binary patch literal 64110 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

W+Fx(Zw1__ynM zQNxpNeC+uPnUblarSvN2Gye(D`4i-{Lx?M|Lit`+zG_SLWzv>YowNsgZr<@&CVa%H zBAQx{bhS;wxzu|1I*SO=CtE=|4sU$ylXEBG?b0Ei>#pP>H;@BCG7#p4X|fa9gjtn` zL|rSoPGCQSJH`Ym!5f4b&wrSixvJ#Q#|EMK z)kWfzi9XQT`!P5phO~)2yH*^CfVtV()y36PISQa39LsMk)D61$KBM|ImmiT;3Gtg$ zp<*dl^gmYrE*csdEt-<{^7ghO%pWMry`RC=$hoR6ZFyzoMOrX93I%Q|be@i;X2$-$ zfsymCP&`oK4Jz~ImXmq2hac7SR2!7>UzqP@o0cf4XsON*s1y&bRNp*eacxb!Na;sp z24bYw?6q4Q9~x@wuEtx_0n1nQ#ZnnXwL;J&jO*2@Q#YUTjs*Kj2eYxAJrg2zLH&ou ziGu!IWcf zLf}gh@=rUOE~XNE_(rRhOMA?`HM|NiBd6AE%Mx*?doJ{;I0!}R#O}GQH%PKjCcGjJ z_Vzz9yK4$j3g@SLM~AD;wFXnwAJJCY+1cJ+etoHehlj_HpZ~`r07lXalh$A)@Ev^a z>GOVBLsUYuS>1pZDF)Rv(UZOcIWludUH?|!A1<<5hrx9p1wH*-eaP$|65{zGNsE}2 z)257oB#ZIm1V~C!{>i}rfI~t=SJ&40e*!o&Gc)+8IdZzHs*0MR?SJ&{?&BUZG+FQ_ zE&H@goh6;Oamjf}%6lFJL@=M~VV0CJa**)RE)F2De#(Oz*I68|fz7d^Mc}Y7`+%;} zM`2WHl$Blj0|UWN_Nk+xM+L=_TVIW0C9P z>Y!L2WM%w3b7PZJxTc<$*GKIi&`qYtpe1Rn-b3&ZxQEBuxzRE!L`rjUT(3J>SJdHX zOjMTDlno_$!g!0HBnF~G>{)p55`v3L;-c8Y(hae)Y9EjI`=mZk9!NVs{KoMD8X%8` zPf4TbaS?m4ia*blRetdW0gz z@Z#C}y+h9!zIOSOrfQGsYd3FwXMzqty0Bhs@nl5jJg9#GDdL-Vx_&l{^loxVBVlqRtF969%3B8U3`>wh?W&{iYz&Nt8!q+ zV6)#I{R8UX3jbVQ83YY2n3V-u@B+`CWYlvbA4k)4a-{^Cun)A?ik@#(PkVA;viR3v zc(HG>BUL_Vj|dVG5TtzqgG=r_*V0Cl4Srsgl3^_$}}U zJULFYmE?(tPv1K=onA?z={VYy7IdfIkUWJmEFY16gwt0lpSS!xe>eDbU@E$1h6}7S z*{~o2v9Xxlqg_-1aXB4?BRn#B9XpVn_Df<)jFzCO6hC(kJFrN!0L(^IhaAnO6E>M|?W z9n}a6%3IJLduY7;d+Z)g#R!0bFpZb>1DpPvuDV+Po22FUsQ>f1)KdOm`AkOL4<`hd zwwVaEYf?BkF!i+FLAI=YvI(t@BSIH|=>&Su1!t(^nNbD7b=GFw)t8RjW8Gy)Z3nt~ z8ag989hA|QKYr?;uj=@Z0&v_0Ck$?SFr$yVp)bM@r{F2wbTO_eS42ens@7Wf3CvCX zThHSt^Sr+AkGR_zdDSnkkq2IvLc_il{G zM8D%fi@TmCS8o(~Q3FHRlrz8G8E@a;WC4yEr@No-tiI4tq`laAS1tkCq|7BfUwa@| z9ycUZ8LTdgNBA<~y~x7Xuo%(o1K446HM!t6W^S`GR5Ke<3htKRcgq>Ay!z2XdZ6&yLlr_KPajF`jrNS1-^X~{R!L=zZK%5}FuD1Vy=S@#e=5Rr8 zqu3aOoXh#Nq)&E%i{!hvv9q8coejyHoK@`)+I`d>z93ox^B5hC!y>`iff$ujA{sT` zT5Z05mgX}k>#4P}@D)2bJ%g828>$l-@()88z>Dz+-~?x$WO5{Mi0p>-tx}7 z4{+*Y_(8InJUgzU%eouRBM@&346%EBJxm;0t2=?ayXh#lq9AQ{(-?6fgG1U5>fZV` zw45_8z!gQGdwfnotoM;FkX^DuCzAa3)-#~g%N<ziFoB!z!KKMVL&W*P5E!0Z+kq9o#>Xo{ z?vQ>Fy%R+ww$I98&p+T%S3bO5a0f(F=WKVtS=4;#?B3M~qB{7S+%^9BB7PiJ=OhvH z8qo!l9INH4j~JdEyc*x!~`&Jqvi8*p69-r z&s^Cf=2;o?qdpvI&6iR@aoL5-!_fXI0C?b}>n3b2k$eFW=S8z;9Z2a~5*F>p{Dy*p z;*>Mg)$w<{x7Th2mJ|+)%k1I7twOP-`dBQ<_i_}J&$H)*-NCoM(6&1raBZS?2 znmpS?@-BPuMom_OiB30&ocNo@Ni3Gq39@#ew+`9sFKPFx9qRKhw}a$BCltE`C4|DE z6BitcKRkvpQ_88bav1_q|YEZFUu&!_!_b2LA*{ z`J!WSvHQuQU@>!qD#ke%VOzUFyr5-qWtw6nre!Z3qTXB4WwV;@o|fv73QHsFX~^?M z2yjB-Gi#VhygPz*FE$RG{I#|S($XN)rlDlg9s7E-wA|)m-KASq_lAtk zndbRuFz6ay9>hXXLj?NN)?r@rWWN7c%Ip3!EWbjtd+6%3iM5_GShy`2PjUnRmRym- zM=%~@j6qDn-RLbSqjX`1C^9gm-C-P8gPeSH_OD{^o}}yj$?R`Xb!Dp?#gvQIX`+4F z4jzXOJu8w5EgTBYo886`uPghsxcAXDk=E5|9vy~3*V3}y~hq6rQ$9vWL4tQY&fV{jILT>iAubzmKRoqat1;Cs{T!~z}X z<>;aE68e8Dqc z4O`tMgVv230GQV%y{h)o^vjs!wr9+h_4ExOmw@Uz%v5sA1$3fCrzxo;Ma)A{a zGUXBG_!44Rb;Sf&?My1@t9#V6vrT5Snw}^qE9qXZ#O3yn#*eUgc-Zh2RTP`_;;v|z z49Es>>ePQ$^uXT8cG^c2NOW(^&1DUzhnlVkS-JY-_|-%kbIV2>Z*!tjTxS$ z(xz(Ok2OA>Xi^%tI+;omCJbZqokTlL(VzX4Gbrw<7*+2|1142?C*X zSTU#+5#aAaXnNgLxL8TYXUFMTS%xYU4e!0b#ThZFcef1-rH8FmY}FgKMalmqFp6b! zVMvkuS3M}2m+|*E%Lc-KvR&ZgiFVfk;?q)HW>*D3}n|()yBr= z$BWL~)D&Z;@2V#Cll#fj57P2W9u*+)fT(KXS#%RGieF8|pjy#)|47CZs4CQQ+p_%FIM zX?2L&9a!!Yk4E1)(1k*k4Q_sb{vu>EoCcG{>a{Z0YBL5Dl$D_6T>_Ebe@&byh6Fhd zmdRmt#d~6@8UmpAJqE-x`Hd}P-nT;%uUmOOt2W;=$_v8cWq5Bbby_+56v zgwQG5jn_P*+OeX+x1CJ~Me9gy2eh~2I@p@ExERMNuv9f51Sj&)JTRs|ej1XiOEc)9 z5^+-@$^OZU-o@!nZL`Ai1EgZ93T3*Qo5%S_tCVixixwgbG;Gg+P_zC}1R5RWdt8IOWIi9j@c8Y#9qRfJ7Ty(U8 zOvDLi+M}135mjFHqM||5+>o23Y6cav%AcP{MRcx{;17l3KiLREE|2Uzfx5ps%;{8{ zVbcL^&hOzN9}$PFo3l-~fym3S>VFo+ngB^h8AEfM)rRWkZNE3%f12{ee6~^5pc`%v zgt-$F>eT=>xt;yJm72J+t>yrQ5ykaQ?8e8{$`6VBqP#*&)h_2F0nUXZ_;vHF!?-;6 zdQ&C+7DsFO%q{pTgK!n;VMV(I<-Ir#r6dvA%Ll z=H7JPv!NFB$X@Cu*~OPuIa_?)kD0Ay^M`uZ{9s5Xjp+jSZa5kJ+kOq zFI~tV`ve`g&sQi;y`dP7uSZp6`k(~J84u5Yje2gRE_k<_cPS#P29MCu_{f-{B~jV0 z$DZV%z`roiFCy{(PN#G0c*61NeLS2Zb>{Zo(BBGXM&?|_T+?W=eV1IRSu?9n;K`o{Ez`A!*kx`3BpUoX9yG3X#8wN}LsA&2z=OuY9mUoTuzUA~jr zoN`UfkNxFVSM`4os_IbUC+i)ysN>sacdGWTicBjC-_y_0vwD=Rt}`Zs_iPj)YVT~c zyc+o1Yx2CtkGOXKbtJ;YgMERRKMiXpy{8xLYj#015wD$EefYPNYRsej^Z^+l$lWUV z5&l%U7JdoiL*X+FxiI{uwH{`TpyTa6q0(;@(AU7zD6vpPk$FFtI+tz!9u7B7(bZ@S zi^uv=^bKJ#uo{K_eZTc;0wi-R1#sO?-6h(9l?V9F@5Ov4`*v7^QH`-ScJ zWIN=D%=6smmgBwal18Jsv6^Tnw^aJRI+LcE^E!f7iG?R#k$rhFXp6VzjZBsH8KjTV zt!!vK*Rmd?j!H-eWU2Z>T0M(-W(!Nf8)*+bIZen*poPe9_(ZrBJWTEln$|+A7yPVa zbE_5up6h~q83%)wGO!sPo|`*Af0F*QFYp*G4Q1ZmN!E3TvV*ABFo^zqd!B_L z6RCZe((w<$67WHH(tj|6SN?nx{YFOOb-CTpu3&bqpFIyd;gWc`7Gf0>qt)~NP+y`q z;+L(>8KvIQ!x?Vrch0E4-l;0$)9{6nu!ES0N4-2O_Wl^aMAl}{G&6=@nHCB;m#Q)} zyLr?yHdY{A9@%+^@&_@!*k&9(1f`ulV1$?A?sRCUsNGd`OXH6A{TL+u3C|>i-fOoO8|mVL@3Kp2KlP8AnXBzK?tXxfRKq=UcJSu%=X@9b{1vWrlR|OCc5w7e zL;96%4{1=(VZG+_!En0}NSE*5dxUEwhKpf$D1po>-==lYR%q=a^^vPfU*qLM+VzAX zUkSs$)Jb{yx?cpIQ?L1oLi5M*3CuSJ+|!Z`RMwzU&S;&{jAhblQBpTbc-~@)D4^l)_HI5+BI#cNwN;d%ft!3 zwakL+R3W(O_m}C;j?V?x$}Tg53@d^ZLMq1`jq}FP@UoWMQ!~6Y_lDZOToMKl`nK4< zVq^|1vc@)5tm2Noo= zq&BlyjQ7zCimnChhht@psfcSDmX(JZVqYUkDAP;QEucC@YnY^Rw_U2PZ-gJNH&uk- z?Yda;bJ^jql5@nCl!kPhT|Ra!Wd{(oxm9N;px310*bydlPa+6o06TAtUcm< z^viE^maRl`Ll*n$@bq{x2;Jrxe8&4b1fON3t-m7s;CbK}f0-uWt@C-~UxzRIMG>;4 zZu;#o?M~DqSQDlwi|=CygHW&IBzjLL`+X6uOecy7(Uka>`hRxpqHc^Qy%k2jz!5wB z$0%0k=U#9DpOgB1>EQ*Y3+hT&EV@G?tJKg=r`Q}wldD~OaSM7R2>3yWoUzGA{?AK_ z@Mel$+Gp5`%TM$@fMnjmE}NOabxTrc)H~USsn%?c?TV7E-HILTtz2O?FE0L_>2;4??NaYO=-7Nb1B%Hqx_xk1PX{2JsIoz3V6bHHwpSY1Ao@kM*JG>yy#V6v7Zz?2%M z$k^)Nw0#JiY&v@uMvw_Y29IIt>feK@N75M@_4}&tH`M_h9c+l6ShUa29OLu7zF=eg z;LlI-yTNCl-gcxU^d5jK<}nL)%t!7bjbzmhat@u6!p9V*RJQs;+9vCG~_mS#R~ z3vHwW2BWD3%u}g|iszZq8>`z(`a^@??Hqm)7yyiyY3u!n>?)IWOUGx)-g$9RfXu3? z^X2%TF|&1pWwM75uObv=pty9|h>bM}(~gI`(BL4ikm!7bpn`~OTLoBsc|2FzbF1Fl z3nlAUs3hBIRWMp1$30szYU8Vfc@Y*upw{L@PAbl^51j)3fA<31M?*oix@ns907mn# ze=PXoPm1t$OMnc|u@wA=vyd)RLyp*wJ882|E)VX{`WE=EXGH4v9muC1r6FVkayhLl zDr-{GQ_2-@_=|BZpOqc=Y9#;>?b0Nd0(gJ>4vOFD%W1B;H;()7qqDg-)sq|UN1c%g zUB&&Iq>C#nL;`30Rzv~=+3GRuN~PvvQvimamv?}zreMe<_C$&v5@qxjcyxwT5P}_2 z%ZzL(yoo|qv7)jpBkaDyu%d7(!y+iAdByT4;ab!zlO^!1Bm;wNKe*#tlZKZ0s|>YW zCxMnh)g0iC6?}3~S@bO!41Ge`cwcHe2Eo@jThD=iLIl}B|Ls(6h9i5y;$Uiwm$A+D z@;5Oi1lEMWiYgW;I^^L;R>w!5Mj1zL$VT7;X-3&CwI~zlBaYjBghb-@4{pik4$>&| zasZ1&Yic0QBvV4CSc(?%j$cl6Gvb@UT-Pbx#%iSa`=cVl=3=w|Pv$B9FO+Ei(`mBC0}a zw^$e$%6l_l_k%AsJh~d}cDY>=Pr9_PuRHyUrbm-$+-NC=*)QeJO>iMNB@M+SYYI_U zUxVl*ujf8O+^}q1;DM&d3DizaHrkb&noLiTXbmRHhVRbRpRwv5J@xc}MhRK6T<&7- ztd?!~F0n9<3U;WlcfPPvAU>YqC@`_FOUZer*4mg+OCxl3xC|klyMu(4v8mjcG5L=(myN!kb`+s1(&)f5b ze^#3p2XcHKhwQAJv44*2VS9dV>v4?RUZy17q%?4gHXN5+Z*A@e&e(FE!O|GWS1Ts( zmW=#p7(W3{v%~iCyX6_-BjrT`tC0zr{yk>h9TU=y{rNYtVrn>MsD*2)%d`g-m|sTH zQ#&6yTdUR9=;vrYNUZ4@_Ji4yUEP+S-EdYFXC4)ZqCuQmTo66B<20vyd ze8t}AzcNuN6hEXzunr*>J(>f&;91IIM#ah?)28e)=(tcbKQ7}$r-T*cA56t$R|42 zdC#m>-7R2!wB&g_103EZL+(i~+g=!XS=wn;T6Sk^ zb^5!&{`C55(4lhkrjX8N`H=}3<_<1u$a6fhHx76*f75FBcp)a!$NYIM^Ufp4r;%3^ zU4Cmm^io3G=XyNLquP;|Fcuff)W?3rTu||P(zwO`&J)NX?-!cvW1KW6PIA|WyjcW_ z8hw#E=L&ws6$Osb$5X+1ecQDclSX;IzNVDz8~s3{!&zVN5q>n-+hvWu>5IX?{jqBw zIvH@K$CZYNHllsVZve=`*(S5#?g|r05xrpwi>(7-y_*OkVDeLhR`!mZYlqXk89fy7*Ee3X#FMyMcTvctWXB8sr{w%gX2Th7S$nwvgab zNH{BK0_$8lo`zpi(h=6np(4=#I+fSWiU9UMBSOuPVE-Q{6#TE*PX2c@N@=x?&3}1L zOk_zPenFK}Q~>SI&#JrvM{pb$lr z>WX4UEYt~A0A}=?55fcyGLqAA|i0Wkq*1Pi4x zD}Y0oXfN4A#Eke=`$I0E6=~oa?fR6Ao9pUuq_7Z*zN&gBj&-lrl9w)f-9yBmctJhs zp<_Lno=PvDxB1p%!uYYLAPT5^s3h1;s^NY4jmt*fmi1)mn0vnrjDY+kn?;z-?}!%; z21YY{w%3gl!F{&8X(d|1Ybt53Kc;QBKc9J!lb^g{^aHs#^NwP+TAJ{!KZa$nc~eKg zB*brDt$hlY%YpTvOQzFyM~Xn2Dj$aZv_l&H4mZ?evKdbc@gfLQkF&o_Tul~FhaV12 zXR&0C+{HZB!(THoKOd8wce3iS>ASrdizs} zKAnUkyt(aX%^ojFZn)s$=)H3+0L>_oTZ%cGIo+;w=X7-V-cI9Cs^tObx?Te4gE;io z<+4-Px>nRm4*n%mY0TYDpWfmRj>v54nk(5=N^`FV=)^-0GdylPVlD`EGt!OX-};wF z!@KIXQkg7VKIchjhC?tV)4y4+HeSS|G3ZtvJ^eerJ0F+m zxvU@jWs4yh!ezQ|)gLFmr7;IBa_+CMtvGB`lUiRscyqcUOoa=ANI2N5M55VwLl;G85*xz1O@ZAIU=TAEJjKp{KJtGWt|-z zvXGGcNXb|Fgimcg7PD3dkaBd&o>~Q?14z-4NT^hzho&iZclAP-NWAgNQYR>!{?>Sl zLxGc7Jg*moJP*G+H=?a}1BGib&u3uj_Zi^tn%_(y#;WtEZS{5T`giGo8 zHtChRK#!8ZCUQvcboM58i@Cz40rwFfcG&I1VjuFZL`sgiGUG(6%=Uwzw9IU7g(D{ zFIn6M?H{rHEx*MaEVrz=EKp2kib;PepAb4R?d`A=bu9& z{1$cc{%F9|dq*P$=N>J@Crp(YMoW8UO?-C z@qqJ`J2?9euj^rLyj;!fYhN!71qk+mbV+^%Ij!ZU-IIz4MP@yYn|Yt3%lu)~0X!#} ztq0|B*hc~RNw2^+pBd#r;9nf!rx633LOF zO?q?YM{n~Kav!KHFYhgFS&8w_sW|g3Y4AK{+InUWK|ip$4>K-nTTt-o5-0|$g?xaz zMSarruyv1y`9?fS!JYI?Ngwd+U{vw+xPRO93)r+qIr%1oR>z3srMwmMGEUY#>bw5( zR9ti)kH@kvlvU^y-1Y_&MqXX%5T)P(a{KiB_`LsyX zBWqkuOJQ|px8O#Z8D}@USS7Fyl_H4)&T61W`=={fg*HH$)@KLI9bD#uFNza)=A<8P zn>KP_Jod?7vyb$-uXMa8ElLZ@Kx$C!Gn55tM`!+#xI69>*~N0Y%eV=7s5>??Vo2!- z)8_~}^v**GUKuO)J?zOF7AZV1JT|PR`>L-vBCjRNwSDv<%Ghc7=VwP6_|N=q<5l?N zxZ2)o#i@8*uw%V=-z4Re6zcD8=~-IgC43N1&J+}&+G?9Yx^7&cA^5eI6waq@4^A2# zwkzFfJiat%Z|Ri*nRkbZo@m!6gbRgKenzfHuGG9a|Vc5*P z0!=vp(gVt55S|du{15K&`a1!^$A#C9CP!sHyzoDJ2TknjQ7oAG0@f% zU#A*stjcqrerKJLsEb1@`>U77?g2(y?k+_(d9vN+=9*@(GBpkn$Yf%W3vmqS}zZ4DvI>n)t+* z$Wk$+j9kGybcvQLhSRufYn5p>@KSSh|G^G@Jd77bl;XtG@b=z z>b6{SIptj%w@iC)0910QzgtdbZ2v;Q3c8`wEU^aJ-hkyt@An2GqCU6st1h?*s z?mvL)x`?$9_E`(RS9nGjfyl# z3$UeYsEp;%BZw*beN?hTvx2Zg_YMu|-caUX{}oj!VO0o!o`Y<=H*t3FcxPE?K^RL- z*bbp`KDxj9-@Sm&T>=wmdnuO(*vC0u_ewym4);3#Dw#T|OA~$qW{=lp521dFT5^Zs z!ZTuWQuO})yL58327GBFWR_$pq)CwqXdo~`|ELZcd61o5tD|1%>*TEWKj>mK_zzHeJB z@uLN$i|rIypn4x1a6Wa^>&Q1(WK_!SFimzPyx}a2YxPKuurBfxfSWKmA?bL!oVV*| z4`#qfE>NqbquPby0nxR$9zn1|i9)6KDTBn(u>=$zCnWZwHhnonq`w9 z-}p;H=IAuf#mPOltkZ(Iv5StfF*`a;?lDR_Z{BF0q&Li4|8}={VubdRLxJW_b}nN! zy|O^mMlfNE*2H2zbT=Xh^99>Ha~1k)NOT$9F?+#yz|ly&NIEy=r?#QzwHm5-gI>DJT@@ra#;+H|r=OjG3F!WPOtrqR%_>!&^m1 zQB19Kg1J=7`{UeJ2$au|4h6N$C;3-dQjuxQHVX!gQnZhYc_NfhiC%z| zE6*$ULa<;$I59*G&;n;57e?{}AtZ=Cc_Y(A;SGIFr}(0chVV%22-pt~ZjQX=*=u`5 z6nAz$@c)Aw^gkek{$E}$B&>sek=e#!$Poy4+Z|$ z0d@a_JkRx(g~`^J@cUEE+Mk$R6hZ5{30Lu#EICz8=*uXdE4H}!aM(Z!#kw^>;8>U# zF)njGN58d>oz<6*WSnyRzp zv!cl3MqBNNScs&S*ML^?VhKZ&$?lVb#o*&EQJb{4!t!TkDjI&bL*pD|6b@lU7y}*k zVy`rc&T~x4=jd~B0Ud_y&;52PeJC)M-$*^Hg5=btWQt@HzT4BEb?W#kx4x_TNs^Qw z3$lbldV)Lw;ghk^U0^`xs#6jhFEwlrEd#fIz*gu^NgW|&3DOSnbe}6&%awu-HJ8y1 z1biLE-)QR>K@e^8_4>l26~=I5q2#_#c9gc$?WoG;mj8{kZ;p=iUAK&FJKeEuCmp+E z+qP|2Y?~e1wma$AwvEZ}cg{Wc-dSg6*3A4@>s|HLs_$K2z4h#8?`Lldv0gj>AE(3V z9n@}YMiBIRP&ra@N(V*~V+R^2a87S2BG&fs>YK`yu2hCah z_?T^4BM;Ho_CdJD%%5W^Z@t%^k%2^!`OsyMV$Y>Jky}H?@0LNsKXzHZWmNbT!f z104-sCW+kI#`{?euKGmPGPrKR(J?SXySJTz#A2w+977Ynw8kXUFiT)D-uBNEdO|22 zdDpdhd{vB^l^r|r2A$zvSiRS%@A$a22@wcRGdbVvr7>hRUv|Lq;B#+@ay+e7!elaD zaPe>KdNXHZ21<5yW-hUWeH`Lq@@w8Krf>HBYjpaWx#t0{%M1$gb zt=zetGg@`Up^Cv-B;Y}n(E6GS<-*rE03_ABNU|Z7l1K$OzRcFM1^L+ej_Ju>8xkW| z2YhXgE0Hi}M<5QlG+ckR32X-~qqe~~!A03reUFLc-#qYfNxmqc;ccIrC6}*I)!A8N z%&g=sp@uU(TQJ32>e_YFLA@SbNSUUZn3}WRqwdUB1h(bUnt41nY)4&@oaBE)Q zH;9oqmEGqRV;rn7c|r{xw}0G^5RWr6ejN8h`p@u0dmL1cQi3fkr8om}Pb-+g=NsD{tSuY!QMJ^W!gq$e3o#`H^=I_fB&aVaex5mo= zrpHcm!`)^x!@-1R=F>1A54P>un(#qzbhoj@)e|Ws|NAWlT$enD`+m?*o#Rg@cP_qB z=&uHhs(+DK*Sp+m^|mn$3U2!Njl(Py1ng>dMhXY1xYyk)anYIZ3?&*05_WPKT{V(o z+RWxJNbgKOvaO+;c#NIW-27ymg9{?gy3e4;uz|9lJgSJ~Y=H`u&WBdu1*Q{Lz>6^# zl{?HC)c4p|qU1L>k2*~`C5^&PI907(Rm8s&?VrA=7yA`)#1tO{JZg*Y^%;`aJX(T- z=2hd>Q)BdU53a$g$hmXIGS;CRFxAG?3J|aYf}=A)C2x^SS>oZ=5Z0j49XRr5R;fVq zA%J$`V0N3q2zxagl;BaC@0HNLzsJxSmw=;zB`?fw_W<6P>$ME6b!3j4O_oC^!zd&Z zdksLEVgwa?cXGuO3mD31mRVPx=&WkYmiQ6}xzPQIC5S1(gOTAa$20;lI%a4u$`;HFp6i&xC0e1iMTm^Vu%9v={#otj|*!7UAXP+$i1oeU`Gb)3Gy3`=4KtQH1^@7(+MyJ zrG~BH^oC`z9y!Q-B-$!7!cD%!S_;0<0X^g zxnG;J=PhNHp?dUEUv>bmSHhqP$#;LeRo$NWS99aYU*$Zl4TRQdiSI4xI-T}dIznrM zN9X&9ovmllt1zjtb%5)JAa<5q`^;7=HcMEe;pV;1hic7#uPZ=n6iR~58x8A$1ULPe zgxzD7yt#Dr63AY%w4=D}i!&hdQGDpFGQB&bvL%|jUz_&4u5t~Qi0r&;bu=JX{`=xrewIg0OO6?pjbCU;B_MjtS$j~#9#3shSx{!x1RUuNT zM^82bPsh>16|3*@*ZDH-f9@svwEc+YV#H8g%%C~s>WI9~=S@^0@Y?{DF{}ho8p|GW zB9i|S5XFN$JQ@wP7aF{ny_Qj8GdYdk=6Al%*cF*Tar-;GQYdZ!CK;qn#EH5(1QSbi zt(P}HD5fa5^=c%}n!3Eq3bUDvSCa(FlW&HSUdl6xrO5X4EP=jz^J%gq=b~jH4AOWX zje!@OhOx3+d^?N7Rgz*>Q?V)RDgkA5!Xqfp+`LZ_U1u7-7GGONy!QrwTWlDC13A#W z@hjv#+#!G%f9|nZ5^hHyKh|Y3CCPhp$g~s_oVy7c8d)6Hk-^%7gf4sA?fKO@ZSpE4 zzV*DCM(0L~kwDmstePK|pT0s zA_i(rCK8$rQd->hm27QBq(}ZT8THpjjh{)`d{#>t@ab%>46L`+F6?trmT9%~2UTz( zDoQ^5)XkJ%SFyeet7e;?hie}mPHMlY6v8oJ&t<;zYung|t1~qD9*1{x51?zy(nCu* zwK}%RG;3@amBQMc_V{dK9(LU)D1Gv_NsM7-b|JK!;ILbiuj(^*gqW{$X|U|71byu|nDVep zl9mkNp9{u^grRsF5Sizx`*>s225ETg-TVlOGA}jXGEz1K2*t zzS&+!ATIXKW#yFy%QaME+?PS$ zI1tu!HSEkRn@`Tw@jXD3l*ob&Ew7vga)(Pvi0XB+nAv?0-Dk*xRW&j!ZXi~abWYn3 zFz;x;Xc(TVyCslL(_Tvn2iil@7INPtO=TY--7n+q5C0P z=E^Tqu-qm4;j@uUk~GEP5Ld1WhUBE95D7;LR1TBa%A)sdu)1Y5!14hGhK9s(;zv#% ziV5zBS_G}&CJr2QeNQ8Lt_J0y%2!dr5?+H@%;eLmYN3-kxT_}R(b_R#F#pjDXiZ>) z-))wQ6yWjaIXUdf^ebibiHV^R;0bhsBAnG_k7hoVHI^uajgFaAg1QA>64pW`x8}l% z+@zxgxhA=541-}tu;SJ|XSOO;R*mD9UHRhlO$e&}lCI>+eS14a$UxyV+hq+66WFvn zHA*&j6WFL}^ykPxu4COgKz>coCBg`a+Ffbbg+R8kqnoG-8N>9gRMM0bBuHdr4T*ir zb|Sd7D(nO0w(a1ty)LIHiw~HVS=WUM6Qs=Ti2vgw(<4h}?Sez-?>2XgS|3+4n(t&> zP{!=TE&cUHXz<3f5u;=b~5}#1(|9q_g4EhV+ew@NjFORG;rxF4OB<`22Ey z6KrN}01Eli;hTGL4?`>=bDX22uc-IqXbuWNAh=2Jga#*fkcRX9#HiFGD=;%=H`&hOV{q>Hp&Z_O9 zEF3ykrKzaCJ;&S96S9}8C2BlBD~|)L6|2Dumh6EoE&|#vVLem1_;|@6^z_-lAv$Z4 zR#$uozE*22o5gH?t{zsNOiLV`d#@ltRYFkFAU1ogwhkpiKo1aRvX+t?vsCkG1-!3# zZiNk`f%)@&lnH>rbatP6MVSxJORPnz`Vh#MKQ_z%l4bl3%7*s}`)V*V-e)d|MRLE_iUYMWSjNH!zSMutnb06KR&7I!|{S7ez zf>Ad@>EFU2*E`HK?C@PdS}3US@5wt5seQ;PDOm8vFRGBIj*{|&WmBc0Hh#RHFy&b zgBfE!Z>`~bzHyc55L6_hvd)J18E$ftGN?`#KDN`IoI#ER6FnoPxR%x^qZ#(&%m4#B zLMV)6yUYj6^$2YZeU9qagh31Ix63OzT)@6_6h&Mb8~Z390~6iAX2x`=@5lGrS^rc{ zOj*s3xgY^ty?uhDIxmTihl4XhRyOId;X6VCR7xkXNxHthaQzilfez6qM8}d*yr7>; zsvIwdp{Xg!(@_oupfL>Q$Q{dulLzRcGy~vpG5W?|hs8VQ^^5pR?1)}RQ{PkTxNgLj z%S{zKKSzZ4DSC1&kLwf|F#ZyPcxt;-dX4pQA9OwWk>w5s3Lz?yS;88l$%iE+vAaqS zncZ3BxG4m)e_cKlm~2i)*!kuu78X9b8R7zUCL6!Rw`wHw-F6LNm#rX?$l)7-_S-qa zW(ck!X_@e0fTrg3cbC7gVXe<>oyyy@O@1HEJBUP4+GFASI}{)indd7YFWs>HqG4IR z<7y&?zqv%!CFkvU=clHg4!_t;yqq+dMI#$mJ+#$Ye~6)S{?aQPtU;me^bFZ;m~JhR zisxGF!z-X<)#{LXl)DRmGnrsB7Y#^OIw<$%Np*ED55L6@RO6;)2DQ6rdsW%=vfpq= z(+XrJK3SRIlt0z}IUnu`?g8|<{Q{UF*RU$MmYBkv-)4Yq4%|HYR+TI$Yr_NiE_KY3 z`(ps(x-Q(!ytO^lrup?@Gaz>P@)`9@#Mak2;8SFt?@mozz^Pv1TdBTAxDl(TFJpPP+lSn_9MM+r9u6 z6i!@f&hG=rvGkaK`y(2fwd~M3KCdrA7V4MYG(T!Z6fYzg{j1v0XqE{ldd&24$I-MI^BG}JXutF> zUt+v^`XALZvqo+dDP0Rr(Wxs3DYcgmkcxklF(MZ~W^c zsKbjP9C@vVR&%~fDl6|{iM4xjgaD16xf>XXL_ln2a?wyGkre|c#eNmm`XA+EUzJ%fSkk&XWdY8;>LT7ia zEKNz4i{i1iYF}C57K`b#I_^j{9SR1|rterjr(1=H`G}VXBXqCLf|ZfPIr2AVlkv;sr4V-ED5wHdtldJzPn2+-jar zopg-OS}m7K*XuLOXt~cL8&H84N&tHpxq4!MQc#3yiT8hkg z&XG%QWW3pYjeR208)Gdb1UA=)=LX)w<*-sIDU~}lHg@Mbl`gq$e*^;E6?%0m1khL;)zMtC((c;5WUyzhDo)fiI?1t>&mM zCiRxt@|9k;^5dv~T&f%g;45)h z4sL066-6+JjysG7Q{m&4S{38tG-7p#U&WSZ`L%CzyRR!`RlK#QZyl|Xn-Ra89^_Iq zOW$fEi(5^<*mW}CmFv#AdHxF{Itlk*=C_wuTDp?zAz9SO{1uVBm!tVn{UxjPB8#c^ zTUM*MMYSU17IL<$rk^`&%@C(_fjLupy112-Ahu{Tw*XUfQgQtr~NahNjkQPdFEB0eWqc^JPmc{PhU?9lbRmZ+Cnn%)83xs zl@q!c%QLBIc;f|~_2nuL;6+?78cX{|am|{+`t9R8FI90?JmI6Jl6RnM&k0Z+i1YaQ z!1ev**X&}|x|e}3l4L+p7C_68KH>LoY~_CB$se1L)-*S#u-tpGB>oFk$WZ>zsKT!I zpQs`VX!XCN3T#|ED^$YJiO5tGLtXpko9_TmVkF-Fp&?PCxS8X-VzOJZaXtrFIKs77 zs9oZ~^>A}Im0o5HvTJnLsZ1VSeS9`w8>@^*=dF41Uy%%SRBGJxzsZaq;?q9HUdu}8 z(d2~=IvEX-K%LMD%@ldrx!DBR0ciei0dBvi{W*bu8ouG-tNW>0^?&yg{_K0t`3UTE z&u}iOBl#T+fe)g&e)qG<*C@ZcpaA|`WtpoLTD9J1+xwH@OXXX#`Z#euo=tYC^AQOj z0yPO`h@!&EOnoyGav0xaK~qou>Fej34~_0=AoE)Xp46DqH8UoyZkw5CrJ*qnpQbjy zcLU#U&jbGOZG&uZ1$~ZkYL)M(s0VLJpCHo6ISU^ITYGRqtK8;1ZycVDYNg{Y6R8b zDt-KAK1MBnLmX~5JsubH#xV4=L9jOT5T9%M**nz!p>=rV8DeoL9Su6V9=1A`=5y8JX}S$F6knvCAk!E{QsLfp1qiN> zz-{y(3;OVQS|}QOXBg9`y(mGrb3Mgu#YtWz`VD@08vWVCul8#XEN+q!R8rl(67=!% z6qS=a#i_{UO<1q ziU~sIdw&p!wsdiWk^w)(OjntL^ch)1V^U;Y;)Eq_ZG|X9W%x(xvIsMXHzmGLTnW&) zdeR(}5?M#+e_?7o{$gV$C_ICaskLi^=5^8uN~vfX5Hs0)z!JpwcnySFARECW6Yu)g zpx@JahRF4&Ea!ukQV_Oplld|CWg(kDQ4Z+kpqm2NvwKF41iVJ2hEvNZuLl_6qF}Ed z4{kf3^%GKPZu^*~2r0QRx7)hww3c{=-c z?zxFx0ht^INGe>L{3KsH6~jp1$;uvL3T_4BEDPf(Kem&$9V1Xwcb!vX_mgP41_xi# zs>;mEh(RalFPuY>UdkNz{1T#t#Dk21>i02@Fx2DdCOfwyB{!+d-PyN~2GWh2Kjx4O9aE+&zbxcECQ9Dfr&dV{wpm~!SBwA6;Lf1b{ce#c{17!azTqTw-J8J|m^;YOwlK!~7g;!%^Fun5n5;-13Z+?-iIMX~KDZu<34jiN@ z>|2br@G{%JH%#@tg#vsO6kt(#z#VhkzT$#N3{}XI0&?y>x_gwnwNR;jF1xq(o`qE0 zP1k0kv{25j#ccrfRs)s~-soN$(u?`bnqbO!DcmNMQ;kNgF`5`eg0U8_-X9cZ6Kfg* zMyiU%ys;Qbkp|jNJRz{9Ba7N=*xda6D(By%3zV;dy^Dh8^=vUS* zrT7;yqx~wc*?ZIqf+=|(F0@n6McvJ_yop{aDMEBqT8T9r>OZLt`Je={1stumF@wgy)^cE5riR*(cZ|HkI9r1mYSqJv2-W{f( zlMtahLS~Y8&gkhh%0i^@y=2ZntKyGv=OuJ>F}5=bj42<^II-V%Dkj;To4>KTi_e_i zLAW{uU?Yc~cCM|yMg`4Z=^8r4S!rd|^78vm zTZx(qELR17{)o&U_lUIFUub!H8Mz)|(`Pmrd`b0@az5_1oO0gtZBK)9 z?irikt9uyrljry}UboBfzwbDO^ZhW429g8&6cmwha9osSe2M(Vl_ys@0zAr9v+4WM z;i@`XXk=Aefq%Fad@kYzUY)v$k}~0gZS{FAp2tH?ORTRVetyia(aDRFL`M+&*LUb7*`1{Lk{7`#1|k5u>HA${{NWo)Avp zm#(~KH=l+L1F?$Ne(Oexa(p8q4w#I_;!{rDfw+u8H50)J+&`Wh2)8kVIW@Vlzs0@m ztH3||D)7IiH;p3iE97(t+RQdIzf*zd&g{9rviBF-)Fh#(R7UwfD`q$#*wF4x;={Fp zn)ncm^VG3Arlf)!zNTb9wHxleL>?FEhfi^u!e@xmCWx;ZE!85s^<46NE)}77d3iT64x)d#4v^=zQNPH6b+}sO-;FXIKGBEOReq^$CN zg{Z)_=4e@5j*9Jjeagh0>V_Pzcb*>#(`7VvAXbQOy^zUd%>7~ek?D{Ak}f;f~}XFgzYlR9N|#?swDv_~8BE5SYsFO|+%x^h?^w%X=sX{XZon z9hqQ+ExasB=|@__FCospLG3mgAq`J`=<8&%jc)rM$AIMJFiVkk`SMmML7a62yr+?x zFE?87RCOLX&^=7$|LB2I{i&hSTF2_c_ko%>Y-Lx<&j$4mA<{WZ>@hOlMAhtK zY|lSsH$HFZJO2qFX1ZX8U}R$U6VcdfH8c8nSr{h5SqZIUg*zbP68HW7tc8Y|BN&! zyP@=%OX+5Q`|4lm>`nZ^0POgO1mL_rwN3}4%twT)*K{nUn20fnB#p6M|1G+KH{+I3 z^QLfYn7Pm_W4ygRWBD~kX5H*jmvFrDtnIx6#k64Z`1})CfK-=SiPhq z`Nou4p8L0qWbrFK*K55RmMBVYJ6f~W z0Pn$HSf5EMYzprm>JfjNE`N-TBVnD7jq!(DxRg)^oFxPe+|Llheh`_bKAieMst4a} z2wRDDx4iRsP2dCyzRqVts|V|C{_eU=l@K^%BdyqbS>%p^e|8|tA;S2Ca*+R_>QJZ> z<(~SQ<+oO*QdUTtQ74PH%T2N*;!#ZQ?p9R%z?TR!l*W4T_;C zjMR55scY4rSRhb&+WTH+Fx$B&+R93i2U}nTG_spy+~^+i(=QfV<<0#h%Ux}ZnK<=U zdfJ7_tGm+Gg|9~B5#&QAw6Q_><+1!ux^_r2Hhp=b5584N8ogb=T+(*V64D@JU#6)s2nl)H!!rLaHropsC`kMF-lZ^Z95~2Kgz=}OTd?r zuG6wXlCd(J%CBTIxkb32)s~5f4ywoCJc{3HW>ykBZ&y|_WBl!qsI8EyqeDI4MPq*a zX6XooCp`bBhQM!(x!dOHB9xH*GwL0`Wgg6yGy|}QC83j^y+DCipluX6Mu7 zeB#}4hYh<%WDIcMt%9cN0b0QP>=_b?p4d7!S~;l#_3Zp&^>=A0SvdYu3cSKD=P~O< zB@(aFXK{a1AnXryqiWLin- zh7ZfMxABq1p1kGgt<2Ivinszd(9ukIoqU zpy<6AGV- z;Es-$E#m((cXU7z+`R$a(TQA@H)kw!>f7z4+!K~N9BjKUufdJgAA~&gV}z71L+aVc zme7T^l%rqNH!$5JNj_Q-WI~OVFH^pB2evckzS}3|Em|!zky5F=~;G%^%gU+j>SDueZBZva$zfs#cHaKZ`}})|y45v> zy}UjAQoK`Lr%Ny|dcc&k^K=G>X??@7DJ2q?VPfosSFTAMw|6UbNaxfLza03)Lx&bhkN;tJlgt?`cI6FHV|EJ%ewMu4!0@4oWK?3 z!82~dAls!Bf(lS#-uKYBNH(oDz^d|nh$rUr1F9~XM~pNr*B|4)E&*M~lQLa^xEAhM zzYAK!y?Pv0bIKCs{D$XCY)vPlAZV)m$wmDxDt((`dpN(-QpLvNi-EEnQRWaYd)P&h9Nb(w~)Z0HXi0lH4Vs~ecD)2d33B}Wfx1?Hq8 zmaALKs<@lD$z?QdeIEdJ)$f={D-NqG?ics6AYZ?hHpI5?EO21SZDrV;X=scVe||UY z#BgtSqkUA4NX7~d0U|2gBEIX!icqs)+nC|?HH;bT&Mx?MXca!@18e8GJJY$w>DhQc z;2ct(+d797xJEr_0Fj;2Vxr97icb&jo9x0@fe%fSn{kpa2Yeq!)s3CcOr`zeD;NeZ#GqMFrg%RaCji|YCR~BgZ z_&8E~L*QCrmd;3mZhU31n*o}wO2fR^^}+PC^_r;Q1IKlc5jT%UFJE;@eb&DMGTCmu zih2=x3cql-o``kTmIO5ZiWdOS56GEX^F`%X@4?uJyv;-yEBY0%otO_lY`c|$<7|2N zG|Shtg|LAdm-Oib&adbdrXNp79HM+XRgi+Y9et~Fm5T1R3&-SxL1tyUXl#jVODC~- zGymMZP2R}r@OJhsW&aqWLh$!~sP5>W#n$i4Z)~#_1~&L6mEI>jx_8DK9bOa&(|(s6 zPX@nx5FP2KIvvno;o94Q4ZMjPLMKf?&5a}Vt+~IYp9q;^U<~)psxPD(?zYA){f;iiP;6zOo|&;ew}RxH8E7m&&X$+Ok}g|W z?gid6pyZ6n#)Y;Widf%1kY48^@r(0(kMM-*It%Cr@)QwiJa5l#5{5T&VA|}(P&$DG zPsAO&K+S&sMy2<-TZ;>G0b{AA zL;9}2t8^WmBl1WbrrpSv#5*^iz|iMKozGZ%Ks7=ACgZBWpR6p0W|!hO2EU#-FY!9F z_7o9M?{q_7**aU@E`yT;@sbK2GGhhVI_E@K=sJD^6aFK*oHa&>?v#zMv|Gc1do&RC zL?ihs>*8P?XbQApGd4B*7u^e~G}ZVREP9V{DjQwkoi$lShh{~mWBs`n1oFrCg>>MR zwJEW-Q0a!Q&yT^7*^3tjn9x(E5tT;?B_Gw_wGb-A-fsol+941y%+!yd6B;&%h`8qh zDH6D_BF;Nxs4hqgr7-uylEDq_^+(xL8W{%g+Uh%E+gMMdOd=Jx?y~wXGgY+@-wjJ< z`m;1}2Ml`ldm@_I>S+l#rWq4v)Rv$^=2u{PhmxyQTvKY~W}3mY%H)BZ?`=KApfqsP zU#RRS^csKR7@3}epvgOH4?=F42+kgvT{b@A1X@deQYuE12yK&!*zl#eICI)_#*Lz4 z@8x6Yfxwi3h+Eb=SQ5pbhW4ISVA9*lubyzV zNtVTHsTW2fqEG2Dp@)26dF_cq)(xc{#u(&OLat#mKh57TbFV`Jn&`ZJeKD@#c2AMt zL!DI(dyIsbrCM6NxY;zz&|Ez**5{Qiaj&;)1GLVp?)myq+$u{M^*I}5SB52^J2Qag zhXxQ$_gy$fK1@UxGm5RGHsp0n@sPkExi3y_C>Cven&#SD{y6?p;aOdM@6^2ioL$#n zd~gJ2Wp{N+siB|w3ZHSoSfg(^`OI&oJ&204ZVmygV~zb;k)g6}imiZ0M5(E`ur)ho z;w#KMiWsm~2rF@PAI*4a_ucQTU`mk?q?;dI%Do5;6t#{_MZ{hTJ*Eq6j*0XMG{o}f^IS@;3e1E8 zIK?)yYSM-pw$asW7AYYsWL%)I3}HJVn)cvkOY^ZEo!61}h^RPSzGr8F%d%Ik6LfsL z%=0`C4|wTb+H9+-u`_+#cbemSLVTQ%XFo?gB*z<4K~K-u;hD~H7wbMdZ-d8bHug z%a46JK1%hN(^=GhuK~bgZB@av_3OPJ`3dbQM<7Sn($-7oAh9-}F@aE80YgXEUVZiw zMKBd~R;P`vdvVdPU? zO`B9lR>I%;73Q((^0S)9$iaiPoao^%^Y7ZYzDc*Rp^b~FWZdUWc(~d9imbPTFOxx- zCAIP70pZX(X=_|9prshgJUA)$4kM&9+BJGdOj*}S2o@a>qG7HMdPAwVMUNP5K5N0p$Z70|JF7=b>wrbRgzbUmMQx+lewQ#M%0eK0c< z(y|MmZPeXQ84@&F>jz1s=2(Lz&Gl23v3S)T%h!!j9H;V85Qs-%e|yjV`v9K*|J4KgGg z3i?*h^S<-);V#q6^`0QCKM~C2%(y@x*Jkc`7)z64BlQI%e(jF}o|cNuYUDKt>2(aG zW9#L7{Pn`eN9-0uZ{fgjGp2ShIjwpoEvR1}!N~s-7#HmTM-lW-O|erXt~*uuouTeX z(aB8Hr<6%ckK@I&up$|KH0}$C+N*D`XQU}S#_I90KAOa#Wkdh5yb25Zu4Coks9XiM z8l1N38`kU`7=??6dNFQBQDxI)Pl$ob*(0l=Itz4(t5yB|Jq_ML*3K!hM?*lg>dt5iVZ2 zN4#>bCDY{OVly>XO;6qIi7V(xr~7mkY38jhuge$xPDNjCT?{Fmo`QBDWMNi&4GoRE zQN8ctl4Q_RYT5@1_Wt@aNgD9I|BaV7Xv4*!?KC&`drYHw>wTB~JaG^oA5TR3HZtD9 zWiKH`P13yEm1SspLx)F69_kQ$;l?g&Mo5^ViD<3%NXcL*mzyQGCVOnu6mF1KI;o$DW>f`0E)?(7dH^fIzglW;Em%vt z+MMV4n{gAL$=S|Z&2KKwe?2Vb=9NntA}Q(Gz1uXxEWs1(fZrh4Y+O%&;PanPC$}TQ zx(;`nmfj#*f0}+ipt>4Atc5UlUw)Vl=VidNkY`hWuqvkc>b-t+H|I>mEw8d?zFU7? z3u(h9pT(oyUJB88vO`~!dk$&CzU=;tJ3!Os)>VVef|>dGO1MNwH!^DLa)qGRPk#pT zvdX?WO$7ucOn(~&F5PJI%CS63q7af5TAwAnXk|S_p;0dlU8z2l+;H#U2((c2JP;ZX z!PQe&|EJizbohffX-v>r1lUFGr!B+c?=^9+s#yOOhaJnG#78(1sBwZK(JkX{BI@q& z4}AU)ezbS?W^^r<8*2C<`Y-^so()DyMn35fv8M@j{a=3j%w+Ml9y=j(5hmps?WUGc z#7+kl)w0;a3RJ9qy))4!aRkFNZOBw#49)T*;SuZ1YS;Hm7v!&T-YhYit@cn^%<^=b z%jLWNUKqpU11Yt`zTy-fLKaK z1XSgJ#)1;WMx=Y_9q!n`BfdVnFQ+FKcS%4T(O^hCGT!RoyKWr`ytZ{{q67IKc@s3& z);Vq|;A}0Nam~o8B$!+T&bN(wA~KN;icR~F;(V@YxtYB7wqI>sj22vs8pi7qgaxzh z6Rvx%cMK~IwPd+4J6Sxv6>ST|=jg&qyK|7Vd$;SEO|+<{u&uqErp%)Yc+u87*|Ah# zJXo`61-Vhg9!cZYqdY-@(N5BCU4!I^F#6ZE=Bdwq$75mPX>qxa#d2xlokms}wth+s zpK|qmemBtd90j$mnk%vU8j^?`nB@PDUO;(e008120~2CxktRf^!io%dcU0++qqF8$ zPn3a`C)EVUjwd2KjB3Sxw1Fq%tG+F8NMWH+|6ZvS_%%7M#_+!x#Qyhhm`^wk%GSvS z(tmDgX#)xho<{}NmF$EYAmHsvBf`Y_f49G)v9cvWNZXMs;f^aq zLxJXDEoDi!Xk^l)!z@z<@@MFY2ZLMSjyKo-rKF|IbMY=iNDGHD3eErMIA>C*AM`zW zPw2-g?1E;#LO=;znkeXWn|zrcEf5kED2+tVjN>n#h;x8iRlq-1jsyJOb<84r=3#gq zOUe%c4B#v<(O)|w7a(<@zuQSlCafn05wT)vIxStM00hu?{qcI-MZa2mc!Kk!%j7C$ z<&+7FDo!nz#m8Gs@JbiMZsi@+jIX{fZ|AeTf1_BHhS0uR?bWj%KNVTzjh4(XJdRL` zTc-d3&?^JYM>1&e!nM;v_xC34-r@j#{kr7*{O}it5gqBcUk|QvwvfBnJg!c%ROOh| z;C?PLRlO;>Kl!SJ4i2fWf10>ra2xGp9>o^D&UM#bYhv!}Bz5_!e|cjS9sw*|#r7%V zc_8R_S8KD@u~?I|6Vp+U*oS}AUG`kV>eyQr5dFF2>y*~FKt>iVKdfOK(-k;`$rPY+ zNI)hte5PwCNQu>Hc=U))6hg+#+`sI2VFVINhL4rJ+44(~?5b9e3m$X?+!mT>cVDOV zF%AHaq+S%@^=5u-$mXw}-jYlayq_64Aj)~!G|~hL5C3YG4cmF@ z+wv1uO+^Su;Z!Plz1>ytw@-`a5hn-b1ikR<=+v^PHfgfx)ej-zLqt_zw(+q$q9`Rq zalS9x)a6b|MuBe=Jv-oMaD>rJq$MBA%zD$=?kSd85YVci4nMRd7ANO_azDZ^xi&^{ zyO9wBP0%Nej|8-4D|=oZZ-9OWO;hM}xcVkKH96hp$=66}$o~nbw>?pe-)Ac7FBjbV zoxx>jZGk*g9x8AL6^U5`$A^uPbRMTaTw-yGTiOI-c|V+niLt+cX{fu|t^%IP=^{WA zV!}iuO406q%gh=%sWguEO_fH!1tIHHs|DS~yDCk9u9~S)?WZ!TB7;>+?$HVn_WUx; z$eu$&B!dbsSiYEAho3KHb^LPsw2{HEqnnM(WaEtMdVH#bT^Oj73UI$?X?VUj!pd@E=9tyh z)=TKpA5#n|8M;2Rd!(>zfqZ7`3CS&Dq`kv^|6xI<@r(F|R>P-&T>A=8d*Wh?7MB+e zuc*D=`&VL{8c0xxGTe(}f(-^9IcX@&9)U)l%ejvyA(4!RomE1@u0{##$KgVIWC)o# zyH|O62(lXRUQ|^?tEIfh{4ekFAu{2bZG3s{EO)Ol+O_<2B`^jBULPm@pp0J5q-G4G z9;o7b9f`|QeA=^(zt7hH96);_fx-$Dk}~k)IS-=)=A25Oij_iac6Y{s1!Fp<3?!)j zmp>|KeYhUec_J_M*Zs8tLqACr4TJb7Y*Z;zJ~XB@y(rZ;{NN$>ACxq=mpc?Il=RdJ znmzfBbl|TOBX-A`Dh-jKPl^)RLp;17(k>RKM3pe6vDKYx`*qSDX~N;4O&lxXSV0s8cKkun6pHccnZazNbo<#>gOpj?XN96Ub!t@ zZR4?(2x&kQFrmQ&3l9+tx3sk#9Bx*W_YshNB}4M@flx(509Y*=B^SgFYxz)sSKYv# zxn>&(abT+t7f&QzA19?`kx z07H=kOh#czjp+7gySwn8ce=r$0Kd;Bmgd5uB7eS7V&oduaY>apd%#Q?L{5|8;l-he zjKRwCXoU0>nI;{fO)%@-e6hZP1U@^}xt3|*RWf3+4jD1)J<**Z|8HM}7p&f~T^quEr0p(*48a z%#uc-;#Wh%)BJINsfyfozKh&dfLf48wN5Jtpn{58PYlh)&vs)12mp3OP{BGQp+b!w zfuLJAtD#_@| z4v=s#=OrqNBRI3~(ntK&9&(!~dLnzTBy~GiPeft@&`itm^9O>aOZq)ocBp=k50)>EQ1-V3KCV6Acco zVr1;}fqDw?F!c6=xf)vUBMZqQ#^hlI3MAR03^x9rxx$r%VRM$6^Db%^s)UvQK*$dF z%ERhG@!VWf15by?tA;OPgu+jJH@p&D&*cL22HQwUdnBQkaRgbamaDAC-QKE?d7|Nm z_w~#3>MmdPS+wNW)ya=z``x02i}u;{qq>>9(>u}048E`6HcTpZs>D8JugnS-Y!``G z4@c%hIhlB2-m|vkVJiP?DFMFuZ3Tpbe*6B$SpkQ^?yp7j} zGi95Eng_1Gpq%@v$!HVsvGg}t%!L1F+kypN79hgS`94p+=Va`D;L4qPPZ%0_)(Bz9 z!qF(yWt1n_Fi>o3pZ##l=sh{uc2hB0tiz%c-aV4({B_=a^mn5Tk}$iiW%GmU_v zmEl%|^XPlJ`Sz~EPE$^7R3?m_#)F**@bPiiq11MA$RD^O|Nb{}u~N_4zjN zeADa%T?Cun9*6m%q0P2e4o+7~9tGqDCgY10{z<4vlcdKEL@E=_syI75BrsCW@uB)0 zdrIW5eQJWjp^(;51^Z>cf4ZG`LPxf8;UiUTN51-F;4FsuMq(oa7$ zGJ>0)Q*?@~8HQzLnuA5l2Sfa1kZ?U1p~9b@$tn#=o7&rwga*p^3;}5_|#bP)f%4jl4p7Z*=VowgDp|f-Xen>t^AzmL(%p+lSbaf z8~v6bwgLyB*TF#-4Og}WZk^q|O!&Q3mK?j0Jzhp48@50I;|;Az5E|7*(2c*T<3ny@ zlZ!@;c<(sJ<=$)--k&KO9;X(S6(Ln69bfp*v zZzM~^1<$rv)L=zol+6d#yT3VK?va1<$cticr)r6P^qV*i3>Tf?n81UNj^@AMA(}83*xTJNzh}>N zn+mPUwKnF;Iud|Pg{vwG4L)CfT9eXdONgSjbIu#g4~2rCaf7T%9C213DIL%6di7#&BtJwA{c!eW>W)h*Rc2mY+-NC@#3V$0sH&7GgaJ+*`0@;dU?AMT{8w5ku2^upC|%Jv34c3eQ6 z3fWpklLOKD15g2e&=AU)kU`LKCc8g}DSF$e2$ArmM5NPp@7;}3HS6aq8V9`0U*_=u z&`9vO|1m^$4+vAE=G!P)qLX6xPg6KjBidq$Q#crorJYUI zKWXu64VUtTj&giP6W3;l&OxfDxuWTztQJxK;W24e6x40V&}{3yWrPN(5W!6B4xbB+ zV5`cYwz86M0)L3O{*1;N=QwTivfsQBkaOn?`=WZzWs!{RrLOI{UdoPxlie*BQBn3{ zSp}C8^YYykslOx&y$_N0?f7*YEDHM`^BSt$w5C&)QTEn&w_6}M@rqJLX@@GBx=UNv z`LzhR?8~F34PL`YJEEEkK>mjo&|M`34fss%1!1?EN&e~i@%NW%iCy>Qinr1|HeoJD zm@By@`#|+>b%Aj$cVEl>AGNnaU`-ceLo%aZ4YBO`R}3K(uC9$XQU%hgto*vI>p_1O zcfXtrDJ-W^=lGj3g?YjNKns3bth_8SvjN% z;RBn5VM`~%1JuMWsD4N)ksV(xA< zYXr85m6jIkAG4ku$E+`w- zlz>+;u20VQJ3#TzuFwSDkUv%$#a5#WmCbdT4^AXb`=(wHvp7ti=DI*%jKn9*+nkR6 z0NN-jO29vQd-3Jmw}{1MNn?Y~JL6Y`uK8Vkw9;htbsF*!ZiC4~W$B(_cL!SW1w3)- z70DwYJFHO{fv4@a}(tACG@>_|!c%NH_u(e87Djh0#xjpk!2Mbk%(vv!l=;CfA z0G?Azv(c}>)Y`_c(pPm^XQtu)tFIy9nNPKM<25<`x~e!DyF1{*tXn|}fXd9=2BYDs zfGHWr+B_INpJ{UTOl7Rcv}0;^!J)MQFWK$Cq{-SuO#x#>0&;ifQALodAf(Uj?96UV zRA?niICr?NM0&v5zH9+|fd4$1$wF8B*)yY%+?Urw;&tPV0rPQ~nVifO!jrm8KhCl< zZ)sn$8)piHqxNqGy>d;97(GKPs3>bRNXvxTvTbw^inh5@|3Vk*@O>isMHWXBvw0Ff zJUra>whnT%o7y+b`98bouBqYVtrb&&JzaC>NpOXbcp4_ytJmC=}^=g3@SS^y&|} zS=N{Wb-i`c>#@7GJC{TFVl$nsG~@VA%1o|y`4U%3&kJ`u;tk78Spy_dM{9oje`v`u z{efDJbIF%CqZf`Z(1itax(|78X4WKGBxt5IXEryZqnmeZF=o8qUrYaq)?k*SFYM_l{RAt)m`^B^lo?43 zch<@GCV*V*%1*XtWl+Edz3*^l#1LA%U+tdtbtSI}H(lB;XMsvYKF$4!EbfD99qdlk z23Np44ffa8a$_Nw^SYG12<~=!ZH8?w^u=9$)~&SN%W6jY2pC19gk-m>`|N6pr}}$~ z41)L!?|bW-7Fu1;PTF=|oh%|XA_2~2%wbcfJM)d2DbK45mHPP2SF@%G*_`;yTMQ2&txDc?}?Q+?+H_#03xyu5R31I(mT zD`SXPE*+DsGbfq+K+sv)Wv}>FJ;2^I-_Br~mO(4s{L3<(3OUWG4I}LaJc9h|OyF&P zVg9Vz%9(QCH%W-$iNEvOKF#de$oS;QR4YXf_N`P--*cRfm551ZD)|1SB`g8w+0Vlt zK0IW6obF0lqN|{DORXQ;e7SRhqUq%!XP&)!R^z8D*=&J?7P@@W&>n^V!0KqlSqn>n z0?U-g+IRA4ncwJbDk%Y(e5#WVJ*(%9FZLb%tfcAJ<;yzHnLn| zLY9g56cCGwbe2?`2;Q()tp_Eb(>qy7H{tS zO3(7y2@K+d(ZX$JIQg4tNLriHf!Z1$8QL7u?j$6K<2KRQ^D=T#VaZ6Oj=Q5`_gtxI zmrDzHbL$My(o}JL7Ce8^C+>8~=!>1ErI@ICvL<*l2#dl93S1~r z`QEdP`1Ifbh7$*7Z;F{@zMR`7H+(Y%JH_g6rC6avlWD+xY^6t@099@K*2)|a`>?nI z9-xBkggtd!uxXX2N0eQYjx|QJHk%9z<2d{tZPfH`t1w2tUQVYRM2gw9Q&4}c_e;01 zIzq~t zMN5xDT!C3g_A95WEL}!yI$6MP{q#TLxlVwvD4K^N&T=injf^_F_bQHt$6dsHYvqY> zz9sJ6`bK9ToMVTXPJgDmOE`L)jTAx6Xm%o>qv6V< zh2#^~N_Z51A;`MwTOPV`@Gt|WqJK82aS>J@8uc{aRV_x}G@+7XI&~1@S3&|H#Uvm<=4wjP zS5kpLaDw3h$z&7|0{3vUB2no`_;K*P#|L4~2zJ~>hpJp!hf(gp=k=3I*O154t7 z8cfo!MpJ|fzulU{idH09=aXl{i}yJFT*JDx^4yWZ?Ne;kp8)Hy7QwIp2q?&ZcBoIU z{o^SMMkVnY&@qNb}6uM)Lkjz}L4?Majx2gRAB+#S?xY`rOEIO}lEdU=#cz`hKGz#Q`r-NpY5mx4X zYS|-H9H8rsUEEMWku(x0^>IiOE^BCbEoUAH~eCni*t9ic(kA_xg%uUs1PBvX=L+Z z9m^jofKO@PSwT@d{X=)@3(u$G`=SO@kqjXs`2PsOPSx^9yIQ**eB%5m-VV1CZ8%a+ zijRFO`5tM0*1rXQA0`k%qjE1>jqnOS^LVLUmcC6Wr4)t5fb>g3^Fe5LaEkeHu^nix zR~q(?UCo!agL@x#v+7`eqCFm`0i(}m#*U0mqVMXhNA^Ve6fB8ttZxf(<5$;8td-Nx zN~H!;6010ttc?>UE65v^3fY;W2MguEI^*ldu6nzZiAAutsg0dRN*;`&1JJWD9td@o zzYFGns?Ekgog$OxM!NxZneJL`+m56=S5jDR4vHpE z_1Rk~e|=|v(ZrihEb4~Wi81_6%28Dg7-zsAHSE$!|KK35Bg?s zmhp4=#x7d&gaas3yHGJmdYw?Od5+)2T%|aZjXBR>0=3-_Z}rP5QK|96PVpszR{L+< z$*l9%+a#L+4)L^CcARMnnz+FoVY(TA!s7aCdTMn=!ruJBY+6>}ru2AsEPE40wlIIr z=V^4tCx z3LYMnUxS{U3Ouac4pETQb>OPlEk^ezEk?uCOEWEx^PP`vfUAfR6GYIDK%`lhJR=Qmtqi2_|aV})`!)(Dpl<}Sw3qoZs$`YpS(yz z{*@#aEJ<|k`*fJgMa!wg%52(kyW-U~t8}MyDIh;}s0%=BtNz?Dtd%lDsXiqBDTd<% zE;8gknxvG3NrqV^Qx?2ad*Y2dK{8U-{wK5@n-8>GKa9!*Ppz(Dwf#0wF+^!!$|K2S zuH5XVyQg*NA)pB>E3~?&Sew|p=ey`^sw|hm>0Qh*E?ouMCm@bhq_KV0l!t+tknSe>vi zNlcpC^ov`j?&JRvkjdRplcR@k!*?>KWoABuK`)Fr0{DVOO15j?F{K}J&gchWAWs^M z?PQ?|nNnB^KE3SxPSDgVOSFwlCOB_7FhWafH9k-~bDJD_ljq~#uuVfE?n@6jNS>8M zleVQ_fG5VCh(C`JEU}sb>{?sG*{Pc3ak6TWlP+rsNzo0#_C??pV0TAa+PlOTr-2<9xh#4g zpwaF@J8ks-d0QN_(WId5FFsvfoJ1kw9U2-k@QPY{Jw8>;VvJ6Vk0llmJ4tFpt=Yvyov%Y7mo#PvFLSF%~L&aI^a9NunC#3gy|Th2xiA)IHbu2-f8_PW$7eWrUIu<8$L)Jl3VYU;W@1Mj4t^Eng1v~5}(|?f5 zE?3(0qDu)s;F(oHS-3d+7iP9FR$Wb z9>jT1ALIJ^O9S!jZYM;dLoiej9>BfZD3|x$-6U$PPttj7L|J;VC%e@x<>-mA3-=aM z@2h`Ghek&guGNK+xw%8~lEEF1mmVfo)PKolj|wuZ!wzDln4*g33mME8UQc=o4D>m=ofj zA?dcwYJZqAye2SHl5Dg%H5XgLTt%91#{=`4=~gbAzW~1%SF_YRS2<}pexDrNgXJ>v z3QJ@)K2v==t6cgCzQFKa*pt?GqcD#UU|3<+aB5Tq^6c6^ZTq)}&vfxtXd+EK{S=Ad zWk0=U>t)JnHn#Txw!6O-C-$=~(&M1K^pA71-xyu#>V+-g~gKcR9W%Rws80 zjjia{T_d^J-ozX3EizwxYHM$ASSzKO0^d|hsyocE@M3X_4|~AQI(@^4K7t*BK_b2T zW>}B3g&T?+_T@$aUu-t4&{uq(<*hQ*zta!#pdBkxFoc&#?K;K_8lRiayR4=v{z|pz zux&)MEH((&Et3|S$SyPYGPJ#4_Gwu+N<$rgRJCDzH6y6gvEd)4kB0QcW*0+5j=?=R z5|?YRyiVELp;B=&+@Y<9hY+NI-w0AG!rwtNu2*Az=02i!`DJ~dKH*4@e~FEYfw+UF zl?j!jqoJ!5_QskJhEBn!Bb5XrmehQiAK|OQBT=T--r{Rs4nD&)= zayXehMl4Ua9#Qc^2A1KX=r;p>Xdk-iL#9P+Vj>{|ks(Ga!UsbV$o#^OV-NP?rMogy za-Y`RSz9t&L;6C_r_*|Sud!xF^5b{l96@hS7mX_vK8bRq4lZ-%D-UqrOfpFb+xd%> zFy{6C3@)q)aE{y(;`fLC@7N6F2K>$o5DB@EwTK;^ATyQHazCz8`eX&183hqZ;JZVm zZkX+`RTPFFl6B*k4K~9Fus)f zW~zsemx{3&_1-Ywy{(^Wv}#C|Nx4!~I^Z)B7T0&P!=qTIg~GbWU$kVn&qWB{(A;o- zLtz2>5%p#LmmRd_(-fle8S~ zqxA-NAQ{aNBmdB(}V%i$ur zT%V`07#;57D1YObd(P>Ge!3KEn0BjK#=T)%@@~ZlPXF`cJ}D%|wH^uzbq(IqDyjD} zf|1J03KX#>VTUM0m{&M9jjX&*^LzrXY^UXsD06tqvI&9IF0c4(v=1({_nQJ?1y_LCQ|Q?tr?Onp#f-QZV)LHl=169)6??h{QOTZZ(c3} z(&3-pJ+KB#(4McCj_Q?wcW8Z#G4)?2n2zlaUJm`op=oYe+C7UwKAbn39?TUu#0X0Z_RDaF_!nP79C;=XO_xu{i=njLHUkg{~5cGXL_7??=ALX4E(WjSE{~l+frn4p9FB}iyKkLoa-O9lg?DX zdgq|=IP$M#Nr%ENQX2BDl@Qdxl(%2R78L&!7k1SjKFf8_;Ss1DD`sNUnhJXAiR-1p z@_}+R){V~LLrVUIChFfqZAZipkviH z;5gPo*Arf!EN+UXu{MiN@Gu9B@)=H?38BZq};xd-;l>ACz{d-MJFsrL>wC< ze(%Y8v2E4OD3x~eBHbT!ZN=hEUU&Pu0|$2^Qz(|lG7FD7tMcFnP+}ZjDTFZtF`f=2 zFv2e}1Qlfsrx;mCTc^CBh;h!=vvQ?yZ@H&(q9iCH$RAow938JfUH5G|&lZ3rDWG$? zBK?+cQ#~OLe8o)op%vMt8!!s*>@X+cj2?Uy!1mQRK?&1sWX1USX@!)CZvH$u4 zw$QD^hD;unFpDsQk_gZU@#a!f$lJ(fo8uU=NfLD-=D=y;_);%R$ACU+WUttEsD~P< z&LpZu-(34C1IQ3bQM8z-O8|cS9SDbqhZhxFyP}`PS2j}=r*w6>GicHAesk zSI?I548erE&<;8K+)fw(0KraDL`bC*Rqe33Y_&@uGiuT!PF7l))&|vu58ZV`B7Nkm(RMXMldks{8)uymzd!RqY$a(#Gho==+)E z_t}jVA+FQ3^=%k8$|{WSoq~q(;WaYTv#RkyUb{DWoT5qrCf_ZVN28Eft`!HR_ug&F zG+Z047|Xwa2_OD{HoPD$tbZ61R#6F&d-Ag*K*q4x8)N-tjwRR@O13rHXb4Nf3-q>A zsi>no=k$|lRn8yng588V?0VCq``&YBrYLhM!WfK>JX>@L`lUFO0OS1kaM=&uY&d-7 z&KH4{w2t-$B%0;pLnAsU$Nfh_kRlS_Xlp$XX_s0y-oi9Nf?mlwxTy?5WQn<+2V@gv-<9Ziun=)5_$;MfuI+xn5D3-nC=%{B zo_;!_t0|^x4_@_)y+iuCW?Px7&;FQ6%lLVv!M?7>0Sy#pdy)b7%}%vx$IjewPDbC@ z>}2(Z_Pq{0MhE=mn!n?Lso)B?v-@aR4TaB+MB?Hsyenh4hTTcJf#N*{S zx=$idSn++Wtgc+qUpST;d!q}~y7Bfp*kT=j=pUG$8Es(fKzdcq>by%=HR07u%|`?+ zIG|B8JwV(-qM;*aWT@_z{PYp`?yZbKm}u~>mb3<63RK$YmDZAgM1G0KHBe;J#f?fr zMgvncR~(GR@{ICtTj#_I(*h`6N*Q6eJj=2#gMn*S;4P0xQ(?9P^+w=BhRu*;<0C~q z+lOb(#cX;uPNU2cVy>y;as80k42ALF=#nuqXh0l^7lu~S_bBnGajoAMCxtnSd39@6 z+@rM?ecA>x^ikp#4j;W74V@9Xn$f;+EgIx}@T|vpV!LveU)$Y;i}5yn!d$Bf^zDE2 zPKH4_5C>0Q$8GywWmTVO7KZ9|2bH2DLmkH6aEC_%4jHUo1O7avdlo7`HMLx>bf zL@;sIACGtxbgtf@Ebf|(#8^^ATASDQWB=m93#PH|*Y1P=D!7Z^>x?~|xJX$dQ}=d> z{q;909yL5%wS4JpP$SOGW(`09UK0~N+>wpWY_~& z^~)}e;v3g?ov%ayvTqMm4TGlUajcY;yw2*SF^#K79bum&$?X8wD;4d>y41;5+eJ*1 zIMM5Fl5*e8Aihq`hs>=`o*8F%ioK!qPj^r>mOa|ww0q1IeodXY@#cyaRI0wbI2G-c z?nXIg$u0b7D|@-%5T)d}&)t-x8Q)l5%tiPV^lz){f9-+&+v@tiwYm~`_kg`-Ga>HO z>hd$M;%x6GQy3%!wHh(qbQD{TwO7aw@C4?8`s?hKzLH#PCD!#7;$na=-8~`OX!d*d ziz=3nmY$AVe&;QZsM_2soBByngrfJHK!kks!g+HoW$W{Y4y7VV(j2ZglKHx`eaAJG zm+I(d_KeBXx7^k{Ef@kz%wp!@gkS8?70m>bFs7pq?eG9H!3V0FfpM;)Wbk4s0s25Gk+)Io*blgrlqaN-n83(9}7!S!F17Rnb*lK{`{-UvoBFee+{ + test.setTimeout(90000) + let rules:FilterRule[]=Array.from({length:1000},(_,i)=>({id:"r"+(i+1),community:"65001:"+String(i+1).padStart(5,"0"),gateway:"",gatewayTunnelId:"",action:"blackhole",description:"rule-"+String(i+1).padStart(4,"0")})) + let reads=0,failed=false,writeFail=false;const payloads:FilterRule[][]=[] + await page.route("**/health",r=>r.fulfill({json:{ok:true}})) + await page.route("**/api/**",r=>{const p=new URL(r.request().url()).pathname + if(p==="/api/filters/rules"&&r.request().method()==="PUT"){const body=r.request().postDataJSON();expect(body.serverId).toBe("1");expect(body.source).toBe("apply");payloads.push(body.rules);if(writeFail)return r.fulfill({status:403,json:{error:"Перемещение запрещено тест1000"}});rules=body.rules;return r.fulfill({json:{ok:true,rules}})} + if(p==="/api/filters/rules"){reads++;return r.fulfill(failed?{status:503,json:{error:"Каталог Filters недоступен тест"}}:{json:{rulesets:[{serverId:"1",rules}],greTunnels:[],live:true}})} + return r.fulfill({json:p==="/api/auth/config"?{required:false}:p==="/api/servers"?[{id:1,name:"Роутер",host:"192.0.2.1",country:"RU",type:"exit-node",enabled:true,status:null}]:p==="/api/filters/gre-tunnels"?{tunnels:[]}:p==="/api/recursive-routes"?{routes:[]}:{} }) + }) + const started=Date.now();await page.goto("/filters");const rows=page.locator("tr[data-row-id]");await expect(rows).toHaveCount(50) + const profile={count:1000,jsonBytes:Buffer.byteLength(JSON.stringify(rules)),rows:await rows.count(),nodes:await page.locator("*").count(),readyMs:Date.now()-started};console.log("Filters profile",JSON.stringify(profile));await info.attach("profile",{body:JSON.stringify(profile),contentType:"application/json"}) + await expect(rows.first().getByRole("button",{name:"Поднять правило 65001:00001",exact:true})).toBeDisabled() + await rows.last().getByRole("button",{name:"Опустить правило 65001:00050",exact:true}).click();await expect.poll(()=>payloads.length).toBe(1) + expect(payloads[0]).toHaveLength(1000);expect(payloads[0].slice(48,52).map(r=>r.id)).toEqual(["r49","r51","r50","r52"]);await expect(rows.last()).toHaveAttribute("data-row-id","r51") + const next=page.getByRole("button",{name:"Следующая страница",exact:true});await next.click();await expect(rows.first()).toHaveAttribute("data-row-id","r50") + await rows.first().getByRole("button",{name:"Поднять правило 65001:00050",exact:true}).focus();await page.keyboard.press("Enter");await expect.poll(()=>payloads.length).toBe(2);expect(payloads[1].slice(48,52).map(r=>r.id)).toEqual(["r49","r50","r51","r52"]);await expect(rows.first()).toHaveAttribute("data-row-id","r51") + writeFail=true;await rows.first().getByRole("button",{name:"Поднять правило 65001:00051",exact:true}).click();await expect(page.getByRole("alert").filter({hasText:"Перемещение запрещено тест1000"})).toBeVisible();await expect(rows.first()).toHaveAttribute("data-row-id","r51");writeFail=false + const before=reads;await page.getByRole("button",{name:"Обновить",exact:true}).click();await expect.poll(()=>reads).toBeGreaterThan(before);await expect(rows.first()).toHaveAttribute("data-row-id","r51") + const search=page.getByPlaceholder("Community, gateway, описание…");await search.fill("rule-1000");await expect(rows).toHaveCount(1);await expect(rows.first().getByRole("button",{name:"Опустить правило 65001:01000",exact:true})).toBeDisabled();await expect(rows.first().getByLabel("Наивысший приоритет",{exact:true})).toBeVisible() + await search.fill("rule");await expect(rows).toHaveCount(50);await page.getByRole("table").getByRole("button",{name:"Community",exact:true}).click();await page.getByRole("table").getByRole("button",{name:"Community",exact:true}).click();await expect(rows.first()).toHaveAttribute("data-row-id","r1000") + await search.fill("");await expect(rows.first()).toHaveAttribute("data-row-id","r1");await expect(page.getByRole("table").getByRole("button",{name:"Community",exact:true})).toHaveCount(0) + await next.click();const previous=await rows.first().getAttribute("data-row-id");failed=true;await page.getByRole("button",{name:"Обновить",exact:true}).click();await expect(page.getByText("Роутер недоступен — показан кэш. Изменения заблокированы, пока не удастся прочитать CHR.",{exact:true})).toBeVisible();await expect(rows.first()).toHaveAttribute("data-row-id",previous!);await expect(rows.first().getByRole("button",{name:"Редактировать правило",exact:true})).toBeDisabled() + await page.setViewportSize({width:320,height:1000});const edit=rows.first().getByRole("button",{name:"Редактировать правило",exact:true});await edit.scrollIntoViewIfNeeded();await page.locator('[data-slot="data-grid"] [data-slot="scroll-area-viewport"]').evaluate(el=>{el.scrollLeft=el.scrollWidth});await expect(edit).toBeInViewport();await expect.poll(()=>page.evaluate(()=>document.documentElement.scrollWidth)).toBeLessThanOrEqual(320) + await page.addScriptTag({content:axe.source});expect((await page.evaluate(async()=>(window as unknown as {axe:typeof axe}).axe.run(document.querySelector('[data-slot="data-grid"]')!,{runOnly:{type:"tag",values:["wcag2a","wcag2aa","wcag21a","wcag21aa"]}}))).violations).toEqual([]) + await page.addStyleTag({content:"nextjs-portal{display:none!important}"});await page.screenshot({path:info.outputPath("filters-320.png"),animations:"disabled"}) + failed=false;rules=[rules[999]];await page.getByRole("button",{name:"Обновить",exact:true}).click();await expect(rows).toHaveCount(1);await expect(rows.first()).toHaveAttribute("data-row-id","r1000");expect(payloads).toHaveLength(3) +})