From e5a8326a5e3def1bf5d5dc94794da82a2af801ab Mon Sep 17 00:00:00 2001 From: Codex Date: Sat, 24 Oct 2026 19:12:05 +0300 Subject: [PATCH 1/3] Polish search, account, and lab screens --- CHANGELOG.md | 4 + README.md | 8 +- backend/search/minjust_opensearch.py | 2 +- backend/search/review.html | 351 ++++++++++++++---- docs/product/interface-correction-plan.md | 26 +- tools/frontend-visual-review/check.cjs | 143 ++++--- tools/frontend-visual-review/fixtures.cjs | 28 ++ tools/frontend-visual-review/package.json | 3 +- .../frontend-visual-review/preview-server.cjs | 82 ++++ 9 files changed, 530 insertions(+), 117 deletions(-) create mode 100644 tools/frontend-visual-review/fixtures.cjs create mode 100644 tools/frontend-visual-review/preview-server.cjs diff --git a/CHANGELOG.md b/CHANGELOG.md index 7549aaa..aa7b835 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Не выпущено +- Frontend `0.3.0` / Backend `0.13.1`: добавлен доступный splitter для + изменения ширины результатов и документа. Язык поиска находится в фильтрах; + состояния открытия, оглавление правовых заголовков, лаборатория и кабинет + приведены к последовательной и компактной компоновке. - Frontend `0.2.6` / Backend `0.13.1`: двухпанельная компоновка поиска сохраняется до ширины 1175 px, чтобы три панели не обрезались при промежуточных ширинах окна. diff --git a/README.md b/README.md index c3f7aea..6afd602 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Telegram-бот — только часть рабочего окружения ## Текущее состояние Сейчас реализованы Telegram-бот-секретарь версии `0.2.2`, backend версии -`0.13.0` и frontend `0.2.3` с поисковым экраном и внутренней лабораторией. +`0.13.1` и frontend `0.3.0` с поисковым экраном и внутренней лабораторией. Авторизация хранится в SQLite; первый пользователь `admin` создаётся интерактивной CLI-командой. Поиск расширяет аббревиатуры организационно-правовых форм и поднимает @@ -19,8 +19,8 @@ SQLite; первый пользователь `admin` создаётся инт | Компонент | Версия | Состояние | |---|---:|---| | Telegram-бот | `0.2.2` | на Synology работает `0.2.1`; обновление после слияния | -| Backend | `0.13.0` | авторизация, поиск с фильтрами, ограниченный staging и статические ресурсы | -| Frontend | `0.2.3` | поиск по правовой базе, просмотр редакций и внутренняя лаборатория | +| Backend | `0.13.1` | авторизация, поиск с фильтрами, ограниченный staging и статические ресурсы | +| Frontend | `0.3.0` | поиск по правовой базе, просмотр редакций, настраиваемая ширина панелей и внутренняя лаборатория | | Сбор и обработка правовых данных | `0.8.0` | добавлены relevance set и оценка выдачи | | RAG и база знаний | — | ещё не созданы | @@ -63,4 +63,4 @@ python3 -m unittest discover -s tools/telegram-bot -v --- -Акылдаш · Telegram-бот v0.2.2 · Backend v0.13.0 · Frontend v0.2.3 +Акылдаш · Telegram-бот v0.2.2 · Backend v0.13.1 · Frontend v0.3.0 diff --git a/backend/search/minjust_opensearch.py b/backend/search/minjust_opensearch.py index 807ef09..614e3b2 100644 --- a/backend/search/minjust_opensearch.py +++ b/backend/search/minjust_opensearch.py @@ -465,7 +465,7 @@ def main() -> int: else: documents, fragments = export_bulk(arguments.input, arguments.output, arguments.index, arguments.limit) destination = arguments.output - print(f"documents={documents} fragments={fragments} destination={destination}\nAkyldash · Backend v{APP_VERSION} · Frontend v0.2.6") + print(f"documents={documents} fragments={fragments} destination={destination}\nAkyldash · Backend v{APP_VERSION} · Frontend v0.3.0") return 0 diff --git a/backend/search/review.html b/backend/search/review.html index 6a95198..5138c19 100644 --- a/backend/search/review.html +++ b/backend/search/review.html @@ -14,14 +14,14 @@ @font-face { font-family: "Noto Serif"; font-style: normal; font-weight: 100 900; font-display: swap; src: url("/static/fonts/noto-serif-cyrillic-ext.woff2") format("woff2"); unicode-range: U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F; } @font-face { font-family: "Noto Serif"; font-style: normal; font-weight: 100 900; font-display: swap; src: url("/static/fonts/noto-serif-cyrillic.woff2") format("woff2"); unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116; } @font-face { font-family: "Noto Serif"; font-style: normal; font-weight: 100 900; font-display: swap; src: url("/static/fonts/noto-serif-latin.woff2") format("woff2"); unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; } - :root { color-scheme: light; font: 16px/1.5 "Noto Sans", sans-serif; color: #38262A; background: #F7F2E8; --ink: #38262A; --muted: #786469; --line: #DED3CE; --surface: #fff; --surface-muted: #FBF8F4; --brand: #9D2633; --brand-dark: #84202B; --accent: #A37B32; --focus: #245C78; --subtle: #F8EBED; --serif: "Noto Serif", serif; } + :root { color-scheme: light; font: 16px/1.5 "Noto Sans", sans-serif; color: #38262A; background: #F7F2E8; --ink: #38262A; --muted: #786469; --line: #DED3CE; --surface: #fff; --surface-muted: #FBF8F4; --brand: #9D2633; --brand-dark: #84202B; --accent: #A37B32; --focus: #245C78; --subtle: #F8EBED; --sans: "Noto Sans", sans-serif; --serif: "Noto Serif", serif; } * { box-sizing: border-box; } body { margin: 0; color: var(--ink); background: #F7F2E8; } .review__skip { position: absolute; inset-block-start: 0; inset-inline-start: -10000px; padding: .5rem 1rem; background: var(--surface); } .review__skip:focus { inset-inline-start: 1rem; z-index: 2; } .review__header, .review__main { max-width: 1320px; margin: auto; padding-inline: clamp(1rem, 3vw, 3rem); } .review__header { padding-block: 0 1.5rem; background: var(--surface); border-block-end: 1px solid var(--line); } - .review__header h1 { max-width: 24ch; margin: 1.5rem 0 .4rem; font: 700 clamp(1.75rem, 3vw, 2rem)/1.2 var(--serif); } + .review__header h1 { max-width: none; margin: 1.5rem 0 .4rem; font: 700 clamp(1.75rem, 3vw, 2rem)/1.2 var(--serif); } .review__header p { max-width: 65ch; margin: 0; color: var(--muted); } .review__header-top { display: flex; justify-content: space-between; gap: 1rem; align-items: start; } .review__eyebrow { display: inline-flex; align-items: center; gap: .5rem; color: var(--ink); font: 600 1.1rem/1.25 var(--serif); } @@ -39,7 +39,8 @@ button:active { scale: .96; } button:disabled { cursor: wait; opacity: .55; } .review__button--primary { background: var(--brand); color: #fff; border-color: var(--brand); } - .review__status { min-height: 1.7rem; margin-block: 1rem; color: var(--muted); } + .review__status { min-height: 0; margin-block: 0; color: var(--muted); } + .review__status:not(:empty) { margin-block: .5rem; } .review__status--error { color: #9D2633; } .review__workspace { display: grid; grid-template-columns: minmax(24rem, .9fr) minmax(28rem, 1.1fr); gap: 1rem; align-items: start; } .review__results, .review__document { min-width: 0; background: var(--surface); border: 1px solid var(--line); border-radius: 6px; padding: clamp(1rem, 2vw, 1.5rem); } @@ -110,7 +111,7 @@ .search__layout { display: grid; grid-template-columns: 230px minmax(320px, .9fr) minmax(420px, 1.2fr); min-height: 65vh; border-block: 1px solid var(--line); background: var(--surface); } .search__filters, .search__results, .search__document { min-width: 0; padding: 1rem; } .search__filters, .search__results { border-inline-end: 1px solid var(--line); } - .search__filters h2, .search__results h2, .search__document h2 { margin: 0; font: 600 1.5rem/1.3 var(--serif); } + .search__filters > .review__panel-heading h2, .search__results > .review__panel-heading h2 { margin: 0; font: 600 1.25rem/1.3 var(--sans); } .search__filters .review__panel-heading, .search__results .review__panel-heading { align-items: center; } .search__filter { margin-block: 1.25rem; } .search__filter h3 { margin: 0 0 .4rem; font-size: 1rem; } @@ -161,9 +162,11 @@ .review__workspace { grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); } .review__document { position: static; max-height: min(68dvh, 860px); overflow: auto; overscroll-behavior: contain; } .review__document-body { max-width: 72ch; margin-inline: auto; } + .review__document-body > h2:first-child { font: 600 30px/38px var(--serif); } .review__document-body table { display: block; max-width: 100%; overflow-x: auto; } .review__document-body p:empty { display: none; } .review__document-body a { color: var(--brand-dark); text-underline-offset: .18em; } + .review__document-meta a { color: var(--brand-dark); text-underline-offset: .18em; } .search__layout[data-filters-hidden="true"] { grid-template-columns: minmax(320px, .8fr) minmax(0, 1.5fr); } .search__layout[data-filters-hidden="true"] .search__filters { display: none; } .search__layout.is-expanded { position: fixed; z-index: 15; inset: 0; display: block; overflow: auto; background: var(--surface); } @@ -178,14 +181,15 @@ .search__layout:not([data-has-document="true"]) .search__toc, .search__layout:not([data-has-document="true"]) #document-source { display: none; } .search__layout:not([data-has-document="true"]) .search__document-body { display: none; } + .search__layout:not([data-has-document="true"]) .search__document-head h2 { display: none; } .search__mobile-filters { display: inline-flex; } .search__account button { display: inline-flex; width: auto; min-height: 44px; gap: 8px; align-items: center; padding: 8px 12px; } .search__account-label { display: inline; } .search__document-body table, .review__document-body table { display: block; max-width: 100%; overflow-x: auto; } .search__table-scroll { max-width: 100%; margin-block: 1rem; overflow-x: auto; overscroll-behavior-inline: contain; } .search__table-scroll table { width: max-content; min-width: 100%; border-collapse: collapse; } - .search__filters .review__panel-heading { align-items: center; flex-wrap: wrap; } - .search__filters .review__panel-heading h2 { flex: 1 1 auto; } + .search__filters .review__panel-heading { align-items: center; flex-wrap: nowrap; justify-content: space-between; gap: 8px; } + .search__filters .review__panel-heading h2 { flex: 0 1 auto; white-space: nowrap; } .search__filters .review__panel-heading button { flex: 0 0 auto; } .search__filter label { display: grid; grid-template-columns: 24px minmax(0, 1fr) auto; align-items: center; gap: 8px; min-height: 40px; } .search__filter label span { min-width: 0; overflow-wrap: anywhere; } @@ -212,6 +216,7 @@ body.is-users-route { min-height: 100dvh; display: flex; flex-direction: column; } body.is-users-route > .review__header { display: block; width: 100%; padding-block-end: 0; } body.is-users-route > .review__header > .review__header-content { display: none; } + body.is-users-route > .review__actions { display: none; } body.is-users-route > footer.review__header { display: block; margin-block-start: auto; } .review__users-page { width: min(1200px, 100%); flex: 1; margin-inline: auto; padding: 28px clamp(16px, 4vw, 48px); } .review__users-page[hidden] { display: none !important; } @@ -233,7 +238,6 @@ .search__layout:not([data-filters-hidden="true"]) .search__filters > .search__dates, .search__layout:not([data-filters-hidden="true"]) .search__filters > .search__date-label, .search__layout:not([data-filters-hidden="true"]) .search__filters > #filter-fields { grid-column: 1 / -1; } - .search__filters .search__ornament { display: none; } } @media (max-width: 900px) { body:has(.search:not([hidden])) { height: auto; min-height: 100dvh; overflow: visible; } @@ -300,9 +304,10 @@ .search__ui-language button[aria-pressed="true"] { color: var(--ink); border-block-end: 2px solid var(--brand); } .search__account { display: flex; align-items: center; gap: 6px; margin-inline-start: auto; } .search__account button { width: 40px; min-height: 40px; padding: 8px; } - .search__account-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-block-end: 16px; } + .search__account-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-block: 24px 0; } .search__subnav { min-height: var(--search-nav-height); display: flex; align-items: center; gap: 12px; padding: 6px 26px; overflow-x: auto; white-space: nowrap; } - .search__subnav a, .search__subnav button { min-height: 36px; padding: 5px 14px; text-decoration: none; } + .search__subnav a, .search__subnav button { display: inline-flex; align-items: center; justify-content: center; min-height: 40px; padding: 5px 14px; text-align: center; text-decoration: none; } + .search__subnav a:not(.is-active) { color: var(--ink); } .search__mobile-filters, .search__mobile-back, .search__filter-close, .search__filter-overlay { display: none; } .search__subnav a.is-active { min-width: 97px; background: var(--brand); color: #fff; border-color: var(--brand); } .search__subnav .search__nav-text { margin-inline: 11px 28px; padding-inline: 0; border: 0; color: var(--ink); font-size: 13px; } @@ -311,8 +316,7 @@ .search__chips .search__chip { padding-inline: 4px; } .search__chips .search__chip button { width: 16px; } .search__language-chip { padding-inline: 4px; } - .search__language-chip select { width: 78px; min-width: 0; min-height: 24px; border: 0; padding: 0 12px 0 0; background: transparent; font-size: 14px; } - html[lang="ky"] .search__language-chip select { width: 100px; } + .search__language-chip select { width: auto; min-width: 126px; min-height: 36px; border: 0; padding: 0 12px 0 0; background: transparent; font-size: 14px; } .search__chip button { min-height: 24px; width: 24px; padding: 0; border: 0; font-size: 18px; line-height: 1; } .search { width: 100%; max-width: none; min-height: 0; flex: 1; display: flex; flex-direction: column; margin: 0; } .search__sr-only { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } @@ -320,7 +324,9 @@ .search__layout { flex: 1; min-height: 0; grid-template-columns: minmax(210px, 226px) minmax(350px, 422px) minmax(400px, 1fr); border-block: 1px solid var(--line); } .search__filters, .search__results, .search__document { min-height: 0; padding: 14px 16px 20px; } .search__filters { position: relative; display: flex; flex-direction: column; overflow: auto; background: var(--surface-muted); padding-inline: 30px 16px; } - .search__filters .review__panel-heading { margin-block-end: 18px; } + .search__filters .review__panel-heading { margin-block-end: 8px; } + #search-filters > .review__panel-heading { margin-block-end: 0; } + #search-filters > .search__filter-language { margin-block-start: 0; } .search__filters .review__panel-heading button { min-height: 36px; padding: 2px; border: 0; color: var(--brand); text-decoration: underline; text-underline-offset: 3px; } .search__filter { margin-block: 0 16px; } .search__filter--document-type { margin-block-end: 24px; } @@ -340,7 +346,6 @@ .search__dates label:not(.has-value) input { color: transparent; } .search__date-placeholder { position: absolute; inset-inline-start: 9px; inset-block-start: 50%; color: var(--muted); font-size: 14px; pointer-events: none; transform: translateY(-50%); } .search__dates label.has-value .search__date-placeholder { display: none; } - .search__ornament { width: calc(100% - 12px); height: 56px; flex: none; margin: auto 6px 0; color: var(--accent); pointer-events: none; } .search__results { overflow: auto; background: var(--surface-muted); } .search__results .review__panel-heading { align-items: start; margin-block-end: 0; } .search__results .review__panel-heading select { min-height: 40px; padding: 6px 10px; font-size: 14px; } @@ -363,7 +368,7 @@ .search__document-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; align-items: start; } .search__breadcrumbs { display: flex; gap: 12px; align-items: center; color: var(--muted); font-size: 14px; } .search__breadcrumbs span:first-child { color: var(--brand); } - .search__document-head h2 { grid-column: 1 / -1; margin-block: 0 4px; color: var(--ink); font: 700 36px/1 var(--serif); } + .search__document-head h2 { grid-column: 1 / -1; margin-block: 0 4px; color: var(--ink); font: 600 30px/38px var(--serif); } .search__document-head .search__expand { min-height: 32px; border: 0; padding: 0 4px; } .search__document-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; border: 0; color: var(--muted); } .search__document-meta a { color: var(--brand); } @@ -374,7 +379,7 @@ .search__document-toolbar .search__edition-label { display: block; } .search__document-toolbar .search__edition-label select { width: 160px; max-width: 160px; } .search__source-link { max-width: 150px; margin-inline-start: auto; color: var(--brand); font-size: 14px; white-space: nowrap; } - .search__document-language { display: inline-flex !important; align-items: center; gap: 6px !important; margin-inline-start: auto; font-size: 12px !important; } + .search__document-language { display: inline-flex; align-items: center; gap: 6px; margin-inline-start: auto; font-size: 12px; } .search__document-language select { min-height: 28px; max-width: 130px; padding: 4px 8px; font-size: 14px; } .search__toc { margin-block-end: 0; } .search__toc summary { width: fit-content; min-height: 42px; padding: 9px 8px; border: 1px solid var(--line); border-radius: 6px; cursor: pointer; font-size: 14px; } @@ -428,7 +433,6 @@ .search__layout[data-mobile-view="results"] .search__document { display: none; } .search__layout[data-mobile-view="results"] .search__results { display: block; } .search__layout[data-mobile-view="document"] .search__filters { display: none; } - .search__ornament { display: none; } .search__document { min-height: 30rem; } } @media (max-width: 600px) { @@ -466,6 +470,7 @@ body.is-users-route { width: 100%; height: auto; min-height: 100dvh; overflow: visible; display: flex; flex-direction: column; } body.is-users-route > header.review__header { display: block; width: 100%; padding-block-end: 0; } body.is-users-route > header.review__header > .review__header-content { display: none; } + body.is-users-route > .review__actions { display: none; } body.is-users-route > footer.review__header { display: block; width: 100%; margin-block-start: auto; } .search__layout { grid-template-columns: clamp(256px, 19.45vw, 280px) clamp(360px, 30vw, 408px) minmax(560px, 1fr); } .search__account button { width: auto; min-width: 44px; min-height: 44px; padding: 8px 12px; } @@ -486,6 +491,106 @@ .review__nav-links { order: 3; width: 100%; flex-wrap: wrap; } .review__nav-account { margin-inline-start: auto; } } + /* Shared follow-up corrections: consistent navigation, compact public search, + and a continuous workspace that keeps controls aligned to the same shell. */ + .review__nav { width: min(100%, 1440px); max-width: 1440px; } + .review__nav-links a, .review__nav-links button { + display: inline-flex; align-items: center; justify-content: center; min-height: 44px; + padding: 8px 14px; border: 1px solid transparent; border-radius: 6px; + color: var(--ink); background: transparent; text-decoration: none; font: inherit; + } + .review__nav-links a:hover, .review__nav-links button:hover { border-color: var(--line); background: var(--surface-muted); } + .review__nav-links .is-active { border-color: var(--brand); background: var(--subtle); color: var(--brand); } + .review__nav-links [hidden], .search__account-actions [hidden] { display: none !important; } + .review__nav-account > span { color: var(--muted); } + .review__header-content { width: min(100%, 1440px); } + body:has(#review:not([hidden])) { min-height: 100dvh; height: 100dvh; overflow: hidden; } + body:has(#review:not([hidden])) > .review__header { padding: 0; } + body:has(#review:not([hidden])) > #review { width: min(100%, 1440px); min-height: 0; margin: 0 auto; padding-inline: clamp(16px, 3vw, 40px); display: flex; flex-direction: column; } + body:has(#review:not([hidden])) > .review__actions { width: min(100%, 1440px); min-height: 96px; box-sizing: border-box; margin: 0 auto; padding: 8px clamp(16px, 3vw, 40px) 0; } + body:has(#review:not([hidden])) > footer.review__header { width: 100%; margin-block-start: 12px; } + .review__header-content, .review__actions-inner { max-width: 1440px; } + body:has(#review:not([hidden])) .review__nav { height: 64px; min-height: 64px; padding-block: 0; } + body:has(#review:not([hidden])) .review__header-content { display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: 32px 20px; column-gap: 24px; align-content: center; height: 64px; } + body:has(#review:not([hidden])) .review__header-top { grid-column: 1; grid-row: 1 / 3; align-self: center; padding: 0; } + body:has(#review:not([hidden])) .review__header-content h1 { grid-column: 2; grid-row: 1; max-width: none; margin: 0; font: 600 26px/32px var(--sans); } + body:has(#review:not([hidden])) .review__header-content p { grid-column: 2; grid-row: 2; max-width: none; margin: 0; font: 400 14px/20px var(--sans); white-space: nowrap; } + .review__search { gap: 12px; padding: 12px 0; border: 0; border-block-end: 1px solid var(--line); border-radius: 0; background: transparent; } + .review__workspace { min-height: 0; max-height: min(58dvh, 620px); flex: 1 1 0; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: 0; align-items: stretch; overflow: hidden; border-block: 1px solid var(--line); background: var(--surface); } + .review__results, .review__document { min-height: 0; max-height: none; padding: 14px clamp(12px, 1.5vw, 22px); border: 0; border-radius: 0; background: var(--surface); } + .review__results { overflow: auto; border-inline-end: 1px solid var(--line); } + .review__document { position: static; overflow: auto; overscroll-behavior: contain; } + .review__document-meta { overflow-wrap: anywhere; } + .review__actions-inner { padding: 5px 0; border: 0; border-block-start: 1px solid var(--line); border-radius: 0; background: transparent; } + body:has(#review:not([hidden])) > footer.review__header { height: 44px; min-height: 44px; } + body:has(#review:not([hidden])) > footer.review__header .review__header-content { display: flex; align-items: center; height: 44px; padding-block: 0; } + .search__subnav { flex-wrap: wrap; overflow: visible; white-space: normal; } + .search__subnav a.is-active { min-width: 0; text-align: center; } + .search__nav-text { flex: 0 0 auto; } + .search__chips { flex: 1 1 8rem; } + .search__filter-language { display: grid; gap: 5px; margin-block: 0 16px; color: var(--muted); font-size: .875rem; font-weight: 600; } + .search__filter-language select { min-height: 42px; width: 100%; padding: 7px 10px; color: var(--ink); background: var(--surface); border: 1px solid var(--line); } + .search__layout { grid-template-columns: minmax(190px, clamp(190px, 18vw, 250px)) minmax(260px, 36fr) 12px minmax(320px, 64fr); } + .search__layout[data-filters-hidden="true"] { grid-template-columns: minmax(260px, 36fr) 12px minmax(320px, 64fr); } + .search__mobile-filters { display: inline-flex; } + .search__layout[data-filters-hidden="true"] .search__filters { display: none; } + .search__splitter { z-index: 1; align-self: stretch; width: 12px; min-width: 12px; min-height: 100%; padding: 0; border: 0; border-radius: 0; background: linear-gradient(90deg, transparent 4px, var(--brand-dark) 4px 8px, transparent 8px); cursor: col-resize; touch-action: none; } + .search__splitter:hover, .search__splitter:focus-visible { background: linear-gradient(90deg, transparent 3px, var(--brand) 3px 9px, transparent 9px); } + body:has(#review:not([hidden])) > .review__header, body:has(#review:not([hidden])) > footer.review__header { width: min(calc(100% - 2 * clamp(16px, 3vw, 40px)), 1240px); max-width: 1240px; margin-inline: auto; padding-inline: 0; } + body:has(#review:not([hidden])) .review__nav, body:has(#review:not([hidden])) .review__header-content { width: 100%; max-width: none; padding-inline: 0; } + body:has(#review:not([hidden])) .review__header-content h1 { font: 600 26px/32px var(--sans); } + body:has(#review:not([hidden])) .review__panel-heading h2 { font: 600 20px/26px var(--sans); } + + .search__pagination[hidden] { display: none; } + .search__document-language[hidden] { display: none; } + .search__account-actions a { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 8px 12px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface); color: var(--brand-dark); font-weight: 600; text-decoration: none; } + .search__account-actions a:hover { border-color: var(--brand); background: var(--subtle); } + #account-dialog dl { display: grid; grid-template-columns: minmax(7.5rem, max-content) minmax(0, 1fr); gap: 8px 16px; margin: 16px 0 24px; } + #account-dialog > .review__page { padding: 16px; } + #account-dialog dt { color: var(--muted); } + #account-dialog dd { min-width: 0; margin: 0; overflow-wrap: anywhere; } + #account-dialog .review__dialog-heading { inset-block-start: -16px; align-items: center; min-height: 44px; height: 44px; margin: -16px -16px 12px; padding: 0 16px; } + .review__password-field { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 8px; } + .review__password-field input { min-width: 0; } + .review__password-toggle { min-height: 44px; padding-inline: 10px; white-space: nowrap; } + #account-dialog .review__dialog-heading h2 { max-width: none; padding: 0; font: 600 20px/28px var(--sans); } + #account-dialog .review__dialog-heading button { display: grid; place-items: center; flex: 0 0 44px; width: 44px; min-height: 44px; padding: 0; } + #public-document-body img, #document-body img { max-width: 100%; height: auto; object-fit: contain; } + @media (min-width: 901px) and (max-width: 1175px) { + .search__layout { grid-template-columns: minmax(180px, 22%) minmax(260px, 36fr) 12px minmax(320px, 64fr); } + .search__layout[data-filters-hidden="true"] { grid-template-columns: minmax(260px, 36fr) 12px minmax(320px, 64fr); } + .search__layout:not([data-filters-hidden="true"]) .search__filters { display: flex; } + } + @media (max-width: 900px) { + body:has(#review:not([hidden])) { min-height: 100svh; height: auto; overflow: visible; } + body:has(#review:not([hidden])) > #review { flex: none; padding-inline: 16px; } + body:has(#review:not([hidden])) > .review__header, body:has(#review:not([hidden])) > footer.review__header { width: calc(100% - 32px); } + body:has(#review:not([hidden])) .review__nav, body:has(#review:not([hidden])) .review__header-content { padding-inline: 0; } + body:has(#review:not([hidden])) .review__header-content { display: block; height: auto; padding-block: 12px; } + body:has(#review:not([hidden])) .review__header-top { padding-block: 0 8px; } + body:has(#review:not([hidden])) .review__header-content h1, body:has(#review:not([hidden])) .review__header-content p { display: block; } + body:has(#review:not([hidden])) .review__header-content p { white-space: normal; } + body:has(#review:not([hidden])) > footer.review__header { height: auto; min-height: 44px; } + .review__workspace { min-height: 0; max-height: none; flex: none; display: grid; grid-template-columns: minmax(0, 1fr); overflow: visible; } + .review__results, .review__document { max-height: none; overflow: visible; border-inline: 0; } + .review__results { border-block-end: 1px solid var(--line); } + .review__document { display: block; } + body:has(#review:not([hidden])) > .review__actions { padding-inline: 16px; } + .search__layout, .search__layout[data-filters-hidden="true"] { display: block; } + .search__splitter { display: none; } + .search__filter-language { margin-block-end: 16px; } + .search__filters { display: none; } + .search__filters.is-open { display: block; } + .search__mobile-filters { display: inline-flex; } + } + @media (max-width: 600px) { + .search__subnav { gap: 4px; padding-inline: 12px; } + .search__subnav a, .search__subnav button { padding-inline: 10px; } + .search__chips { flex: 1 1 100%; order: 4; } + .search__account { margin-inline-start: auto; } + #account-dialog dl { grid-template-columns: minmax(0, 1fr); gap: 2px; } + #account-dialog dd { margin-block-end: 10px; } + } @@ -504,7 +609,7 @@
- +

Создайте новый пароль

Для продолжения замените временный пароль. Используйте не менее 12 символов.

-

Личный кабинет

Логин
Роль
Администратор
Дата создания
+

Личный кабинет

Логин
Роль
Администратор
Дата создания

Пользователи

Права на действия определяются сервером.

@@ -545,7 +651,7 @@

Документ

Источники документов

Поиск выполняется по документам, подготовленным из правовых источников Кыргызской Республики. Для каждого результата доступная редакция и ссылка на официальный источник показываются в панели документа.

Официальный источник: Централизованный банк данных правовой информации Министерства юстиции Кыргызской Республики.

Короткое знакомство

-
Акылдаш · Frontend v0.2.6 · Backend v0.13.1 · Внутренняя лаборатория релевантности
+
Акылдаш · Frontend v0.3.0 · Backend v0.13.1 · Внутренняя лаборатория релевантности
`; +const previewHtml = html.replace('', `${warning}`); +const json = (response, status, value) => { + response.writeHead(status, {'Content-Type':'application/json; charset=utf-8','Cache-Control':'no-store','X-Content-Type-Options':'nosniff'}); + response.end(JSON.stringify(value)); +}; +const readBody = (request) => new Promise((resolve) => { + let body = ''; + request.on('data', (chunk) => { body += chunk; if (body.length > 32768) request.destroy(); }); + request.on('end', () => { try { resolve(JSON.parse(body || '{}')); } catch { resolve({}); } }); +}); +const sendHtml = (response) => { + response.writeHead(200, { + 'Content-Type':'text/html; charset=utf-8', + 'Cache-Control':'no-store', + 'X-Content-Type-Options':'nosniff', + 'Referrer-Policy':'no-referrer', + 'Content-Security-Policy':"default-src 'self' data:; connect-src 'self'; img-src 'self' data:; font-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; form-action 'self'; base-uri 'none'; object-src 'none'; frame-ancestors 'none'; navigate-to 'self'" + }); + response.end(previewHtml); +}; + +const server = http.createServer(async (request, response) => { + const url = new URL(request.url, 'http://127.0.0.1'); + const method = request.method || 'GET'; + if (method === 'GET' && ['/', '/review', '/users'].includes(url.pathname)) return sendHtml(response); + if (method === 'GET' && url.pathname === '/auth/me') return json(response, 200, {account:{username:'fixture-admin',role:'admin',created_at:1780000000,must_change_password:false}}); + if (method === 'POST' && ['/auth/logout','/auth/change-password'].includes(url.pathname)) return json(response, 200, {ok:true}); + if (method === 'GET' && url.pathname === '/search/filters') return json(response, 200, catalogs); + if (method === 'GET' && url.pathname === '/search') { + const query = url.searchParams.get('q') || ''; + const lab = url.searchParams.has('page_size') && !url.searchParams.has('sort'); + return json(response, 200, {results:query === 'not-found' ? [] : (lab ? visualReviewDocs : visualDocs),has_next:false,review_token:'fixture-only-token'}); + } + if (method === 'GET' && url.pathname === '/documents/doc-2/editions') return json(response, 200, {available_languages:[],editions:[]}); + if (method === 'GET' && url.pathname === '/documents/doc-3/editions') return json(response, 503, {error:'Fixture editions error'}); + if (method === 'GET' && url.pathname === '/documents/doc-1/editions') return json(response, 200, {available_languages:['ru','ky'],editions:[{source_code:'2024',name:{ru:'Редакция от 12 января 2024 года',ky:'2024-жылдын 12-январындагы редакция'},available_languages:['ru','ky']},{source_code:'2023',name:{ru:'Редакция только на русском'},available_languages:['ru']}]}); + const visualReviewEdition = url.pathname.match(/^\/documents\/(review-a|review-b)\/editions\/(2026|2025)$/); + if (method === 'GET' && visualReviewEdition) return json(response, 200, {content:{ru:{html:visualReviewArticles[visualReviewEdition[1]]}}}); + const edition = url.pathname.match(/^\/documents\/doc-1\/editions\/(2024|2023)$/); + if (method === 'GET' && edition) { + const language = url.searchParams.get('language') || 'ru'; + const content = edition[1] === '2023' ? '

Russian-only edition

Regression fixture.

' : language === 'ky' ? articleKy : visualArticle; + return json(response, 200, {content:{[language]:{html:content}}}); + } + if (method === 'GET' && url.pathname === '/admin/users') return json(response, 200, {users}); + if (method === 'POST' && url.pathname === '/admin/users') { + const body = await readBody(request); const username = String(body.username || 'fixture-created'); + users.push({username,role:'user',must_change_password:true,last_login_at:null,first_login_at:1780000000,password_reset_at:null}); + return json(response, 201, {username}); + } + if (method === 'POST' && /^\/admin\/users\/[^/]+\/reset-password$/.test(url.pathname)) return json(response, 200, {ok:true}); + if (method === 'DELETE' && /^\/admin\/users\/[^/]+$/.test(url.pathname)) return json(response, 200, {ok:true}); + if (method === 'POST' && url.pathname === '/search-reviews') return json(response, 200, {id:42}); + if (method === 'GET' && url.pathname.startsWith('/static/')) { + const name = path.basename(url.pathname); + const file = path.join(staticRoot, url.pathname.endsWith('.woff2') ? 'fonts' : '', name); + if (!fs.existsSync(file) || !fs.statSync(file).isFile()) return json(response, 404, {error:'Not found'}); + const type = name.endsWith('.woff2') ? 'font/woff2' : name.endsWith('.svg') ? 'image/svg+xml' : 'image/png'; + response.writeHead(200, {'Content-Type':type,'Cache-Control':'no-store','X-Content-Type-Options':'nosniff'}); + return fs.createReadStream(file).pipe(response); + } + return json(response, 404, {error:'Fixture route not found'}); +}); + +server.on('error', (error) => { process.stderr.write(`${error.code || error.name}\n`); process.exitCode = 1; }); +server.listen(port, '127.0.0.1', () => { + process.stdout.write(`fixture preview listening at http://127.0.0.1:${port}/ (pid ${process.pid})\n`); +}); -- 2.54.0 From 48cb424afdee6b7f82b916671f2cd2d22ee91eed Mon Sep 17 00:00:00 2001 From: Codex Date: Sat, 24 Oct 2026 19:49:55 +0300 Subject: [PATCH 2/3] Refine search, account, and lab layouts --- CHANGELOG.md | 4 + README.md | 6 +- backend/search/minjust_opensearch.py | 2 +- backend/search/review.html | 138 +++++++++++------- tools/frontend-visual-review/check.cjs | 76 ++++++---- tools/frontend-visual-review/fixtures.cjs | 3 +- .../frontend-visual-review/preview-server.cjs | 7 +- 7 files changed, 144 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa7b835..31785ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Не выпущено +- Frontend `0.3.1`: уточнена компоновка поиска, лаборатории и кабинета; + splitter сохраняет минимальную ширину панелей, а на средних экранах фильтры + открываются доступной боковой панелью. Исправлено отображение футера на + маршруте пользователей и browser fixture смены пароля. - Frontend `0.3.0` / Backend `0.13.1`: добавлен доступный splitter для изменения ширины результатов и документа. Язык поиска находится в фильтрах; состояния открытия, оглавление правовых заголовков, лаборатория и кабинет diff --git a/README.md b/README.md index 6afd602..b67f526 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Telegram-бот — только часть рабочего окружения ## Текущее состояние Сейчас реализованы Telegram-бот-секретарь версии `0.2.2`, backend версии -`0.13.1` и frontend `0.3.0` с поисковым экраном и внутренней лабораторией. +`0.13.1` и frontend `0.3.1` с поисковым экраном и внутренней лабораторией. Авторизация хранится в SQLite; первый пользователь `admin` создаётся интерактивной CLI-командой. Поиск расширяет аббревиатуры организационно-правовых форм и поднимает @@ -20,7 +20,7 @@ SQLite; первый пользователь `admin` создаётся инт |---|---:|---| | Telegram-бот | `0.2.2` | на Synology работает `0.2.1`; обновление после слияния | | Backend | `0.13.1` | авторизация, поиск с фильтрами, ограниченный staging и статические ресурсы | -| Frontend | `0.3.0` | поиск по правовой базе, просмотр редакций, настраиваемая ширина панелей и внутренняя лаборатория | +| Frontend | `0.3.1` | поиск по правовой базе, просмотр редакций, настраиваемая ширина панелей и внутренняя лаборатория | | Сбор и обработка правовых данных | `0.8.0` | добавлены relevance set и оценка выдачи | | RAG и база знаний | — | ещё не созданы | @@ -63,4 +63,4 @@ python3 -m unittest discover -s tools/telegram-bot -v --- -Акылдаш · Telegram-бот v0.2.2 · Backend v0.13.1 · Frontend v0.3.0 +Акылдаш · Telegram-бот v0.2.2 · Backend v0.13.1 · Frontend v0.3.1 diff --git a/backend/search/minjust_opensearch.py b/backend/search/minjust_opensearch.py index 614e3b2..4f06bc9 100644 --- a/backend/search/minjust_opensearch.py +++ b/backend/search/minjust_opensearch.py @@ -465,7 +465,7 @@ def main() -> int: else: documents, fragments = export_bulk(arguments.input, arguments.output, arguments.index, arguments.limit) destination = arguments.output - print(f"documents={documents} fragments={fragments} destination={destination}\nAkyldash · Backend v{APP_VERSION} · Frontend v0.3.0") + print(f"documents={documents} fragments={fragments} destination={destination}\nAkyldash · Backend v{APP_VERSION} · Frontend v0.3.1") return 0 diff --git a/backend/search/review.html b/backend/search/review.html index 5138c19..3423b00 100644 --- a/backend/search/review.html +++ b/backend/search/review.html @@ -49,13 +49,13 @@ .review__panel-hint { color: var(--muted); font-size: .875rem; } .review__results-list { display: grid; gap: .75rem; margin: 0; padding: 0; list-style: none; } .review__result { padding: 1rem 0; border: 0; border-block-end: 1px solid var(--line); border-radius: 0; background: var(--surface); transition-property: background-color, border-color; transition-duration: 150ms; transition-timing-function: cubic-bezier(.2, 0, 0, 1); } - .review__result--selected { background: var(--subtle); box-shadow: none; } + .review__result--selected { padding: 8px 10px; background: var(--subtle); box-shadow: none; } .review__result:first-child { border-block-start: 1px solid var(--line); } .review__result-title { display: flex; gap: .65rem; align-items: baseline; width: 100%; min-height: 44px; text-align: start; font-weight: 700; border: 0; padding: 0; background: none; color: var(--brand-dark); } .review__rank { flex: 0 0 auto; color: var(--brand); font-variant-numeric: tabular-nums; } - .review__meta { margin-block: .5rem; color: var(--muted); font-size: .875rem; } - .review__rating { display: grid; grid-template-columns: repeat(4, 1fr); gap: .4rem; margin-block: 1rem .75rem; padding: 0; border: 0; } - .review__rating legend { width: 100%; margin-block-end: .35rem; font-size: .875rem; font-weight: 700; color: var(--muted); grid-column: 1 / -1; } + .review__meta { margin-block: 4px; color: var(--muted); font-size: .875rem; } + .review__rating { display: grid; grid-template-columns: repeat(4, 1fr); gap: .35rem; margin-block: 8px 6px; padding: 0; border: 0; } + .review__rating legend { width: 100%; margin-block-end: 2px; font-size: .875rem; font-weight: 700; color: var(--muted); grid-column: 1 / -1; } .review__rating label { display: grid; place-items: center; min-width: 0; min-height: 44px; padding: .45rem .25rem; border: 1px solid var(--line); border-radius: 6px; color: var(--muted); text-align: center; font-size: .875rem; cursor: pointer; } .review__rating label:has(input:checked) { border-color: var(--brand); background: var(--brand); color: #fff; } .review__rating label:has(input:focus-visible) { outline: 3px solid var(--focus); outline-offset: 2px; } @@ -217,6 +217,7 @@ body.is-users-route > .review__header { display: block; width: 100%; padding-block-end: 0; } body.is-users-route > .review__header > .review__header-content { display: none; } body.is-users-route > .review__actions { display: none; } + body.is-users-route > .search__footer { display: none; } body.is-users-route > footer.review__header { display: block; margin-block-start: auto; } .review__users-page { width: min(1200px, 100%); flex: 1; margin-inline: auto; padding: 28px clamp(16px, 4vw, 48px); } .review__users-page[hidden] { display: none !important; } @@ -285,12 +286,11 @@ body:has(.search:not([hidden])) > .search__chrome { display: block; } .search__chrome { display: none; background: var(--surface); border-block-end: 1px solid var(--line); } .search[hidden] { display: none !important; } - .search__topbar { min-height: var(--search-header-height); display: grid; grid-template-columns: minmax(390px, 430px) minmax(0, 1fr) auto; gap: 16px; align-items: center; padding: 5px 26px; border-block-end: 1px solid var(--line); } + .search__topbar { min-height: var(--search-header-height); display: grid; grid-template-columns: 166px minmax(0, 1fr) auto; gap: 16px; align-items: center; padding: 5px 26px; border-block-end: 1px solid var(--line); } .search__brand { display: flex; min-width: 0; align-items: center; gap: 12px; color: var(--ink); text-decoration: none; white-space: nowrap; } .search__brand-mark { width: 44px; height: 44px; flex: none; color: var(--brand); } .search__brand-name { font: 700 26px/1.1 var(--serif); } - .search__brand-divider { width: 1px; height: 32px; background: var(--line); } - .search__brand-description { color: var(--muted); font-size: 14px; } + .search__brand-divider, .search__brand-description { display: none; } .search__query { display: grid; grid-template-columns: minmax(0, 1fr) 160px; gap: 12px; align-items: end; min-width: 0; padding: 0; border: 0; background: transparent; } .search__query label { display: grid; gap: 4px; color: var(--muted); font-size: 14px; font-weight: 500; } .search__query label > span { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } @@ -503,25 +503,29 @@ .review__nav-links .is-active { border-color: var(--brand); background: var(--subtle); color: var(--brand); } .review__nav-links [hidden], .search__account-actions [hidden] { display: none !important; } .review__nav-account > span { color: var(--muted); } - .review__header-content { width: min(100%, 1440px); } + .review__header-content { width: 100%; max-width: none; padding-inline: 24px; } body:has(#review:not([hidden])) { min-height: 100dvh; height: 100dvh; overflow: hidden; } body:has(#review:not([hidden])) > .review__header { padding: 0; } - body:has(#review:not([hidden])) > #review { width: min(100%, 1440px); min-height: 0; margin: 0 auto; padding-inline: clamp(16px, 3vw, 40px); display: flex; flex-direction: column; } - body:has(#review:not([hidden])) > .review__actions { width: min(100%, 1440px); min-height: 96px; box-sizing: border-box; margin: 0 auto; padding: 8px clamp(16px, 3vw, 40px) 0; } - body:has(#review:not([hidden])) > footer.review__header { width: 100%; margin-block-start: 12px; } - .review__header-content, .review__actions-inner { max-width: 1440px; } + body:has(#review:not([hidden])) > #review { width: 100%; max-width: none; min-height: 0; margin: 0; padding: 0; display: flex; flex-direction: column; } + body:has(#review:not([hidden])) > .review__actions { width: 100%; min-height: 96px; flex: 0 0 96px; box-sizing: border-box; margin: 0; padding: 0 24px; } + body:has(#review:not([hidden])) > footer.review__header { width: 100%; margin: 0; } + .review__header-content, .review__actions-inner { width: 100%; max-width: none; } body:has(#review:not([hidden])) .review__nav { height: 64px; min-height: 64px; padding-block: 0; } - body:has(#review:not([hidden])) .review__header-content { display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: 32px 20px; column-gap: 24px; align-content: center; height: 64px; } - body:has(#review:not([hidden])) .review__header-top { grid-column: 1; grid-row: 1 / 3; align-self: center; padding: 0; } - body:has(#review:not([hidden])) .review__header-content h1 { grid-column: 2; grid-row: 1; max-width: none; margin: 0; font: 600 26px/32px var(--sans); } - body:has(#review:not([hidden])) .review__header-content p { grid-column: 2; grid-row: 2; max-width: none; margin: 0; font: 400 14px/20px var(--sans); white-space: nowrap; } - .review__search { gap: 12px; padding: 12px 0; border: 0; border-block-end: 1px solid var(--line); border-radius: 0; background: transparent; } - .review__workspace { min-height: 0; max-height: min(58dvh, 620px); flex: 1 1 0; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: 0; align-items: stretch; overflow: hidden; border-block: 1px solid var(--line); background: var(--surface); } - .review__results, .review__document { min-height: 0; max-height: none; padding: 14px clamp(12px, 1.5vw, 22px); border: 0; border-radius: 0; background: var(--surface); } + body:has(#review:not([hidden])) .review__header-content { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; height: 64px; } + body:has(#review:not([hidden])) .review__heading-copy { min-width: 0; display: grid; grid-template-rows: 32px 20px; align-content: center; } + body:has(#review:not([hidden])) .review__header-top { grid-column: 2; grid-row: 1; align-self: center; padding: 0; } + body:has(#review:not([hidden])) .review__header-content h1 { max-width: none; margin: 0; font: 600 26px/32px var(--sans); } + body:has(#review:not([hidden])) .review__header-content p { max-width: none; margin: 0; font: 400 14px/20px var(--sans); white-space: nowrap; } + .review__search { gap: 12px; padding: 12px 24px; border: 0; border-block-end: 1px solid var(--line); border-radius: 0; background: transparent; } + #status.review__status { grid-column: 1 / -1; margin: 0; } + #status.review__status:empty { display: none; } + #status.review__status--success { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } + .review__workspace { min-height: 0; flex: 1 1 0; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: 0; align-items: stretch; overflow: hidden; border-block: 1px solid var(--line); background: var(--surface); } + .review__results, .review__document { min-height: 0; max-height: none; padding: 14px 24px; border: 0; border-radius: 0; background: var(--surface); } .review__results { overflow: auto; border-inline-end: 1px solid var(--line); } .review__document { position: static; overflow: auto; overscroll-behavior: contain; } .review__document-meta { overflow-wrap: anywhere; } - .review__actions-inner { padding: 5px 0; border: 0; border-block-start: 1px solid var(--line); border-radius: 0; background: transparent; } + .review__actions-inner { padding: 5px 24px; border: 0; border-block-start: 1px solid var(--line); border-radius: 0; background: transparent; } body:has(#review:not([hidden])) > footer.review__header { height: 44px; min-height: 44px; } body:has(#review:not([hidden])) > footer.review__header .review__header-content { display: flex; align-items: center; height: 44px; padding-block: 0; } .search__subnav { flex-wrap: wrap; overflow: visible; white-space: normal; } @@ -530,22 +534,29 @@ .search__chips { flex: 1 1 8rem; } .search__filter-language { display: grid; gap: 5px; margin-block: 0 16px; color: var(--muted); font-size: .875rem; font-weight: 600; } .search__filter-language select { min-height: 42px; width: 100%; padding: 7px 10px; color: var(--ink); background: var(--surface); border: 1px solid var(--line); } - .search__layout { grid-template-columns: minmax(190px, clamp(190px, 18vw, 250px)) minmax(260px, 36fr) 12px minmax(320px, 64fr); } - .search__layout[data-filters-hidden="true"] { grid-template-columns: minmax(260px, 36fr) 12px minmax(320px, 64fr); } + .search__layout { grid-template-columns: minmax(264px, clamp(264px, calc(20vw + 8px), 288px)) minmax(360px, 38.1fr) 8px minmax(560px, 61.9fr); } + .search__layout[data-filters-hidden="true"] { grid-template-columns: minmax(360px, 38.1fr) 8px minmax(560px, 61.9fr); } + .search__filters { margin-inline-end: 8px; } .search__mobile-filters { display: inline-flex; } .search__layout[data-filters-hidden="true"] .search__filters { display: none; } - .search__splitter { z-index: 1; align-self: stretch; width: 12px; min-width: 12px; min-height: 100%; padding: 0; border: 0; border-radius: 0; background: linear-gradient(90deg, transparent 4px, var(--brand-dark) 4px 8px, transparent 8px); cursor: col-resize; touch-action: none; } - .search__splitter:hover, .search__splitter:focus-visible { background: linear-gradient(90deg, transparent 3px, var(--brand) 3px 9px, transparent 9px); } - body:has(#review:not([hidden])) > .review__header, body:has(#review:not([hidden])) > footer.review__header { width: min(calc(100% - 2 * clamp(16px, 3vw, 40px)), 1240px); max-width: 1240px; margin-inline: auto; padding-inline: 0; } - body:has(#review:not([hidden])) .review__nav, body:has(#review:not([hidden])) .review__header-content { width: 100%; max-width: none; padding-inline: 0; } + .search__splitter { position: relative; z-index: 1; align-self: stretch; justify-self: center; width: 12px; min-width: 12px; min-height: 100%; margin-inline: -2px; padding: 0; border: 0; border-radius: 0; background: linear-gradient(90deg, transparent 2px, var(--surface-muted) 2px 10px, transparent 10px); cursor: col-resize; touch-action: none; } + .search__splitter::before { position: absolute; inset-block: 0; inset-inline-start: 50%; width: 1px; background: var(--line); content: ''; transform: translateX(-50%); } + .search__splitter::after { position: absolute; inset-block-start: 50%; inset-inline-start: 50%; width: 3px; height: 40px; border-radius: 2px; background: var(--muted); content: ''; transform: translate(-50%, -50%); } + .search__splitter:hover::after, .search__splitter:focus-visible::after { background: var(--brand); } + body:has(#review:not([hidden])) > .review__header, body:has(#review:not([hidden])) > footer.review__header { width: 100%; max-width: none; margin: 0; padding-inline: 0; } + body:has(#review:not([hidden])) .review__nav, body:has(#review:not([hidden])) .review__header-content { width: 100%; max-width: none; padding-inline: 24px; } body:has(#review:not([hidden])) .review__header-content h1 { font: 600 26px/32px var(--sans); } body:has(#review:not([hidden])) .review__panel-heading h2 { font: 600 20px/26px var(--sans); } + body.is-users-route > .search__footer { display: none !important; } .search__pagination[hidden] { display: none; } .search__document-language[hidden] { display: none; } + .search__account-actions { display: grid; grid-template-columns: max-content max-content; justify-content: start; gap: 8px; } .search__account-actions a { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 8px 12px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface); color: var(--brand-dark); font-weight: 600; text-decoration: none; } .search__account-actions a:hover { border-color: var(--brand); background: var(--subtle); } + #search-logout { grid-column: 1 / -1; justify-self: start; min-height: 36px; margin-block-start: 2px; padding-inline: 0; border: 0; color: var(--muted); background: transparent; } #account-dialog dl { display: grid; grid-template-columns: minmax(7.5rem, max-content) minmax(0, 1fr); gap: 8px 16px; margin: 16px 0 24px; } + #account-dialog { width: min(560px, calc(100vw - 32px)); max-width: none; } #account-dialog > .review__page { padding: 16px; } #account-dialog dt { color: var(--muted); } #account-dialog dd { min-width: 0; margin: 0; overflow-wrap: anywhere; } @@ -556,17 +567,22 @@ #account-dialog .review__dialog-heading h2 { max-width: none; padding: 0; font: 600 20px/28px var(--sans); } #account-dialog .review__dialog-heading button { display: grid; place-items: center; flex: 0 0 44px; width: 44px; min-height: 44px; padding: 0; } #public-document-body img, #document-body img { max-width: 100%; height: auto; object-fit: contain; } - @media (min-width: 901px) and (max-width: 1175px) { - .search__layout { grid-template-columns: minmax(180px, 22%) minmax(260px, 36fr) 12px minmax(320px, 64fr); } - .search__layout[data-filters-hidden="true"] { grid-template-columns: minmax(260px, 36fr) 12px minmax(320px, 64fr); } - .search__layout:not([data-filters-hidden="true"]) .search__filters { display: flex; } + @media (min-width: 901px) and (max-width: 1191px) { + #search-layout { grid-template-columns: minmax(360px, 38.1fr) minmax(560px, 61.9fr); } + #search-layout .search__filters { display: none; } + #search-layout .search__filters.is-open { position: fixed; z-index: 21; inset: 16px auto 16px 16px; display: block; width: min(360px, calc(100vw - 32px)); overflow: auto; padding: 20px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); box-shadow: 0 12px 40px rgb(34 28 28 / .2); } + .search__filter-close { display: inline-flex; } + .search__filter-overlay.is-open { position: fixed; z-index: 20; inset: 0; display: block; background: rgb(56 38 42 / .42); } + .search__splitter { display: none; } } @media (max-width: 900px) { body:has(#review:not([hidden])) { min-height: 100svh; height: auto; overflow: visible; } body:has(#review:not([hidden])) > #review { flex: none; padding-inline: 16px; } - body:has(#review:not([hidden])) > .review__header, body:has(#review:not([hidden])) > footer.review__header { width: calc(100% - 32px); } - body:has(#review:not([hidden])) .review__nav, body:has(#review:not([hidden])) .review__header-content { padding-inline: 0; } - body:has(#review:not([hidden])) .review__header-content { display: block; height: auto; padding-block: 12px; } + body:has(#review:not([hidden])) .review__nav, body:has(#review:not([hidden])) .review__header-content { padding-inline: 16px; } + body:has(#review:not([hidden])) .review__header-content { display: flex; flex-direction: column; align-items: stretch; gap: 8px; height: auto; padding-block: 12px; } + body:has(#review:not([hidden])) .review__heading-copy { display: block; } + body:has(#review:not([hidden])) .review__header-top { align-self: flex-start; } + .review__search { padding-inline: 16px; } body:has(#review:not([hidden])) .review__header-top { padding-block: 0 8px; } body:has(#review:not([hidden])) .review__header-content h1, body:has(#review:not([hidden])) .review__header-content p { display: block; } body:has(#review:not([hidden])) .review__header-content p { white-space: normal; } @@ -575,7 +591,10 @@ .review__results, .review__document { max-height: none; overflow: visible; border-inline: 0; } .review__results { border-block-end: 1px solid var(--line); } .review__document { display: block; } - body:has(#review:not([hidden])) > .review__actions { padding-inline: 16px; } + .review__results, .review__document { padding-inline: 16px; } + body:has(#review:not([hidden])) > .review__actions { flex: 0 0 auto; padding-inline: 0; } + .review__actions-inner { padding-inline: 16px; } + body:has(#review:not([hidden])) > footer.review__header { height: auto; min-height: 44px; } .search__layout, .search__layout[data-filters-hidden="true"] { display: block; } .search__splitter { display: none; } .search__filter-language { margin-block-end: 16px; } @@ -597,8 +616,7 @@ Перейти к результатам
Акылдаш
-
-

Проверка качества поиска

Сопоставляйте запрос с текстом документов и сохраняйте оценку выдачи.

+

Проверка качества поиска

Сопоставляйте запрос с текстом документов и сохраняйте оценку выдачи.

@@ -617,8 +635,8 @@ +
-

Результаты поиска

Оцените каждый документ
  1. Начните с запросаВведите юридический вопрос выше, чтобы увидеть результаты.

Просмотр документа

Откройте результат
Выберите название в списке, чтобы прочитать документ.
@@ -633,7 +651,7 @@

Документ

Выберите документ в выдаче, чтобы открыть текст.

Содержание
-
Акылдаш Правовая база КыргызстанаFrontend v0.3.0 Backend v0.13.1
+
Акылдаш Правовая база КыргызстанаFrontend v0.3.1 Backend v0.13.1

Черновик появится после поиска.

Вход в Акылдаш

Введите учетные данные, выданные администратором.

Создайте новый пароль

Для продолжения замените временный пароль. Используйте не менее 12 символов.

@@ -651,7 +669,7 @@

Документ

Источники документов

Поиск выполняется по документам, подготовленным из правовых источников Кыргызской Республики. Для каждого результата доступная редакция и ссылка на официальный источник показываются в панели документа.

Официальный источник: Централизованный банк данных правовой информации Министерства юстиции Кыргызской Республики.

Короткое знакомство

-
Акылдаш · Frontend v0.3.0 · Backend v0.13.1 · Внутренняя лаборатория релевантности
+
Акылдаш · Frontend v0.3.1 · Backend v0.13.1 · Внутренняя лаборатория релевантности