mirror of
https://github.com/dartdavros/chatballs.git
synced 2026-10-05 09:14:58 +03:00
🔥 chore: прежние имена продукта убраны из отслеживаемых файлов
Требование к open-source публикации: в репозитории не должно остаться CustoCRM и eDevs Hub. В docs/ это сделано ранее, здесь — код и дизайн. Дизайн-система (design/design-system): - заголовки, брендинг и примерные данные переведены на Chatballs; - переименованы глобали справочника: CUSTOCRM_ICON_SPRITE → CHATBALLS_ICON_SPRITE, CUSTOCRM_INVENTORY → CHATBALLS_INVENTORY, data-атрибут спрайта — обе стороны замкнуты внутри справочника; - в README поправлены пути открытия: справочник живёт в design/, а не в apps/internal-ui/; - личный адрес andrey@edevs.tech в примере таблицы заменён на example.com. Макеты (design/baseline): - каталоги _ds/edevs-hub-design-system-<uuid>/ переименованы в _ds/design-system/, ссылки в .dc.html обновлены; - JS-namespace бандла EdevsHubDesignSystem_e4c9df → ChatballsDesignSystem_e4c9df (21 вхождение: бандл, манифест, все x-import в макетах); - readme.md внутри бандлов удалён — это описание прежнего продукта (hub.edevs.tech, checkout, командный центр), к текущему отношения не имеет; - assets/custocrm-mark.svg → chatballs-mark.svg; - удалён каталог «Каналы обработки» целиком: макеты сущности, упразднённой ADR-CHATBALLS-0041. Восстанавливается из истории git, если понадобится. Тесты: tests/cli/test_custocrm_cli.py → test_chatballs_cli.py, набор проходит (9 passed). Ссылки в макетах и справочнике проверены: из 121 ссылки битых 6, и все шесть — в «Сотрудники/Сотрудники (новая модель).dc.html», где каталог _ds отсутствовал и до этих правок. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e088ead06f
commit
90be94af43
56 files changed
+118
-7508
No files matched your search
File renamed without changes.
+14
-14
@@ -1,8 +1,8 @@
|
||||
/* @ds-bundle: {"format":4,"namespace":"EdevsHubDesignSystem_e4c9df","components":[{"name":"CommerceStatusTimeline","sourcePath":"components/cards/CommerceStatusTimeline.jsx"},{"name":"DepartmentCard","sourcePath":"components/cards/DepartmentCard.jsx"},{"name":"IntegrationHealthCard","sourcePath":"components/cards/IntegrationHealthCard.jsx"},{"name":"MetricCard","sourcePath":"components/cards/MetricCard.jsx"},{"name":"ProductAIReleaseCard","sourcePath":"components/cards/ProductAIReleaseCard.jsx"},{"name":"Avatar","sourcePath":"components/core/Avatar.jsx"},{"name":"Button","sourcePath":"components/core/Button.jsx"},{"name":"Checkbox","sourcePath":"components/core/Checkbox.jsx"},{"name":"Icon","sourcePath":"components/core/Icon.jsx"},{"name":"ICON_NAMES","sourcePath":"components/core/Icon.jsx"},{"name":"IconButton","sourcePath":"components/core/IconButton.jsx"},{"name":"Input","sourcePath":"components/core/Input.jsx"},{"name":"Tag","sourcePath":"components/core/Tag.jsx"},{"name":"ConversationInbox","sourcePath":"components/inbox/ConversationInbox.jsx"},{"name":"KnowledgeDocumentEditor","sourcePath":"components/inbox/KnowledgeDocumentEditor.jsx"},{"name":"ActorBadge","sourcePath":"components/status/ActorBadge.jsx"},{"name":"AttentionStatus","sourcePath":"components/status/AttentionStatus.jsx"},{"name":"ChannelBadge","sourcePath":"components/status/ChannelBadge.jsx"}],"sourceHashes":{"components/cards/CommerceStatusTimeline.jsx":"a71f119a6bcb","components/cards/DepartmentCard.jsx":"743b4f9632ec","components/cards/IntegrationHealthCard.jsx":"4888c60e9532","components/cards/MetricCard.jsx":"4edb7590ee04","components/cards/ProductAIReleaseCard.jsx":"53de80d598b8","components/core/Avatar.jsx":"e963633b7162","components/core/Button.jsx":"52b57248ad92","components/core/Checkbox.jsx":"412f119cdbb2","components/core/Icon.jsx":"f6c5a199fcf5","components/core/IconButton.jsx":"e8c066b43714","components/core/Input.jsx":"4561efdc9997","components/core/Tag.jsx":"48a8a3543145","components/inbox/ConversationInbox.jsx":"ea2ad8f6a755","components/inbox/KnowledgeDocumentEditor.jsx":"f97e9057fb25","components/status/ActorBadge.jsx":"11e6274f6875","components/status/AttentionStatus.jsx":"a22cbb5b37d2","components/status/ChannelBadge.jsx":"e15a0c45d45f","ui_kits/checkout/CheckoutWidget.jsx":"6d563825a7e0","ui_kits/internal-hub/AuthLoginPage.jsx":"b3ee3d8ea9ab","ui_kits/internal-hub/ClientsPage.jsx":"0a9fb9f5b11d","ui_kits/internal-hub/CommandCenterPage.jsx":"870dd4cd0c22","ui_kits/internal-hub/HubShell.jsx":"ce0eb4d2dc70","ui_kits/web-chat/WebChatWidget.jsx":"e4099f49f9c0"},"inlinedExternals":[],"unexposedExports":[]} */
|
||||
/* @ds-bundle: {"format":4,"namespace":"ChatballsDesignSystem_e4c9df","components":[{"name":"CommerceStatusTimeline","sourcePath":"components/cards/CommerceStatusTimeline.jsx"},{"name":"DepartmentCard","sourcePath":"components/cards/DepartmentCard.jsx"},{"name":"IntegrationHealthCard","sourcePath":"components/cards/IntegrationHealthCard.jsx"},{"name":"MetricCard","sourcePath":"components/cards/MetricCard.jsx"},{"name":"ProductAIReleaseCard","sourcePath":"components/cards/ProductAIReleaseCard.jsx"},{"name":"Avatar","sourcePath":"components/core/Avatar.jsx"},{"name":"Button","sourcePath":"components/core/Button.jsx"},{"name":"Checkbox","sourcePath":"components/core/Checkbox.jsx"},{"name":"Icon","sourcePath":"components/core/Icon.jsx"},{"name":"ICON_NAMES","sourcePath":"components/core/Icon.jsx"},{"name":"IconButton","sourcePath":"components/core/IconButton.jsx"},{"name":"Input","sourcePath":"components/core/Input.jsx"},{"name":"Tag","sourcePath":"components/core/Tag.jsx"},{"name":"ConversationInbox","sourcePath":"components/inbox/ConversationInbox.jsx"},{"name":"KnowledgeDocumentEditor","sourcePath":"components/inbox/KnowledgeDocumentEditor.jsx"},{"name":"ActorBadge","sourcePath":"components/status/ActorBadge.jsx"},{"name":"AttentionStatus","sourcePath":"components/status/AttentionStatus.jsx"},{"name":"ChannelBadge","sourcePath":"components/status/ChannelBadge.jsx"}],"sourceHashes":{"components/cards/CommerceStatusTimeline.jsx":"a71f119a6bcb","components/cards/DepartmentCard.jsx":"743b4f9632ec","components/cards/IntegrationHealthCard.jsx":"4888c60e9532","components/cards/MetricCard.jsx":"4edb7590ee04","components/cards/ProductAIReleaseCard.jsx":"53de80d598b8","components/core/Avatar.jsx":"e963633b7162","components/core/Button.jsx":"52b57248ad92","components/core/Checkbox.jsx":"412f119cdbb2","components/core/Icon.jsx":"f6c5a199fcf5","components/core/IconButton.jsx":"e8c066b43714","components/core/Input.jsx":"4561efdc9997","components/core/Tag.jsx":"48a8a3543145","components/inbox/ConversationInbox.jsx":"ea2ad8f6a755","components/inbox/KnowledgeDocumentEditor.jsx":"f97e9057fb25","components/status/ActorBadge.jsx":"11e6274f6875","components/status/AttentionStatus.jsx":"a22cbb5b37d2","components/status/ChannelBadge.jsx":"e15a0c45d45f","ui_kits/checkout/CheckoutWidget.jsx":"6d563825a7e0","ui_kits/internal-hub/AuthLoginPage.jsx":"b3ee3d8ea9ab","ui_kits/internal-hub/ClientsPage.jsx":"0a9fb9f5b11d","ui_kits/internal-hub/CommandCenterPage.jsx":"870dd4cd0c22","ui_kits/internal-hub/HubShell.jsx":"ce0eb4d2dc70","ui_kits/web-chat/WebChatWidget.jsx":"e4099f49f9c0"},"inlinedExternals":[],"unexposedExports":[]} */
|
||||
|
||||
(() => {
|
||||
|
||||
const __ds_ns = (window.EdevsHubDesignSystem_e4c9df = window.EdevsHubDesignSystem_e4c9df || {});
|
||||
const __ds_ns = (window.ChatballsDesignSystem_e4c9df = window.ChatballsDesignSystem_e4c9df || {});
|
||||
|
||||
const __ds_scope = {};
|
||||
|
||||
@@ -1094,10 +1094,10 @@ const {
|
||||
CommerceStatusTimeline,
|
||||
Icon,
|
||||
Checkbox
|
||||
} = window.EdevsHubDesignSystem_e4c9df;
|
||||
} = window.ChatballsDesignSystem_e4c9df;
|
||||
|
||||
/* Recreation of design/baseline/CheckoutPanel.dc.html — the public
|
||||
pay.hub.edevs.tech checkout flow (SPEC-HUB-0007). Mobile-first, no Hub chrome. */
|
||||
pay.chatballs checkout flow (SPEC-HUB-0007). Mobile-first, no Hub chrome. */
|
||||
function CheckoutWidget() {
|
||||
const [st, setSt] = React.useState("checkout");
|
||||
const [buyer, setBuyer] = React.useState("person");
|
||||
@@ -1823,7 +1823,7 @@ const {
|
||||
Input,
|
||||
Button,
|
||||
Icon
|
||||
} = window.EdevsHubDesignSystem_e4c9df;
|
||||
} = window.ChatballsDesignSystem_e4c9df;
|
||||
|
||||
/* Recreation of design/baseline/AUTH · Вход.dc.html */
|
||||
function AuthLoginPage({
|
||||
@@ -1872,7 +1872,7 @@ function AuthLoginPage({
|
||||
fontWeight: 700,
|
||||
letterSpacing: "-0.01em"
|
||||
}
|
||||
}, "Edevs Hub"), /*#__PURE__*/React.createElement("p", {
|
||||
}, "Chatballs"), /*#__PURE__*/React.createElement("p", {
|
||||
style: {
|
||||
margin: "5px 0 0",
|
||||
fontSize: 13,
|
||||
@@ -1919,7 +1919,7 @@ function AuthLoginPage({
|
||||
}),
|
||||
value: email,
|
||||
onChange: e => setEmail(e.target.value),
|
||||
placeholder: "you@edevs.tech"
|
||||
placeholder: "you@chatballs"
|
||||
})), /*#__PURE__*/React.createElement("div", {
|
||||
style: {
|
||||
marginBottom: 22
|
||||
@@ -1962,7 +1962,7 @@ function AuthLoginPage({
|
||||
fontSize: 12,
|
||||
color: "var(--n-5)"
|
||||
}
|
||||
}, "\u0414\u043E\u0441\u0442\u0443\u043F \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0441\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A\u043E\u0432 Edevs \xB7 \u0437\u0430\u0449\u0438\u0449\u0451\u043D\u043D\u043E\u0435 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435")));
|
||||
}, "\u0414\u043E\u0441\u0442\u0443\u043F \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0441\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A\u043E\u0432 Chatballs \xB7 \u0437\u0430\u0449\u0438\u0449\u0451\u043D\u043D\u043E\u0435 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435")));
|
||||
}
|
||||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/internal-hub/AuthLoginPage.jsx", error: String((e && e.message) || e) }); }
|
||||
|
||||
@@ -1972,7 +1972,7 @@ const {
|
||||
Avatar,
|
||||
Tag,
|
||||
Icon
|
||||
} = window.EdevsHubDesignSystem_e4c9df;
|
||||
} = window.ChatballsDesignSystem_e4c9df;
|
||||
const DATA = [{
|
||||
name: "Мария Соколова",
|
||||
initials: "МС",
|
||||
@@ -2265,7 +2265,7 @@ const {
|
||||
MetricCard,
|
||||
IntegrationHealthCard,
|
||||
AttentionStatus
|
||||
} = window.EdevsHubDesignSystem_e4c9df;
|
||||
} = window.ChatballsDesignSystem_e4c9df;
|
||||
|
||||
/* Recreation of design/baseline/Командный центр.dc.html */
|
||||
function CommandCenterPage({
|
||||
@@ -2508,7 +2508,7 @@ try { (() => {
|
||||
const {
|
||||
Icon,
|
||||
Avatar
|
||||
} = window.EdevsHubDesignSystem_e4c9df;
|
||||
} = window.ChatballsDesignSystem_e4c9df;
|
||||
const NAV = [{
|
||||
key: "command",
|
||||
label: "Командный центр",
|
||||
@@ -2597,7 +2597,7 @@ function HubShell({
|
||||
color: "var(--text-heading)",
|
||||
letterSpacing: "-0.01em"
|
||||
}
|
||||
}, "Edevs Hub"), /*#__PURE__*/React.createElement("span", {
|
||||
}, "Chatballs"), /*#__PURE__*/React.createElement("span", {
|
||||
style: {
|
||||
fontSize: 11,
|
||||
color: "var(--text-tertiary)"
|
||||
@@ -2715,7 +2715,7 @@ function HubShell({
|
||||
fontWeight: 500,
|
||||
color: "var(--text-secondary)"
|
||||
}
|
||||
}, "Edevs"), /*#__PURE__*/React.createElement("span", {
|
||||
}, "Chatballs"), /*#__PURE__*/React.createElement("span", {
|
||||
style: {
|
||||
color: "var(--n-6)"
|
||||
}
|
||||
@@ -2787,7 +2787,7 @@ try { (() => {
|
||||
const {
|
||||
ActorBadge,
|
||||
Icon
|
||||
} = window.EdevsHubDesignSystem_e4c9df;
|
||||
} = window.ChatballsDesignSystem_e4c9df;
|
||||
|
||||
/* Recreation of design/baseline/ChatPanel.dc.html — Foxray's embedded web-chat
|
||||
widget. States: welcome (consent) / ai / operator handoff / checkout card / unavailable. */
|
||||
@@ -0,0 +1 @@
|
||||
{"namespace":"ChatballsDesignSystem_e4c9df","components":[{"name":"CommerceStatusTimeline","sourcePath":"components/cards/CommerceStatusTimeline.jsx"},{"name":"DepartmentCard","sourcePath":"components/cards/DepartmentCard.jsx"},{"name":"IntegrationHealthCard","sourcePath":"components/cards/IntegrationHealthCard.jsx"},{"name":"MetricCard","sourcePath":"components/cards/MetricCard.jsx"},{"name":"ProductAIReleaseCard","sourcePath":"components/cards/ProductAIReleaseCard.jsx"},{"name":"Avatar","sourcePath":"components/core/Avatar.jsx"},{"name":"Button","sourcePath":"components/core/Button.jsx"},{"name":"Checkbox","sourcePath":"components/core/Checkbox.jsx"},{"name":"Icon","sourcePath":"components/core/Icon.jsx"},{"name":"ICON_NAMES","sourcePath":"components/core/Icon.jsx"},{"name":"IconButton","sourcePath":"components/core/IconButton.jsx"},{"name":"Input","sourcePath":"components/core/Input.jsx"},{"name":"Tag","sourcePath":"components/core/Tag.jsx"},{"name":"ConversationInbox","sourcePath":"components/inbox/ConversationInbox.jsx"},{"name":"KnowledgeDocumentEditor","sourcePath":"components/inbox/KnowledgeDocumentEditor.jsx"},{"name":"ActorBadge","sourcePath":"components/status/ActorBadge.jsx"},{"name":"AttentionStatus","sourcePath":"components/status/AttentionStatus.jsx"},{"name":"ChannelBadge","sourcePath":"components/status/ChannelBadge.jsx"}],"startingPoints":[{"name":"CommerceStatusTimeline","path":"components/cards/CommerceStatusTimeline.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Payment vs delivery step timeline for checkout/orders","viewport":"700x160"},{"name":"DepartmentCard","path":"components/cards/DepartmentCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Command Center department summary card","viewport":"900x360"},{"name":"IntegrationHealthCard","path":"components/cards/IntegrationHealthCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Single integration row (connected/degraded/error)","viewport":"700x90"},{"name":"MetricCard","path":"components/cards/MetricCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Single KPI cell for metric grids","viewport":"700x120"},{"name":"ProductAIReleaseCard","path":"components/cards/ProductAIReleaseCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"AI knowledge/prompt release snapshot for one product","viewport":"700x180"},{"name":"Button","path":"components/core/Button.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Primary/secondary/ghost/danger button","viewport":"700x220"},{"name":"IconButton","path":"components/core/IconButton.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Square icon-only button with optional badge","viewport":"700x150"},{"name":"Input","path":"components/core/Input.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Text field with label, icon and error state","viewport":"700x260"},{"name":"Tag","path":"components/core/Tag.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Status pill and rectangular label tag","viewport":"700x150"},{"name":"KnowledgeDocumentEditor","path":"components/inbox/KnowledgeDocumentEditor.jsx","previewPath":"components/inbox/inbox.card.html","kind":"component","section":"Inbox","subtitle":"Plain-text knowledge base document editor","viewport":"700x380"},{"name":"ActorBadge","path":"components/status/ActorBadge.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"AI vs human avatar for conversation timelines","viewport":"700x110"},{"name":"AttentionStatus","path":"components/status/AttentionStatus.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"Company/department health chip (ok/attention/critical)","viewport":"700x120"},{"name":"ChannelBadge","path":"components/status/ChannelBadge.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"MAX / Telegram / Web Chat channel chip","viewport":"700x100"}],"cards":[{"path":"guidelines/logo-mark.card.html","group":"Brand","viewport":"700x160","subtitle":"Only mark found in the codebase — a blue rounded square with a bar-chart glyph","name":"Logo Mark"},{"path":"guidelines/radii-shadows.card.html","group":"Brand","viewport":"700x180","subtitle":"Soft, low-opacity shadows only — no glassmorphism","name":"Radii & Shadows"},{"path":"ui_kits/checkout/index.html","group":"Checkout","viewport":"440x760"},{"path":"guidelines/colors-ai-channels.card.html","group":"Colors","viewport":"700x160","subtitle":"AI/human split, MAX/Telegram/Web CLine truncated
|
||||
File renamed without changes.
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* Edevs Hub — color tokens
|
||||
/* Chatballs — color tokens
|
||||
Source: packages/ui/src/theme.ts (Ant Design ThemeConfig), apps/internal-ui/src/styles/base.css,
|
||||
and design/baseline/*.dc.html (approved HTML baseline). Ant Design's default light palette,
|
||||
customized with a single accent (#1677ff) per ADR-HUB-0013. */
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* Edevs Hub — radii, shadows, motion. "Премиальный минимализм": no gradients,
|
||||
/* Chatballs — radii, shadows, motion. "Премиальный минимализм": no gradients,
|
||||
no glassmorphism/blur, no neon — shadows stay soft and near-black at low opacity. */
|
||||
|
||||
:root {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* Edevs Hub — spacing tokens. Compact-enterprise density (ADR-HUB-0013):
|
||||
/* Chatballs — spacing tokens. Compact-enterprise density (ADR-HUB-0013):
|
||||
"большие пустые поля и oversized-карточки запрещены". Values are the exact
|
||||
paddings/gaps observed in the baseline, not snapped to a rounder grid. */
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* Edevs Hub — typography tokens
|
||||
/* Chatballs — typography tokens
|
||||
The internal Hub uses the Ant Design default system font stack — no bespoke webfont
|
||||
is loaded (see ADR-HUB-0013: "используется системный font stack Ant Design без
|
||||
обязательной внешней зависимости от загружаемого шрифта"). Technical identifiers
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"namespace":"EdevsHubDesignSystem_e4c9df","components":[{"name":"CommerceStatusTimeline","sourcePath":"components/cards/CommerceStatusTimeline.jsx"},{"name":"DepartmentCard","sourcePath":"components/cards/DepartmentCard.jsx"},{"name":"IntegrationHealthCard","sourcePath":"components/cards/IntegrationHealthCard.jsx"},{"name":"MetricCard","sourcePath":"components/cards/MetricCard.jsx"},{"name":"ProductAIReleaseCard","sourcePath":"components/cards/ProductAIReleaseCard.jsx"},{"name":"Avatar","sourcePath":"components/core/Avatar.jsx"},{"name":"Button","sourcePath":"components/core/Button.jsx"},{"name":"Checkbox","sourcePath":"components/core/Checkbox.jsx"},{"name":"Icon","sourcePath":"components/core/Icon.jsx"},{"name":"ICON_NAMES","sourcePath":"components/core/Icon.jsx"},{"name":"IconButton","sourcePath":"components/core/IconButton.jsx"},{"name":"Input","sourcePath":"components/core/Input.jsx"},{"name":"Tag","sourcePath":"components/core/Tag.jsx"},{"name":"ConversationInbox","sourcePath":"components/inbox/ConversationInbox.jsx"},{"name":"KnowledgeDocumentEditor","sourcePath":"components/inbox/KnowledgeDocumentEditor.jsx"},{"name":"ActorBadge","sourcePath":"components/status/ActorBadge.jsx"},{"name":"AttentionStatus","sourcePath":"components/status/AttentionStatus.jsx"},{"name":"ChannelBadge","sourcePath":"components/status/ChannelBadge.jsx"}],"startingPoints":[{"name":"CommerceStatusTimeline","path":"components/cards/CommerceStatusTimeline.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Payment vs delivery step timeline for checkout/orders","viewport":"700x160"},{"name":"DepartmentCard","path":"components/cards/DepartmentCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Command Center department summary card","viewport":"900x360"},{"name":"IntegrationHealthCard","path":"components/cards/IntegrationHealthCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Single integration row (connected/degraded/error)","viewport":"700x90"},{"name":"MetricCard","path":"components/cards/MetricCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Single KPI cell for metric grids","viewport":"700x120"},{"name":"ProductAIReleaseCard","path":"components/cards/ProductAIReleaseCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"AI knowledge/prompt release snapshot for one product","viewport":"700x180"},{"name":"Button","path":"components/core/Button.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Primary/secondary/ghost/danger button","viewport":"700x220"},{"name":"IconButton","path":"components/core/IconButton.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Square icon-only button with optional badge","viewport":"700x150"},{"name":"Input","path":"components/core/Input.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Text field with label, icon and error state","viewport":"700x260"},{"name":"Tag","path":"components/core/Tag.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Status pill and rectangular label tag","viewport":"700x150"},{"name":"KnowledgeDocumentEditor","path":"components/inbox/KnowledgeDocumentEditor.jsx","previewPath":"components/inbox/inbox.card.html","kind":"component","section":"Inbox","subtitle":"Plain-text knowledge base document editor","viewport":"700x380"},{"name":"ActorBadge","path":"components/status/ActorBadge.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"AI vs human avatar for conversation timelines","viewport":"700x110"},{"name":"AttentionStatus","path":"components/status/AttentionStatus.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"Company/department health chip (ok/attention/critical)","viewport":"700x120"},{"name":"ChannelBadge","path":"components/status/ChannelBadge.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"MAX / Telegram / Web Chat channel chip","viewport":"700x100"}],"cards":[{"path":"guidelines/logo-mark.card.html","group":"Brand","viewport":"700x160","subtitle":"Only mark found in the codebase — a blue rounded square with a bar-chart glyph","name":"Logo Mark"},{"path":"guidelines/radii-shadows.card.html","group":"Brand","viewport":"700x180","subtitle":"Soft, low-opacity shadows only — no glassmorphism","name":"Radii & Shadows"},{"path":"ui_kits/checkout/index.html","group":"Checkout","viewport":"440x760"},{"path":"guidelines/colors-ai-channels.card.html","group":"Colors","viewport":"700x160","subtitle":"AI/human split, MAX/Telegram/Web ChLine truncated
|
||||
-216
@@ -1,216 +0,0 @@
|
||||
# Edevs Hub — Design System
|
||||
|
||||
Design system for **Edevs**, a Russian product IT company (`edevs.tech`) that builds applied
|
||||
digital products for narrow professional niches — currently **FoxRay** (cephalometric/TRG
|
||||
analysis for orthodontists) and **FirePage** (ready-made niche websites on a proprietary CMS,
|
||||
sold as a one-time license). This design system, however, documents **Edevs Hub**
|
||||
(`hub.edevs.tech`) — the internal company platform that runs sales, support, AI agents, and
|
||||
commerce for those products, plus the two small public-facing surfaces it exposes (Web Chat
|
||||
widget and Checkout).
|
||||
|
||||
## Sources
|
||||
|
||||
Everything here was extracted from the attached codebase, mounted read-only at
|
||||
`hub.edevs.tech/`:
|
||||
|
||||
- `hub.edevs.tech/design/baseline/*.dc.html` — the team's own **approved HTML visual baseline**
|
||||
(explicitly the canonical design source per `SPEC-HUB-0007`, section 3: *"Утверждённые
|
||||
дизайн-файлы размещаются только в едином каноническом каталоге:
|
||||
`code/hub.edevs.tech/design/baseline/`"*). ~35 screens covering Command Center, Sales
|
||||
(overview/clients/dialogs/orders), Departments, Employees, Products, AI agents (list/create/
|
||||
detail/knowledge), Integrations, Settings, Auth, the Web Chat widget, and the Checkout flow.
|
||||
- `hub.edevs.tech/design/baseline/uploads/ADR-HUB-0013-Internal-UI-Design-System.md` — the
|
||||
Internal Hub UI design-system decision record (Ant Design + Ant Design X + "Edevs Hub Theme").
|
||||
- `hub.edevs.tech/design/baseline/uploads/SPEC-HUB-0007-Checkout-UI.md` — the public checkout
|
||||
interface spec (`pay.hub.edevs.tech`).
|
||||
- `hub.edevs.tech/design/baseline/uploads/SPEC-HUB-0003-Web-Chat.md`,
|
||||
`SPEC-HUB-0004-Internal-Hub-UI.md`, `SPEC-HUB-0005-Implemented-Internal-UI-Baseline.md`,
|
||||
`SPEC-HUB-0001-First-Iteration.md`, `ADR-HUB-0017-AI-Agent-Configuration-UX.md` — supporting
|
||||
specs referenced but not individually quoted below.
|
||||
- `hub.edevs.tech/packages/ui/src/theme.ts` — the actual Ant Design `ThemeConfig` ("Edevs Hub
|
||||
Theme") used by the Internal UI: primary color, radii, per-component overrides.
|
||||
`hub.edevs.tech/apps/internal-ui/src/styles/base.css` — global resets.
|
||||
- `hub.edevs.tech/apps/internal-ui/public/favicon.svg` — the one brand mark present in the repo.
|
||||
- `hub.edevs.tech/content/ai-content-company-filled.md` — the AI agent's system/persona prompts
|
||||
for the main company site, used for the Content Fundamentals section below.
|
||||
- `hub.edevs.tech/apps/checkout` and `hub.edevs.tech/apps/web-chat` — app shells for the public
|
||||
surfaces (the checkout app has no implementation yet; the design baseline is ground truth for
|
||||
both).
|
||||
|
||||
No Figma file or link was provided for this project — the HTML baseline above is the sole
|
||||
design source, and per the team's own spec it *is* the canonical one.
|
||||
|
||||
## Products in scope
|
||||
|
||||
1. **Internal Hub** (`hub.edevs.tech`, `apps/internal-ui`) — the OWNER/OPERATOR back office:
|
||||
Command Center, Departments, Employees, Products, Sales workspace (overview, clients,
|
||||
dialogs, orders), AI agents & knowledge, Integrations, Settings, Auth. Built on Ant Design +
|
||||
Ant Design X, desktop-first (1024px+, designed for 1440px).
|
||||
2. **Web Chat** (`apps/web-chat`) — the embeddable public support/sales chat widget for
|
||||
products like FoxRay, handling AI, human handoff, and inline checkout cards.
|
||||
3. **Checkout** (`apps/checkout`, `pay.hub.edevs.tech`) — the public, mobile-first purchase flow
|
||||
that hands off to Bank Tochka for payment and separately tracks payment vs. product delivery.
|
||||
|
||||
## Index
|
||||
|
||||
- `styles.css` — root stylesheet, imports everything under `tokens/`.
|
||||
- `tokens/colors.css`, `typography.css`, `spacing.css`, `effects.css` — design tokens.
|
||||
- `assets/logo-mark.svg`, `favicon.svg` — the one brand mark found in the codebase.
|
||||
- `components/core/` — Button, IconButton, Input, Checkbox, Tag, Avatar, Icon (intentional
|
||||
additions — see below).
|
||||
- `components/status/` — AttentionStatus, ActorBadge, ChannelBadge.
|
||||
- `components/cards/` — MetricCard, DepartmentCard, IntegrationHealthCard,
|
||||
ProductAIReleaseCard, CommerceStatusTimeline.
|
||||
- `components/inbox/` — ConversationInbox, KnowledgeDocumentEditor.
|
||||
- `guidelines/` — foundation specimen cards (Colors, Type, Spacing, Brand).
|
||||
- `ui_kits/internal-hub/` — Auth → Command Center → Sales · Clients, clickable.
|
||||
- `ui_kits/web-chat/` — the embeddable chat widget, all 5 states.
|
||||
- `ui_kits/checkout/` — the public checkout flow, all 8 states.
|
||||
|
||||
## Components
|
||||
|
||||
Full list (16), grouped by directory:
|
||||
|
||||
- **Core** (intentional additions, see below): `Button`, `IconButton`, `Input`, `Checkbox`,
|
||||
`Tag`, `Avatar`, `Icon`.
|
||||
- **Status** (from ADR-HUB-0013's local-component list): `AttentionStatus`, `ActorBadge`,
|
||||
`ChannelBadge`.
|
||||
- **Cards** (from ADR-HUB-0013): `MetricCard`, `DepartmentCard`, `IntegrationHealthCard`,
|
||||
`ProductAIReleaseCard`, `CommerceStatusTimeline`.
|
||||
- **Inbox** (from ADR-HUB-0013): `ConversationInbox`, `KnowledgeDocumentEditor`.
|
||||
|
||||
### Intentional additions
|
||||
|
||||
ADR-HUB-0013 states the Internal Hub is built on **Ant Design + Ant Design X**, with only ten
|
||||
named local composite components on top (listed under "Status/Cards/Inbox" above — built
|
||||
exactly as named). Ant Design itself isn't installable in this static-HTML environment, so to
|
||||
make the UI kits and composite components actually renderable, this system also includes a
|
||||
small set of Ant-Design-styled primitives that the ADR assumes but doesn't name:
|
||||
`Button`, `IconButton`, `Input`, `Checkbox`, `Tag`, `Avatar`, `Icon`. Their visuals (radii,
|
||||
heights, colors) are copied exactly from the approved HTML baseline, not invented — treat them
|
||||
as a faithful stand-in for the real Ant Design instance, not a design decision of their own.
|
||||
|
||||
## Content fundamentals
|
||||
|
||||
Drawn from the AI agent system prompts (`content/ai-content-company-filled.md`) and the copy
|
||||
throughout the baseline screens (Russian-language product, primary audience is Russian).
|
||||
|
||||
- **Language & register:** Russian, informal-but-respectful "вы" register — direct, calm,
|
||||
no hard-sell. The agent prompt is explicit: "Пиши как нормальный человек в мессенджере. Не как объявление, не как пресс-релиз и не как робот, который сразу вываливает всю информацию."
|
||||
- **Tone:** short, human paragraphs, answer the actual question first, then suggest a next
|
||||
step: "Отвечай по сути вопроса, короткими живыми абзацами." and "Не дави на покупку. Главная задача общего агента — правильно понять потребность и направить человека туда, где он быстрее получит пользу."
|
||||
- **Formatting discipline:** no markdown inside chat replies — "Не используй markdown-разметку внутри ответа: не ставь заголовки, списки с маркерами, жирный текст, таблицы и разделители." UI copy elsewhere (Hub, checkout) mirrors this: plain sentences, no bullet-heavy microcopy.
|
||||
- **Emoji:** rare and situational, never decorative — "Уместные смайлики допустимы, но редко и по ситуации." No emoji appear anywhere in the Hub, Web Chat or Checkout baseline screens.
|
||||
- **Cultural register:** "Учитывай российский контекст общения: уважительно, прямо, без давления и без чрезмерной рекламности."
|
||||
- **Honesty/scope discipline:** never invent facts, prices, or promises outside the knowledge
|
||||
base — "Если данных не хватает, не выдумывай. Скажи, что этот момент лучше уточнить у специалиста, и передай оператору." and pricing/legal specifics always come from the server, never the client: see Checkout spec §16 ("не доверять цене и составу из состояния браузера").
|
||||
- **Handoff phrasing:** warm, not robotic, when passing to a human — "При передаче не отвечай сухо. Напиши по-человечески: понял задачу, здесь лучше подключить специалиста, передаю вопрос."
|
||||
- **UI microcopy style (from the baseline):** short declarative status lines ("Готовим оплату",
|
||||
"Оплата получена", "Требует внимания"), technical IDs always in monospace, money always as
|
||||
`₽95 040` (₽ prefix, space thousands separator, no decimals for round sums).
|
||||
- **Domains:** only `edevs.tech` is the confirmed public site; `edevs.ru` is explicitly
|
||||
forbidden in agent replies.
|
||||
|
||||
## Visual foundations
|
||||
|
||||
- **Overall direction (ADR-HUB-0013):** *"светлая тема; премиальный минимализм; высокая, но
|
||||
контролируемая информационная плотность; спокойная нейтральная основа; один основной
|
||||
акцентный цвет; цвет используется прежде всего для статусов и действий; минимум декоративных
|
||||
элементов; отсутствие градиентов, стекломорфизма, неоновых эффектов и визуального шума;
|
||||
desktop-first."* (light theme, premium minimalism, one accent color, color reserved for
|
||||
status/action, no gradients/glassmorphism/neon, desktop-first for the internal Hub).
|
||||
- **Color:** one accent, `#1677ff` (Ant Design blue-6) with a `#0958d9` hover/active shade.
|
||||
Semantic tokens are mandatory and separate from the accent: success/warning/error/info, plus
|
||||
two Hub-specific roles — `ai` (purple, `#722ed1`) vs `human` (blue, same as primary) — and a
|
||||
`channel-*` family (MAX purple, Telegram blue, Web Chat teal) used sparingly so multi-channel
|
||||
screens don't turn into "a colorful mosaic" (ADR wording). Status color is never the sole
|
||||
signal — always paired with text and, in tables, an icon or label.
|
||||
- **Type:** system font stack only — no bespoke webfont is loaded
|
||||
(`-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif`).
|
||||
Technical identifiers (order/release/event IDs, emails, obscured phone numbers) switch to a
|
||||
monospace stack. Headings use tight letter-spacing (−0.01 to −0.02em); table headers use wide
|
||||
spacing (+0.03 to +0.06em) with all-caps and a muted gray.
|
||||
Sizes are exact pixel values pulled from the baseline (26/24/20/18/16/14.5/13.5/13/12.5/12/
|
||||
11/10.5px) — not snapped to a 4/8 grid.
|
||||
- **Spacing / density:** "compact enterprise" density is an explicit rule — *"большие пустые
|
||||
поля и oversized-карточки запрещены"*. Padding values are odd/precise (9px, 11px, 13px, 14px,
|
||||
18px…), not rounded. Control heights: 30/34/36/42/44/48px; topbar is a fixed 56px.
|
||||
- **Backgrounds:** flat solid colors only. Page background `#f0f2f5`, card surfaces pure white.
|
||||
No photography, no illustrations, no repeating patterns/textures, no gradients anywhere
|
||||
(buttons, cards, banners are all flat fills). The one "textured" pattern in the system is the
|
||||
1px-gap metric grid (white cells on a `#f0f0f0` background, forming hairline dividers) — see
|
||||
the Spacing → "Metric Grid In Use" card.
|
||||
- **Corners:** 7–9px on controls/inputs, 8–9px on buttons, 10–14px on cards/modals, full pill
|
||||
on chips/segmented controls, circle on avatars.
|
||||
- **Cards:** white surface, 1px `#f0f0f0` border, soft shadow (`0 1px 3px rgba(0,0,0,.04)`),
|
||||
12px radius as the default; no colored left-border accent except the Command Center's status
|
||||
banner (a deliberate, singular exception tied to company health, not a general card pattern).
|
||||
- **Shadows:** shallow and near-neutral throughout — hairline (`0 1px 2px rgba(0,0,0,.03)`),
|
||||
card (`0 1px 3px rgba(0,0,0,.04)`), modal (`0 2px 12px rgba(0,0,0,.05)`), dropdown
|
||||
(`0 6px 20px rgba(0,0,0,.12)`). The one colored shadow is the primary button's blue-tinted
|
||||
`0 1px 2px rgba(22,119,255,.3)`, used to make the single CTA per screen pop slightly.
|
||||
- **Animation:** minimal and functional only — a 3-dot typing indicator (`hub-typing`, opacity/
|
||||
translateY loop), a spinner (`hub-spin`, rotate) for loading states, and a slow opacity pulse
|
||||
(`hub-pulse`) for "in progress" states (e.g. delivering a purchased product). No entrance
|
||||
animations, bounces, or parallax anywhere in the baseline.
|
||||
- **Hover states:** buttons/links darken (primary `#1677ff → #0958d9`); neutral surfaces get a
|
||||
light gray fill (`transparent → #f5f5f5`) on hover; secondary buttons swap border+text to the
|
||||
accent color on hover. No lightening-on-hover pattern is used.
|
||||
**Press/active states:** not distinctly styled in the baseline (no scale/shrink pattern
|
||||
observed) — treat hover as the primary interactive affordance; focus-visible gets a solid
|
||||
2px accent outline (see `apps/internal-ui/src/styles/base.css`).
|
||||
**Disabled:** 55% opacity + `cursor: not-allowed`.
|
||||
**Focus:** border-color changes to the accent (inputs) or a visible 2px outline (buttons) —
|
||||
never a glow/box-shadow ring.
|
||||
- **Borders:** hairline `#f0f0f0` almost everywhere (card edges, table row dividers, header
|
||||
separators); slightly stronger `#d9d9d9`/`#e8e8e8` on interactive control outlines
|
||||
(buttons, inputs) so they read as tappable against the flat background.
|
||||
- **Transparency & blur:** no blur/glassmorphism anywhere. The only translucent surfaces are
|
||||
the Web Chat header's icon buttons (`rgba(255,255,255,0.14–0.26)` over the solid blue header)
|
||||
and a full-viewport `position:fixed` transparent scrim used to close open dropdowns/menus.
|
||||
- **Imagery:** none — the product is data/status-dense enterprise software and transactional
|
||||
flows, not marketing pages. No photography, no hand-drawn illustrations, no generic stock
|
||||
imagery anywhere in the baseline; nothing to copy in for that reason.
|
||||
- **Layout rules:** Internal Hub is a fixed sidebar (≈248px) + topbar (56px) + scrollable
|
||||
content shell, min-width 1024–1180px depending on screen, content capped at 1200–1340px and
|
||||
centered. Web Chat and Checkout are separate, chrome-free, mobile-first single-column flows
|
||||
with no sidebar/topbar — explicitly not governed by the Internal Hub's layout rules
|
||||
(SPEC-HUB-0007 §4).
|
||||
|
||||
## Iconography
|
||||
|
||||
- **System:** hand-authored inline SVG, Feather/Lucide-style stroke icons (round caps/joins,
|
||||
1.7–2.2px stroke, 24×24 viewBox) — every baseline screen inlines its own `<svg>` rather than
|
||||
referencing a shared font or sprite sheet, so there is no icon font or `.svg` sprite file in
|
||||
the repo to copy wholesale. This design system's `Icon` component (`components/core/Icon.jsx`)
|
||||
collects the ~35 recurring glyphs actually used across the baseline (nav icons, status icons,
|
||||
form icons, payment icons) into one reusable primitive with the *exact* path data copied from
|
||||
the source screens — nothing was redrawn from imagination.
|
||||
- **Emoji:** never used anywhere in the product UI (only "rarely, situationally" in AI chat
|
||||
replies per the content guidelines above).
|
||||
**Unicode-as-icon:** limited to pagination chevrons (`‹ › …`) in table footers.
|
||||
- **Color:** icons are almost always `currentColor`/neutral gray (`#8c8c8c`/`#595959`), tinted
|
||||
to the semantic/accent color only when they sit inside a status chip or colored icon tile
|
||||
(e.g. a purple AI bolt icon on a light-purple tile).
|
||||
|
||||
## Caveats & where I need your help
|
||||
|
||||
1. **No Figma was attached** — everything above comes from the approved HTML baseline in
|
||||
`design/baseline/`, which the team's own spec names as canonical. If a Figma file exists,
|
||||
attach it and I can cross-check/tighten values.
|
||||
2. **No FoxRay/FirePage brand assets** — this system only covers Edevs Hub (the internal
|
||||
platform + its two public surfaces). FoxRay/Foxray and FirePage are referenced only as
|
||||
*product tags* inside Hub (colored labels, no logos). If you want their actual product UI
|
||||
or marks in this system, please attach their codebases/design files.
|
||||
3. **No logo beyond the one favicon mark** — I did not draw one. If Edevs has a real wordmark
|
||||
or icon set beyond `favicon.svg`, please attach it and I'll swap it in everywhere.
|
||||
4. **Ant Design isn't literally bundled** — see "Intentional additions" above; I built
|
||||
faithful lightweight stand-ins instead of pulling in the real library, since only static
|
||||
HTML/JS/CSS work in this environment.
|
||||
5. **Internal Hub UI kit covers 2 of many screens** (Command Center + Sales · Clients, behind a
|
||||
working Auth gate) rather than all ~35 baseline screens — tell me which screens matter most
|
||||
(Departments, AI agents, Orders, Settings…) and I'll extend the kit.
|
||||
|
||||
**Ask:** tell me which of the ~35 baseline screens to turn into additional UI-kit pages next,
|
||||
and whether the Ant-Design-styled primitives above should stay as lightweight stand-ins or be
|
||||
swapped for real `antd` components if this ever moves into a real build environment.
|
||||
-88
@@ -1,88 +0,0 @@
|
||||
/* Edevs Hub — color tokens
|
||||
Source: packages/ui/src/theme.ts (Ant Design ThemeConfig), apps/internal-ui/src/styles/base.css,
|
||||
and design/baseline/*.dc.html (approved HTML baseline). Ant Design's default light palette,
|
||||
customized with a single accent (#1677ff) per ADR-HUB-0013. */
|
||||
|
||||
:root {
|
||||
/* ---- base neutrals (Ant Design neutral scale as used in the baseline) ---- */
|
||||
--n-1: #1f1f1f; /* page/heading titles */
|
||||
--n-2: #262626; /* primary body text */
|
||||
--n-3: #595959; /* secondary text */
|
||||
--n-4: #8c8c8c; /* tertiary text / captions */
|
||||
--n-5: #bfbfbf; /* disabled / placeholder / faint */
|
||||
--n-6: #d9d9d9; /* strong border, control border */
|
||||
--n-7: #e8e8e8; /* input border */
|
||||
--n-8: #f0f0f0; /* hairline border */
|
||||
--n-9: #f5f5f5; /* hover surface */
|
||||
--n-10: #fafafa; /* table header surface */
|
||||
--n-11: #f0f2f5; /* app/page background */
|
||||
--n-white: #ffffff;
|
||||
|
||||
/* ---- primary (blue-6 / blue-7) ---- */
|
||||
--primary: #1677ff;
|
||||
--primary-hover: #0958d9;
|
||||
--primary-bg: #e6f4ff;
|
||||
--primary-border: #91caff;
|
||||
--primary-shadow: rgba(22, 119, 255, 0.3);
|
||||
|
||||
/* ---- semantic: success / warning / error / info ---- */
|
||||
--success: #52c41a;
|
||||
--success-text: #389e0d;
|
||||
--success-bg: #f6ffed;
|
||||
--success-bg-strong: #f1f9ec;
|
||||
--success-border: #b7eb8f;
|
||||
|
||||
--warning: #faad14;
|
||||
--warning-text: #d48806;
|
||||
--warning-bg: #fffbe6;
|
||||
--warning-bg-strong: #fff7e6;
|
||||
--warning-border: #ffe58f;
|
||||
|
||||
--error: #ff4d4f;
|
||||
--error-text: #cf1322;
|
||||
--error-bg: #fff2f0;
|
||||
--error-border: #ffccc7;
|
||||
|
||||
--info: #1677ff;
|
||||
|
||||
/* ---- role accents: AI vs human ---- */
|
||||
--ai: #722ed1;
|
||||
--ai-light: #9254de;
|
||||
--ai-lighter: #b37feb;
|
||||
--ai-bg: #f9f0ff;
|
||||
--human: #1677ff;
|
||||
|
||||
/* ---- channel accents (MAX / Telegram / Web Chat) ---- */
|
||||
--channel-max: #6b5be0;
|
||||
--channel-max-bg: #f2f0ff;
|
||||
--channel-telegram: #2f8fd0;
|
||||
--channel-telegram-bg: #eaf6fd;
|
||||
--channel-webchat: #0f9b8e;
|
||||
--channel-webchat-bg: #e8f7f4;
|
||||
|
||||
/* ---- product accents (as tagged in tables/lists) ---- */
|
||||
--product-firepage: #0958d9;
|
||||
--product-firepage-bg: #e6f4ff;
|
||||
--product-foxray: #722ed1;
|
||||
--product-foxray-bg: #f9f0ff;
|
||||
|
||||
/* ---- surfaces ---- */
|
||||
--surface-page: var(--n-11);
|
||||
--surface-card: var(--n-white);
|
||||
--surface-sunken: #fafafa;
|
||||
--surface-chip: #f7f8fa;
|
||||
|
||||
/* ---- text aliases ---- */
|
||||
--text-heading: var(--n-1);
|
||||
--text-body: var(--n-2);
|
||||
--text-secondary: var(--n-3);
|
||||
--text-tertiary: var(--n-4);
|
||||
--text-disabled: var(--n-5);
|
||||
--text-inverse: var(--n-white);
|
||||
--text-link: var(--primary);
|
||||
|
||||
/* ---- borders ---- */
|
||||
--border-default: var(--n-8);
|
||||
--border-input: var(--n-7);
|
||||
--border-strong: var(--n-6);
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/* Edevs Hub — typography tokens
|
||||
The internal Hub uses the Ant Design default system font stack — no bespoke webfont
|
||||
is loaded (see ADR-HUB-0013: "используется системный font stack Ant Design без
|
||||
обязательной внешней зависимости от загружаемого шрифта"). Technical identifiers
|
||||
(order/release/event IDs, emails) use a monospace stack. */
|
||||
|
||||
:root {
|
||||
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
--font-mono: "SF Mono", ui-monospace, Menlo, Consolas, monospace;
|
||||
|
||||
/* type scale, taken verbatim from the baseline (px, not snapped to a 4/8 grid) */
|
||||
--text-2xl: 26px; /* page hero title (Command Center) */
|
||||
--text-xl: 24px; /* page title */
|
||||
--text-lg: 20px; /* auth title */
|
||||
--text-md: 18px; /* card title */
|
||||
--text-base-lg: 16px;
|
||||
--text-base: 14.5px; /* buttons, primary body */
|
||||
--text-sm-lg: 13.5px;
|
||||
--text-sm: 13px; /* table body */
|
||||
--text-sm-tight: 12.5px;
|
||||
--text-xs: 12px; /* meta */
|
||||
--text-xs-tight: 11.5px;
|
||||
--text-2xs: 11px; /* table header / eyebrow */
|
||||
--text-2xs-tight: 10.5px;
|
||||
|
||||
--weight-regular: 400;
|
||||
--weight-medium: 500;
|
||||
--weight-semibold: 600;
|
||||
--weight-bold: 700;
|
||||
--weight-black: 800;
|
||||
|
||||
--tracking-tight: -0.02em; /* large headings */
|
||||
--tracking-tight-sm: -0.01em;
|
||||
--tracking-wide: 0.03em; /* table header eyebrows */
|
||||
--tracking-wider: 0.06em; /* nav section labels */
|
||||
|
||||
--leading-tight: 1.15;
|
||||
--leading-snug: 1.2;
|
||||
--leading-normal: 1.4;
|
||||
--leading-relaxed: 1.5;
|
||||
--leading-loose: 1.55;
|
||||
}
|
||||
@@ -8,12 +8,12 @@
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/colors.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/typography.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/spacing.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/effects.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/styles.css">
|
||||
<script src="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/_ds_bundle.js"></script>
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/colors.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/typography.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/spacing.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/effects.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/styles.css">
|
||||
<script src="_ds/design-system/_ds_bundle.js"></script>
|
||||
<style>
|
||||
body { margin: 0; background: #0b0b12; }
|
||||
@keyframes edv-ring2 { 0% { transform: scale(1); opacity: .5; } 100% { transform: scale(1.9); opacity: 0; } }
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/colors.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/typography.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/spacing.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/effects.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/styles.css">
|
||||
<script src="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/_ds_bundle.js"></script>
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/colors.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/typography.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/spacing.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/effects.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/styles.css">
|
||||
<script src="_ds/design-system/_ds_bundle.js"></script>
|
||||
<style>
|
||||
body { margin: 0; background: var(--surface-page); }
|
||||
a { color: var(--primary); text-decoration: none; }
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
<header style="display:flex; align-items:center; gap:10px; padding:18px 28px; border-bottom:1px solid var(--border-default);">
|
||||
<div style="width:30px; height:30px; border-radius:8px; background:var(--primary); color:#fff; display:flex; align-items:center; justify-content:center; font-weight:700; font-size:16px;">E</div>
|
||||
<span style="font-size:15px; font-weight:600; color:var(--text-heading);">Edevs</span>
|
||||
<span style="font-size:15px; font-weight:600; color:var(--text-heading);">Chatballs</span>
|
||||
<div style="flex:1;"></div>
|
||||
<span style="font-size:12.5px; color:var(--text-tertiary);">Защищённое соединение</span>
|
||||
</header>
|
||||
@@ -85,7 +85,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer style="text-align:center; padding:18px; font-size:12px; color:var(--text-tertiary);">Работает на платформе Edevs Hub</footer>
|
||||
<footer style="text-align:center; padding:18px; font-size:12px; color:var(--text-tertiary);">Работает на платформе Chatballs</footer>
|
||||
|
||||
</div>
|
||||
</x-dc>
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/colors.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/typography.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/spacing.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/effects.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/styles.css">
|
||||
<script src="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/_ds_bundle.js"></script>
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/colors.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/typography.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/spacing.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/effects.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/styles.css">
|
||||
<script src="_ds/design-system/_ds_bundle.js"></script>
|
||||
<style>
|
||||
body { margin: 0; background: var(--surface-page); }
|
||||
a { color: var(--primary); text-decoration: none; }
|
||||
@@ -73,7 +73,7 @@
|
||||
<div style="display:flex; align-items:center; gap:7px;">
|
||||
<span style="font-size:14px; font-weight:600; color:var(--text-heading); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">{{ peerName }}</span>
|
||||
<sc-if value="{{ showChannel }}" hint-placeholder-val="{{ true }}">
|
||||
<x-import component-from-global-scope="EdevsHubDesignSystem_e4c9df.ChannelBadge" channel="{{ channel }}" hint-size="auto,16px"></x-import>
|
||||
<x-import component-from-global-scope="ChatballsDesignSystem_e4c9df.ChannelBadge" channel="{{ channel }}" hint-size="auto,16px"></x-import>
|
||||
</sc-if>
|
||||
</div>
|
||||
<span style="font-size:12px; color:var(--text-secondary);">{{ subtitle }}</span>
|
||||
@@ -93,7 +93,7 @@
|
||||
<div style="position:relative; aspect-ratio:16/9; background:#141414; overflow:hidden;">
|
||||
|
||||
<sc-if value="{{ videoVisible }}" hint-placeholder-val="{{ false }}">
|
||||
<x-import component-from-global-scope="image-slot" from="./image-slot.js" id="edevs-call-main" placeholder="Кадр с камеры" shape="rect" style="position:absolute; inset:0; width:100%; height:100%;" hint-size="100%,100%"></x-import>
|
||||
<x-import component-from-global-scope="image-slot" from="./image-slot.js" id="chatballs-call-main" placeholder="Кадр с камеры" shape="rect" style="position:absolute; inset:0; width:100%; height:100%;" hint-size="100%,100%"></x-import>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ showMainAvatar }}" hint-placeholder-val="{{ true }}">
|
||||
@@ -148,7 +148,7 @@
|
||||
<sc-if value="{{ showPip }}" hint-placeholder-val="{{ false }}">
|
||||
<div style="position:absolute; right:12px; bottom:12px; width:100px; height:66px; border-radius:10px; overflow:hidden; background:#1f1f1f; border:2px solid rgba(255,255,255,.9); box-shadow:0 4px 14px rgba(0,0,0,.4); z-index:4;">
|
||||
<sc-if value="{{ camOn }}" hint-placeholder-val="{{ true }}">
|
||||
<x-import component-from-global-scope="image-slot" from="./image-slot.js" id="edevs-call-pip" placeholder="Вы" shape="rect" style="position:absolute; inset:0; width:100%; height:100%;" hint-size="100%,100%"></x-import>
|
||||
<x-import component-from-global-scope="image-slot" from="./image-slot.js" id="chatballs-call-pip" placeholder="Вы" shape="rect" style="position:absolute; inset:0; width:100%; height:100%;" hint-size="100%,100%"></x-import>
|
||||
</sc-if>
|
||||
<sc-if value="{{ camOff }}" hint-placeholder-val="{{ false }}">
|
||||
<div style="position:absolute; inset:0; display:flex; align-items:center; justify-content:center;">
|
||||
@@ -284,7 +284,7 @@ class Component extends DCLogic {
|
||||
|
||||
const peer = isOperator
|
||||
? { name: clientName, initials: (clientName.trim()[0] || 'К').toUpperCase() + ((clientName.split(' ')[1] || '')[0] || '').toUpperCase(), color: '#722ed1' }
|
||||
: { name: 'Оператор Edevs', initials: 'ОЭ', color: '#1677ff' };
|
||||
: { name: 'Оператор', initials: 'ОЭ', color: '#1677ff' };
|
||||
const self = { name: 'Вы', initials: 'ВЫ', color: '#595959' };
|
||||
const P = peer.name;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Edevs Hub — color tokens
|
||||
/* Chatballs — color tokens
|
||||
Source: packages/ui/src/theme.ts (Ant Design ThemeConfig), apps/internal-ui/src/styles/base.css,
|
||||
and design/baseline/*.dc.html (approved HTML baseline). Ant Design's default light palette,
|
||||
customized with a single accent (#1677ff) per ADR-HUB-0013. */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Edevs Hub — radii, shadows, motion. "Премиальный минимализм": no gradients,
|
||||
/* Chatballs — radii, shadows, motion. "Премиальный минимализм": no gradients,
|
||||
no glassmorphism/blur, no neon — shadows stay soft and near-black at low opacity. */
|
||||
|
||||
:root {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Edevs Hub — spacing tokens. Compact-enterprise density (ADR-HUB-0013):
|
||||
/* Chatballs — spacing tokens. Compact-enterprise density (ADR-HUB-0013):
|
||||
"большие пустые поля и oversized-карточки запрещены". Values are the exact
|
||||
paddings/gaps observed in the baseline, not snapped to a rounder grid. */
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Edevs Hub — typography tokens
|
||||
/* Chatballs — typography tokens
|
||||
The internal Hub uses the Ant Design default system font stack — no bespoke webfont
|
||||
is loaded (see ADR-HUB-0013: "используется системный font stack Ant Design без
|
||||
обязательной внешней зависимости от загружаемого шрифта"). Technical identifiers
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<meta name="design_doc_mode" content="canvas">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/colors.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/typography.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/spacing.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/effects.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/styles.css">
|
||||
<script src="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/_ds_bundle.js"></script>
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/colors.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/typography.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/spacing.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/effects.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/styles.css">
|
||||
<script src="_ds/design-system/_ds_bundle.js"></script>
|
||||
<style>
|
||||
* { box-sizing: border-box; }
|
||||
body { margin: 0; background: #e9ebee; }
|
||||
@@ -57,9 +57,9 @@
|
||||
<!-- SIDEBAR -->
|
||||
<aside style="width: 248px; flex: none; background: #fff; border-right: 1px solid var(--n-8); display: flex; flex-direction: column;">
|
||||
<div style="height: 56px; flex: none; display: flex; align-items: center; gap: 11px; padding: 0 20px; border-bottom: 1px solid var(--n-9);">
|
||||
<img src="assets/custocrm-mark.svg" alt="CustoCRM" style="width: 30px; height: 30px; border-radius: 8px; flex: none;">
|
||||
<img src="assets/chatballs-mark.svg" alt="Chatballs" style="width: 30px; height: 30px; border-radius: 8px; flex: none;">
|
||||
<div style="display: flex; flex-direction: column; line-height: 1.15;">
|
||||
<span style="font-size: 14px; font-weight: 600; color: var(--text-heading); letter-spacing: -0.01em;">CustoCRM</span>
|
||||
<span style="font-size: 14px; font-weight: 600; color: var(--text-heading); letter-spacing: -0.01em;">Chatballs</span>
|
||||
<span style="font-size: 11px; color: var(--text-tertiary);">Управление компанией</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# База знаний AI-агентов — design baseline (DG-01)
|
||||
|
||||
Макет раздела **AI → Знания** (CustoCRM / ООО «Эдевс») по SPEC-HUB-0026 / ADR-HUB-0036.
|
||||
Макет раздела **AI → Знания** (Chatballs / ООО «Эдевс») по SPEC-HUB-0026 / ADR-HUB-0036.
|
||||
|
||||
## Состав
|
||||
|
||||
```
|
||||
Knowledge Library Baseline.dc.html — макет (6 кадров: A–E + состояния)
|
||||
support.js — рантайм Design Component (шаблон + логика)
|
||||
_ds/edevs-hub-design-system-…/ — дизайн-система: токены, styles.css, _ds_bundle.js
|
||||
assets/custocrm-mark.svg — логотип CustoCRM
|
||||
_ds/chatballs-hub-design-system-…/ — дизайн-система: токены, styles.css, _ds_bundle.js
|
||||
assets/chatballs-mark.svg — логотип Chatballs
|
||||
```
|
||||
|
||||
## Запуск
|
||||
|
||||
File renamed without changes.
+14
-14
@@ -1,8 +1,8 @@
|
||||
/* @ds-bundle: {"format":4,"namespace":"EdevsHubDesignSystem_e4c9df","components":[{"name":"CommerceStatusTimeline","sourcePath":"components/cards/CommerceStatusTimeline.jsx"},{"name":"DepartmentCard","sourcePath":"components/cards/DepartmentCard.jsx"},{"name":"IntegrationHealthCard","sourcePath":"components/cards/IntegrationHealthCard.jsx"},{"name":"MetricCard","sourcePath":"components/cards/MetricCard.jsx"},{"name":"ProductAIReleaseCard","sourcePath":"components/cards/ProductAIReleaseCard.jsx"},{"name":"Avatar","sourcePath":"components/core/Avatar.jsx"},{"name":"Button","sourcePath":"components/core/Button.jsx"},{"name":"Checkbox","sourcePath":"components/core/Checkbox.jsx"},{"name":"Icon","sourcePath":"components/core/Icon.jsx"},{"name":"ICON_NAMES","sourcePath":"components/core/Icon.jsx"},{"name":"IconButton","sourcePath":"components/core/IconButton.jsx"},{"name":"Input","sourcePath":"components/core/Input.jsx"},{"name":"Tag","sourcePath":"components/core/Tag.jsx"},{"name":"ConversationInbox","sourcePath":"components/inbox/ConversationInbox.jsx"},{"name":"KnowledgeDocumentEditor","sourcePath":"components/inbox/KnowledgeDocumentEditor.jsx"},{"name":"ActorBadge","sourcePath":"components/status/ActorBadge.jsx"},{"name":"AttentionStatus","sourcePath":"components/status/AttentionStatus.jsx"},{"name":"ChannelBadge","sourcePath":"components/status/ChannelBadge.jsx"}],"sourceHashes":{"components/cards/CommerceStatusTimeline.jsx":"a71f119a6bcb","components/cards/DepartmentCard.jsx":"743b4f9632ec","components/cards/IntegrationHealthCard.jsx":"4888c60e9532","components/cards/MetricCard.jsx":"4edb7590ee04","components/cards/ProductAIReleaseCard.jsx":"53de80d598b8","components/core/Avatar.jsx":"e963633b7162","components/core/Button.jsx":"52b57248ad92","components/core/Checkbox.jsx":"412f119cdbb2","components/core/Icon.jsx":"f6c5a199fcf5","components/core/IconButton.jsx":"e8c066b43714","components/core/Input.jsx":"4561efdc9997","components/core/Tag.jsx":"48a8a3543145","components/inbox/ConversationInbox.jsx":"ea2ad8f6a755","components/inbox/KnowledgeDocumentEditor.jsx":"f97e9057fb25","components/status/ActorBadge.jsx":"11e6274f6875","components/status/AttentionStatus.jsx":"a22cbb5b37d2","components/status/ChannelBadge.jsx":"e15a0c45d45f","ui_kits/checkout/CheckoutWidget.jsx":"6d563825a7e0","ui_kits/internal-hub/AuthLoginPage.jsx":"b3ee3d8ea9ab","ui_kits/internal-hub/ClientsPage.jsx":"0a9fb9f5b11d","ui_kits/internal-hub/CommandCenterPage.jsx":"870dd4cd0c22","ui_kits/internal-hub/HubShell.jsx":"ce0eb4d2dc70","ui_kits/web-chat/WebChatWidget.jsx":"e4099f49f9c0"},"inlinedExternals":[],"unexposedExports":[]} */
|
||||
/* @ds-bundle: {"format":4,"namespace":"ChatballsDesignSystem_e4c9df","components":[{"name":"CommerceStatusTimeline","sourcePath":"components/cards/CommerceStatusTimeline.jsx"},{"name":"DepartmentCard","sourcePath":"components/cards/DepartmentCard.jsx"},{"name":"IntegrationHealthCard","sourcePath":"components/cards/IntegrationHealthCard.jsx"},{"name":"MetricCard","sourcePath":"components/cards/MetricCard.jsx"},{"name":"ProductAIReleaseCard","sourcePath":"components/cards/ProductAIReleaseCard.jsx"},{"name":"Avatar","sourcePath":"components/core/Avatar.jsx"},{"name":"Button","sourcePath":"components/core/Button.jsx"},{"name":"Checkbox","sourcePath":"components/core/Checkbox.jsx"},{"name":"Icon","sourcePath":"components/core/Icon.jsx"},{"name":"ICON_NAMES","sourcePath":"components/core/Icon.jsx"},{"name":"IconButton","sourcePath":"components/core/IconButton.jsx"},{"name":"Input","sourcePath":"components/core/Input.jsx"},{"name":"Tag","sourcePath":"components/core/Tag.jsx"},{"name":"ConversationInbox","sourcePath":"components/inbox/ConversationInbox.jsx"},{"name":"KnowledgeDocumentEditor","sourcePath":"components/inbox/KnowledgeDocumentEditor.jsx"},{"name":"ActorBadge","sourcePath":"components/status/ActorBadge.jsx"},{"name":"AttentionStatus","sourcePath":"components/status/AttentionStatus.jsx"},{"name":"ChannelBadge","sourcePath":"components/status/ChannelBadge.jsx"}],"sourceHashes":{"components/cards/CommerceStatusTimeline.jsx":"a71f119a6bcb","components/cards/DepartmentCard.jsx":"743b4f9632ec","components/cards/IntegrationHealthCard.jsx":"4888c60e9532","components/cards/MetricCard.jsx":"4edb7590ee04","components/cards/ProductAIReleaseCard.jsx":"53de80d598b8","components/core/Avatar.jsx":"e963633b7162","components/core/Button.jsx":"52b57248ad92","components/core/Checkbox.jsx":"412f119cdbb2","components/core/Icon.jsx":"f6c5a199fcf5","components/core/IconButton.jsx":"e8c066b43714","components/core/Input.jsx":"4561efdc9997","components/core/Tag.jsx":"48a8a3543145","components/inbox/ConversationInbox.jsx":"ea2ad8f6a755","components/inbox/KnowledgeDocumentEditor.jsx":"f97e9057fb25","components/status/ActorBadge.jsx":"11e6274f6875","components/status/AttentionStatus.jsx":"a22cbb5b37d2","components/status/ChannelBadge.jsx":"e15a0c45d45f","ui_kits/checkout/CheckoutWidget.jsx":"6d563825a7e0","ui_kits/internal-hub/AuthLoginPage.jsx":"b3ee3d8ea9ab","ui_kits/internal-hub/ClientsPage.jsx":"0a9fb9f5b11d","ui_kits/internal-hub/CommandCenterPage.jsx":"870dd4cd0c22","ui_kits/internal-hub/HubShell.jsx":"ce0eb4d2dc70","ui_kits/web-chat/WebChatWidget.jsx":"e4099f49f9c0"},"inlinedExternals":[],"unexposedExports":[]} */
|
||||
|
||||
(() => {
|
||||
|
||||
const __ds_ns = (window.EdevsHubDesignSystem_e4c9df = window.EdevsHubDesignSystem_e4c9df || {});
|
||||
const __ds_ns = (window.ChatballsDesignSystem_e4c9df = window.ChatballsDesignSystem_e4c9df || {});
|
||||
|
||||
const __ds_scope = {};
|
||||
|
||||
@@ -1094,10 +1094,10 @@ const {
|
||||
CommerceStatusTimeline,
|
||||
Icon,
|
||||
Checkbox
|
||||
} = window.EdevsHubDesignSystem_e4c9df;
|
||||
} = window.ChatballsDesignSystem_e4c9df;
|
||||
|
||||
/* Recreation of design/baseline/CheckoutPanel.dc.html — the public
|
||||
pay.hub.edevs.tech checkout flow (SPEC-HUB-0007). Mobile-first, no Hub chrome. */
|
||||
pay.chatballs checkout flow (SPEC-HUB-0007). Mobile-first, no Hub chrome. */
|
||||
function CheckoutWidget() {
|
||||
const [st, setSt] = React.useState("checkout");
|
||||
const [buyer, setBuyer] = React.useState("person");
|
||||
@@ -1823,7 +1823,7 @@ const {
|
||||
Input,
|
||||
Button,
|
||||
Icon
|
||||
} = window.EdevsHubDesignSystem_e4c9df;
|
||||
} = window.ChatballsDesignSystem_e4c9df;
|
||||
|
||||
/* Recreation of design/baseline/AUTH · Вход.dc.html */
|
||||
function AuthLoginPage({
|
||||
@@ -1872,7 +1872,7 @@ function AuthLoginPage({
|
||||
fontWeight: 700,
|
||||
letterSpacing: "-0.01em"
|
||||
}
|
||||
}, "Edevs Hub"), /*#__PURE__*/React.createElement("p", {
|
||||
}, "Chatballs"), /*#__PURE__*/React.createElement("p", {
|
||||
style: {
|
||||
margin: "5px 0 0",
|
||||
fontSize: 13,
|
||||
@@ -1919,7 +1919,7 @@ function AuthLoginPage({
|
||||
}),
|
||||
value: email,
|
||||
onChange: e => setEmail(e.target.value),
|
||||
placeholder: "you@edevs.tech"
|
||||
placeholder: "you@chatballs"
|
||||
})), /*#__PURE__*/React.createElement("div", {
|
||||
style: {
|
||||
marginBottom: 22
|
||||
@@ -1962,7 +1962,7 @@ function AuthLoginPage({
|
||||
fontSize: 12,
|
||||
color: "var(--n-5)"
|
||||
}
|
||||
}, "\u0414\u043E\u0441\u0442\u0443\u043F \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0441\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A\u043E\u0432 Edevs \xB7 \u0437\u0430\u0449\u0438\u0449\u0451\u043D\u043D\u043E\u0435 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435")));
|
||||
}, "\u0414\u043E\u0441\u0442\u0443\u043F \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0441\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A\u043E\u0432 Chatballs \xB7 \u0437\u0430\u0449\u0438\u0449\u0451\u043D\u043D\u043E\u0435 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435")));
|
||||
}
|
||||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/internal-hub/AuthLoginPage.jsx", error: String((e && e.message) || e) }); }
|
||||
|
||||
@@ -1972,7 +1972,7 @@ const {
|
||||
Avatar,
|
||||
Tag,
|
||||
Icon
|
||||
} = window.EdevsHubDesignSystem_e4c9df;
|
||||
} = window.ChatballsDesignSystem_e4c9df;
|
||||
const DATA = [{
|
||||
name: "Мария Соколова",
|
||||
initials: "МС",
|
||||
@@ -2265,7 +2265,7 @@ const {
|
||||
MetricCard,
|
||||
IntegrationHealthCard,
|
||||
AttentionStatus
|
||||
} = window.EdevsHubDesignSystem_e4c9df;
|
||||
} = window.ChatballsDesignSystem_e4c9df;
|
||||
|
||||
/* Recreation of design/baseline/Командный центр.dc.html */
|
||||
function CommandCenterPage({
|
||||
@@ -2508,7 +2508,7 @@ try { (() => {
|
||||
const {
|
||||
Icon,
|
||||
Avatar
|
||||
} = window.EdevsHubDesignSystem_e4c9df;
|
||||
} = window.ChatballsDesignSystem_e4c9df;
|
||||
const NAV = [{
|
||||
key: "command",
|
||||
label: "Командный центр",
|
||||
@@ -2597,7 +2597,7 @@ function HubShell({
|
||||
color: "var(--text-heading)",
|
||||
letterSpacing: "-0.01em"
|
||||
}
|
||||
}, "Edevs Hub"), /*#__PURE__*/React.createElement("span", {
|
||||
}, "Chatballs"), /*#__PURE__*/React.createElement("span", {
|
||||
style: {
|
||||
fontSize: 11,
|
||||
color: "var(--text-tertiary)"
|
||||
@@ -2715,7 +2715,7 @@ function HubShell({
|
||||
fontWeight: 500,
|
||||
color: "var(--text-secondary)"
|
||||
}
|
||||
}, "Edevs"), /*#__PURE__*/React.createElement("span", {
|
||||
}, "Chatballs"), /*#__PURE__*/React.createElement("span", {
|
||||
style: {
|
||||
color: "var(--n-6)"
|
||||
}
|
||||
@@ -2787,7 +2787,7 @@ try { (() => {
|
||||
const {
|
||||
ActorBadge,
|
||||
Icon
|
||||
} = window.EdevsHubDesignSystem_e4c9df;
|
||||
} = window.ChatballsDesignSystem_e4c9df;
|
||||
|
||||
/* Recreation of design/baseline/ChatPanel.dc.html — Foxray's embedded web-chat
|
||||
widget. States: welcome (consent) / ai / operator handoff / checkout card / unavailable. */
|
||||
@@ -0,0 +1 @@
|
||||
{"namespace":"ChatballsDesignSystem_e4c9df","components":[{"name":"CommerceStatusTimeline","sourcePath":"components/cards/CommerceStatusTimeline.jsx"},{"name":"DepartmentCard","sourcePath":"components/cards/DepartmentCard.jsx"},{"name":"IntegrationHealthCard","sourcePath":"components/cards/IntegrationHealthCard.jsx"},{"name":"MetricCard","sourcePath":"components/cards/MetricCard.jsx"},{"name":"ProductAIReleaseCard","sourcePath":"components/cards/ProductAIReleaseCard.jsx"},{"name":"Avatar","sourcePath":"components/core/Avatar.jsx"},{"name":"Button","sourcePath":"components/core/Button.jsx"},{"name":"Checkbox","sourcePath":"components/core/Checkbox.jsx"},{"name":"Icon","sourcePath":"components/core/Icon.jsx"},{"name":"ICON_NAMES","sourcePath":"components/core/Icon.jsx"},{"name":"IconButton","sourcePath":"components/core/IconButton.jsx"},{"name":"Input","sourcePath":"components/core/Input.jsx"},{"name":"Tag","sourcePath":"components/core/Tag.jsx"},{"name":"ConversationInbox","sourcePath":"components/inbox/ConversationInbox.jsx"},{"name":"KnowledgeDocumentEditor","sourcePath":"components/inbox/KnowledgeDocumentEditor.jsx"},{"name":"ActorBadge","sourcePath":"components/status/ActorBadge.jsx"},{"name":"AttentionStatus","sourcePath":"components/status/AttentionStatus.jsx"},{"name":"ChannelBadge","sourcePath":"components/status/ChannelBadge.jsx"}],"startingPoints":[{"name":"CommerceStatusTimeline","path":"components/cards/CommerceStatusTimeline.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Payment vs delivery step timeline for checkout/orders","viewport":"700x160"},{"name":"DepartmentCard","path":"components/cards/DepartmentCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Command Center department summary card","viewport":"900x360"},{"name":"IntegrationHealthCard","path":"components/cards/IntegrationHealthCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Single integration row (connected/degraded/error)","viewport":"700x90"},{"name":"MetricCard","path":"components/cards/MetricCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Single KPI cell for metric grids","viewport":"700x120"},{"name":"ProductAIReleaseCard","path":"components/cards/ProductAIReleaseCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"AI knowledge/prompt release snapshot for one product","viewport":"700x180"},{"name":"Button","path":"components/core/Button.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Primary/secondary/ghost/danger button","viewport":"700x220"},{"name":"IconButton","path":"components/core/IconButton.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Square icon-only button with optional badge","viewport":"700x150"},{"name":"Input","path":"components/core/Input.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Text field with label, icon and error state","viewport":"700x260"},{"name":"Tag","path":"components/core/Tag.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Status pill and rectangular label tag","viewport":"700x150"},{"name":"KnowledgeDocumentEditor","path":"components/inbox/KnowledgeDocumentEditor.jsx","previewPath":"components/inbox/inbox.card.html","kind":"component","section":"Inbox","subtitle":"Plain-text knowledge base document editor","viewport":"700x380"},{"name":"ActorBadge","path":"components/status/ActorBadge.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"AI vs human avatar for conversation timelines","viewport":"700x110"},{"name":"AttentionStatus","path":"components/status/AttentionStatus.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"Company/department health chip (ok/attention/critical)","viewport":"700x120"},{"name":"ChannelBadge","path":"components/status/ChannelBadge.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"MAX / Telegram / Web Chat channel chip","viewport":"700x100"}],"cards":[{"path":"guidelines/logo-mark.card.html","group":"Brand","viewport":"700x160","subtitle":"Only mark found in the codebase — a blue rounded square with a bar-chart glyph","name":"Logo Mark"},{"path":"guidelines/radii-shadows.card.html","group":"Brand","viewport":"700x180","subtitle":"Soft, low-opacity shadows only — no glassmorphism","name":"Radii & Shadows"},{"path":"ui_kits/checkout/index.html","group":"Checkout","viewport":"440x760"},{"path":"guidelines/colors-ai-channels.card.html","group":"Colors","viewport":"700x160","subtitle":"AI/human split, MAX/Telegram/Web CLine truncated
|
||||
File renamed without changes.
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* Edevs Hub — color tokens
|
||||
/* Chatballs — color tokens
|
||||
Source: packages/ui/src/theme.ts (Ant Design ThemeConfig), apps/internal-ui/src/styles/base.css,
|
||||
and design/baseline/*.dc.html (approved HTML baseline). Ant Design's default light palette,
|
||||
customized with a single accent (#1677ff) per ADR-HUB-0013. */
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* Edevs Hub — radii, shadows, motion. "Премиальный минимализм": no gradients,
|
||||
/* Chatballs — radii, shadows, motion. "Премиальный минимализм": no gradients,
|
||||
no glassmorphism/blur, no neon — shadows stay soft and near-black at low opacity. */
|
||||
|
||||
:root {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* Edevs Hub — spacing tokens. Compact-enterprise density (ADR-HUB-0013):
|
||||
/* Chatballs — spacing tokens. Compact-enterprise density (ADR-HUB-0013):
|
||||
"большие пустые поля и oversized-карточки запрещены". Values are the exact
|
||||
paddings/gaps observed in the baseline, not snapped to a rounder grid. */
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* Edevs Hub — typography tokens
|
||||
/* Chatballs — typography tokens
|
||||
The internal Hub uses the Ant Design default system font stack — no bespoke webfont
|
||||
is loaded (see ADR-HUB-0013: "используется системный font stack Ant Design без
|
||||
обязательной внешней зависимости от загружаемого шрифта"). Technical identifiers
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"namespace":"EdevsHubDesignSystem_e4c9df","components":[{"name":"CommerceStatusTimeline","sourcePath":"components/cards/CommerceStatusTimeline.jsx"},{"name":"DepartmentCard","sourcePath":"components/cards/DepartmentCard.jsx"},{"name":"IntegrationHealthCard","sourcePath":"components/cards/IntegrationHealthCard.jsx"},{"name":"MetricCard","sourcePath":"components/cards/MetricCard.jsx"},{"name":"ProductAIReleaseCard","sourcePath":"components/cards/ProductAIReleaseCard.jsx"},{"name":"Avatar","sourcePath":"components/core/Avatar.jsx"},{"name":"Button","sourcePath":"components/core/Button.jsx"},{"name":"Checkbox","sourcePath":"components/core/Checkbox.jsx"},{"name":"Icon","sourcePath":"components/core/Icon.jsx"},{"name":"ICON_NAMES","sourcePath":"components/core/Icon.jsx"},{"name":"IconButton","sourcePath":"components/core/IconButton.jsx"},{"name":"Input","sourcePath":"components/core/Input.jsx"},{"name":"Tag","sourcePath":"components/core/Tag.jsx"},{"name":"ConversationInbox","sourcePath":"components/inbox/ConversationInbox.jsx"},{"name":"KnowledgeDocumentEditor","sourcePath":"components/inbox/KnowledgeDocumentEditor.jsx"},{"name":"ActorBadge","sourcePath":"components/status/ActorBadge.jsx"},{"name":"AttentionStatus","sourcePath":"components/status/AttentionStatus.jsx"},{"name":"ChannelBadge","sourcePath":"components/status/ChannelBadge.jsx"}],"startingPoints":[{"name":"CommerceStatusTimeline","path":"components/cards/CommerceStatusTimeline.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Payment vs delivery step timeline for checkout/orders","viewport":"700x160"},{"name":"DepartmentCard","path":"components/cards/DepartmentCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Command Center department summary card","viewport":"900x360"},{"name":"IntegrationHealthCard","path":"components/cards/IntegrationHealthCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Single integration row (connected/degraded/error)","viewport":"700x90"},{"name":"MetricCard","path":"components/cards/MetricCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Single KPI cell for metric grids","viewport":"700x120"},{"name":"ProductAIReleaseCard","path":"components/cards/ProductAIReleaseCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"AI knowledge/prompt release snapshot for one product","viewport":"700x180"},{"name":"Button","path":"components/core/Button.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Primary/secondary/ghost/danger button","viewport":"700x220"},{"name":"IconButton","path":"components/core/IconButton.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Square icon-only button with optional badge","viewport":"700x150"},{"name":"Input","path":"components/core/Input.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Text field with label, icon and error state","viewport":"700x260"},{"name":"Tag","path":"components/core/Tag.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Status pill and rectangular label tag","viewport":"700x150"},{"name":"KnowledgeDocumentEditor","path":"components/inbox/KnowledgeDocumentEditor.jsx","previewPath":"components/inbox/inbox.card.html","kind":"component","section":"Inbox","subtitle":"Plain-text knowledge base document editor","viewport":"700x380"},{"name":"ActorBadge","path":"components/status/ActorBadge.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"AI vs human avatar for conversation timelines","viewport":"700x110"},{"name":"AttentionStatus","path":"components/status/AttentionStatus.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"Company/department health chip (ok/attention/critical)","viewport":"700x120"},{"name":"ChannelBadge","path":"components/status/ChannelBadge.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"MAX / Telegram / Web Chat channel chip","viewport":"700x100"}],"cards":[{"path":"guidelines/logo-mark.card.html","group":"Brand","viewport":"700x160","subtitle":"Only mark found in the codebase — a blue rounded square with a bar-chart glyph","name":"Logo Mark"},{"path":"guidelines/radii-shadows.card.html","group":"Brand","viewport":"700x180","subtitle":"Soft, low-opacity shadows only — no glassmorphism","name":"Radii & Shadows"},{"path":"ui_kits/checkout/index.html","group":"Checkout","viewport":"440x760"},{"path":"guidelines/colors-ai-channels.card.html","group":"Colors","viewport":"700x160","subtitle":"AI/human split, MAX/Telegram/Web ChLine truncated
|
||||
-216
@@ -1,216 +0,0 @@
|
||||
# Edevs Hub — Design System
|
||||
|
||||
Design system for **Edevs**, a Russian product IT company (`edevs.tech`) that builds applied
|
||||
digital products for narrow professional niches — currently **FoxRay** (cephalometric/TRG
|
||||
analysis for orthodontists) and **FirePage** (ready-made niche websites on a proprietary CMS,
|
||||
sold as a one-time license). This design system, however, documents **Edevs Hub**
|
||||
(`hub.edevs.tech`) — the internal company platform that runs sales, support, AI agents, and
|
||||
commerce for those products, plus the two small public-facing surfaces it exposes (Web Chat
|
||||
widget and Checkout).
|
||||
|
||||
## Sources
|
||||
|
||||
Everything here was extracted from the attached codebase, mounted read-only at
|
||||
`hub.edevs.tech/`:
|
||||
|
||||
- `hub.edevs.tech/design/baseline/*.dc.html` — the team's own **approved HTML visual baseline**
|
||||
(explicitly the canonical design source per `SPEC-HUB-0007`, section 3: *"Утверждённые
|
||||
дизайн-файлы размещаются только в едином каноническом каталоге:
|
||||
`code/hub.edevs.tech/design/baseline/`"*). ~35 screens covering Command Center, Sales
|
||||
(overview/clients/dialogs/orders), Departments, Employees, Products, AI agents (list/create/
|
||||
detail/knowledge), Integrations, Settings, Auth, the Web Chat widget, and the Checkout flow.
|
||||
- `hub.edevs.tech/design/baseline/uploads/ADR-HUB-0013-Internal-UI-Design-System.md` — the
|
||||
Internal Hub UI design-system decision record (Ant Design + Ant Design X + "Edevs Hub Theme").
|
||||
- `hub.edevs.tech/design/baseline/uploads/SPEC-HUB-0007-Checkout-UI.md` — the public checkout
|
||||
interface spec (`pay.hub.edevs.tech`).
|
||||
- `hub.edevs.tech/design/baseline/uploads/SPEC-HUB-0003-Web-Chat.md`,
|
||||
`SPEC-HUB-0004-Internal-Hub-UI.md`, `SPEC-HUB-0005-Implemented-Internal-UI-Baseline.md`,
|
||||
`SPEC-HUB-0001-First-Iteration.md`, `ADR-HUB-0017-AI-Agent-Configuration-UX.md` — supporting
|
||||
specs referenced but not individually quoted below.
|
||||
- `hub.edevs.tech/packages/ui/src/theme.ts` — the actual Ant Design `ThemeConfig` ("Edevs Hub
|
||||
Theme") used by the Internal UI: primary color, radii, per-component overrides.
|
||||
`hub.edevs.tech/apps/internal-ui/src/styles/base.css` — global resets.
|
||||
- `hub.edevs.tech/apps/internal-ui/public/favicon.svg` — the one brand mark present in the repo.
|
||||
- `hub.edevs.tech/content/ai-content-company-filled.md` — the AI agent's system/persona prompts
|
||||
for the main company site, used for the Content Fundamentals section below.
|
||||
- `hub.edevs.tech/apps/checkout` and `hub.edevs.tech/apps/web-chat` — app shells for the public
|
||||
surfaces (the checkout app has no implementation yet; the design baseline is ground truth for
|
||||
both).
|
||||
|
||||
No Figma file or link was provided for this project — the HTML baseline above is the sole
|
||||
design source, and per the team's own spec it *is* the canonical one.
|
||||
|
||||
## Products in scope
|
||||
|
||||
1. **Internal Hub** (`hub.edevs.tech`, `apps/internal-ui`) — the OWNER/OPERATOR back office:
|
||||
Command Center, Departments, Employees, Products, Sales workspace (overview, clients,
|
||||
dialogs, orders), AI agents & knowledge, Integrations, Settings, Auth. Built on Ant Design +
|
||||
Ant Design X, desktop-first (1024px+, designed for 1440px).
|
||||
2. **Web Chat** (`apps/web-chat`) — the embeddable public support/sales chat widget for
|
||||
products like FoxRay, handling AI, human handoff, and inline checkout cards.
|
||||
3. **Checkout** (`apps/checkout`, `pay.hub.edevs.tech`) — the public, mobile-first purchase flow
|
||||
that hands off to Bank Tochka for payment and separately tracks payment vs. product delivery.
|
||||
|
||||
## Index
|
||||
|
||||
- `styles.css` — root stylesheet, imports everything under `tokens/`.
|
||||
- `tokens/colors.css`, `typography.css`, `spacing.css`, `effects.css` — design tokens.
|
||||
- `assets/logo-mark.svg`, `favicon.svg` — the one brand mark found in the codebase.
|
||||
- `components/core/` — Button, IconButton, Input, Checkbox, Tag, Avatar, Icon (intentional
|
||||
additions — see below).
|
||||
- `components/status/` — AttentionStatus, ActorBadge, ChannelBadge.
|
||||
- `components/cards/` — MetricCard, DepartmentCard, IntegrationHealthCard,
|
||||
ProductAIReleaseCard, CommerceStatusTimeline.
|
||||
- `components/inbox/` — ConversationInbox, KnowledgeDocumentEditor.
|
||||
- `guidelines/` — foundation specimen cards (Colors, Type, Spacing, Brand).
|
||||
- `ui_kits/internal-hub/` — Auth → Command Center → Sales · Clients, clickable.
|
||||
- `ui_kits/web-chat/` — the embeddable chat widget, all 5 states.
|
||||
- `ui_kits/checkout/` — the public checkout flow, all 8 states.
|
||||
|
||||
## Components
|
||||
|
||||
Full list (16), grouped by directory:
|
||||
|
||||
- **Core** (intentional additions, see below): `Button`, `IconButton`, `Input`, `Checkbox`,
|
||||
`Tag`, `Avatar`, `Icon`.
|
||||
- **Status** (from ADR-HUB-0013's local-component list): `AttentionStatus`, `ActorBadge`,
|
||||
`ChannelBadge`.
|
||||
- **Cards** (from ADR-HUB-0013): `MetricCard`, `DepartmentCard`, `IntegrationHealthCard`,
|
||||
`ProductAIReleaseCard`, `CommerceStatusTimeline`.
|
||||
- **Inbox** (from ADR-HUB-0013): `ConversationInbox`, `KnowledgeDocumentEditor`.
|
||||
|
||||
### Intentional additions
|
||||
|
||||
ADR-HUB-0013 states the Internal Hub is built on **Ant Design + Ant Design X**, with only ten
|
||||
named local composite components on top (listed under "Status/Cards/Inbox" above — built
|
||||
exactly as named). Ant Design itself isn't installable in this static-HTML environment, so to
|
||||
make the UI kits and composite components actually renderable, this system also includes a
|
||||
small set of Ant-Design-styled primitives that the ADR assumes but doesn't name:
|
||||
`Button`, `IconButton`, `Input`, `Checkbox`, `Tag`, `Avatar`, `Icon`. Their visuals (radii,
|
||||
heights, colors) are copied exactly from the approved HTML baseline, not invented — treat them
|
||||
as a faithful stand-in for the real Ant Design instance, not a design decision of their own.
|
||||
|
||||
## Content fundamentals
|
||||
|
||||
Drawn from the AI agent system prompts (`content/ai-content-company-filled.md`) and the copy
|
||||
throughout the baseline screens (Russian-language product, primary audience is Russian).
|
||||
|
||||
- **Language & register:** Russian, informal-but-respectful "вы" register — direct, calm,
|
||||
no hard-sell. The agent prompt is explicit: "Пиши как нормальный человек в мессенджере. Не как объявление, не как пресс-релиз и не как робот, который сразу вываливает всю информацию."
|
||||
- **Tone:** short, human paragraphs, answer the actual question first, then suggest a next
|
||||
step: "Отвечай по сути вопроса, короткими живыми абзацами." and "Не дави на покупку. Главная задача общего агента — правильно понять потребность и направить человека туда, где он быстрее получит пользу."
|
||||
- **Formatting discipline:** no markdown inside chat replies — "Не используй markdown-разметку внутри ответа: не ставь заголовки, списки с маркерами, жирный текст, таблицы и разделители." UI copy elsewhere (Hub, checkout) mirrors this: plain sentences, no bullet-heavy microcopy.
|
||||
- **Emoji:** rare and situational, never decorative — "Уместные смайлики допустимы, но редко и по ситуации." No emoji appear anywhere in the Hub, Web Chat or Checkout baseline screens.
|
||||
- **Cultural register:** "Учитывай российский контекст общения: уважительно, прямо, без давления и без чрезмерной рекламности."
|
||||
- **Honesty/scope discipline:** never invent facts, prices, or promises outside the knowledge
|
||||
base — "Если данных не хватает, не выдумывай. Скажи, что этот момент лучше уточнить у специалиста, и передай оператору." and pricing/legal specifics always come from the server, never the client: see Checkout spec §16 ("не доверять цене и составу из состояния браузера").
|
||||
- **Handoff phrasing:** warm, not robotic, when passing to a human — "При передаче не отвечай сухо. Напиши по-человечески: понял задачу, здесь лучше подключить специалиста, передаю вопрос."
|
||||
- **UI microcopy style (from the baseline):** short declarative status lines ("Готовим оплату",
|
||||
"Оплата получена", "Требует внимания"), technical IDs always in monospace, money always as
|
||||
`₽95 040` (₽ prefix, space thousands separator, no decimals for round sums).
|
||||
- **Domains:** only `edevs.tech` is the confirmed public site; `edevs.ru` is explicitly
|
||||
forbidden in agent replies.
|
||||
|
||||
## Visual foundations
|
||||
|
||||
- **Overall direction (ADR-HUB-0013):** *"светлая тема; премиальный минимализм; высокая, но
|
||||
контролируемая информационная плотность; спокойная нейтральная основа; один основной
|
||||
акцентный цвет; цвет используется прежде всего для статусов и действий; минимум декоративных
|
||||
элементов; отсутствие градиентов, стекломорфизма, неоновых эффектов и визуального шума;
|
||||
desktop-first."* (light theme, premium minimalism, one accent color, color reserved for
|
||||
status/action, no gradients/glassmorphism/neon, desktop-first for the internal Hub).
|
||||
- **Color:** one accent, `#1677ff` (Ant Design blue-6) with a `#0958d9` hover/active shade.
|
||||
Semantic tokens are mandatory and separate from the accent: success/warning/error/info, plus
|
||||
two Hub-specific roles — `ai` (purple, `#722ed1`) vs `human` (blue, same as primary) — and a
|
||||
`channel-*` family (MAX purple, Telegram blue, Web Chat teal) used sparingly so multi-channel
|
||||
screens don't turn into "a colorful mosaic" (ADR wording). Status color is never the sole
|
||||
signal — always paired with text and, in tables, an icon or label.
|
||||
- **Type:** system font stack only — no bespoke webfont is loaded
|
||||
(`-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif`).
|
||||
Technical identifiers (order/release/event IDs, emails, obscured phone numbers) switch to a
|
||||
monospace stack. Headings use tight letter-spacing (−0.01 to −0.02em); table headers use wide
|
||||
spacing (+0.03 to +0.06em) with all-caps and a muted gray.
|
||||
Sizes are exact pixel values pulled from the baseline (26/24/20/18/16/14.5/13.5/13/12.5/12/
|
||||
11/10.5px) — not snapped to a 4/8 grid.
|
||||
- **Spacing / density:** "compact enterprise" density is an explicit rule — *"большие пустые
|
||||
поля и oversized-карточки запрещены"*. Padding values are odd/precise (9px, 11px, 13px, 14px,
|
||||
18px…), not rounded. Control heights: 30/34/36/42/44/48px; topbar is a fixed 56px.
|
||||
- **Backgrounds:** flat solid colors only. Page background `#f0f2f5`, card surfaces pure white.
|
||||
No photography, no illustrations, no repeating patterns/textures, no gradients anywhere
|
||||
(buttons, cards, banners are all flat fills). The one "textured" pattern in the system is the
|
||||
1px-gap metric grid (white cells on a `#f0f0f0` background, forming hairline dividers) — see
|
||||
the Spacing → "Metric Grid In Use" card.
|
||||
- **Corners:** 7–9px on controls/inputs, 8–9px on buttons, 10–14px on cards/modals, full pill
|
||||
on chips/segmented controls, circle on avatars.
|
||||
- **Cards:** white surface, 1px `#f0f0f0` border, soft shadow (`0 1px 3px rgba(0,0,0,.04)`),
|
||||
12px radius as the default; no colored left-border accent except the Command Center's status
|
||||
banner (a deliberate, singular exception tied to company health, not a general card pattern).
|
||||
- **Shadows:** shallow and near-neutral throughout — hairline (`0 1px 2px rgba(0,0,0,.03)`),
|
||||
card (`0 1px 3px rgba(0,0,0,.04)`), modal (`0 2px 12px rgba(0,0,0,.05)`), dropdown
|
||||
(`0 6px 20px rgba(0,0,0,.12)`). The one colored shadow is the primary button's blue-tinted
|
||||
`0 1px 2px rgba(22,119,255,.3)`, used to make the single CTA per screen pop slightly.
|
||||
- **Animation:** minimal and functional only — a 3-dot typing indicator (`hub-typing`, opacity/
|
||||
translateY loop), a spinner (`hub-spin`, rotate) for loading states, and a slow opacity pulse
|
||||
(`hub-pulse`) for "in progress" states (e.g. delivering a purchased product). No entrance
|
||||
animations, bounces, or parallax anywhere in the baseline.
|
||||
- **Hover states:** buttons/links darken (primary `#1677ff → #0958d9`); neutral surfaces get a
|
||||
light gray fill (`transparent → #f5f5f5`) on hover; secondary buttons swap border+text to the
|
||||
accent color on hover. No lightening-on-hover pattern is used.
|
||||
**Press/active states:** not distinctly styled in the baseline (no scale/shrink pattern
|
||||
observed) — treat hover as the primary interactive affordance; focus-visible gets a solid
|
||||
2px accent outline (see `apps/internal-ui/src/styles/base.css`).
|
||||
**Disabled:** 55% opacity + `cursor: not-allowed`.
|
||||
**Focus:** border-color changes to the accent (inputs) or a visible 2px outline (buttons) —
|
||||
never a glow/box-shadow ring.
|
||||
- **Borders:** hairline `#f0f0f0` almost everywhere (card edges, table row dividers, header
|
||||
separators); slightly stronger `#d9d9d9`/`#e8e8e8` on interactive control outlines
|
||||
(buttons, inputs) so they read as tappable against the flat background.
|
||||
- **Transparency & blur:** no blur/glassmorphism anywhere. The only translucent surfaces are
|
||||
the Web Chat header's icon buttons (`rgba(255,255,255,0.14–0.26)` over the solid blue header)
|
||||
and a full-viewport `position:fixed` transparent scrim used to close open dropdowns/menus.
|
||||
- **Imagery:** none — the product is data/status-dense enterprise software and transactional
|
||||
flows, not marketing pages. No photography, no hand-drawn illustrations, no generic stock
|
||||
imagery anywhere in the baseline; nothing to copy in for that reason.
|
||||
- **Layout rules:** Internal Hub is a fixed sidebar (≈248px) + topbar (56px) + scrollable
|
||||
content shell, min-width 1024–1180px depending on screen, content capped at 1200–1340px and
|
||||
centered. Web Chat and Checkout are separate, chrome-free, mobile-first single-column flows
|
||||
with no sidebar/topbar — explicitly not governed by the Internal Hub's layout rules
|
||||
(SPEC-HUB-0007 §4).
|
||||
|
||||
## Iconography
|
||||
|
||||
- **System:** hand-authored inline SVG, Feather/Lucide-style stroke icons (round caps/joins,
|
||||
1.7–2.2px stroke, 24×24 viewBox) — every baseline screen inlines its own `<svg>` rather than
|
||||
referencing a shared font or sprite sheet, so there is no icon font or `.svg` sprite file in
|
||||
the repo to copy wholesale. This design system's `Icon` component (`components/core/Icon.jsx`)
|
||||
collects the ~35 recurring glyphs actually used across the baseline (nav icons, status icons,
|
||||
form icons, payment icons) into one reusable primitive with the *exact* path data copied from
|
||||
the source screens — nothing was redrawn from imagination.
|
||||
- **Emoji:** never used anywhere in the product UI (only "rarely, situationally" in AI chat
|
||||
replies per the content guidelines above).
|
||||
**Unicode-as-icon:** limited to pagination chevrons (`‹ › …`) in table footers.
|
||||
- **Color:** icons are almost always `currentColor`/neutral gray (`#8c8c8c`/`#595959`), tinted
|
||||
to the semantic/accent color only when they sit inside a status chip or colored icon tile
|
||||
(e.g. a purple AI bolt icon on a light-purple tile).
|
||||
|
||||
## Caveats & where I need your help
|
||||
|
||||
1. **No Figma was attached** — everything above comes from the approved HTML baseline in
|
||||
`design/baseline/`, which the team's own spec names as canonical. If a Figma file exists,
|
||||
attach it and I can cross-check/tighten values.
|
||||
2. **No FoxRay/FirePage brand assets** — this system only covers Edevs Hub (the internal
|
||||
platform + its two public surfaces). FoxRay/Foxray and FirePage are referenced only as
|
||||
*product tags* inside Hub (colored labels, no logos). If you want their actual product UI
|
||||
or marks in this system, please attach their codebases/design files.
|
||||
3. **No logo beyond the one favicon mark** — I did not draw one. If Edevs has a real wordmark
|
||||
or icon set beyond `favicon.svg`, please attach it and I'll swap it in everywhere.
|
||||
4. **Ant Design isn't literally bundled** — see "Intentional additions" above; I built
|
||||
faithful lightweight stand-ins instead of pulling in the real library, since only static
|
||||
HTML/JS/CSS work in this environment.
|
||||
5. **Internal Hub UI kit covers 2 of many screens** (Command Center + Sales · Clients, behind a
|
||||
working Auth gate) rather than all ~35 baseline screens — tell me which screens matter most
|
||||
(Departments, AI agents, Orders, Settings…) and I'll extend the kit.
|
||||
|
||||
**Ask:** tell me which of the ~35 baseline screens to turn into additional UI-kit pages next,
|
||||
and whether the Ant-Design-styled primitives above should stay as lightweight stand-ins or be
|
||||
swapped for real `antd` components if this ever moves into a real build environment.
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
/* Edevs Hub — radii, shadows, motion. "Премиальный минимализм": no gradients,
|
||||
no glassmorphism/blur, no neon — shadows stay soft and near-black at low opacity. */
|
||||
|
||||
:root {
|
||||
--radius-xs: 5px;
|
||||
--radius-sm: 7px;
|
||||
--radius-md: 8px;
|
||||
--radius-lg: 9px;
|
||||
--radius-xl: 10px;
|
||||
--radius-2xl: 12px;
|
||||
--radius-3xl: 13px;
|
||||
--radius-4xl: 14px;
|
||||
--radius-pill: 999px;
|
||||
--radius-circle: 50%;
|
||||
|
||||
--shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.03);
|
||||
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.04);
|
||||
--shadow-md: 0 2px 12px rgba(0, 0, 0, 0.05);
|
||||
--shadow-lg: 0 6px 20px rgba(0, 0, 0, 0.12);
|
||||
--shadow-sticky: 0 -4px 16px rgba(0, 0, 0, 0.04);
|
||||
--shadow-primary: 0 1px 2px rgba(22, 119, 255, 0.3);
|
||||
|
||||
--ease-standard: cubic-bezier(0.4, 0, 0.2, 1); /* @kind other */
|
||||
--duration-fast: 0.15s; /* @kind other */
|
||||
--duration-base: 0.2s; /* @kind other */
|
||||
}
|
||||
|
||||
@keyframes hub-typing {
|
||||
0%, 80%, 100% { opacity: 0.25; transform: translateY(0); }
|
||||
40% { opacity: 1; transform: translateY(-2px); }
|
||||
}
|
||||
|
||||
@keyframes hub-spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
@keyframes hub-pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.5; }
|
||||
}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
/* Edevs Hub — spacing tokens. Compact-enterprise density (ADR-HUB-0013):
|
||||
"большие пустые поля и oversized-карточки запрещены". Values are the exact
|
||||
paddings/gaps observed in the baseline, not snapped to a rounder grid. */
|
||||
|
||||
:root {
|
||||
--space-1: 2px;
|
||||
--space-2: 4px;
|
||||
--space-3: 6px;
|
||||
--space-4: 8px;
|
||||
--space-5: 9px;
|
||||
--space-6: 10px;
|
||||
--space-7: 11px;
|
||||
--space-8: 12px;
|
||||
--space-9: 14px;
|
||||
--space-10: 16px;
|
||||
--space-11: 18px;
|
||||
--space-12: 20px;
|
||||
--space-13: 22px;
|
||||
--space-14: 24px;
|
||||
--space-15: 28px;
|
||||
--space-16: 32px;
|
||||
--space-17: 36px;
|
||||
|
||||
/* control heights */
|
||||
--h-control-sm: 30px;
|
||||
--h-control-md: 34px;
|
||||
--h-control: 36px;
|
||||
--h-control-lg: 42px;
|
||||
--h-control-xl: 44px;
|
||||
--h-control-2xl: 48px;
|
||||
--h-topbar: 56px;
|
||||
|
||||
/* layout */
|
||||
--sidebar-width: 248px;
|
||||
--content-max: 1340px;
|
||||
}
|
||||
File renamed without changes.
@@ -1,80 +0,0 @@
|
||||
# Каналы обработки — design baseline (DG-02)
|
||||
|
||||
Макет раздела **Компания → Каналы** (CustoCRM / ООО «Эдевс») по SPEC-HUB-0027 / ADR-HUB-0037.
|
||||
|
||||
## Состав
|
||||
|
||||
```
|
||||
Каналы Baseline.dc.html — макет (6 кадров: A–E + состояния)
|
||||
support.js — рантайм Design Component (шаблон + логика)
|
||||
_ds/edevs-hub-design-system-…/ — дизайн-система: токены, styles.css, _ds_bundle.js
|
||||
assets/custocrm-mark.svg — логотип CustoCRM
|
||||
```
|
||||
|
||||
## Запуск
|
||||
|
||||
Открыть `Каналы Baseline.dc.html` через локальный HTTP-сервер
|
||||
(из-за загрузки внешних файлов `file://` не подойдёт):
|
||||
|
||||
```bash
|
||||
python3 -m http.server 8080
|
||||
# → http://localhost:8080/Каналы%20Baseline.dc.html
|
||||
```
|
||||
|
||||
## Карта кадров (SPEC-HUB-0027 §11.6)
|
||||
|
||||
- **A** — Список каналов: полная оболочка (sidebar + topbar). Фильтры-`UnderlineTabs` с count
|
||||
(`Все · Продажи · Поддержка · Без отдела`), поиск, тумблер «Показывать архивные».
|
||||
Плотная `baseline-table` в `table-card`. Колонки `КАНАЛ / ПРОДУКТ / ПОДКЛЮЧЕНИЯ /
|
||||
AI-АГЕНТ / ДИАЛОГИ / ⋯`. Показано открытое меню строки с заблокированным «Удалить»
|
||||
и причиной. §11.1.
|
||||
- **B** — Карточка канала **одной страницей, без вкладок**. Заголовок (`code · отдел ·
|
||||
продукт`, действия «Изменить / Деактивировать / Удалить») и секции сверху вниз:
|
||||
Назначение, Политика, Подключения, AI-агент (одна строка: имя · статус · модель +
|
||||
ссылка «Открыть агента» на страницу агента наружу), Счётчики (открытые диалоги,
|
||||
подключения + ссылка на диалоги). Настроек агента и знаний в карточке нет. §11.2.
|
||||
- **C** — Секция «Политика» на **непродуктовом** канале «Партнёрская линия».
|
||||
Пять флагов с однострочным пояснением следствия; три флага (checkout P1,
|
||||
attribution P2, обязательная идентичность P3) выключены и заблокированы с причиной. §11.2.
|
||||
- **D** — Секция «Подключения». Список подключений канала с отвязкой, действие
|
||||
«Привязать» и модалка **переноса** подключения из другого канала (`force`),
|
||||
с оговоркой, что диалоги остаются в прежнем канале. §11.1 / §6.6.
|
||||
- **E** — Мастер создания, **три шага** (Канал · Назначение · Подключения). Показан
|
||||
финальный экран: канал создан, ведут его операторы, ссылка в раздел AI для создания
|
||||
агента отдельным действием. Настроек агента и знаний в мастере нет. §11.3.
|
||||
- **S** — Состояния: пустой список (приглашение без «здесь пусто»), канал без агента
|
||||
(секция AI-агент), архивный канал, ограниченный доступ (department scope), конфликт
|
||||
удаления (409 с блокерами). §11.5 / §7.2.
|
||||
|
||||
## Зафиксированные решения по открытым вопросам (README §5 задания)
|
||||
|
||||
1. **Канал без отдела.** В колонке `КАНАЛ` под именем идёт `code · <чип «Без отдела»>` —
|
||||
нейтральный чип на `--n-9`, а не пустая ячейка: канал читается как намеренно
|
||||
безотдельный, а не как незаполненный черновик. Плюс отдельный таб-фильтр «Без отдела».
|
||||
Такой канал виден только organization-scoped `channels.view` (§5.2).
|
||||
2. **Архивный канал (`isActive=false`).** Отдельный статус `Архивный` (полая точка,
|
||||
приглушённый текст, фон строки `#fcfcfc`), а не «Выключено». По умолчанию скрыт,
|
||||
показывается тумблером «Показывать архивные». Меню строки предлагает только
|
||||
«Активировать». История диалогов сохраняется и доступна ссылкой из карточки
|
||||
(«История сохраняется даже после деактивации канала»).
|
||||
3. **Запрещённый инвариантом флаг политики.** Флаг выключен **и** заблокирован, рядом —
|
||||
бейдж «Запрещено инвариантом» / «Недоступно» и однострочная причина со ссылкой на
|
||||
инвариант (P1/P2/P3) и способ разблокировать («Назначить продукт»). Причина
|
||||
объясняется, а не игнорируется молча при сохранении. Кадр C, флаг checkout выделен.
|
||||
4. **Колонка «Диалоги» в списке.** Оставлена. Обоснование: это дешёвый агрегат
|
||||
(`counters.openConversations`, один запрос на список, §6.1), а открытые диалоги —
|
||||
ключевой операционный сигнал канала. Полный разрез счётчиков (открытые диалоги и
|
||||
подключения) остаётся в секции «Счётчики» карточки; в списке — только открытые
|
||||
диалоги, numeric. Счётчика знаний в карточке канала нет: знания принадлежат агенту.
|
||||
|
||||
## Технические примечания
|
||||
|
||||
- Вёрстка — инлайн-стили поверх токенов дизайн-системы (`var(--*)` из `_ds/.../tokens`).
|
||||
Цвета/типографика/отступы менять только через токены; сырые hex вне токенов не
|
||||
используются (кроме служебного фона холста и подсветок строк из baseline-образца).
|
||||
- `ChannelBadge` (точка + короткий лейбл MAX/TG/Web на токенах `--channel-*`) применяется
|
||||
экономно — только в колонке «Подключения» списка и в секции «Подключения» карточки
|
||||
(ADR-HUB-0013).
|
||||
- Терминология: MAX/TG/Web — «Подключения»; «Канал» — сущность маршрутизации.
|
||||
- Данные — примеры; авторизация, инварианты и счётчики вычисляются на backend
|
||||
(frontend не источник прав), см. SPEC-HUB-0027 §5–§7.
|
||||
-508
@@ -1,508 +0,0 @@
|
||||
{
|
||||
"plugins": [
|
||||
"react",
|
||||
"import"
|
||||
],
|
||||
"rules": {
|
||||
"react/forbid-elements": [
|
||||
"warn",
|
||||
{
|
||||
"forbid": []
|
||||
}
|
||||
],
|
||||
"no-restricted-imports": [
|
||||
"warn",
|
||||
{
|
||||
"patterns": [
|
||||
{
|
||||
"group": [
|
||||
"components/cards/**",
|
||||
"components/core/**",
|
||||
"components/inbox/**",
|
||||
"components/status/**",
|
||||
"ui_kits/checkout/**",
|
||||
"ui_kits/internal-hub/**",
|
||||
"ui_kits/web-chat/**"
|
||||
],
|
||||
"message": "Import design-system components from 'index.js', not component internals."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-restricted-syntax": [
|
||||
"warn",
|
||||
{
|
||||
"selector": "Literal[value=/#[0-9a-fA-F]{3,8}\\b/]",
|
||||
"message": "Raw hex color — use a design-system color token via var()."
|
||||
},
|
||||
{
|
||||
"selector": "Literal[value=/\\b\\d+px\\b/]",
|
||||
"message": "Raw px value — use a design-system spacing token via var()."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='ActorBadge'] > JSXAttribute > JSXIdentifier[name!=/^(?:actor|initials|color|key|ref|className|style|children)$/]",
|
||||
"message": "<ActorBadge> doesn't accept that prop. Declared props: actor, initials, color."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='ActorBadge'] > JSXAttribute[name.name='actor'] > Literal[value!=/^(?:ai|human)$/]",
|
||||
"message": "<ActorBadge> actor must be one of 'ai' | 'human'."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='AttentionStatus'] > JSXAttribute > JSXIdentifier[name!=/^(?:level|label|key|ref|className|style|children)$/]",
|
||||
"message": "<AttentionStatus> doesn't accept that prop. Declared props: level, label."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='AttentionStatus'] > JSXAttribute[name.name='level'] > Literal[value!=/^(?:ok|attention|critical)$/]",
|
||||
"message": "<AttentionStatus> level must be one of 'ok' | 'attention' | 'critical'."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='Avatar'] > JSXAttribute > JSXIdentifier[name!=/^(?:initials|color|size|key|ref|className|style|children)$/]",
|
||||
"message": "<Avatar> doesn't accept that prop. Declared props: initials, color, size."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='Button'] > JSXAttribute > JSXIdentifier[name!=/^(?:children|variant|size|disabled|onClick|type|key|ref|className|style|children)$/]",
|
||||
"message": "<Button> doesn't accept that prop. Declared props: children, variant, size, disabled, onClick, type."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='Button'] > JSXAttribute[name.name='variant'] > Literal[value!=/^(?:primary|secondary|ghost|danger)$/]",
|
||||
"message": "<Button> variant must be one of 'primary' | 'secondary' | 'ghost' | 'danger'."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='Button'] > JSXAttribute[name.name='size'] > Literal[value!=/^(?:sm|md|lg)$/]",
|
||||
"message": "<Button> size must be one of 'sm' | 'md' | 'lg'."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='Button'] > JSXAttribute[name.name='type'] > Literal[value!=/^(?:button|submit)$/]",
|
||||
"message": "<Button> type must be one of 'button' | 'submit'."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='ChannelBadge'] > JSXAttribute > JSXIdentifier[name!=/^(?:channel|title|key|ref|className|style|children)$/]",
|
||||
"message": "<ChannelBadge> doesn't accept that prop. Declared props: channel, title."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='ChannelBadge'] > JSXAttribute[name.name='channel'] > Literal[value!=/^(?:max|telegram|webchat)$/]",
|
||||
"message": "<ChannelBadge> channel must be one of 'max' | 'telegram' | 'webchat'."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='Checkbox'] > JSXAttribute > JSXIdentifier[name!=/^(?:checked|onChange|label|size|key|ref|className|style|children)$/]",
|
||||
"message": "<Checkbox> doesn't accept that prop. Declared props: checked, onChange, label, size."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='Checkbox'] > JSXAttribute[name.name='size'] > Literal[value!=/^(?:sm|md)$/]",
|
||||
"message": "<Checkbox> size must be one of 'sm' | 'md'."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='CommerceStatusTimeline'] > JSXAttribute > JSXIdentifier[name!=/^(?:steps|key|ref|className|style|children)$/]",
|
||||
"message": "<CommerceStatusTimeline> doesn't accept that prop. Declared props: steps."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='ConversationInboxItem'] > JSXAttribute > JSXIdentifier[name!=/^(?:name|preview|channel|lastActor|initials|color|time|waiting|active|onClick|key|ref|className|style|children)$/]",
|
||||
"message": "<ConversationInboxItem> doesn't accept that prop. Declared props: name, preview, channel, lastActor, initials, color, time, waiting, active, onClick."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='ConversationInboxItem'] > JSXAttribute[name.name='channel'] > Literal[value!=/^(?:max|telegram|webchat)$/]",
|
||||
"message": "<ConversationInboxItem> channel must be one of 'max' | 'telegram' | 'webchat'."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='ConversationInboxItem'] > JSXAttribute[name.name='lastActor'] > Literal[value!=/^(?:ai|human)$/]",
|
||||
"message": "<ConversationInboxItem> lastActor must be one of 'ai' | 'human'."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='DepartmentCard'] > JSXAttribute > JSXIdentifier[name!=/^(?:name|meta|level|summary|icon|openLabel|onOpen|children|key|ref|className|style|children)$/]",
|
||||
"message": "<DepartmentCard> doesn't accept that prop. Declared props: name, meta, level, summary, icon, openLabel, onOpen, children."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='DepartmentCard'] > JSXAttribute[name.name='level'] > Literal[value!=/^(?:ok|attention|critical)$/]",
|
||||
"message": "<DepartmentCard> level must be one of 'ok' | 'attention' | 'critical'."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='Icon'] > JSXAttribute > JSXIdentifier[name!=/^(?:name|size|color|strokeWidth|key|ref|className|style|children)$/]",
|
||||
"message": "<Icon> doesn't accept that prop. Declared props: name, size, color, strokeWidth."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='Icon'] > JSXAttribute[name.name='name'] > Literal[value!=/^(?:dashboard|departments|employees|products|ai|integrations|settings|search|chevronDown|chevronRight|moreVertical|check|checkCircle|alertTriangle|alertCircle|xCircle|clock|refresh|arrowRight|arrowLeft|mail|lock|eye|eyeOff|card|sbp|shield|download|columns|bell|trash|edit|merge|bolt|cart|history|team|package2)$/]",
|
||||
"message": "<Icon> name must be one of 'dashboard' | 'departments' | 'employees' | 'products' | 'ai' | 'integrations' | 'settings' | 'search' | 'chevronDown' | 'chevronRight' | 'moreVertical' | 'check' | 'checkCircle' | 'alertTriangle' | 'alertCircle' | 'xCircle' | 'clock' | 'refresh' | 'arrowRight' | 'arrowLeft' | 'mail' | 'lock' | 'eye' | 'eyeOff' | 'card' | 'sbp' | 'shield' | 'download' | 'columns' | 'bell' | 'trash' | 'edit' | 'merge' | 'bolt' | 'cart' | 'history' | 'team' | 'package2'."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='IconButton'] > JSXAttribute > JSXIdentifier[name!=/^(?:children|size|badge|bare|label|onClick|key|ref|className|style|children)$/]",
|
||||
"message": "<IconButton> doesn't accept that prop. Declared props: children, size, badge, bare, label, onClick."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='Input'] > JSXAttribute > JSXIdentifier[name!=/^(?:value|onChange|placeholder|label|required|type|disabled|error|hint|icon|suffix|fullWidth|key|ref|className|style|children)$/]",
|
||||
"message": "<Input> doesn't accept that prop. Declared props: value, onChange, placeholder, label, required, type, disabled, error, hint, icon, suffix, fullWidth."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='Input'] > JSXAttribute[name.name='type'] > Literal[value!=/^(?:text|email|password|tel)$/]",
|
||||
"message": "<Input> type must be one of 'text' | 'email' | 'password' | 'tel'."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='IntegrationHealthCard'] > JSXAttribute > JSXIdentifier[name!=/^(?:name|group|status|key|ref|className|style|children)$/]",
|
||||
"message": "<IntegrationHealthCard> doesn't accept that prop. Declared props: name, group, status."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='IntegrationHealthCard'] > JSXAttribute[name.name='status'] > Literal[value!=/^(?:connected|degraded|error)$/]",
|
||||
"message": "<IntegrationHealthCard> status must be one of 'connected' | 'degraded' | 'error'."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='KnowledgeDocumentEditor'] > JSXAttribute > JSXIdentifier[name!=/^(?:title|onTitleChange|docId|body|onBodyChange|rows|savedLabel|key|ref|className|style|children)$/]",
|
||||
"message": "<KnowledgeDocumentEditor> doesn't accept that prop. Declared props: title, onTitleChange, docId, body, onBodyChange, rows, savedLabel."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='MetricCard'] > JSXAttribute > JSXIdentifier[name!=/^(?:label|value|valueColor|dotColor|key|ref|className|style|children)$/]",
|
||||
"message": "<MetricCard> doesn't accept that prop. Declared props: label, value, valueColor, dotColor."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='ProductAIReleaseCard'] > JSXAttribute > JSXIdentifier[name!=/^(?:productName|productInitial|releaseId|live|iconBg|iconColor|stats|key|ref|className|style|children)$/]",
|
||||
"message": "<ProductAIReleaseCard> doesn't accept that prop. Declared props: productName, productInitial, releaseId, live, iconBg, iconColor, stats."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='Tag'] > JSXAttribute > JSXIdentifier[name!=/^(?:children|tone|pill|dot|dotColor|key|ref|className|style|children)$/]",
|
||||
"message": "<Tag> doesn't accept that prop. Declared props: children, tone, pill, dot, dotColor."
|
||||
},
|
||||
{
|
||||
"selector": "JSXOpeningElement[name.name='Tag'] > JSXAttribute[name.name='tone'] > Literal[value!=/^(?:neutral|primary|success|warning|error|ai)$/]",
|
||||
"message": "<Tag> tone must be one of 'neutral' | 'primary' | 'success' | 'warning' | 'error' | 'ai'."
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"**/index.js"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-imports": "off"
|
||||
}
|
||||
}
|
||||
],
|
||||
"x-omelette": {
|
||||
"components": {
|
||||
"ActorBadge": {
|
||||
"replaces": []
|
||||
},
|
||||
"AttentionStatus": {
|
||||
"replaces": []
|
||||
},
|
||||
"Avatar": {
|
||||
"replaces": []
|
||||
},
|
||||
"Button": {
|
||||
"replaces": []
|
||||
},
|
||||
"ChannelBadge": {
|
||||
"replaces": []
|
||||
},
|
||||
"Checkbox": {
|
||||
"replaces": []
|
||||
},
|
||||
"CommerceStatusTimeline": {
|
||||
"replaces": []
|
||||
},
|
||||
"ConversationInboxItem": {
|
||||
"replaces": []
|
||||
},
|
||||
"DepartmentCard": {
|
||||
"replaces": []
|
||||
},
|
||||
"Icon": {
|
||||
"replaces": []
|
||||
},
|
||||
"IconButton": {
|
||||
"replaces": []
|
||||
},
|
||||
"Input": {
|
||||
"replaces": []
|
||||
},
|
||||
"IntegrationHealthCard": {
|
||||
"replaces": []
|
||||
},
|
||||
"KnowledgeDocumentEditor": {
|
||||
"replaces": []
|
||||
},
|
||||
"MetricCard": {
|
||||
"replaces": []
|
||||
},
|
||||
"ProductAIReleaseCard": {
|
||||
"replaces": []
|
||||
},
|
||||
"Tag": {
|
||||
"replaces": []
|
||||
}
|
||||
},
|
||||
"tokens": [
|
||||
"--ai",
|
||||
"--ai-bg",
|
||||
"--ai-light",
|
||||
"--ai-lighter",
|
||||
"--border-default",
|
||||
"--border-input",
|
||||
"--border-strong",
|
||||
"--channel-max",
|
||||
"--channel-max-bg",
|
||||
"--channel-telegram",
|
||||
"--channel-telegram-bg",
|
||||
"--channel-webchat",
|
||||
"--channel-webchat-bg",
|
||||
"--content-max",
|
||||
"--duration-base",
|
||||
"--duration-fast",
|
||||
"--ease-standard",
|
||||
"--error",
|
||||
"--error-bg",
|
||||
"--error-border",
|
||||
"--error-text",
|
||||
"--font-mono",
|
||||
"--font-sans",
|
||||
"--h-control",
|
||||
"--h-control-2xl",
|
||||
"--h-control-lg",
|
||||
"--h-control-md",
|
||||
"--h-control-sm",
|
||||
"--h-control-xl",
|
||||
"--h-topbar",
|
||||
"--human",
|
||||
"--info",
|
||||
"--leading-loose",
|
||||
"--leading-normal",
|
||||
"--leading-relaxed",
|
||||
"--leading-snug",
|
||||
"--leading-tight",
|
||||
"--n-1",
|
||||
"--n-10",
|
||||
"--n-11",
|
||||
"--n-2",
|
||||
"--n-3",
|
||||
"--n-4",
|
||||
"--n-5",
|
||||
"--n-6",
|
||||
"--n-7",
|
||||
"--n-8",
|
||||
"--n-9",
|
||||
"--n-white",
|
||||
"--primary",
|
||||
"--primary-bg",
|
||||
"--primary-border",
|
||||
"--primary-hover",
|
||||
"--primary-shadow",
|
||||
"--product-firepage",
|
||||
"--product-firepage-bg",
|
||||
"--product-foxray",
|
||||
"--product-foxray-bg",
|
||||
"--radius-2xl",
|
||||
"--radius-3xl",
|
||||
"--radius-4xl",
|
||||
"--radius-circle",
|
||||
"--radius-lg",
|
||||
"--radius-md",
|
||||
"--radius-pill",
|
||||
"--radius-sm",
|
||||
"--radius-xl",
|
||||
"--radius-xs",
|
||||
"--shadow-lg",
|
||||
"--shadow-md",
|
||||
"--shadow-primary",
|
||||
"--shadow-sm",
|
||||
"--shadow-sticky",
|
||||
"--shadow-xs",
|
||||
"--sidebar-width",
|
||||
"--space-1",
|
||||
"--space-10",
|
||||
"--space-11",
|
||||
"--space-12",
|
||||
"--space-13",
|
||||
"--space-14",
|
||||
"--space-15",
|
||||
"--space-16",
|
||||
"--space-17",
|
||||
"--space-2",
|
||||
"--space-3",
|
||||
"--space-4",
|
||||
"--space-5",
|
||||
"--space-6",
|
||||
"--space-7",
|
||||
"--space-8",
|
||||
"--space-9",
|
||||
"--success",
|
||||
"--success-bg",
|
||||
"--success-bg-strong",
|
||||
"--success-border",
|
||||
"--success-text",
|
||||
"--surface-card",
|
||||
"--surface-chip",
|
||||
"--surface-page",
|
||||
"--surface-sunken",
|
||||
"--text-2xl",
|
||||
"--text-2xs",
|
||||
"--text-2xs-tight",
|
||||
"--text-base",
|
||||
"--text-base-lg",
|
||||
"--text-body",
|
||||
"--text-disabled",
|
||||
"--text-heading",
|
||||
"--text-inverse",
|
||||
"--text-lg",
|
||||
"--text-link",
|
||||
"--text-md",
|
||||
"--text-secondary",
|
||||
"--text-sm",
|
||||
"--text-sm-lg",
|
||||
"--text-sm-tight",
|
||||
"--text-tertiary",
|
||||
"--text-xl",
|
||||
"--text-xs",
|
||||
"--text-xs-tight",
|
||||
"--tracking-tight",
|
||||
"--tracking-tight-sm",
|
||||
"--tracking-wide",
|
||||
"--tracking-wider",
|
||||
"--warning",
|
||||
"--warning-bg",
|
||||
"--warning-bg-strong",
|
||||
"--warning-border",
|
||||
"--warning-text",
|
||||
"--weight-black",
|
||||
"--weight-bold",
|
||||
"--weight-medium",
|
||||
"--weight-regular",
|
||||
"--weight-semibold"
|
||||
],
|
||||
"tokenKinds": {
|
||||
"--n-1": "color",
|
||||
"--n-2": "color",
|
||||
"--n-3": "color",
|
||||
"--n-4": "color",
|
||||
"--n-5": "color",
|
||||
"--n-6": "color",
|
||||
"--n-7": "color",
|
||||
"--n-8": "color",
|
||||
"--n-9": "color",
|
||||
"--n-10": "color",
|
||||
"--n-11": "color",
|
||||
"--n-white": "color",
|
||||
"--primary": "color",
|
||||
"--primary-hover": "color",
|
||||
"--primary-bg": "color",
|
||||
"--primary-border": "color",
|
||||
"--primary-shadow": "shadow",
|
||||
"--success": "color",
|
||||
"--success-text": "font",
|
||||
"--success-bg": "color",
|
||||
"--success-bg-strong": "color",
|
||||
"--success-border": "color",
|
||||
"--warning": "color",
|
||||
"--warning-text": "font",
|
||||
"--warning-bg": "color",
|
||||
"--warning-bg-strong": "color",
|
||||
"--warning-border": "color",
|
||||
"--error": "color",
|
||||
"--error-text": "font",
|
||||
"--error-bg": "color",
|
||||
"--error-border": "color",
|
||||
"--info": "color",
|
||||
"--ai": "color",
|
||||
"--ai-light": "color",
|
||||
"--ai-lighter": "color",
|
||||
"--ai-bg": "color",
|
||||
"--human": "color",
|
||||
"--channel-max": "color",
|
||||
"--channel-max-bg": "color",
|
||||
"--channel-telegram": "color",
|
||||
"--channel-telegram-bg": "color",
|
||||
"--channel-webchat": "color",
|
||||
"--channel-webchat-bg": "color",
|
||||
"--product-firepage": "color",
|
||||
"--product-firepage-bg": "color",
|
||||
"--product-foxray": "color",
|
||||
"--product-foxray-bg": "color",
|
||||
"--surface-page": "color",
|
||||
"--surface-card": "color",
|
||||
"--surface-sunken": "color",
|
||||
"--surface-chip": "color",
|
||||
"--text-heading": "font",
|
||||
"--text-body": "font",
|
||||
"--text-secondary": "font",
|
||||
"--text-tertiary": "font",
|
||||
"--text-disabled": "font",
|
||||
"--text-inverse": "font",
|
||||
"--text-link": "font",
|
||||
"--border-default": "color",
|
||||
"--border-input": "color",
|
||||
"--border-strong": "color",
|
||||
"--font-sans": "font",
|
||||
"--font-mono": "font",
|
||||
"--text-2xl": "font",
|
||||
"--text-xl": "font",
|
||||
"--text-lg": "font",
|
||||
"--text-md": "font",
|
||||
"--text-base-lg": "font",
|
||||
"--text-base": "font",
|
||||
"--text-sm-lg": "font",
|
||||
"--text-sm": "font",
|
||||
"--text-sm-tight": "font",
|
||||
"--text-xs": "font",
|
||||
"--text-xs-tight": "font",
|
||||
"--text-2xs": "font",
|
||||
"--text-2xs-tight": "font",
|
||||
"--weight-regular": "font",
|
||||
"--weight-medium": "font",
|
||||
"--weight-semibold": "font",
|
||||
"--weight-bold": "font",
|
||||
"--weight-black": "font",
|
||||
"--tracking-tight": "font",
|
||||
"--tracking-tight-sm": "font",
|
||||
"--tracking-wide": "font",
|
||||
"--tracking-wider": "font",
|
||||
"--leading-tight": "font",
|
||||
"--leading-snug": "font",
|
||||
"--leading-normal": "font",
|
||||
"--leading-relaxed": "font",
|
||||
"--leading-loose": "font",
|
||||
"--space-1": "spacing",
|
||||
"--space-2": "spacing",
|
||||
"--space-3": "spacing",
|
||||
"--space-4": "spacing",
|
||||
"--space-5": "spacing",
|
||||
"--space-6": "spacing",
|
||||
"--space-7": "spacing",
|
||||
"--space-8": "spacing",
|
||||
"--space-9": "spacing",
|
||||
"--space-10": "spacing",
|
||||
"--space-11": "spacing",
|
||||
"--space-12": "spacing",
|
||||
"--space-13": "spacing",
|
||||
"--space-14": "spacing",
|
||||
"--space-15": "spacing",
|
||||
"--space-16": "spacing",
|
||||
"--space-17": "spacing",
|
||||
"--h-control-sm": "spacing",
|
||||
"--h-control-md": "spacing",
|
||||
"--h-control": "spacing",
|
||||
"--h-control-lg": "spacing",
|
||||
"--h-control-xl": "spacing",
|
||||
"--h-control-2xl": "spacing",
|
||||
"--h-topbar": "spacing",
|
||||
"--sidebar-width": "spacing",
|
||||
"--content-max": "spacing",
|
||||
"--radius-xs": "radius",
|
||||
"--radius-sm": "radius",
|
||||
"--radius-md": "radius",
|
||||
"--radius-lg": "radius",
|
||||
"--radius-xl": "radius",
|
||||
"--radius-2xl": "radius",
|
||||
"--radius-3xl": "radius",
|
||||
"--radius-4xl": "radius",
|
||||
"--radius-pill": "radius",
|
||||
"--radius-circle": "radius",
|
||||
"--shadow-xs": "shadow",
|
||||
"--shadow-sm": "shadow",
|
||||
"--shadow-md": "shadow",
|
||||
"--shadow-lg": "shadow",
|
||||
"--shadow-sticky": "shadow",
|
||||
"--shadow-primary": "shadow",
|
||||
"--ease-standard": "other",
|
||||
"--duration-fast": "other",
|
||||
"--duration-base": "other"
|
||||
},
|
||||
"fontFamilies": []
|
||||
}
|
||||
}
|
||||
-3489
File diff suppressed because it is too large.
Load diff
-1
@@ -1 +0,0 @@
|
||||
{"namespace":"EdevsHubDesignSystem_e4c9df","components":[{"name":"CommerceStatusTimeline","sourcePath":"components/cards/CommerceStatusTimeline.jsx"},{"name":"DepartmentCard","sourcePath":"components/cards/DepartmentCard.jsx"},{"name":"IntegrationHealthCard","sourcePath":"components/cards/IntegrationHealthCard.jsx"},{"name":"MetricCard","sourcePath":"components/cards/MetricCard.jsx"},{"name":"ProductAIReleaseCard","sourcePath":"components/cards/ProductAIReleaseCard.jsx"},{"name":"Avatar","sourcePath":"components/core/Avatar.jsx"},{"name":"Button","sourcePath":"components/core/Button.jsx"},{"name":"Checkbox","sourcePath":"components/core/Checkbox.jsx"},{"name":"Icon","sourcePath":"components/core/Icon.jsx"},{"name":"ICON_NAMES","sourcePath":"components/core/Icon.jsx"},{"name":"IconButton","sourcePath":"components/core/IconButton.jsx"},{"name":"Input","sourcePath":"components/core/Input.jsx"},{"name":"Tag","sourcePath":"components/core/Tag.jsx"},{"name":"ConversationInbox","sourcePath":"components/inbox/ConversationInbox.jsx"},{"name":"KnowledgeDocumentEditor","sourcePath":"components/inbox/KnowledgeDocumentEditor.jsx"},{"name":"ActorBadge","sourcePath":"components/status/ActorBadge.jsx"},{"name":"AttentionStatus","sourcePath":"components/status/AttentionStatus.jsx"},{"name":"ChannelBadge","sourcePath":"components/status/ChannelBadge.jsx"}],"startingPoints":[{"name":"CommerceStatusTimeline","path":"components/cards/CommerceStatusTimeline.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Payment vs delivery step timeline for checkout/orders","viewport":"700x160"},{"name":"DepartmentCard","path":"components/cards/DepartmentCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Command Center department summary card","viewport":"900x360"},{"name":"IntegrationHealthCard","path":"components/cards/IntegrationHealthCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Single integration row (connected/degraded/error)","viewport":"700x90"},{"name":"MetricCard","path":"components/cards/MetricCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Single KPI cell for metric grids","viewport":"700x120"},{"name":"ProductAIReleaseCard","path":"components/cards/ProductAIReleaseCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"AI knowledge/prompt release snapshot for one product","viewport":"700x180"},{"name":"Button","path":"components/core/Button.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Primary/secondary/ghost/danger button","viewport":"700x220"},{"name":"IconButton","path":"components/core/IconButton.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Square icon-only button with optional badge","viewport":"700x150"},{"name":"Input","path":"components/core/Input.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Text field with label, icon and error state","viewport":"700x260"},{"name":"Tag","path":"components/core/Tag.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Status pill and rectangular label tag","viewport":"700x150"},{"name":"KnowledgeDocumentEditor","path":"components/inbox/KnowledgeDocumentEditor.jsx","previewPath":"components/inbox/inbox.card.html","kind":"component","section":"Inbox","subtitle":"Plain-text knowledge base document editor","viewport":"700x380"},{"name":"ActorBadge","path":"components/status/ActorBadge.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"AI vs human avatar for conversation timelines","viewport":"700x110"},{"name":"AttentionStatus","path":"components/status/AttentionStatus.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"Company/department health chip (ok/attention/critical)","viewport":"700x120"},{"name":"ChannelBadge","path":"components/status/ChannelBadge.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"MAX / Telegram / Web Chat channel chip","viewport":"700x100"}],"cards":[{"path":"guidelines/logo-mark.card.html","group":"Brand","viewport":"700x160","subtitle":"Only mark found in the codebase — a blue rounded square with a bar-chart glyph","name":"Logo Mark"},{"path":"guidelines/radii-shadows.card.html","group":"Brand","viewport":"700x180","subtitle":"Soft, low-opacity shadows only — no glassmorphism","name":"Radii & Shadows"},{"path":"ui_kits/checkout/index.html","group":"Checkout","viewport":"440x760"},{"path":"guidelines/colors-ai-channels.card.html","group":"Colors","viewport":"700x160","subtitle":"AI/human split, MAX/Telegram/Web ChLine truncated
|
||||
-216
@@ -1,216 +0,0 @@
|
||||
# Edevs Hub — Design System
|
||||
|
||||
Design system for **Edevs**, a Russian product IT company (`edevs.tech`) that builds applied
|
||||
digital products for narrow professional niches — currently **FoxRay** (cephalometric/TRG
|
||||
analysis for orthodontists) and **FirePage** (ready-made niche websites on a proprietary CMS,
|
||||
sold as a one-time license). This design system, however, documents **Edevs Hub**
|
||||
(`hub.edevs.tech`) — the internal company platform that runs sales, support, AI agents, and
|
||||
commerce for those products, plus the two small public-facing surfaces it exposes (Web Chat
|
||||
widget and Checkout).
|
||||
|
||||
## Sources
|
||||
|
||||
Everything here was extracted from the attached codebase, mounted read-only at
|
||||
`hub.edevs.tech/`:
|
||||
|
||||
- `hub.edevs.tech/design/baseline/*.dc.html` — the team's own **approved HTML visual baseline**
|
||||
(explicitly the canonical design source per `SPEC-HUB-0007`, section 3: *"Утверждённые
|
||||
дизайн-файлы размещаются только в едином каноническом каталоге:
|
||||
`code/hub.edevs.tech/design/baseline/`"*). ~35 screens covering Command Center, Sales
|
||||
(overview/clients/dialogs/orders), Departments, Employees, Products, AI agents (list/create/
|
||||
detail/knowledge), Integrations, Settings, Auth, the Web Chat widget, and the Checkout flow.
|
||||
- `hub.edevs.tech/design/baseline/uploads/ADR-HUB-0013-Internal-UI-Design-System.md` — the
|
||||
Internal Hub UI design-system decision record (Ant Design + Ant Design X + "Edevs Hub Theme").
|
||||
- `hub.edevs.tech/design/baseline/uploads/SPEC-HUB-0007-Checkout-UI.md` — the public checkout
|
||||
interface spec (`pay.hub.edevs.tech`).
|
||||
- `hub.edevs.tech/design/baseline/uploads/SPEC-HUB-0003-Web-Chat.md`,
|
||||
`SPEC-HUB-0004-Internal-Hub-UI.md`, `SPEC-HUB-0005-Implemented-Internal-UI-Baseline.md`,
|
||||
`SPEC-HUB-0001-First-Iteration.md`, `ADR-HUB-0017-AI-Agent-Configuration-UX.md` — supporting
|
||||
specs referenced but not individually quoted below.
|
||||
- `hub.edevs.tech/packages/ui/src/theme.ts` — the actual Ant Design `ThemeConfig` ("Edevs Hub
|
||||
Theme") used by the Internal UI: primary color, radii, per-component overrides.
|
||||
`hub.edevs.tech/apps/internal-ui/src/styles/base.css` — global resets.
|
||||
- `hub.edevs.tech/apps/internal-ui/public/favicon.svg` — the one brand mark present in the repo.
|
||||
- `hub.edevs.tech/content/ai-content-company-filled.md` — the AI agent's system/persona prompts
|
||||
for the main company site, used for the Content Fundamentals section below.
|
||||
- `hub.edevs.tech/apps/checkout` and `hub.edevs.tech/apps/web-chat` — app shells for the public
|
||||
surfaces (the checkout app has no implementation yet; the design baseline is ground truth for
|
||||
both).
|
||||
|
||||
No Figma file or link was provided for this project — the HTML baseline above is the sole
|
||||
design source, and per the team's own spec it *is* the canonical one.
|
||||
|
||||
## Products in scope
|
||||
|
||||
1. **Internal Hub** (`hub.edevs.tech`, `apps/internal-ui`) — the OWNER/OPERATOR back office:
|
||||
Command Center, Departments, Employees, Products, Sales workspace (overview, clients,
|
||||
dialogs, orders), AI agents & knowledge, Integrations, Settings, Auth. Built on Ant Design +
|
||||
Ant Design X, desktop-first (1024px+, designed for 1440px).
|
||||
2. **Web Chat** (`apps/web-chat`) — the embeddable public support/sales chat widget for
|
||||
products like FoxRay, handling AI, human handoff, and inline checkout cards.
|
||||
3. **Checkout** (`apps/checkout`, `pay.hub.edevs.tech`) — the public, mobile-first purchase flow
|
||||
that hands off to Bank Tochka for payment and separately tracks payment vs. product delivery.
|
||||
|
||||
## Index
|
||||
|
||||
- `styles.css` — root stylesheet, imports everything under `tokens/`.
|
||||
- `tokens/colors.css`, `typography.css`, `spacing.css`, `effects.css` — design tokens.
|
||||
- `assets/logo-mark.svg`, `favicon.svg` — the one brand mark found in the codebase.
|
||||
- `components/core/` — Button, IconButton, Input, Checkbox, Tag, Avatar, Icon (intentional
|
||||
additions — see below).
|
||||
- `components/status/` — AttentionStatus, ActorBadge, ChannelBadge.
|
||||
- `components/cards/` — MetricCard, DepartmentCard, IntegrationHealthCard,
|
||||
ProductAIReleaseCard, CommerceStatusTimeline.
|
||||
- `components/inbox/` — ConversationInbox, KnowledgeDocumentEditor.
|
||||
- `guidelines/` — foundation specimen cards (Colors, Type, Spacing, Brand).
|
||||
- `ui_kits/internal-hub/` — Auth → Command Center → Sales · Clients, clickable.
|
||||
- `ui_kits/web-chat/` — the embeddable chat widget, all 5 states.
|
||||
- `ui_kits/checkout/` — the public checkout flow, all 8 states.
|
||||
|
||||
## Components
|
||||
|
||||
Full list (16), grouped by directory:
|
||||
|
||||
- **Core** (intentional additions, see below): `Button`, `IconButton`, `Input`, `Checkbox`,
|
||||
`Tag`, `Avatar`, `Icon`.
|
||||
- **Status** (from ADR-HUB-0013's local-component list): `AttentionStatus`, `ActorBadge`,
|
||||
`ChannelBadge`.
|
||||
- **Cards** (from ADR-HUB-0013): `MetricCard`, `DepartmentCard`, `IntegrationHealthCard`,
|
||||
`ProductAIReleaseCard`, `CommerceStatusTimeline`.
|
||||
- **Inbox** (from ADR-HUB-0013): `ConversationInbox`, `KnowledgeDocumentEditor`.
|
||||
|
||||
### Intentional additions
|
||||
|
||||
ADR-HUB-0013 states the Internal Hub is built on **Ant Design + Ant Design X**, with only ten
|
||||
named local composite components on top (listed under "Status/Cards/Inbox" above — built
|
||||
exactly as named). Ant Design itself isn't installable in this static-HTML environment, so to
|
||||
make the UI kits and composite components actually renderable, this system also includes a
|
||||
small set of Ant-Design-styled primitives that the ADR assumes but doesn't name:
|
||||
`Button`, `IconButton`, `Input`, `Checkbox`, `Tag`, `Avatar`, `Icon`. Their visuals (radii,
|
||||
heights, colors) are copied exactly from the approved HTML baseline, not invented — treat them
|
||||
as a faithful stand-in for the real Ant Design instance, not a design decision of their own.
|
||||
|
||||
## Content fundamentals
|
||||
|
||||
Drawn from the AI agent system prompts (`content/ai-content-company-filled.md`) and the copy
|
||||
throughout the baseline screens (Russian-language product, primary audience is Russian).
|
||||
|
||||
- **Language & register:** Russian, informal-but-respectful "вы" register — direct, calm,
|
||||
no hard-sell. The agent prompt is explicit: "Пиши как нормальный человек в мессенджере. Не как объявление, не как пресс-релиз и не как робот, который сразу вываливает всю информацию."
|
||||
- **Tone:** short, human paragraphs, answer the actual question first, then suggest a next
|
||||
step: "Отвечай по сути вопроса, короткими живыми абзацами." and "Не дави на покупку. Главная задача общего агента — правильно понять потребность и направить человека туда, где он быстрее получит пользу."
|
||||
- **Formatting discipline:** no markdown inside chat replies — "Не используй markdown-разметку внутри ответа: не ставь заголовки, списки с маркерами, жирный текст, таблицы и разделители." UI copy elsewhere (Hub, checkout) mirrors this: plain sentences, no bullet-heavy microcopy.
|
||||
- **Emoji:** rare and situational, never decorative — "Уместные смайлики допустимы, но редко и по ситуации." No emoji appear anywhere in the Hub, Web Chat or Checkout baseline screens.
|
||||
- **Cultural register:** "Учитывай российский контекст общения: уважительно, прямо, без давления и без чрезмерной рекламности."
|
||||
- **Honesty/scope discipline:** never invent facts, prices, or promises outside the knowledge
|
||||
base — "Если данных не хватает, не выдумывай. Скажи, что этот момент лучше уточнить у специалиста, и передай оператору." and pricing/legal specifics always come from the server, never the client: see Checkout spec §16 ("не доверять цене и составу из состояния браузера").
|
||||
- **Handoff phrasing:** warm, not robotic, when passing to a human — "При передаче не отвечай сухо. Напиши по-человечески: понял задачу, здесь лучше подключить специалиста, передаю вопрос."
|
||||
- **UI microcopy style (from the baseline):** short declarative status lines ("Готовим оплату",
|
||||
"Оплата получена", "Требует внимания"), technical IDs always in monospace, money always as
|
||||
`₽95 040` (₽ prefix, space thousands separator, no decimals for round sums).
|
||||
- **Domains:** only `edevs.tech` is the confirmed public site; `edevs.ru` is explicitly
|
||||
forbidden in agent replies.
|
||||
|
||||
## Visual foundations
|
||||
|
||||
- **Overall direction (ADR-HUB-0013):** *"светлая тема; премиальный минимализм; высокая, но
|
||||
контролируемая информационная плотность; спокойная нейтральная основа; один основной
|
||||
акцентный цвет; цвет используется прежде всего для статусов и действий; минимум декоративных
|
||||
элементов; отсутствие градиентов, стекломорфизма, неоновых эффектов и визуального шума;
|
||||
desktop-first."* (light theme, premium minimalism, one accent color, color reserved for
|
||||
status/action, no gradients/glassmorphism/neon, desktop-first for the internal Hub).
|
||||
- **Color:** one accent, `#1677ff` (Ant Design blue-6) with a `#0958d9` hover/active shade.
|
||||
Semantic tokens are mandatory and separate from the accent: success/warning/error/info, plus
|
||||
two Hub-specific roles — `ai` (purple, `#722ed1`) vs `human` (blue, same as primary) — and a
|
||||
`channel-*` family (MAX purple, Telegram blue, Web Chat teal) used sparingly so multi-channel
|
||||
screens don't turn into "a colorful mosaic" (ADR wording). Status color is never the sole
|
||||
signal — always paired with text and, in tables, an icon or label.
|
||||
- **Type:** system font stack only — no bespoke webfont is loaded
|
||||
(`-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif`).
|
||||
Technical identifiers (order/release/event IDs, emails, obscured phone numbers) switch to a
|
||||
monospace stack. Headings use tight letter-spacing (−0.01 to −0.02em); table headers use wide
|
||||
spacing (+0.03 to +0.06em) with all-caps and a muted gray.
|
||||
Sizes are exact pixel values pulled from the baseline (26/24/20/18/16/14.5/13.5/13/12.5/12/
|
||||
11/10.5px) — not snapped to a 4/8 grid.
|
||||
- **Spacing / density:** "compact enterprise" density is an explicit rule — *"большие пустые
|
||||
поля и oversized-карточки запрещены"*. Padding values are odd/precise (9px, 11px, 13px, 14px,
|
||||
18px…), not rounded. Control heights: 30/34/36/42/44/48px; topbar is a fixed 56px.
|
||||
- **Backgrounds:** flat solid colors only. Page background `#f0f2f5`, card surfaces pure white.
|
||||
No photography, no illustrations, no repeating patterns/textures, no gradients anywhere
|
||||
(buttons, cards, banners are all flat fills). The one "textured" pattern in the system is the
|
||||
1px-gap metric grid (white cells on a `#f0f0f0` background, forming hairline dividers) — see
|
||||
the Spacing → "Metric Grid In Use" card.
|
||||
- **Corners:** 7–9px on controls/inputs, 8–9px on buttons, 10–14px on cards/modals, full pill
|
||||
on chips/segmented controls, circle on avatars.
|
||||
- **Cards:** white surface, 1px `#f0f0f0` border, soft shadow (`0 1px 3px rgba(0,0,0,.04)`),
|
||||
12px radius as the default; no colored left-border accent except the Command Center's status
|
||||
banner (a deliberate, singular exception tied to company health, not a general card pattern).
|
||||
- **Shadows:** shallow and near-neutral throughout — hairline (`0 1px 2px rgba(0,0,0,.03)`),
|
||||
card (`0 1px 3px rgba(0,0,0,.04)`), modal (`0 2px 12px rgba(0,0,0,.05)`), dropdown
|
||||
(`0 6px 20px rgba(0,0,0,.12)`). The one colored shadow is the primary button's blue-tinted
|
||||
`0 1px 2px rgba(22,119,255,.3)`, used to make the single CTA per screen pop slightly.
|
||||
- **Animation:** minimal and functional only — a 3-dot typing indicator (`hub-typing`, opacity/
|
||||
translateY loop), a spinner (`hub-spin`, rotate) for loading states, and a slow opacity pulse
|
||||
(`hub-pulse`) for "in progress" states (e.g. delivering a purchased product). No entrance
|
||||
animations, bounces, or parallax anywhere in the baseline.
|
||||
- **Hover states:** buttons/links darken (primary `#1677ff → #0958d9`); neutral surfaces get a
|
||||
light gray fill (`transparent → #f5f5f5`) on hover; secondary buttons swap border+text to the
|
||||
accent color on hover. No lightening-on-hover pattern is used.
|
||||
**Press/active states:** not distinctly styled in the baseline (no scale/shrink pattern
|
||||
observed) — treat hover as the primary interactive affordance; focus-visible gets a solid
|
||||
2px accent outline (see `apps/internal-ui/src/styles/base.css`).
|
||||
**Disabled:** 55% opacity + `cursor: not-allowed`.
|
||||
**Focus:** border-color changes to the accent (inputs) or a visible 2px outline (buttons) —
|
||||
never a glow/box-shadow ring.
|
||||
- **Borders:** hairline `#f0f0f0` almost everywhere (card edges, table row dividers, header
|
||||
separators); slightly stronger `#d9d9d9`/`#e8e8e8` on interactive control outlines
|
||||
(buttons, inputs) so they read as tappable against the flat background.
|
||||
- **Transparency & blur:** no blur/glassmorphism anywhere. The only translucent surfaces are
|
||||
the Web Chat header's icon buttons (`rgba(255,255,255,0.14–0.26)` over the solid blue header)
|
||||
and a full-viewport `position:fixed` transparent scrim used to close open dropdowns/menus.
|
||||
- **Imagery:** none — the product is data/status-dense enterprise software and transactional
|
||||
flows, not marketing pages. No photography, no hand-drawn illustrations, no generic stock
|
||||
imagery anywhere in the baseline; nothing to copy in for that reason.
|
||||
- **Layout rules:** Internal Hub is a fixed sidebar (≈248px) + topbar (56px) + scrollable
|
||||
content shell, min-width 1024–1180px depending on screen, content capped at 1200–1340px and
|
||||
centered. Web Chat and Checkout are separate, chrome-free, mobile-first single-column flows
|
||||
with no sidebar/topbar — explicitly not governed by the Internal Hub's layout rules
|
||||
(SPEC-HUB-0007 §4).
|
||||
|
||||
## Iconography
|
||||
|
||||
- **System:** hand-authored inline SVG, Feather/Lucide-style stroke icons (round caps/joins,
|
||||
1.7–2.2px stroke, 24×24 viewBox) — every baseline screen inlines its own `<svg>` rather than
|
||||
referencing a shared font or sprite sheet, so there is no icon font or `.svg` sprite file in
|
||||
the repo to copy wholesale. This design system's `Icon` component (`components/core/Icon.jsx`)
|
||||
collects the ~35 recurring glyphs actually used across the baseline (nav icons, status icons,
|
||||
form icons, payment icons) into one reusable primitive with the *exact* path data copied from
|
||||
the source screens — nothing was redrawn from imagination.
|
||||
- **Emoji:** never used anywhere in the product UI (only "rarely, situationally" in AI chat
|
||||
replies per the content guidelines above).
|
||||
**Unicode-as-icon:** limited to pagination chevrons (`‹ › …`) in table footers.
|
||||
- **Color:** icons are almost always `currentColor`/neutral gray (`#8c8c8c`/`#595959`), tinted
|
||||
to the semantic/accent color only when they sit inside a status chip or colored icon tile
|
||||
(e.g. a purple AI bolt icon on a light-purple tile).
|
||||
|
||||
## Caveats & where I need your help
|
||||
|
||||
1. **No Figma was attached** — everything above comes from the approved HTML baseline in
|
||||
`design/baseline/`, which the team's own spec names as canonical. If a Figma file exists,
|
||||
attach it and I can cross-check/tighten values.
|
||||
2. **No FoxRay/FirePage brand assets** — this system only covers Edevs Hub (the internal
|
||||
platform + its two public surfaces). FoxRay/Foxray and FirePage are referenced only as
|
||||
*product tags* inside Hub (colored labels, no logos). If you want their actual product UI
|
||||
or marks in this system, please attach their codebases/design files.
|
||||
3. **No logo beyond the one favicon mark** — I did not draw one. If Edevs has a real wordmark
|
||||
or icon set beyond `favicon.svg`, please attach it and I'll swap it in everywhere.
|
||||
4. **Ant Design isn't literally bundled** — see "Intentional additions" above; I built
|
||||
faithful lightweight stand-ins instead of pulling in the real library, since only static
|
||||
HTML/JS/CSS work in this environment.
|
||||
5. **Internal Hub UI kit covers 2 of many screens** (Command Center + Sales · Clients, behind a
|
||||
working Auth gate) rather than all ~35 baseline screens — tell me which screens matter most
|
||||
(Departments, AI agents, Orders, Settings…) and I'll extend the kit.
|
||||
|
||||
**Ask:** tell me which of the ~35 baseline screens to turn into additional UI-kit pages next,
|
||||
and whether the Ant-Design-styled primitives above should stay as lightweight stand-ins or be
|
||||
swapped for real `antd` components if this ever moves into a real build environment.
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
@import "./tokens/colors.css";
|
||||
@import "./tokens/typography.css";
|
||||
@import "./tokens/spacing.css";
|
||||
@import "./tokens/effects.css";
|
||||
@@ -1,4 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1386 1386" fill="none">
|
||||
<rect width="1386" height="1386" rx="300" fill="#1677FF"></rect>
|
||||
<path d="M691.947 175C743.896 176.004 775.161 202.368 793.419 230.289C802.544 244.243 808.421 258.585 812.018 270.347C815.61 282.096 816.938 291.306 816.938 295.001C816.938 309.524 816.93 372.653 744.438 407.813V460.002H904.938V540.99L904.45 541.002L744.445 544.989L749.937 882.48C749.937 882.489 749.939 882.5 749.94 882.514C749.944 882.549 749.949 882.602 749.955 882.672C749.968 882.812 749.988 883.021 750.016 883.295C750.071 883.842 750.157 884.648 750.278 885.681C750.521 887.746 750.905 890.716 751.471 894.334C752.601 901.571 754.457 911.395 757.356 921.745C760.257 932.098 764.196 942.963 769.489 952.29C774.619 961.33 780.998 968.885 788.895 973.156L789.664 973.56L789.699 973.577L789.731 973.601C793.751 976.524 799.835 978.199 806.771 979.04C813.693 979.879 821.395 979.88 828.599 979.506C835.8 979.132 842.489 978.384 847.379 977.729C849.823 977.401 851.817 977.097 853.199 976.875C853.89 976.764 854.428 976.673 854.793 976.61C854.975 976.579 855.115 976.555 855.208 976.538C855.255 976.53 855.29 976.524 855.313 976.52C855.323 976.518 855.33 976.516 855.336 976.515C855.345 976.512 855.36 976.509 855.379 976.505C855.418 976.495 855.477 976.481 855.556 976.461C855.713 976.421 855.948 976.36 856.258 976.276C856.878 976.109 857.797 975.851 858.986 975.491C861.365 974.771 864.827 973.639 869.151 971.999C877.801 968.719 889.899 963.401 903.684 955.262C931.141 939.048 965.281 911.632 992.18 866.791C981.29 863.394 967.013 860.713 955.359 858.873C949.428 857.937 944.183 857.218 940.421 856.734C938.54 856.492 937.03 856.309 935.99 856.187C935.471 856.125 935.069 856.079 934.797 856.048C934.661 856.032 934.557 856.02 934.487 856.013C934.453 856.009 934.427 856.006 934.409 856.004C934.401 856.003 934.394 856.002 934.39 856.002C934.388 856.002 934.386 856.002 934.385 856.002L934.384 856.001H934.383L933.401 855.894L934.069 855.166L1073.57 703.165L1074.13 702.559L1074.41 703.333C1090.68 748.154 1096.94 802.964 1099.12 846.542C1100.22 868.336 1100.3 887.331 1100.1 900.879C1100 907.653 1099.84 913.065 1099.7 916.784C1099.63 918.644 1099.56 920.081 1099.51 921.053C1099.49 921.539 1099.47 921.909 1099.46 922.157C1099.45 922.282 1099.45 922.376 1099.44 922.438C1099.44 922.47 1099.44 922.494 1099.44 922.51C1099.44 922.517 1099.44 922.523 1099.44 922.527C1099.44 922.529 1099.44 922.531 1099.44 922.532C1099.43 922.533 1099.39 922.531 1098.94 922.505L1099.44 922.534L1099.39 923.361L1098.68 922.933L1048.66 892.726C1003.9 993.99 945.911 1044.08 883.83 1083.43C821.626 1122.85 755.486 1151.41 694.283 1209.87L693.948 1210.19L693.604 1209.88C626.889 1149.91 559.114 1118.72 497.414 1078.36C435.832 1038.08 380.46 988.73 338.686 892.68C328.31 897.648 315.933 905.371 306.086 911.902C301.091 915.215 296.752 918.217 293.662 920.391C292.117 921.478 290.883 922.358 290.037 922.966C289.614 923.269 289.288 923.505 289.067 923.665C288.957 923.745 288.874 923.806 288.817 923.847C288.789 923.867 288.768 923.883 288.754 923.894C288.747 923.899 288.741 923.903 288.737 923.905C288.736 923.906 288.734 923.907 288.733 923.907L288.732 923.908L288.048 924.408L287.941 923.567L288.438 923.505C287.942 923.568 287.942 923.567 287.941 923.566C287.941 923.566 287.941 923.564 287.94 923.562C287.94 923.559 287.94 923.555 287.939 923.549C287.938 923.537 287.936 923.518 287.933 923.494C287.927 923.446 287.918 923.373 287.906 923.277C287.884 923.086 287.851 922.8 287.81 922.424C287.727 921.67 287.611 920.551 287.478 919.085C287.21 916.153 286.872 911.834 286.587 906.28C286.016 895.173 285.656 879.126 286.5 859.358C288.189 819.824 294.695 765.402 313.962 705.85L314.224 705.041L314.803 705.662L455.303 856.163L455.976 856.884L454.997 857.001L397.147 863.923C397.186 864.016 397.228 864.119 397.276 864.232C397.53 864.832 397.917 865.718 398.445 866.858C399.502 869.139 401.127 872.437 403.397 876.495C407.939 884.612 415.061 895.773 425.381 907.932C446.013 932.242 479.425 960.545 530.546 976.515C553.481 979.493 570.422 978.743 581.621 977.252C587.224 976.506 591.391 975.575 594.151 974.832C595.531 974.461 596.561 974.137 597.242 973.906C597.583 973.791 597.836 973.699 598.004 973.637C598.088 973.606 598.151 973.581 598.191 973.565C598.211 973.558 598.227 973.552 598.236 973.548C598.241 973.546 598.244 973.544 598.246 973.543C598.249 973.542 598.254 973.54 598.26 973.537C598.274 973.531 598.297 973.521 598.326 973.508C598.386 973.48 598.477 973.436 598.598 973.376C598.839 973.256 599.199 973.068 599.661 972.8C600.586 972.264 601.923 971.408 603.553 970.142C606.812 967.608 611.246 963.425 615.904 956.842C625.218 943.678 635.442 920.895 638.938 882.477L642.432 544.989L482.925 541.002L482.438 540.99V460.002H642.483C642.506 459.763 642.536 459.433 642.572 459.019C642.654 458.09 642.768 456.741 642.895 455.058C643.147 451.691 643.45 446.988 643.652 441.648C644.054 431.045 644.053 417.961 642.48 407.824C603.762 387.517 586.111 359.35 578.152 336.227C574.167 324.647 572.613 314.338 572.056 306.921C571.777 303.212 571.748 300.226 571.788 298.164C571.808 297.133 571.846 296.333 571Line truncated
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 5.8 KiB |
File diff suppressed because it is too large.
Load diff
@@ -1,609 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="./support.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<meta name="design_doc_mode" content="canvas">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/colors.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/typography.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/spacing.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/effects.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/styles.css">
|
||||
<script src="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/_ds_bundle.js"></script>
|
||||
<style>
|
||||
* { box-sizing: border-box; }
|
||||
body { margin: 0; background: #e9ebee; }
|
||||
a { color: var(--primary); text-decoration: none; }
|
||||
a:hover { color: var(--primary-hover); }
|
||||
.ch-scroll::-webkit-scrollbar { width: 10px; height: 10px; }
|
||||
.ch-scroll::-webkit-scrollbar-thumb { background: #d0d3d8; border-radius: 8px; border: 3px solid transparent; background-clip: content-box; }
|
||||
</style>
|
||||
</helmet>
|
||||
|
||||
<div style="font-family: var(--font-sans); color: var(--text-body); padding: 40px 48px 80px; min-width: 1480px; display: flex; flex-direction: column; gap: 40px;">
|
||||
|
||||
<!-- DOC HEADER -->
|
||||
<div style="max-width: 1340px;">
|
||||
<div style="display: inline-flex; align-items: center; gap: 8px; padding: 4px 11px; border-radius: var(--radius-pill); background: var(--ai-bg); color: var(--ai); font-size: 11px; font-weight: 600; letter-spacing: 0.04em; margin-bottom: 14px;">
|
||||
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
|
||||
DG-02 · DESIGN BASELINE
|
||||
</div>
|
||||
<h1 style="margin: 0 0 8px; font-size: 26px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading);">Каналы обработки — канал как объект управления</h1>
|
||||
<p style="margin: 0; font-size: 14px; line-height: 1.55; color: var(--text-secondary); max-width: 860px;">Утверждаемый макет раздела <b>Компания → Каналы</b> по SPEC-HUB-0027 / ADR-HUB-0037: список с фильтрами и меню строки, карточка канала одной страницей (без вкладок), секции «Политика» и «Подключения», мастер создания из трёх шагов, служебные состояния. Настройка агента и знания остаются в разделе AI и в этот baseline не входят. Терминология: MAX / TG / Web — это <b>подключения</b>; «канал» — сущность маршрутизации. Все данные — примеры.</p>
|
||||
<div style="display: flex; gap: 8px; margin-top: 14px; flex-wrap: wrap;">
|
||||
<a href="#A" style="font-size: 12.5px; padding: 5px 12px; border: 1px solid var(--n-6); border-radius: var(--radius-pill); background: #fff;">A · Список</a>
|
||||
<a href="#B" style="font-size: 12.5px; padding: 5px 12px; border: 1px solid var(--n-6); border-radius: var(--radius-pill); background: #fff;">B · Карточка</a>
|
||||
<a href="#C" style="font-size: 12.5px; padding: 5px 12px; border: 1px solid var(--n-6); border-radius: var(--radius-pill); background: #fff;">C · Политика</a>
|
||||
<a href="#D" style="font-size: 12.5px; padding: 5px 12px; border: 1px solid var(--n-6); border-radius: var(--radius-pill); background: #fff;">D · Подключения</a>
|
||||
<a href="#E" style="font-size: 12.5px; padding: 5px 12px; border: 1px solid var(--n-6); border-radius: var(--radius-pill); background: #fff;">E · Мастер</a>
|
||||
<a href="#S" style="font-size: 12.5px; padding: 5px 12px; border: 1px solid var(--n-6); border-radius: var(--radius-pill); background: #fff;">S · Состояния</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ============ FRAME A — LIST (FULL SHELL) ============ -->
|
||||
<section id="A" style="display: flex; flex-direction: column; gap: 12px;">
|
||||
<div style="display: flex; align-items: baseline; gap: 12px;">
|
||||
<span style="font-size: 12px; font-weight: 700; color: #fff; background: var(--text-heading); padding: 3px 9px; border-radius: 6px;">A</span>
|
||||
<h2 style="margin: 0; font-size: 17px; font-weight: 600; color: var(--text-heading);">Список каналов — основной вид</h2>
|
||||
<span style="font-size: 12.5px; color: var(--text-tertiary);">фильтры по отделу · поиск и архивные · плотная таблица · меню строки</span>
|
||||
</div>
|
||||
|
||||
<div style="width: 1340px; height: 880px; background: var(--surface-page); border: 1px solid var(--n-6); border-radius: var(--radius-2xl); box-shadow: var(--shadow-md); overflow: hidden; display: flex;">
|
||||
<!-- SIDEBAR -->
|
||||
<aside style="width: 248px; flex: none; background: #fff; border-right: 1px solid var(--n-8); display: flex; flex-direction: column;">
|
||||
<div style="height: 56px; flex: none; display: flex; align-items: center; gap: 11px; padding: 0 20px; border-bottom: 1px solid var(--n-9);">
|
||||
<img src="assets/custocrm-mark.svg" alt="CustoCRM" style="width: 30px; height: 30px; border-radius: 8px; flex: none;">
|
||||
<div style="display: flex; flex-direction: column; line-height: 1.15;">
|
||||
<span style="font-size: 14px; font-weight: 600; color: var(--text-heading); letter-spacing: -0.01em;">CustoCRM</span>
|
||||
<span style="font-size: 11px; color: var(--text-tertiary);">Управление компанией</span>
|
||||
</div>
|
||||
</div>
|
||||
<nav style="flex: 1; overflow-y: auto; padding: 12px 12px 8px;">
|
||||
<a href="#A" style="display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 8px; margin-bottom: 2px; font-size: 13.5px; font-weight: 500; color: var(--text-secondary);"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="9" rx="1.4"/><rect x="14" y="3" width="7" height="5" rx="1.4"/><rect x="14" y="12" width="7" height="9" rx="1.4"/><rect x="3" y="16" width="7" height="5" rx="1.4"/></svg>Обзор</a>
|
||||
<div style="font-size: 11px; font-weight: 600; letter-spacing: 0.06em; color: var(--n-5); padding: 14px 12px 6px;">КОМПАНИЯ</div>
|
||||
<a href="#A" style="display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 8px; margin-bottom: 2px; font-size: 13.5px; font-weight: 500; color: var(--text-secondary);"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21h18"/><path d="M5 21V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16"/><path d="M9 8h1.5M13.5 8H15M9 12h1.5M13.5 12H15M9 16h1.5M13.5 16H15"/></svg>Отделы</a>
|
||||
<a href="#A" style="display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 8px; margin-bottom: 2px; font-size: 13.5px; font-weight: 500; color: var(--text-secondary);"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>Сотрудники</a>
|
||||
<a href="#A" style="display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 8px; margin-bottom: 2px; font-size: 13.5px; font-weight: 500; color: var(--text-secondary);"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"/><path d="m3.3 7 8.7 5 8.7-5"/><path d="M12 22V12"/></svg>Продукты</a>
|
||||
<a href="#A" style="display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 8px; margin-bottom: 2px; position: relative; font-size: 13.5px; font-weight: 600; background: var(--primary-bg); color: #0958d9;"><span style="position: absolute; left: 0; top: 8px; bottom: 8px; width: 3px; border-radius: 0 3px 3px 0; background: var(--primary);"></span><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></svg>Каналы</a>
|
||||
<div style="font-size: 11px; font-weight: 600; letter-spacing: 0.06em; color: var(--n-5); padding: 14px 12px 6px;">ПЛАТФОРМА</div>
|
||||
<a href="#A" style="display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 8px; margin-bottom: 2px; font-size: 13.5px; font-weight: 500; color: var(--text-secondary);"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="8" width="16" height="12" rx="2.5"/><path d="M12 8V4.5"/><circle cx="12" cy="3.5" r="1.2"/><circle cx="9" cy="13.5" r="1"/><circle cx="15" cy="13.5" r="1"/></svg>AI</a>
|
||||
<div style="display: flex; flex-direction: column; padding: 2px 0 2px 30px; gap: 2px;">
|
||||
<a href="#A" style="padding: 6px 12px; border-radius: 7px; font-size: 13px; color: var(--text-secondary);">AI-агенты</a>
|
||||
<a href="#A" style="padding: 6px 12px; border-radius: 7px; font-size: 13px; color: var(--text-secondary);">Знания</a>
|
||||
<a href="#A" style="padding: 6px 12px; border-radius: 7px; font-size: 13px; color: var(--text-secondary);">Использование AI</a>
|
||||
</div>
|
||||
<a href="#A" style="display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 8px; margin-bottom: 2px; font-size: 13.5px; font-weight: 500; color: var(--text-secondary);"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 8V2.5M15 8V2.5M18 8v5.5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z"/><path d="M12 17.5V22"/></svg>Интеграции</a>
|
||||
</nav>
|
||||
<div style="flex: none; border-top: 1px solid var(--n-9); padding: 10px 12px;">
|
||||
<div style="display: flex; align-items: center; gap: 11px; padding: 8px 10px; border-radius: 8px;">
|
||||
<div style="width: 34px; height: 34px; border-radius: 50%; background: var(--ai-bg); color: var(--ai); display: flex; align-items: center; justify-content: center; font-weight: 600; font-size: 13px; flex: none;">ИП</div>
|
||||
<div style="display: flex; flex-direction: column; line-height: 1.2; flex: 1;">
|
||||
<span style="font-size: 13px; font-weight: 600;">Иван Петров</span>
|
||||
<span style="font-size: 11px; color: var(--text-tertiary);">OWNER</span>
|
||||
</div>
|
||||
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="var(--text-tertiary)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- MAIN -->
|
||||
<div style="flex: 1; min-width: 0; display: flex; flex-direction: column;">
|
||||
<header style="height: 56px; flex: none; background: #fff; border-bottom: 1px solid var(--n-8); display: flex; align-items: center; justify-content: space-between; padding: 0 24px;">
|
||||
<div style="display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-tertiary);">
|
||||
<span style="font-weight: 500; color: var(--text-secondary);">ООО «Эдевс»</span><span style="color: var(--n-6);">/</span>
|
||||
<span style="font-weight: 500; color: var(--text-secondary);">Компания</span><span style="color: var(--n-6);">/</span>
|
||||
<span style="font-weight: 600; color: var(--text-body);">Каналы</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 14px;">
|
||||
<div style="position: relative; width: 36px; height: 36px; border-radius: 8px; border: 1px solid var(--n-8); background: #fff; display: flex; align-items: center; justify-content: center; color: var(--text-secondary);"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg><b style="position: absolute; top: -5px; right: -5px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px; background: var(--error); color: #fff; font-size: 10px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 1.5px solid #fff;">3</b></div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="ch-scroll" style="flex: 1; overflow-y: auto; padding: 22px 26px 32px;">
|
||||
<!-- Page header -->
|
||||
<div style="display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; margin-bottom: 18px;">
|
||||
<div>
|
||||
<h1 style="margin: 0 0 4px; font-size: 24px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading);">Каналы</h1>
|
||||
<p style="margin: 0; font-size: 13.5px; color: var(--text-secondary);">Точка маршрутизации диалогов: связывает отдел, продукт, подключения и — необязательно — AI-агента</p>
|
||||
</div>
|
||||
<div style="display: flex; gap: 10px; flex: none;">
|
||||
<button style="display: inline-flex; align-items: center; gap: 7px; height: 36px; padding: 0 14px; border-radius: var(--radius-lg); border: 1px solid transparent; background: var(--primary); color: #fff; font-size: 13px; font-weight: 600; box-shadow: var(--shadow-primary); cursor: pointer;"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Создать канал</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter tabs (UnderlineTabs with count) + tools -->
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; gap: 16px; border-bottom: 1px solid var(--n-8); margin-bottom: 14px;">
|
||||
<div style="display: flex; gap: 4px;">
|
||||
<button style="display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 4px 0 4px; margin: 0 8px; border: none; background: none; border-bottom: 2px solid var(--primary); font-size: 13.5px; font-weight: 600; color: #0958d9; cursor: pointer;">Все<span style="font-size: 11px; font-weight: 600; color: #0958d9; background: var(--primary-bg); padding: 0 6px; border-radius: var(--radius-pill);">5</span></button>
|
||||
<button style="display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 4px; margin: 0 8px; border: none; background: none; border-bottom: 2px solid transparent; font-size: 13.5px; font-weight: 500; color: var(--text-secondary); cursor: pointer;">Продажи<span style="font-size: 11px; font-weight: 600; color: var(--text-tertiary); background: var(--n-9); padding: 0 6px; border-radius: var(--radius-pill);">2</span></button>
|
||||
<button style="display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 4px; margin: 0 8px; border: none; background: none; border-bottom: 2px solid transparent; font-size: 13.5px; font-weight: 500; color: var(--text-secondary); cursor: pointer;">Поддержка<span style="font-size: 11px; font-weight: 600; color: var(--text-tertiary); background: var(--n-9); padding: 0 6px; border-radius: var(--radius-pill);">1</span></button>
|
||||
<button style="display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 4px; margin: 0 8px; border: none; background: none; border-bottom: 2px solid transparent; font-size: 13.5px; font-weight: 500; color: var(--text-secondary); cursor: pointer;">Без отдела<span style="font-size: 11px; font-weight: 600; color: var(--text-tertiary); background: var(--n-9); padding: 0 6px; border-radius: var(--radius-pill);">1</span></button>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 10px; padding-bottom: 6px;">
|
||||
<div style="width: 240px; display: flex; align-items: center; gap: 9px; height: 34px; padding: 0 12px; border: 1px solid var(--border-input); border-radius: var(--radius-lg); background: #fff;">
|
||||
<svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="var(--text-tertiary)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
|
||||
<span style="flex: 1; font-size: 13px; color: var(--text-tertiary);">Поиск по имени и коду</span>
|
||||
</div>
|
||||
<label style="display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-secondary); cursor: pointer;">
|
||||
<span style="width: 34px; height: 20px; border-radius: var(--radius-pill); background: var(--n-6); position: relative; flex: none;"><span style="position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-xs);"></span></span>
|
||||
Показывать архивные
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Table card -->
|
||||
<div style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); overflow: visible;">
|
||||
<table style="width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px;">
|
||||
<thead>
|
||||
<tr style="background: var(--n-10); text-align: left;">
|
||||
<th style="padding: 10px 12px 10px 16px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary); border-top-left-radius: var(--radius-2xl);">КАНАЛ</th>
|
||||
<th style="padding: 10px 12px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary);">ПРОДУКТ</th>
|
||||
<th style="padding: 10px 12px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary);">ПОДКЛЮЧЕНИЯ</th>
|
||||
<th style="padding: 10px 12px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary);">AI-АГЕНТ</th>
|
||||
<th style="padding: 10px 12px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary); text-align: right;">ДИАЛОГИ</th>
|
||||
<th style="padding: 10px 16px 10px 12px; width: 44px; border-top-right-radius: var(--radius-2xl);"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Row 1 — product sales, agent active, row menu OPEN -->
|
||||
<tr style="border-top: 1px solid var(--n-8); cursor: pointer; position: relative;">
|
||||
<td style="padding: 12px 12px 12px 16px;"><a href="#B" style="font-weight: 600; color: var(--text-body);">FoxRay — продажи</a><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;"><span style="font-family: var(--font-mono);">foxray-sales</span> · Продажи</div></td>
|
||||
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 6px; padding: 2px 9px; border-radius: var(--radius-pill); background: var(--product-foxray-bg); font-size: 11.5px; font-weight: 600; color: var(--product-foxray);"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--product-foxray);"></span>FoxRay</span></td>
|
||||
<td style="padding: 12px;"><span style="display: inline-flex; gap: 5px;"><span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-telegram-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-telegram);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-telegram);">TG</span></span><span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-webchat-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-webchat);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-webchat);">Web</span></span></span></td>
|
||||
<td style="padding: 12px;"><div style="display: flex; flex-direction: column; align-items: flex-start; gap: 3px;"><a href="#" style="font-weight: 600; color: var(--primary);">FoxRay Sales</a><span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--success-text);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>Активен</span></div></td>
|
||||
<td style="padding: 12px; text-align: right; color: var(--text-body); font-variant-numeric: tabular-nums;">12</td>
|
||||
<td style="padding: 12px 16px 12px 12px; position: relative;">
|
||||
<span style="display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 7px; border: 1px solid var(--primary-border); background: var(--primary-bg); color: #0958d9;"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></svg></span>
|
||||
<!-- OPEN ROW MENU -->
|
||||
<div style="position: absolute; top: 44px; right: 16px; z-index: 5; width: 246px; background: #fff; border: 1px solid var(--n-7); border-radius: var(--radius-xl); box-shadow: var(--shadow-lg); padding: 6px; text-align: left;">
|
||||
<a href="#B" style="display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 7px; font-size: 13px; color: var(--text-body);"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/></svg>Открыть</a>
|
||||
<a href="#D" style="display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 7px; font-size: 13px; color: var(--text-body);"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 8V2.5M15 8V2.5M18 8v5.5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z"/><path d="M12 17.5V22"/></svg>Привязать подключение</a>
|
||||
<div style="height: 1px; background: var(--n-8); margin: 5px 8px;"></div>
|
||||
<div style="display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 7px; font-size: 13px; color: var(--warning-text); cursor: pointer;"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="4" width="4" height="16" rx="1"/><rect x="14" y="4" width="4" height="16" rx="1"/></svg>Деактивировать</div>
|
||||
<div style="display: flex; align-items: flex-start; gap: 9px; padding: 8px 10px; border-radius: 7px; font-size: 13px; color: var(--n-5); cursor: not-allowed;" title="Есть связанные записи">
|
||||
<svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" style="flex:none;margin-top:1px;"><path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m3 0-1 14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2L4 6"/></svg>
|
||||
<span style="line-height: 1.3;">Удалить<br><span style="font-size: 11px; color: var(--n-5);">Нельзя: 12 диалогов, агент</span></span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Row 2 — support, agent active -->
|
||||
<tr style="border-top: 1px solid var(--n-8); cursor: pointer;">
|
||||
<td style="padding: 12px 12px 12px 16px;"><a href="#B" style="font-weight: 600; color: var(--text-body);">FoxRay — поддержка</a><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;"><span style="font-family: var(--font-mono);">foxray-support</span> · Поддержка</div></td>
|
||||
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 6px; padding: 2px 9px; border-radius: var(--radius-pill); background: var(--product-foxray-bg); font-size: 11.5px; font-weight: 600; color: var(--product-foxray);"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--product-foxray);"></span>FoxRay</span></td>
|
||||
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-webchat-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-webchat);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-webchat);">Web</span></span></td>
|
||||
<td style="padding: 12px;"><div style="display: flex; flex-direction: column; align-items: flex-start; gap: 3px;"><a href="#" style="font-weight: 600; color: var(--primary);">FoxRay Support</a><span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--success-text);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>Активен</span></div></td>
|
||||
<td style="padding: 12px; text-align: right; color: var(--text-body); font-variant-numeric: tabular-nums;">7</td>
|
||||
<td style="padding: 12px 16px 12px 12px; text-align: right;"><span style="display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 7px; color: var(--text-tertiary);"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></svg></span></td>
|
||||
</tr>
|
||||
<!-- Row 3 — FirePage sales, MAX -->
|
||||
<tr style="border-top: 1px solid var(--n-8); cursor: pointer;">
|
||||
<td style="padding: 12px 12px 12px 16px;"><a href="#B" style="font-weight: 600; color: var(--text-body);">FirePage — продажи</a><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;"><span style="font-family: var(--font-mono);">firepage-sales</span> · Продажи</div></td>
|
||||
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 6px; padding: 2px 9px; border-radius: var(--radius-pill); background: var(--product-firepage-bg); font-size: 11.5px; font-weight: 600; color: var(--product-firepage);"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--product-firepage);"></span>FirePage</span></td>
|
||||
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-max-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-max);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-max);">MAX</span></span></td>
|
||||
<td style="padding: 12px;"><div style="display: flex; flex-direction: column; align-items: flex-start; gap: 3px;"><a href="#" style="font-weight: 600; color: var(--primary);">FirePage Sales</a><span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--success-text);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>Активен</span></div></td>
|
||||
<td style="padding: 12px; text-align: right; color: var(--text-body); font-variant-numeric: tabular-nums;">5</td>
|
||||
<td style="padding: 12px 16px 12px 12px; text-align: right;"><span style="display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 7px; color: var(--text-tertiary);"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></svg></span></td>
|
||||
</tr>
|
||||
<!-- Row 4 — non-product, NO AGENT (operator channel), no department -->
|
||||
<tr style="border-top: 1px solid var(--n-8); cursor: pointer;">
|
||||
<td style="padding: 12px 12px 12px 16px;"><a href="#B" style="font-weight: 600; color: var(--text-body);">Партнёрская линия</a><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;"><span style="font-family: var(--font-mono);">partners</span> · <span style="display: inline-flex; align-items: center; gap: 4px; padding: 0 7px; border-radius: var(--radius-pill); background: var(--n-9); font-size: 10.5px; font-weight: 600; color: var(--text-tertiary); vertical-align: middle;">Без отдела</span></div></td>
|
||||
<td style="padding: 12px; color: var(--text-tertiary); font-size: 12.5px;">— непродуктовый</td>
|
||||
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-telegram-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-telegram);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-telegram);">TG</span></span></td>
|
||||
<td style="padding: 12px;"><span style="font-size: 12.5px; color: var(--text-tertiary);">Нет агента</span><div style="font-size: 11px; color: var(--n-5); margin-top: 2px;">операторский канал</div></td>
|
||||
<td style="padding: 12px; text-align: right; color: var(--text-body); font-variant-numeric: tabular-nums;">3</td>
|
||||
<td style="padding: 12px 16px 12px 12px; text-align: right;"><span style="display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 7px; color: var(--text-tertiary);"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></svg></span></td>
|
||||
</tr>
|
||||
<!-- Row 5 — ARCHIVED (visible because toggle on) -->
|
||||
<tr style="border-top: 1px solid var(--n-8); cursor: pointer; background: #fcfcfc;">
|
||||
<td style="padding: 12px 12px 12px 16px;"><a href="#B" style="font-weight: 600; color: var(--text-tertiary);">FoxRay — вебинары</a><div style="font-size: 12px; color: var(--n-5); margin-top: 2px;"><span style="font-family: var(--font-mono);">foxray-webinars</span> · Продажи</div></td>
|
||||
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 6px; padding: 2px 9px; border-radius: var(--radius-pill); background: var(--n-9); font-size: 11.5px; font-weight: 600; color: var(--n-5);"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--n-5);"></span>FoxRay</span></td>
|
||||
<td style="padding: 12px; color: var(--n-5); font-size: 12.5px;">—</td>
|
||||
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text-tertiary);"><span style="width: 7px; height: 7px; border-radius: 50%; border: 1.5px solid var(--n-5); background: transparent;"></span>Архивный</span></td>
|
||||
<td style="padding: 12px; text-align: right; color: var(--text-tertiary); font-variant-numeric: tabular-nums;">0</td>
|
||||
<td style="padding: 12px 16px 12px 12px; text-align: right;"><span style="display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 7px; color: var(--text-tertiary);"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></svg></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; padding: 11px 16px; border-top: 1px solid var(--n-8); font-size: 12.5px; color: var(--text-tertiary);">
|
||||
<span>5 каналов · 1 архивный</span>
|
||||
<span>Счётчик «Диалоги» — открытые диалоги по <span style="font-family: var(--font-mono);">Conversation.channel</span></span>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============ FRAME B — CARD (SINGLE PAGE, NO TABS) ============ -->
|
||||
<section id="B" style="display: flex; flex-direction: column; gap: 12px;">
|
||||
<div style="display: flex; align-items: baseline; gap: 12px;">
|
||||
<span style="font-size: 12px; font-weight: 700; color: #fff; background: var(--text-heading); padding: 3px 9px; border-radius: 6px;">B</span>
|
||||
<h2 style="margin: 0; font-size: 17px; font-weight: 600; color: var(--text-heading);">Карточка канала — одна страница</h2>
|
||||
<span style="font-size: 12.5px; color: var(--text-tertiary);">без вкладок · секции сверху вниз: Назначение · Политика · Подключения · AI-агент · Счётчики</span>
|
||||
</div>
|
||||
|
||||
<div style="width: 1180px; background: var(--surface-page); border: 1px solid var(--n-6); border-radius: var(--radius-2xl); box-shadow: var(--shadow-md); overflow: hidden; padding: 22px 24px 28px;">
|
||||
<!-- breadcrumb -->
|
||||
<div style="display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-tertiary); margin-bottom: 14px;">
|
||||
<a href="#A" style="color: var(--text-secondary); font-weight: 500;">Каналы</a><span style="color: var(--n-6);">/</span><span style="color: var(--text-body); font-weight: 600;">FoxRay — продажи</span>
|
||||
</div>
|
||||
<!-- HEADER -->
|
||||
<div style="display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; margin-bottom: 22px;">
|
||||
<div>
|
||||
<h1 style="margin: 0 0 5px; font-size: 22px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading);">FoxRay — продажи</h1>
|
||||
<div style="display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--text-tertiary);"><span style="font-family: var(--font-mono);">foxray-sales</span><span style="color: var(--n-6);">·</span>Продажи<span style="color: var(--n-6);">·</span><span style="display: inline-flex; align-items: center; gap: 5px;"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--product-foxray);"></span>FoxRay</span></div>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 10px; flex: none;">
|
||||
<span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--success-text); background: var(--success-bg); border: 1px solid var(--success-border); padding: 5px 11px; border-radius: var(--radius-pill);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>Активен</span>
|
||||
<button style="display: inline-flex; align-items: center; gap: 7px; height: 36px; padding: 0 14px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 13px; font-weight: 600; color: var(--text-body); cursor: pointer;"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>Изменить</button>
|
||||
<button style="display: inline-flex; align-items: center; gap: 7px; height: 36px; padding: 0 14px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 13px; font-weight: 600; color: var(--warning-text); cursor: pointer;"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="4" width="4" height="16" rx="1"/><rect x="14" y="4" width="4" height="16" rx="1"/></svg>Деактивировать</button>
|
||||
<span style="display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; color: var(--error-text); cursor: pointer;" title="Удалить"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m3 0-1 14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2L4 6"/></svg></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SECTIONS -->
|
||||
<div style="display: flex; flex-direction: column; gap: 16px;">
|
||||
|
||||
<!-- Назначение -->
|
||||
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 20px;">
|
||||
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 14px;"><h3 style="margin: 0; margin-right: auto; font-size: 15px; font-weight: 600; color: var(--text-heading);">Назначение</h3><span style="font-size: 12px; color: var(--text-tertiary);">Отдел и продукт редактируются здесь</span></div>
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px 24px; font-size: 13px;">
|
||||
<div style="display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid var(--n-9);"><span style="color: var(--text-tertiary);">Отдел</span><span style="color: var(--text-body); font-weight: 500;">Продажи</span></div>
|
||||
<div style="display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid var(--n-9);"><span style="color: var(--text-tertiary);">Продукт</span><span style="color: var(--text-body); font-weight: 500;">FoxRay</span></div>
|
||||
<div style="display: flex; justify-content: space-between; padding: 8px 0;"><span style="color: var(--text-tertiary);">Код</span><span style="color: var(--text-body); font-family: var(--font-mono);">foxray-sales</span></div>
|
||||
<div style="display: flex; justify-content: space-between; padding: 8px 0;"><span style="color: var(--text-tertiary);">Создан</span><span style="color: var(--text-body);">02 июл 2026</span></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Политика -->
|
||||
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 8px 20px 12px;">
|
||||
<div style="display: flex; align-items: center; gap: 12px; padding: 12px 0 4px;"><h3 style="margin: 0; margin-right: auto; font-size: 15px; font-weight: 600; color: var(--text-heading);">Политика</h3><span style="font-size: 12px; color: var(--text-tertiary);">Пресет: Продажи</span></div>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 0; border-top: 1px solid var(--n-9);">
|
||||
<div><div style="font-size: 13.5px; font-weight: 600; color: var(--text-body);">Обязательная продуктовая идентичность</div><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;">Диалог требует авторизации как владелец продукта.</div></div>
|
||||
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--n-8); position: relative;"><span style="position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: var(--n-5);"></span></span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 0; border-top: 1px solid var(--n-9);">
|
||||
<div><div style="font-size: 13.5px; font-weight: 600; color: var(--text-body);">Анонимные сессии</div><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;">Разрешает диалоги без идентификации пользователя.</div></div>
|
||||
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--primary); position: relative;"><span style="position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-xs);"></span></span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 0; border-top: 1px solid var(--n-9);">
|
||||
<div><div style="font-size: 13.5px; font-weight: 600; color: var(--text-body);">Самозаявленный контакт</div><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;">Позволяет пользователю указать контакт вручную.</div></div>
|
||||
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--primary); position: relative;"><span style="position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-xs);"></span></span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 0; border-top: 1px solid var(--n-9);">
|
||||
<div><div style="font-size: 13.5px; font-weight: 600; color: var(--text-body);">Attribution продаж</div><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;">Связывает продажу с диалогом канала.</div></div>
|
||||
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--primary); position: relative;"><span style="position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-xs);"></span></span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 0; border-top: 1px solid var(--n-9);">
|
||||
<div><div style="font-size: 13.5px; font-weight: 600; color: var(--text-body);">Коммерческие действия (checkout)</div><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;">Разрешает оформление заказа в диалоге.</div></div>
|
||||
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--primary); position: relative;"><span style="position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-xs);"></span></span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Подключения -->
|
||||
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 20px;">
|
||||
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 12px;"><h3 style="margin: 0; margin-right: auto; font-size: 15px; font-weight: 600; color: var(--text-heading);">Подключения</h3><button style="display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 12.5px; font-weight: 600; color: var(--text-body); cursor: pointer;"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Привязать подключение</button></div>
|
||||
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||||
<div style="display: flex; align-items: center; gap: 11px; padding: 11px 12px; border: 1px solid var(--n-8); border-radius: var(--radius-lg);">
|
||||
<span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-telegram-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-telegram);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-telegram);">TG</span></span>
|
||||
<div style="flex: 1; line-height: 1.3;"><div style="font-size: 13px; font-weight: 600; color: var(--text-body);">FoxRay Sales Bot</div><div style="font-size: 11.5px; color: var(--text-tertiary);">Telegram · @foxray_sales_bot</div></div>
|
||||
<span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--success-text);"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--success);"></span>OK</span>
|
||||
<button style="height: 28px; padding: 0 11px; border-radius: 7px; border: 1px solid var(--n-6); background: #fff; font-size: 12px; font-weight: 600; color: var(--text-secondary); cursor: pointer;">Отвязать</button>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 11px; padding: 11px 12px; border: 1px solid var(--n-8); border-radius: var(--radius-lg);">
|
||||
<span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-webchat-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-webchat);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-webchat);">Web</span></span>
|
||||
<div style="flex: 1; line-height: 1.3;"><div style="font-size: 13px; font-weight: 600; color: var(--text-body);">Виджет на foxray.ru</div><div style="font-size: 11.5px; color: var(--text-tertiary);">Web Chat · embed foxray-sales</div></div>
|
||||
<span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--success-text);"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--success);"></span>OK</span>
|
||||
<button style="height: 28px; padding: 0 11px; border-radius: 7px; border: 1px solid var(--n-6); background: #fff; font-size: 12px; font-weight: 600; color: var(--text-secondary); cursor: pointer;">Отвязать</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- AI-агент (one line) -->
|
||||
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 18px 20px;">
|
||||
<div style="font-size: 11px; font-weight: 600; letter-spacing: 0.05em; color: var(--text-tertiary); margin-bottom: 12px;">AI-АГЕНТ</div>
|
||||
<div style="display: flex; align-items: center; gap: 12px;">
|
||||
<span style="width: 34px; height: 34px; border-radius: 9px; background: var(--ai-bg); color: var(--ai); display: flex; align-items: center; justify-content: center; flex: none;"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="8" width="16" height="12" rx="2.5"/><path d="M12 8V4.5"/><circle cx="12" cy="3.5" r="1.2"/><circle cx="9" cy="13.5" r="1"/><circle cx="15" cy="13.5" r="1"/></svg></span>
|
||||
<div style="display: flex; align-items: center; gap: 10px; flex: 1; font-size: 13.5px; min-width: 0;">
|
||||
<b style="color: var(--text-body);">FoxRay Sales</b>
|
||||
<span style="color: var(--n-6);">·</span>
|
||||
<span style="display: inline-flex; align-items: center; gap: 6px; color: var(--success-text);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>Активен</span>
|
||||
<span style="color: var(--n-6);">·</span>
|
||||
<code style="font-family: var(--font-mono); font-size: 12px; color: var(--text-tertiary);">claude-sonnet-4.6</code>
|
||||
</div>
|
||||
<a href="#" style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--primary); flex: none;">Открыть агента<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg></a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Счётчики -->
|
||||
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 20px;">
|
||||
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 14px;"><h3 style="margin: 0; margin-right: auto; font-size: 15px; font-weight: 600; color: var(--text-heading);">Счётчики</h3><a href="#A" style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--primary);">Открыть диалоги канала<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg></a></div>
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;">
|
||||
<div style="background: var(--n-10); border: 1px solid var(--n-8); border-radius: var(--radius-xl); padding: 16px 18px;"><div style="font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary); margin-bottom: 8px;">ОТКРЫТЫЕ ДИАЛОГИ</div><div style="font-size: 26px; font-weight: 700; color: var(--text-heading); font-variant-numeric: tabular-nums;">12</div></div>
|
||||
<div style="background: var(--n-10); border: 1px solid var(--n-8); border-radius: var(--radius-xl); padding: 16px 18px;"><div style="font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary); margin-bottom: 8px;">ПОДКЛЮЧЕНИЯ</div><div style="font-size: 26px; font-weight: 700; color: var(--text-heading); font-variant-numeric: tabular-nums;">2</div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============ FRAME C — SECTION: POLICY (forbidden flag) ============ -->
|
||||
<section id="C" style="display: flex; flex-direction: column; gap: 12px;">
|
||||
<div style="display: flex; align-items: baseline; gap: 12px;">
|
||||
<span style="font-size: 12px; font-weight: 700; color: #fff; background: var(--text-heading); padding: 3px 9px; border-radius: 6px;">C</span>
|
||||
<h2 style="margin: 0; font-size: 17px; font-weight: 600; color: var(--text-heading);">Секция «Политика» — запрещённый инвариантом флаг</h2>
|
||||
<span style="font-size: 12.5px; color: var(--text-tertiary);">пять флагов с пояснением следствия · флаг, запрещённый инвариантом, объясняет причину</span>
|
||||
</div>
|
||||
|
||||
<div style="width: 1180px; background: var(--surface-page); border: 1px solid var(--n-6); border-radius: var(--radius-2xl); box-shadow: var(--shadow-md); overflow: hidden; padding: 22px 24px 28px;">
|
||||
<div style="display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-tertiary); margin-bottom: 14px;">
|
||||
<a href="#A" style="color: var(--text-secondary); font-weight: 500;">Каналы</a><span style="color: var(--n-6);">/</span><span style="color: var(--text-body); font-weight: 600;">Партнёрская линия</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; margin-bottom: 18px;">
|
||||
<div>
|
||||
<h1 style="margin: 0 0 5px; font-size: 22px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading);">Партнёрская линия</h1>
|
||||
<div style="display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--text-tertiary);"><span style="font-family: var(--font-mono);">partners</span><span style="color: var(--n-6);">·</span><span style="display: inline-flex; align-items: center; gap: 4px; padding: 0 7px; border-radius: var(--radius-pill); background: var(--n-9); font-size: 10.5px; font-weight: 600;">Без отдела</span><span style="color: var(--n-6);">·</span>— непродуктовый</div>
|
||||
</div>
|
||||
<span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--success-text); background: var(--success-bg); border: 1px solid var(--success-border); padding: 5px 11px; border-radius: var(--radius-pill);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>Активен</span>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: 1fr 320px; gap: 18px; align-items: start;">
|
||||
<!-- flags -->
|
||||
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 8px 20px 12px;">
|
||||
<div style="font-size: 11px; font-weight: 600; letter-spacing: 0.05em; color: var(--text-tertiary); padding: 12px 0 4px;">СЕКЦИЯ «ПОЛИТИКА» · 5 ФЛАГОВ</div>
|
||||
<!-- P3 requires identity — locked off -->
|
||||
<div style="display: flex; align-items: flex-start; gap: 14px; padding: 16px 0; border-top: 1px solid var(--n-9);">
|
||||
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--n-8); position: relative; margin-top: 1px;"><span style="position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: var(--n-5);"></span></span>
|
||||
<div style="flex: 1;">
|
||||
<div style="display: flex; align-items: center; gap: 8px;"><span style="font-size: 13.5px; font-weight: 600; color: var(--text-tertiary);">Обязательная продуктовая идентичность</span><span style="display: inline-flex; align-items: center; gap: 4px; font-size: 10.5px; font-weight: 600; color: var(--warning-text); background: var(--warning-bg); border: 1px solid var(--warning-border); padding: 1px 7px; border-radius: var(--radius-pill);"><svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>Недоступно</span></div>
|
||||
<div style="font-size: 12px; color: var(--text-tertiary); margin-top: 3px; line-height: 1.5;">Требует продукта <b>(инвариант P3)</b>. Пользователь должен быть авторизован как владелец продукта. Назначьте продукт каналу, чтобы включить.</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- anonymous — on -->
|
||||
<div style="display: flex; align-items: flex-start; gap: 14px; padding: 16px 0; border-top: 1px solid var(--n-9);">
|
||||
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--primary); position: relative; margin-top: 1px;"><span style="position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-xs);"></span></span>
|
||||
<div style="flex: 1;">
|
||||
<div style="font-size: 13.5px; font-weight: 600; color: var(--text-body);">Анонимные сессии</div>
|
||||
<div style="font-size: 12px; color: var(--text-tertiary); margin-top: 3px; line-height: 1.5;">Разрешает диалоги без идентификации пользователя — партнёр может написать без входа.</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- self-reported — on -->
|
||||
<div style="display: flex; align-items: flex-start; gap: 14px; padding: 16px 0; border-top: 1px solid var(--n-9);">
|
||||
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--primary); position: relative; margin-top: 1px;"><span style="position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-xs);"></span></span>
|
||||
<div style="flex: 1;">
|
||||
<div style="font-size: 13.5px; font-weight: 600; color: var(--text-body);">Самозаявленный контакт</div>
|
||||
<div style="font-size: 12px; color: var(--text-tertiary); margin-top: 3px; line-height: 1.5;">Позволяет пользователю указать email или телефон вручную для обратной связи.</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- P2 attribution — locked off -->
|
||||
<div style="display: flex; align-items: flex-start; gap: 14px; padding: 16px 0; border-top: 1px solid var(--n-9);">
|
||||
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--n-8); position: relative; margin-top: 1px;"><span style="position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: var(--n-5);"></span></span>
|
||||
<div style="flex: 1;">
|
||||
<div style="display: flex; align-items: center; gap: 8px;"><span style="font-size: 13.5px; font-weight: 600; color: var(--text-tertiary);">Attribution продаж</span><span style="display: inline-flex; align-items: center; gap: 4px; font-size: 10.5px; font-weight: 600; color: var(--warning-text); background: var(--warning-bg); border: 1px solid var(--warning-border); padding: 1px 7px; border-radius: var(--radius-pill);"><svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>Недоступно</span></div>
|
||||
<div style="font-size: 12px; color: var(--text-tertiary); margin-top: 3px; line-height: 1.5;">Attribution недоступна непродуктовому каналу <b>(инвариант P2)</b>. Свяжите канал с продуктом, чтобы включить.</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- P1 checkout — locked off (KEY) -->
|
||||
<div style="display: flex; align-items: flex-start; gap: 14px; padding: 16px 0; background: var(--warning-bg-strong); margin: 0 -20px; padding-left: 20px; padding-right: 20px; border-radius: var(--radius-lg);">
|
||||
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--n-8); position: relative; margin-top: 1px;"><span style="position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: var(--n-5);"></span></span>
|
||||
<div style="flex: 1;">
|
||||
<div style="display: flex; align-items: center; gap: 8px;"><span style="font-size: 13.5px; font-weight: 600; color: var(--text-tertiary);">Коммерческие действия (checkout)</span><span style="display: inline-flex; align-items: center; gap: 4px; font-size: 10.5px; font-weight: 600; color: var(--warning-text); background: #fff; border: 1px solid var(--warning-border); padding: 1px 7px; border-radius: var(--radius-pill);"><svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>Запрещено инвариантом</span></div>
|
||||
<div style="font-size: 12px; color: var(--warning-text); margin-top: 3px; line-height: 1.5;">Коммерческие действия недоступны непродуктовому каналу <b>(инвариант P1)</b>. Флаг не будет сохранён включённым, пока каналу не назначен продукт — причина показана, а не игнорируется молча.</div>
|
||||
<a href="#B" style="display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600; color: var(--primary); margin-top: 8px;">Назначить продукт<svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg></a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- side note -->
|
||||
<div style="display: flex; flex-direction: column; gap: 16px;">
|
||||
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 18px;">
|
||||
<h4 style="margin: 0 0 12px; font-size: 13px; font-weight: 600; color: var(--text-heading);">Контекст политики</h4>
|
||||
<div style="display: flex; flex-direction: column; gap: 10px; font-size: 12.5px;">
|
||||
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Продукт</span><span style="color: var(--text-tertiary);">— непродуктовый</span></div>
|
||||
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Отдел</span><span style="color: var(--text-body);">Без отдела</span></div>
|
||||
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Пресет</span><span style="color: var(--text-body);">Свой (CUSTOM)</span></div>
|
||||
</div>
|
||||
</section>
|
||||
<section style="background: var(--primary-bg); border: 1px solid var(--primary-border); border-radius: var(--radius-2xl); padding: 16px 18px;">
|
||||
<div style="font-size: 12.5px; color: #0958d9; line-height: 1.55;">Инварианты проверяются по итоговому состоянию: частичное сохранение запрещено. Чтобы включить коммерческие флаги, сначала назначьте продукт в секции «Назначение».</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============ FRAME D — SECTION: CONNECTIONS + TRANSFER ============ -->
|
||||
<section id="D" style="display: flex; flex-direction: column; gap: 12px;">
|
||||
<div style="display: flex; align-items: baseline; gap: 12px;">
|
||||
<span style="font-size: 12px; font-weight: 700; color: #fff; background: var(--text-heading); padding: 3px 9px; border-radius: 6px;">D</span>
|
||||
<h2 style="margin: 0; font-size: 17px; font-weight: 600; color: var(--text-heading);">Секция «Подключения» — привязка и перенос</h2>
|
||||
<span style="font-size: 12.5px; color: var(--text-tertiary);">список подключений канала · привязка · перенос между каналами с явным подтверждением (force)</span>
|
||||
</div>
|
||||
|
||||
<div style="width: 1180px; height: 620px; position: relative; background: var(--surface-page); border: 1px solid var(--n-6); border-radius: var(--radius-2xl); box-shadow: var(--shadow-md); overflow: hidden; padding: 22px 24px 28px;">
|
||||
<div style="display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-tertiary); margin-bottom: 14px;">
|
||||
<a href="#A" style="color: var(--text-secondary); font-weight: 500;">Каналы</a><span style="color: var(--n-6);">/</span><span style="color: var(--text-body); font-weight: 600;">FoxRay — продажи</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; gap: 20px; margin-bottom: 18px;">
|
||||
<h1 style="margin: 0; font-size: 22px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading);">FoxRay — продажи</h1>
|
||||
</div>
|
||||
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 20px;">
|
||||
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 12px;"><h3 style="margin: 0; margin-right: auto; font-size: 15px; font-weight: 600; color: var(--text-heading);">Подключения</h3><button style="display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px; border-radius: var(--radius-lg); border: 1px solid transparent; background: var(--primary); color: #fff; font-size: 12.5px; font-weight: 600; box-shadow: var(--shadow-primary); cursor: pointer;"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Привязать подключение</button></div>
|
||||
<table style="width: 100%; border-collapse: collapse; font-size: 13px;">
|
||||
<thead>
|
||||
<tr style="text-align: left;">
|
||||
<th style="padding: 8px 12px 8px 0; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary);">ПОДКЛЮЧЕНИЕ</th>
|
||||
<th style="padding: 8px 12px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary);">ПРОВАЙДЕР</th>
|
||||
<th style="padding: 8px 12px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary);">СТАТУС</th>
|
||||
<th style="padding: 8px 0 8px 12px; width: 110px; text-align: right;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr style="border-top: 1px solid var(--n-8);">
|
||||
<td style="padding: 12px 12px 12px 0;"><div style="font-weight: 600; color: var(--text-body);">FoxRay Sales Bot</div><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;">@foxray_sales_bot</div></td>
|
||||
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-telegram-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-telegram);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-telegram);">TG</span></span></td>
|
||||
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--success-text);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>OK</span></td>
|
||||
<td style="padding: 12px 0 12px 12px; text-align: right;"><button style="height: 30px; padding: 0 12px; border-radius: 8px; border: 1px solid var(--n-6); background: #fff; font-size: 12.5px; font-weight: 600; color: var(--text-secondary); cursor: pointer;">Отвязать</button></td>
|
||||
</tr>
|
||||
<tr style="border-top: 1px solid var(--n-8);">
|
||||
<td style="padding: 12px 12px 12px 0;"><div style="font-weight: 600; color: var(--text-body);">Виджет на foxray.ru</div><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;">embed foxray-sales</div></td>
|
||||
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-webchat-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-webchat);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-webchat);">Web</span></span></td>
|
||||
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--success-text);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>OK</span></td>
|
||||
<td style="padding: 12px 0 12px 12px; text-align: right;"><button style="height: 30px; padding: 0 12px; border-radius: 8px; border: 1px solid var(--n-6); background: #fff; font-size: 12.5px; font-weight: 600; color: var(--text-secondary); cursor: pointer;">Отвязать</button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<!-- overlay + transfer modal -->
|
||||
<div style="position: absolute; inset: 0; background: rgba(15,20,30,0.28);"></div>
|
||||
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); width: 560px; background: #fff; border-radius: var(--radius-4xl); box-shadow: var(--shadow-lg); overflow: hidden;">
|
||||
<div style="padding: 22px 24px 18px; border-bottom: 1px solid var(--n-8); display: flex; gap: 14px;">
|
||||
<span style="flex: none; width: 40px; height: 40px; border-radius: 10px; background: var(--warning-bg); color: var(--warning-text); display: flex; align-items: center; justify-content: center;"><svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M17 1l4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><path d="M7 23l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg></span>
|
||||
<div>
|
||||
<h3 style="margin: 0 0 5px; font-size: 16px; font-weight: 600; color: var(--text-heading);">Перенести подключение в этот канал?</h3>
|
||||
<p style="margin: 0; font-size: 13px; line-height: 1.55; color: var(--text-secondary);">Подключение <b>«FirePage MAX Bot»</b> уже привязано к каналу <b>«FirePage — продажи»</b>. Подключение принадлежит ровно одному каналу — перенос отвяжет его от прежнего.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding: 16px 24px;">
|
||||
<div style="display: flex; align-items: center; gap: 12px; padding: 12px 14px; border: 1px solid var(--n-8); border-radius: var(--radius-lg); background: var(--n-10);">
|
||||
<span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-max-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-max);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-max);">MAX</span></span>
|
||||
<div style="flex: 1; display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--text-secondary);"><span style="color: var(--text-tertiary);">FirePage — продажи</span><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="var(--primary)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg><b style="color: var(--text-body);">FoxRay — продажи</b></div>
|
||||
</div>
|
||||
<p style="margin: 12px 2px 0; font-size: 12px; color: var(--text-tertiary); line-height: 1.5;">Существующие диалоги остаются в прежнем канале (<span style="font-family: var(--font-mono);">Conversation.connection</span> — PROTECT). Действие пишется в аудит как перенос.</p>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 10px; padding: 14px 24px; border-top: 1px solid var(--n-8);">
|
||||
<span style="flex: 1;"></span>
|
||||
<button style="height: 36px; padding: 0 16px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 13px; font-weight: 600; color: var(--text-body); cursor: pointer;">Отмена</button>
|
||||
<button style="height: 36px; padding: 0 16px; border-radius: var(--radius-lg); border: 1px solid transparent; background: var(--primary); color: #fff; font-size: 13px; font-weight: 600; box-shadow: var(--shadow-primary); cursor: pointer;">Перенести подключение</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============ FRAME E — CREATE WIZARD (three steps) ============ -->
|
||||
<section id="E" style="display: flex; flex-direction: column; gap: 12px;">
|
||||
<div style="display: flex; align-items: baseline; gap: 12px;">
|
||||
<span style="font-size: 12px; font-weight: 700; color: #fff; background: var(--text-heading); padding: 3px 9px; border-radius: 6px;">E</span>
|
||||
<h2 style="margin: 0; font-size: 17px; font-weight: 600; color: var(--text-heading);">Мастер создания канала — три шага</h2>
|
||||
<span style="font-size: 12.5px; color: var(--text-tertiary);">Канал · Назначение · Подключения · финальный экран операторского канала</span>
|
||||
</div>
|
||||
|
||||
<div style="width: 1180px; background: var(--surface-page); border: 1px solid var(--n-6); border-radius: var(--radius-2xl); box-shadow: var(--shadow-md); overflow: hidden; padding: 24px 28px 26px;">
|
||||
<h1 style="margin: 0 0 4px; font-size: 22px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading);">Создание канала</h1>
|
||||
<p style="margin: 0 0 20px; font-size: 13.5px; color: var(--text-secondary);">Три шага. Настройка агента и знаний в мастер не входит — агент создаётся отдельным действием в разделе AI. Канал создаётся по завершении шага 2.</p>
|
||||
|
||||
<!-- stepper: 3 steps, all done -->
|
||||
<div style="display: flex; align-items: center; gap: 0; margin-bottom: 24px; max-width: 720px;">
|
||||
<div style="display: flex; align-items: center; gap: 10px;"><span style="width: 26px; height: 26px; border-radius: 50%; background: var(--success); color: #fff; display: flex; align-items: center; justify-content: center; flex: none;"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span><span style="font-size: 13px; font-weight: 600; color: var(--text-body);">Канал</span></div>
|
||||
<div style="flex: 1; height: 2px; background: var(--success); margin: 0 12px;"></div>
|
||||
<div style="display: flex; align-items: center; gap: 10px;"><span style="width: 26px; height: 26px; border-radius: 50%; background: var(--success); color: #fff; display: flex; align-items: center; justify-content: center; flex: none;"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span><span style="font-size: 13px; font-weight: 600; color: var(--text-body);">Назначение</span></div>
|
||||
<div style="flex: 1; height: 2px; background: var(--success); margin: 0 12px;"></div>
|
||||
<div style="display: flex; align-items: center; gap: 10px;"><span style="width: 26px; height: 26px; border-radius: 50%; background: var(--success); color: #fff; display: flex; align-items: center; justify-content: center; flex: none;"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span><span style="font-size: 13px; font-weight: 600; color: var(--text-body);">Подключения</span></div>
|
||||
</div>
|
||||
|
||||
<!-- final screen -->
|
||||
<div style="display: grid; grid-template-columns: 1fr 340px; gap: 18px; align-items: start;">
|
||||
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 32px 28px; text-align: center;">
|
||||
<div style="width: 52px; height: 52px; border-radius: 14px; background: var(--success-bg); color: var(--success-text); display: flex; align-items: center; justify-content: center; margin: 0 auto 16px;"><svg viewBox="0 0 24 24" width="28" height="28" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></div>
|
||||
<h3 style="margin: 0 0 6px; font-size: 18px; font-weight: 700; color: var(--text-heading);">Канал создан</h3>
|
||||
<p style="margin: 0 auto 20px; font-size: 13.5px; color: var(--text-secondary); line-height: 1.55; max-width: 440px;"><b style="color: var(--text-body);">Партнёрская линия</b> — операторский канал: AI-агента нет, диалоги ведут операторы. Канал принимает подключения, диалоги, заказы и attribution.</p>
|
||||
<div style="display: flex; gap: 10px; justify-content: center;">
|
||||
<a href="#B" style="display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 16px; border-radius: var(--radius-lg); border: 1px solid transparent; background: var(--primary); color: #fff; font-size: 13px; font-weight: 600; box-shadow: var(--shadow-primary);">Открыть карточку канала</a>
|
||||
<a href="#A" style="display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 16px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 13px; font-weight: 600; color: var(--text-body);">К списку каналов</a>
|
||||
</div>
|
||||
</section>
|
||||
<div style="display: flex; flex-direction: column; gap: 16px;">
|
||||
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 18px;">
|
||||
<h4 style="margin: 0 0 12px; font-size: 13px; font-weight: 600; color: var(--text-heading);">Сводка канала</h4>
|
||||
<div style="display: flex; flex-direction: column; gap: 10px; font-size: 12.5px;">
|
||||
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Название</span><span style="color: var(--text-body); font-weight: 500;">Партнёрская линия</span></div>
|
||||
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Код</span><span style="color: var(--text-body); font-family: var(--font-mono);">partners</span></div>
|
||||
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Отдел</span><span style="color: var(--text-body);">Без отдела</span></div>
|
||||
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Продукт</span><span style="color: var(--text-tertiary);">— непродуктовый</span></div>
|
||||
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Подключения</span><span style="color: var(--text-body);">TG · 1</span></div>
|
||||
</div>
|
||||
</section>
|
||||
<section style="background: var(--ai-bg); border: 1px solid #e4d4fb; border-radius: var(--radius-2xl); padding: 16px 18px;">
|
||||
<div style="font-size: 12.5px; color: var(--ai); line-height: 1.55; margin-bottom: 12px;"><b>Нужен AI-агент?</b> Создайте его отдельным действием в разделе AI — он подключится к этому каналу.</div>
|
||||
<a href="#A" style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--ai);">Перейти в раздел AI<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg></a>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============ FRAME S — STATES ============ -->
|
||||
<section id="S" style="display: flex; flex-direction: column; gap: 12px;">
|
||||
<div style="display: flex; align-items: baseline; gap: 12px;">
|
||||
<span style="font-size: 12px; font-weight: 700; color: #fff; background: var(--text-heading); padding: 3px 9px; border-radius: 6px;">S</span>
|
||||
<h2 style="margin: 0; font-size: 17px; font-weight: 600; color: var(--text-heading);">Служебные состояния</h2>
|
||||
<span style="font-size: 12.5px; color: var(--text-tertiary);">пустой список · канал без агента · архивный канал · ограниченный доступ · конфликт удаления</span>
|
||||
</div>
|
||||
<div style="display: flex; gap: 18px; flex-wrap: wrap;">
|
||||
<!-- empty list -->
|
||||
<div style="width: 372px; background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 40px 24px; text-align: center;">
|
||||
<div style="width: 46px; height: 46px; border-radius: 12px; background: var(--primary-bg); color: var(--primary); display: flex; align-items: center; justify-content: center; margin: 0 auto 14px;"><svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></svg></div>
|
||||
<div style="font-size: 14px; font-weight: 600; color: var(--text-body); margin-bottom: 5px;">Создайте первый канал</div>
|
||||
<p style="margin: 0 0 16px; font-size: 12.5px; color: var(--text-tertiary); line-height: 1.5;">Канал маршрутизирует диалоги от подключений к отделу, продукту и — при необходимости — к AI-агенту.</p>
|
||||
<button style="height: 34px; padding: 0 14px; border-radius: var(--radius-lg); border: 1px solid transparent; background: var(--primary); color: #fff; font-size: 12.5px; font-weight: 600; box-shadow: var(--shadow-primary); cursor: pointer;">Создать канал</button>
|
||||
</div>
|
||||
<!-- channel without agent -->
|
||||
<div style="width: 372px; background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 24px;">
|
||||
<div style="font-size: 11px; font-weight: 600; letter-spacing: 0.05em; color: var(--text-tertiary); margin-bottom: 14px;">СЕКЦИЯ «AI-АГЕНТ» · КАНАЛ БЕЗ АГЕНТА</div>
|
||||
<div style="text-align: center; padding: 20px 8px;">
|
||||
<div style="width: 44px; height: 44px; border-radius: 11px; background: var(--ai-bg); color: var(--ai); display: flex; align-items: center; justify-content: center; margin: 0 auto 12px;"><svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="8" width="16" height="12" rx="2.5"/><path d="M12 8V4.5"/><circle cx="12" cy="3.5" r="1.2"/><circle cx="9" cy="13.5" r="1"/><circle cx="15" cy="13.5" r="1"/></svg></div>
|
||||
<div style="font-size: 14px; font-weight: 600; color: var(--text-body); margin-bottom: 5px;">Агента нет, канал ведут операторы</div>
|
||||
<p style="margin: 0 0 16px; font-size: 12.5px; color: var(--text-tertiary); line-height: 1.5;">Валидное состояние канала. Агент создаётся отдельным действием в разделе AI.</p>
|
||||
<a href="#A" style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--primary);">Создать агента в разделе AI<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg></a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- archived channel -->
|
||||
<div style="width: 372px; background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 24px;">
|
||||
<div style="font-size: 11px; font-weight: 600; letter-spacing: 0.05em; color: var(--text-tertiary); margin-bottom: 12px;">АРХИВНЫЙ КАНАЛ</div>
|
||||
<div style="display: flex; align-items: center; gap: 12px; padding: 14px; border: 1px solid var(--n-8); border-radius: var(--radius-lg); background: #fcfcfc;">
|
||||
<div style="flex: 1; line-height: 1.35;"><div style="font-size: 13.5px; font-weight: 600; color: var(--text-tertiary);">FoxRay — вебинары</div><div style="font-size: 11.5px; color: var(--n-5); font-family: var(--font-mono);">foxray-webinars</div></div>
|
||||
<span style="display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 600; color: var(--text-tertiary); background: var(--n-9); padding: 3px 9px; border-radius: var(--radius-pill);"><span style="width: 7px; height: 7px; border-radius: 50%; border: 1.5px solid var(--n-5);"></span>Архивный</span>
|
||||
</div>
|
||||
<p style="margin: 12px 0 14px; font-size: 12px; color: var(--text-tertiary); line-height: 1.5;">Не принимает новые диалоги и не выбирается при привязке подключения. История диалогов сохранена и доступна.</p>
|
||||
<button style="height: 32px; padding: 0 14px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 12.5px; font-weight: 600; color: var(--text-body); cursor: pointer;">Активировать</button>
|
||||
</div>
|
||||
<!-- restricted access -->
|
||||
<div style="width: 372px; background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 40px 24px; text-align: center;">
|
||||
<div style="width: 46px; height: 46px; border-radius: 12px; background: var(--warning-bg); color: var(--warning-text); display: flex; align-items: center; justify-content: center; margin: 0 auto 14px;"><svg viewBox="0 0 24 24" width="23" height="23" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg></div>
|
||||
<div style="font-size: 14px; font-weight: 600; color: var(--text-body); margin-bottom: 5px;">Доступ ограничен отделом</div>
|
||||
<p style="margin: 0; font-size: 12.5px; color: var(--text-tertiary); line-height: 1.5;">Ваш scope <span style="font-family: var(--font-mono);">channels.view</span> охватывает отдел «Поддержка». Каналы других отделов и канал без отдела не показываются; счётчики фильтров считаются по видимому подмножеству.</p>
|
||||
</div>
|
||||
<!-- delete conflict -->
|
||||
<div style="width: 566px; background: #fff; border: 1px solid var(--error-border); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); overflow: hidden;">
|
||||
<div style="padding: 20px 22px 16px; display: flex; gap: 14px; border-bottom: 1px solid var(--n-8);">
|
||||
<span style="flex: none; width: 40px; height: 40px; border-radius: 10px; background: var(--error-bg); color: var(--error-text); display: flex; align-items: center; justify-content: center;"><svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m3 0-1 14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2L4 6"/></svg></span>
|
||||
<div><h3 style="margin: 0 0 4px; font-size: 15px; font-weight: 600; color: var(--text-heading);">Канал нельзя удалить</h3><p style="margin: 0; font-size: 12.5px; color: var(--text-secondary); line-height: 1.5;">Есть связанные записи. Вместо удаления используйте деактивацию — история сохранится.</p></div>
|
||||
</div>
|
||||
<div style="padding: 16px 22px;">
|
||||
<div style="font-size: 11px; font-weight: 600; letter-spacing: 0.05em; color: var(--text-tertiary); margin-bottom: 10px;">БЛОКИРУЮЩИЕ СВЯЗИ</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; padding: 9px 12px; border: 1px solid var(--n-8); border-radius: var(--radius-md); font-size: 12.5px;"><span style="color: var(--text-body);">Диалоги</span><span style="font-weight: 600; color: var(--text-body); font-variant-numeric: tabular-nums;">143</span></div>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; padding: 9px 12px; border: 1px solid var(--n-8); border-radius: var(--radius-md); font-size: 12.5px;"><span style="color: var(--text-body);">Подключения</span><span style="font-weight: 600; color: var(--text-body); font-variant-numeric: tabular-nums;">1</span></div>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; padding: 9px 12px; border: 1px solid var(--n-8); border-radius: var(--radius-md); font-size: 12.5px;"><span style="color: var(--text-body);">Агент</span><span style="font-weight: 600; color: var(--text-body); font-variant-numeric: tabular-nums;">1</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 10px; padding: 14px 22px; border-top: 1px solid var(--n-8);">
|
||||
<span style="flex: 1;"></span>
|
||||
<button style="height: 36px; padding: 0 16px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 13px; font-weight: 600; color: var(--text-body); cursor: pointer;">Закрыть</button>
|
||||
<button style="height: 36px; padding: 0 16px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 13px; font-weight: 600; color: var(--warning-text); cursor: pointer;">Деактивировать вместо удаления</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</x-dc>
|
||||
</body>
|
||||
</html>
|
||||
@@ -8,12 +8,12 @@
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/colors.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/typography.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/spacing.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/effects.css">
|
||||
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/styles.css">
|
||||
<script src="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/_ds_bundle.js"></script>
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/colors.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/typography.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/spacing.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/tokens/effects.css">
|
||||
<link rel="stylesheet" href="_ds/design-system/styles.css">
|
||||
<script src="_ds/design-system/_ds_bundle.js"></script>
|
||||
<style>
|
||||
*{box-sizing:border-box;}
|
||||
html,body{margin:0;padding:0;}
|
||||
@@ -29,7 +29,7 @@ html,body{margin:0;padding:0;}
|
||||
<aside style="width:248px;flex:none;background:#ffffff;border-right:1px solid #f0f0f0;display:flex;flex-direction:column;height:100vh;">
|
||||
<div style="height:56px;flex:none;display:flex;align-items:center;gap:11px;padding:0 20px;border-bottom:1px solid #f5f5f5;">
|
||||
<img src="favicon.svg" width="30" height="30" style="border-radius:8px;display:block;flex:none;" />
|
||||
<div style="display:flex;flex-direction:column;line-height:1.15;"><span style="font-size:14px;font-weight:600;color:#1f1f1f;letter-spacing:-0.01em;">CustoCRM</span><span style="font-size:11px;color:#8c8c8c;">Уровень компании</span></div>
|
||||
<div style="display:flex;flex-direction:column;line-height:1.15;"><span style="font-size:14px;font-weight:600;color:#1f1f1f;letter-spacing:-0.01em;">Chatballs</span><span style="font-size:11px;color:#8c8c8c;">Уровень компании</span></div>
|
||||
</div>
|
||||
<nav style="flex:1;overflow-y:auto;padding:12px 12px 8px;">
|
||||
<a href="#" style="display:flex;align-items:center;gap:11px;padding:9px 12px;border-radius:8px;color:#595959;font-size:13.5px;font-weight:500;text-decoration:none;margin-bottom:2px;" style-hover="background:#f5f5f5;color:#262626;"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="9" rx="1.4"/><rect x="14" y="3" width="7" height="5" rx="1.4"/><rect x="14" y="12" width="7" height="9" rx="1.4"/><rect x="3" y="16" width="7" height="5" rx="1.4"/></svg>Командный центр</a>
|
||||
@@ -54,7 +54,7 @@ html,body{margin:0;padding:0;}
|
||||
<div style="flex:1;min-width:0;display:flex;flex-direction:column;height:100vh;">
|
||||
<header style="height:56px;flex:none;background:#ffffff;border-bottom:1px solid #f0f0f0;display:flex;align-items:center;justify-content:space-between;padding:0 24px;">
|
||||
<div style="display:flex;align-items:center;gap:8px;font-size:13px;color:#8c8c8c;">
|
||||
<a href="#" onClick="{{ goCommand }}" style="font-weight:500;color:#595959;text-decoration:none;" style-hover="color:#1677ff;">Edevs</a><span style="color:#d9d9d9;">/</span>
|
||||
<a href="#" onClick="{{ goCommand }}" style="font-weight:500;color:#595959;text-decoration:none;" style-hover="color:#1677ff;">Chatballs</a><span style="color:#d9d9d9;">/</span>
|
||||
<a href="#" onClick="{{ goList }}" style="font-weight:{{ crumbWeight }};color:{{ crumbColor }};text-decoration:none;" style-hover="color:#1677ff;">Сотрудники</a>
|
||||
<sc-if value="{{ crumbTail }}" hint-placeholder-val="{{ false }}"><span style="color:#d9d9d9;">/</span><span style="font-weight:600;color:#262626;">{{ crumbTail }}</span></sc-if>
|
||||
</div>
|
||||
@@ -455,7 +455,7 @@ html,body{margin:0;padding:0;}
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;">
|
||||
<div><label style="display:block;font-size:12px;color:#8c8c8c;margin-bottom:6px;font-weight:500;">Имя</label><input placeholder="Имя и фамилия" style="width:100%;height:38px;padding:0 12px;border:1px solid #e8e8e8;border-radius:8px;font-size:13px;color:#262626;font-family:inherit;outline:none;" style-focus="border-color:#1677ff;" /></div>
|
||||
<div><label style="display:block;font-size:12px;color:#8c8c8c;margin-bottom:6px;font-weight:500;">Телефон</label><input placeholder="+7 …" style="width:100%;height:38px;padding:0 12px;border:1px solid #e8e8e8;border-radius:8px;font-size:13px;color:#262626;font-family:inherit;outline:none;" style-focus="border-color:#1677ff;" /></div>
|
||||
<div style="grid-column:span 2;"><label style="display:block;font-size:12px;color:#8c8c8c;margin-bottom:6px;font-weight:500;">Рабочий email <span style="color:#bfbfbf;">· используется для входа</span></label><input placeholder="name@edevs.tech" style="width:100%;height:38px;padding:0 12px;border:1px solid #e8e8e8;border-radius:8px;font-size:13px;color:#262626;font-family:'SF Mono',ui-monospace,Menlo,monospace;outline:none;" style-focus="border-color:#1677ff;" /></div>
|
||||
<div style="grid-column:span 2;"><label style="display:block;font-size:12px;color:#8c8c8c;margin-bottom:6px;font-weight:500;">Рабочий email <span style="color:#bfbfbf;">· используется для входа</span></label><input placeholder="name@chatballs" style="width:100%;height:38px;padding:0 12px;border:1px solid #e8e8e8;border-radius:8px;font-size:13px;color:#262626;font-family:'SF Mono',ui-monospace,Menlo,monospace;outline:none;" style-focus="border-color:#1677ff;" /></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -587,13 +587,13 @@ class Component extends DCLogic {
|
||||
};
|
||||
|
||||
DATA = [
|
||||
{ id: 'e1', name: 'Иван Петров', initials: 'ИП', avatarBg: '#1677ff', email: 'i.petrov@edevs.tech', phone: '+7 916 000 11 22', role: 'OWNER', position: 'Генеральный директор', dept: null, st: 'active', lastLogin: 'сейчас · онлайн', created: '02 фев 2026', pwdDate: '14 июн 2026', sessions: '1 устройство · Chrome (Москва)', assignments: [], load: null },
|
||||
{ id: 'e2', name: 'Анна Котова', initials: 'АК', avatarBg: '#9254de', email: 'a.kotova@edevs.tech', phone: '+7 916 245 14 02', role: 'ADMIN', position: 'Руководитель продаж', dept: null, st: 'active', lastLogin: '5 мин назад', created: '12 мая 2026', pwdDate: '28 мая 2026', sessions: '2 устройства · Chrome, Safari (Москва)', assignments: 'admin', load: { d: '2', q: '0', s: '9', r: '1м 20с' } },
|
||||
{ id: 'e3', name: 'Дмитрий Соколов', initials: 'ДС', avatarBg: '#3b82c4', email: 'd.sokolov@edevs.tech', phone: '+7 903 118 77 51', role: 'EMPLOYEE', position: 'Менеджер по продажам', dept: 'Отдел продаж', st: 'active', lastLogin: '18 мин назад', created: '20 мая 2026', pwdDate: '20 мая 2026', sessions: '1 устройство · Chrome (Москва)', assignments: [{ profile: 'Продажи · оператор', scopeType: 'DEPARTMENT', scopeName: 'Отдел продаж', caps: ['sales.view', 'sales.operate', 'customers.view', 'customers.manage', 'conversations.view', 'conversations.operate'] }], load: { d: '3', q: '0', s: '5', r: '1м 40с' } },
|
||||
{ id: 'e4', name: 'Мария Орлова', initials: 'МО', avatarBg: '#13a8a8', email: 'm.orlova@edevs.tech', phone: '+7 921 554 30 18', role: 'EMPLOYEE', position: 'Специалист поддержки', dept: 'Отдел поддержки', st: 'active', lastLogin: '1 ч назад', created: '03 июн 2026', pwdDate: '03 июн 2026', sessions: '1 устройство · Firefox (СПб)', assignments: [{ profile: 'Поддержка', scopeType: 'DEPARTMENT', scopeName: 'Отдел поддержки', caps: ['support.view', 'support.operate', 'conversations.view', 'conversations.operate'] }], load: { d: '1', q: '2', s: '0', r: '2м 05с' } },
|
||||
{ id: 'e5', name: 'Павел Верхов', initials: 'ПВ', avatarBg: '#d4784b', email: 'p.verkhov@edevs.tech', phone: '+7 917 903 66 40', role: 'EMPLOYEE', position: 'Аналитик продаж', dept: 'Отдел продаж', st: 'active', lastLogin: '2 ч назад', created: '11 июн 2026', pwdDate: '11 июн 2026', sessions: '1 устройство · Chrome (Казань)', assignments: [{ profile: 'Продажи · оператор', scopeType: 'DEPARTMENT', scopeName: 'Отдел продаж', caps: ['sales.view', 'sales.operate', 'customers.view'] }, { profile: 'Продукты · чтение', scopeType: 'ORGANIZATION', scopeName: null, caps: ['products.view'] }], load: null },
|
||||
{ id: 'e6', name: 'Сергей Лебедев', initials: 'СЛ', avatarBg: '#bfbfbf', email: 's.lebedev@edevs.tech', phone: '—', role: 'EMPLOYEE', position: 'Менеджер по продажам', dept: 'Отдел продаж', st: 'invited', lastLogin: 'не входил', created: '09 июл 2026', pwdDate: '—', sessions: 'нет активных сессий', assignments: [], load: null },
|
||||
{ id: 'e7', name: 'Ольга Зайцева', initials: 'ОЗ', avatarBg: '#c4456b', email: 'o.zaytseva@edevs.tech', phone: '+7 905 771 22 09', role: 'EMPLOYEE', position: 'Контент-менеджер', dept: null, st: 'blocked', lastLogin: '3 дня назад', created: '18 апр 2026', pwdDate: '01 июн 2026', sessions: 'нет активных сессий', assignments: [], load: null },
|
||||
{ id: 'e1', name: 'Иван Петров', initials: 'ИП', avatarBg: '#1677ff', email: 'i.petrov@chatballs', phone: '+7 916 000 11 22', role: 'OWNER', position: 'Генеральный директор', dept: null, st: 'active', lastLogin: 'сейчас · онлайн', created: '02 фев 2026', pwdDate: '14 июн 2026', sessions: '1 устройство · Chrome (Москва)', assignments: [], load: null },
|
||||
{ id: 'e2', name: 'Анна Котова', initials: 'АК', avatarBg: '#9254de', email: 'a.kotova@chatballs', phone: '+7 916 245 14 02', role: 'ADMIN', position: 'Руководитель продаж', dept: null, st: 'active', lastLogin: '5 мин назад', created: '12 мая 2026', pwdDate: '28 мая 2026', sessions: '2 устройства · Chrome, Safari (Москва)', assignments: 'admin', load: { d: '2', q: '0', s: '9', r: '1м 20с' } },
|
||||
{ id: 'e3', name: 'Дмитрий Соколов', initials: 'ДС', avatarBg: '#3b82c4', email: 'd.sokolov@chatballs', phone: '+7 903 118 77 51', role: 'EMPLOYEE', position: 'Менеджер по продажам', dept: 'Отдел продаж', st: 'active', lastLogin: '18 мин назад', created: '20 мая 2026', pwdDate: '20 мая 2026', sessions: '1 устройство · Chrome (Москва)', assignments: [{ profile: 'Продажи · оператор', scopeType: 'DEPARTMENT', scopeName: 'Отдел продаж', caps: ['sales.view', 'sales.operate', 'customers.view', 'customers.manage', 'conversations.view', 'conversations.operate'] }], load: { d: '3', q: '0', s: '5', r: '1м 40с' } },
|
||||
{ id: 'e4', name: 'Мария Орлова', initials: 'МО', avatarBg: '#13a8a8', email: 'm.orlova@chatballs', phone: '+7 921 554 30 18', role: 'EMPLOYEE', position: 'Специалист поддержки', dept: 'Отдел поддержки', st: 'active', lastLogin: '1 ч назад', created: '03 июн 2026', pwdDate: '03 июн 2026', sessions: '1 устройство · Firefox (СПб)', assignments: [{ profile: 'Поддержка', scopeType: 'DEPARTMENT', scopeName: 'Отдел поддержки', caps: ['support.view', 'support.operate', 'conversations.view', 'conversations.operate'] }], load: { d: '1', q: '2', s: '0', r: '2м 05с' } },
|
||||
{ id: 'e5', name: 'Павел Верхов', initials: 'ПВ', avatarBg: '#d4784b', email: 'p.verkhov@chatballs', phone: '+7 917 903 66 40', role: 'EMPLOYEE', position: 'Аналитик продаж', dept: 'Отдел продаж', st: 'active', lastLogin: '2 ч назад', created: '11 июн 2026', pwdDate: '11 июн 2026', sessions: '1 устройство · Chrome (Казань)', assignments: [{ profile: 'Продажи · оператор', scopeType: 'DEPARTMENT', scopeName: 'Отдел продаж', caps: ['sales.view', 'sales.operate', 'customers.view'] }, { profile: 'Продукты · чтение', scopeType: 'ORGANIZATION', scopeName: null, caps: ['products.view'] }], load: null },
|
||||
{ id: 'e6', name: 'Сергей Лебедев', initials: 'СЛ', avatarBg: '#bfbfbf', email: 's.lebedev@chatballs', phone: '—', role: 'EMPLOYEE', position: 'Менеджер по продажам', dept: 'Отдел продаж', st: 'invited', lastLogin: 'не входил', created: '09 июл 2026', pwdDate: '—', sessions: 'нет активных сессий', assignments: [], load: null },
|
||||
{ id: 'e7', name: 'Ольга Зайцева', initials: 'ОЗ', avatarBg: '#c4456b', email: 'o.zaytseva@chatballs', phone: '+7 905 771 22 09', role: 'EMPLOYEE', position: 'Контент-менеджер', dept: null, st: 'blocked', lastLogin: '3 дня назад', created: '18 апр 2026', pwdDate: '01 июн 2026', sessions: 'нет активных сессий', assignments: [], load: null },
|
||||
];
|
||||
|
||||
REG = [
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# CustoCRM Design System
|
||||
# Chatballs Design System
|
||||
|
||||
Статический справочник текущего frontend UI. React, сборка и установка зависимостей не требуются.
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
Из корня репозитория:
|
||||
|
||||
```powershell
|
||||
Start-Process .\apps\internal-ui\design-system\index.html
|
||||
Start-Process .\design\design-system\index.html
|
||||
```
|
||||
|
||||
Для просмотра через локальный HTTP-сервер:
|
||||
|
||||
```powershell
|
||||
python -m http.server 8080 --directory .\apps\internal-ui\design-system
|
||||
python -m http.server 8080 --directory .\design\design-system
|
||||
Start-Process http://localhost:8080
|
||||
```
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
function installIconSprite() {
|
||||
if (!window.CUSTOCRM_ICON_SPRITE || document.querySelector("[data-custocrm-icon-sprite]")) return;
|
||||
if (!window.CHATBALLS_ICON_SPRITE || document.querySelector("[data-chatballs-icon-sprite]")) return;
|
||||
const container = document.createElement("div");
|
||||
container.hidden = true;
|
||||
container.dataset.custocrmIconSprite = "";
|
||||
container.innerHTML = window.CUSTOCRM_ICON_SPRITE;
|
||||
container.dataset.chatballsIconSprite = "";
|
||||
container.innerHTML = window.CHATBALLS_ICON_SPRITE;
|
||||
document.body.prepend(container);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ function buildSidebar() {
|
||||
sidebar.innerHTML = `
|
||||
<a class="ds-brand" href="index.html">
|
||||
<span class="ds-brand-mark">C</span>
|
||||
<span><strong>CustoCRM</strong><small>Design System</small></span>
|
||||
<span><strong>Chatballs</strong><small>Design System</small></span>
|
||||
</a>
|
||||
<nav class="ds-nav" aria-label="Разделы дизайн-системы">${nav}</nav>
|
||||
<div class="ds-sidebar-footer">Статический каталог текущего frontend UI.<br>Источник: <code>apps/internal-ui/src</code></div>
|
||||
@@ -124,7 +124,7 @@ function addCopyButtons() {
|
||||
|
||||
function renderInventory() {
|
||||
const body = document.querySelector("[data-inventory-body]");
|
||||
const payload = window.CUSTOCRM_INVENTORY;
|
||||
const payload = window.CHATBALLS_INVENTORY;
|
||||
if (!body || !payload) return;
|
||||
|
||||
body.innerHTML = payload.items.map((item) => {
|
||||
|
||||
@@ -1 +1 @@
|
||||
window.CUSTOCRM_ICON_SPRITE="<svg xmlns=\"http://www.w3.org/2000/svg\">\n <symbol id=\"i-grid\" viewBox=\"0 0 24 24\"><rect x=\"3\" y=\"3\" width=\"7\" height=\"9\" rx=\"1.4\"/><rect x=\"14\" y=\"3\" width=\"7\" height=\"5\" rx=\"1.4\"/><rect x=\"14\" y=\"12\" width=\"7\" height=\"9\" rx=\"1.4\"/><rect x=\"3\" y=\"16\" width=\"7\" height=\"5\" rx=\"1.4\"/></symbol>\n <symbol id=\"i-box\" viewBox=\"0 0 24 24\"><path d=\"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z\"/><path d=\"m3.3 7 8.7 5 8.7-5M12 22V12\"/></symbol>\n <symbol id=\"i-list\" viewBox=\"0 0 24 24\"><path d=\"M8 6h10M8 12h10M8 18h10\"/><circle cx=\"4\" cy=\"6\" r=\"1\"/><circle cx=\"4\" cy=\"12\" r=\"1\"/><circle cx=\"4\" cy=\"18\" r=\"1\"/></symbol>\n <symbol id=\"i-columns\" viewBox=\"0 0 24 24\"><rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\"/><rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\"/><rect x=\"14\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\"/><rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\"/></symbol>\n <symbol id=\"i-plus\" viewBox=\"0 0 24 24\"><path d=\"M12 5v14M5 12h14\"/></symbol>\n <symbol id=\"i-search\" viewBox=\"0 0 24 24\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21-4.35-4.35\"/></symbol>\n <symbol id=\"i-more\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"5\" r=\"1\"/><circle cx=\"12\" cy=\"12\" r=\"1\"/><circle cx=\"12\" cy=\"19\" r=\"1\"/></symbol>\n <symbol id=\"i-chevron\" viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"/></symbol>\n <symbol id=\"i-bell\" viewBox=\"0 0 24 24\"><path d=\"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9M10.3 21a1.94 1.94 0 0 0 3.4 0\"/></symbol>\n <symbol id=\"i-edit\" viewBox=\"0 0 24 24\"><path d=\"M12 20h9M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/></symbol>\n <symbol id=\"i-trash\" viewBox=\"0 0 24 24\"><path d=\"M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\"/></symbol>\n <symbol id=\"i-warning\" viewBox=\"0 0 24 24\"><path d=\"m21.7 18-8-14a2 2 0 0 0-3.5 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.7-3Z\"/><path d=\"M12 9v4M12 17h.01\"/></symbol>\n <symbol id=\"i-check\" viewBox=\"0 0 24 24\"><path d=\"m20 6-11 11-5-5\"/></symbol>\n <symbol id=\"i-user\" viewBox=\"0 0 24 24\"><path d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\"/><circle cx=\"12\" cy=\"7\" r=\"4\"/></symbol>\n <symbol id=\"i-settings\" viewBox=\"0 0 24 24\"><path d=\"M21 6H9M3 6h2M21 12h-8M3 12h6M21 18h-6M3 18h8\"/><circle cx=\"7\" cy=\"6\" r=\"2\"/><circle cx=\"11\" cy=\"12\" r=\"2\"/><circle cx=\"13\" cy=\"18\" r=\"2\"/></symbol>\n <symbol id=\"i-message\" viewBox=\"0 0 24 24\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2Z\"/></symbol>\n <symbol id=\"i-copy\" viewBox=\"0 0 24 24\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></symbol>\n</svg>\n";
|
||||
window.CHATBALLS_ICON_SPRITE="<svg xmlns=\"http://www.w3.org/2000/svg\">\n <symbol id=\"i-grid\" viewBox=\"0 0 24 24\"><rect x=\"3\" y=\"3\" width=\"7\" height=\"9\" rx=\"1.4\"/><rect x=\"14\" y=\"3\" width=\"7\" height=\"5\" rx=\"1.4\"/><rect x=\"14\" y=\"12\" width=\"7\" height=\"9\" rx=\"1.4\"/><rect x=\"3\" y=\"16\" width=\"7\" height=\"5\" rx=\"1.4\"/></symbol>\n <symbol id=\"i-box\" viewBox=\"0 0 24 24\"><path d=\"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z\"/><path d=\"m3.3 7 8.7 5 8.7-5M12 22V12\"/></symbol>\n <symbol id=\"i-list\" viewBox=\"0 0 24 24\"><path d=\"M8 6h10M8 12h10M8 18h10\"/><circle cx=\"4\" cy=\"6\" r=\"1\"/><circle cx=\"4\" cy=\"12\" r=\"1\"/><circle cx=\"4\" cy=\"18\" r=\"1\"/></symbol>\n <symbol id=\"i-columns\" viewBox=\"0 0 24 24\"><rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\"/><rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\"/><rect x=\"14\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\"/><rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\"/></symbol>\n <symbol id=\"i-plus\" viewBox=\"0 0 24 24\"><path d=\"M12 5v14M5 12h14\"/></symbol>\n <symbol id=\"i-search\" viewBox=\"0 0 24 24\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21-4.35-4.35\"/></symbol>\n <symbol id=\"i-more\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"5\" r=\"1\"/><circle cx=\"12\" cy=\"12\" r=\"1\"/><circle cx=\"12\" cy=\"19\" r=\"1\"/></symbol>\n <symbol id=\"i-chevron\" viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"/></symbol>\n <symbol id=\"i-bell\" viewBox=\"0 0 24 24\"><path d=\"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9M10.3 21a1.94 1.94 0 0 0 3.4 0\"/></symbol>\n <symbol id=\"i-edit\" viewBox=\"0 0 24 24\"><path d=\"M12 20h9M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/></symbol>\n <symbol id=\"i-trash\" viewBox=\"0 0 24 24\"><path d=\"M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\"/></symbol>\n <symbol id=\"i-warning\" viewBox=\"0 0 24 24\"><path d=\"m21.7 18-8-14a2 2 0 0 0-3.5 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.7-3Z\"/><path d=\"M12 9v4M12 17h.01\"/></symbol>\n <symbol id=\"i-check\" viewBox=\"0 0 24 24\"><path d=\"m20 6-11 11-5-5\"/></symbol>\n <symbol id=\"i-user\" viewBox=\"0 0 24 24\"><path d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\"/><circle cx=\"12\" cy=\"7\" r=\"4\"/></symbol>\n <symbol id=\"i-settings\" viewBox=\"0 0 24 24\"><path d=\"M21 6H9M3 6h2M21 12h-8M3 12h6M21 18h-6M3 18h8\"/><circle cx=\"7\" cy=\"6\" r=\"2\"/><circle cx=\"11\" cy=\"12\" r=\"2\"/><circle cx=\"13\" cy=\"18\" r=\"2\"/></symbol>\n <symbol id=\"i-message\" viewBox=\"0 0 24 24\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2Z\"/></symbol>\n <symbol id=\"i-copy\" viewBox=\"0 0 24 24\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></symbol>\n</svg>\n";
|
||||
@@ -1 +1 @@
|
||||
window.CUSTOCRM_INVENTORY={"version":"0.1.0","generatedFrom":"apps/internal-ui/src","generatedOn":"2026-07-30","count":315,"items":[{"name":"Link","kind":"CSS component","category":"Actions","scope":"System","visibility":"system","source":"src/shared/links.css","variants":"base, strong, neutral, muted, mono, icon","documentedAt":"components.html"},{"name":"AppDropdown","kind":"CSS pattern","category":"Overlays","scope":"System","visibility":"system","source":"src/shared/menu.css","variants":"default, wide, channels, warning, danger, success","documentedAt":"patterns.html"},{"name":"BaselineTable","kind":"CSS pattern","category":"Tables","scope":"System","visibility":"system","source":"src/shared/table-controls.css","variants":"header, row hover, numeric, actions","documentedAt":"patterns.html"},{"name":"FilterBar","kind":"CSS pattern","category":"Tables","scope":"System","visibility":"system","source":"src/shared/table-controls.css","variants":"default, employees","documentedAt":"patterns.html"},{"name":"TableCard","kind":"CSS pattern","category":"Tables","scope":"System","visibility":"system","source":"src/shared/table-controls.css","variants":"default, scroll, footer","documentedAt":"patterns.html"},{"name":"ApplicationShell","kind":"Layout pattern","category":"Layouts","scope":"System","visibility":"system","source":"src/layout/*.css","variants":"sidebar, topbar, scroll, page","documentedAt":"layouts.html"},{"name":"ConversationWorkspacePattern","kind":"Page pattern","category":"Layouts","scope":"System","visibility":"system","source":"features/conversations","variants":"dialog list, thread, context","documentedAt":"layouts.html"},{"name":"DetailPage","kind":"Page pattern","category":"Layouts","scope":"System","visibility":"system","source":"feature detail pages","variants":"header, main content, rail","documentedAt":"layouts.html"},{"name":"ListPage","kind":"Page pattern","category":"Layouts","scope":"System","visibility":"system","source":"feature list pages","variants":"header, filters, table, pagination","documentedAt":"layouts.html"},{"name":"SettingsPagePattern","kind":"Page pattern","category":"Layouts","scope":"System","visibility":"system","source":"settings/profile/administration","variants":"section cards, forms, local actions","documentedAt":"layouts.html"},{"name":"App","kind":"React component","category":"Application","scope":"Application","visibility":"exported","source":"apps/internal-ui/src/App.tsx","variants":"—","documentedAt":""},{"name":"SurfaceApp","kind":"React component","category":"Application","scope":"Application","visibility":"local","source":"apps/internal-ui/src/main.tsx","variants":"—","documentedAt":""},{"name":"AdministrationPage","kind":"React component","category":"Feature: administration","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/administration/AdministrationPage.tsx","variants":"—","documentedAt":""},{"name":"AuditTable","kind":"React component","category":"Feature: administration","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/administration/AuditTable.tsx","variants":"—","documentedAt":""},{"name":"CloudSubscriptionPanel","kind":"React component","category":"Feature: administration","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/administration/CloudSubscriptionPanel.tsx","variants":"—","documentedAt":""},{"name":"OrganizationLogoField","kind":"React component","category":"Feature: administration","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/administration/OrganizationLogoField.tsx","variants":"—","documentedAt":""},{"name":"OrganizationSettingsForm","kind":"React component","category":"Feature: administration","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/administration/OrganizationSettingsForm.tsx","variants":"—","documentedAt":""},{"name":"AgentEditForm","kind":"React component","category":"Feature: ai","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/ai/detail/AgentEditForm.tsx","variants":"—","documentedAt":""},{"name":"AgentsKpiStrip","kind":"React component","category":"Feature: ai","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/ai/AgentsKpiStrip.tsx","variants":"—","documentedAt":""},{"name":"AgentsTable","kind":"React component","category":"Feature: ai","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/ai/AgentsTable.tsx","variants":"—","documentedAt":""},{"name":"AiAgentCreatePage","kind":"React component","category":"Feature: ai","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/ai/create/AiAgentCreatePage.tsx","variants":"—","documentedAt":""},{"name":"AiAgentDetailHeader","kind":"React component","category":"Feature: ai","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/ai/detail/AiAgentDetaLine truncated
|
||||
window.CHATBALLS_INVENTORY={"version":"0.1.0","generatedFrom":"apps/internal-ui/src","generatedOn":"2026-07-30","count":315,"items":[{"name":"Link","kind":"CSS component","category":"Actions","scope":"System","visibility":"system","source":"src/shared/links.css","variants":"base, strong, neutral, muted, mono, icon","documentedAt":"components.html"},{"name":"AppDropdown","kind":"CSS pattern","category":"Overlays","scope":"System","visibility":"system","source":"src/shared/menu.css","variants":"default, wide, channels, warning, danger, success","documentedAt":"patterns.html"},{"name":"BaselineTable","kind":"CSS pattern","category":"Tables","scope":"System","visibility":"system","source":"src/shared/table-controls.css","variants":"header, row hover, numeric, actions","documentedAt":"patterns.html"},{"name":"FilterBar","kind":"CSS pattern","category":"Tables","scope":"System","visibility":"system","source":"src/shared/table-controls.css","variants":"default, employees","documentedAt":"patterns.html"},{"name":"TableCard","kind":"CSS pattern","category":"Tables","scope":"System","visibility":"system","source":"src/shared/table-controls.css","variants":"default, scroll, footer","documentedAt":"patterns.html"},{"name":"ApplicationShell","kind":"Layout pattern","category":"Layouts","scope":"System","visibility":"system","source":"src/layout/*.css","variants":"sidebar, topbar, scroll, page","documentedAt":"layouts.html"},{"name":"ConversationWorkspacePattern","kind":"Page pattern","category":"Layouts","scope":"System","visibility":"system","source":"features/conversations","variants":"dialog list, thread, context","documentedAt":"layouts.html"},{"name":"DetailPage","kind":"Page pattern","category":"Layouts","scope":"System","visibility":"system","source":"feature detail pages","variants":"header, main content, rail","documentedAt":"layouts.html"},{"name":"ListPage","kind":"Page pattern","category":"Layouts","scope":"System","visibility":"system","source":"feature list pages","variants":"header, filters, table, pagination","documentedAt":"layouts.html"},{"name":"SettingsPagePattern","kind":"Page pattern","category":"Layouts","scope":"System","visibility":"system","source":"settings/profile/administration","variants":"section cards, forms, local actions","documentedAt":"layouts.html"},{"name":"App","kind":"React component","category":"Application","scope":"Application","visibility":"exported","source":"apps/internal-ui/src/App.tsx","variants":"—","documentedAt":""},{"name":"SurfaceApp","kind":"React component","category":"Application","scope":"Application","visibility":"local","source":"apps/internal-ui/src/main.tsx","variants":"—","documentedAt":""},{"name":"AdministrationPage","kind":"React component","category":"Feature: administration","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/administration/AdministrationPage.tsx","variants":"—","documentedAt":""},{"name":"AuditTable","kind":"React component","category":"Feature: administration","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/administration/AuditTable.tsx","variants":"—","documentedAt":""},{"name":"CloudSubscriptionPanel","kind":"React component","category":"Feature: administration","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/administration/CloudSubscriptionPanel.tsx","variants":"—","documentedAt":""},{"name":"OrganizationLogoField","kind":"React component","category":"Feature: administration","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/administration/OrganizationLogoField.tsx","variants":"—","documentedAt":""},{"name":"OrganizationSettingsForm","kind":"React component","category":"Feature: administration","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/administration/OrganizationSettingsForm.tsx","variants":"—","documentedAt":""},{"name":"AgentEditForm","kind":"React component","category":"Feature: ai","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/ai/detail/AgentEditForm.tsx","variants":"—","documentedAt":""},{"name":"AgentsKpiStrip","kind":"React component","category":"Feature: ai","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/ai/AgentsKpiStrip.tsx","variants":"—","documentedAt":""},{"name":"AgentsTable","kind":"React component","category":"Feature: ai","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/ai/AgentsTable.tsx","variants":"—","documentedAt":""},{"name":"AiAgentCreatePage","kind":"React component","category":"Feature: ai","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/ai/create/AiAgentCreatePage.tsx","variants":"—","documentedAt":""},{"name":"AiAgentDetailHeader","kind":"React component","category":"Feature: ai","scope":"Feature","visibility":"exported","source":"apps/internal-ui/src/features/ai/detail/AiAgentDetLine truncated
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Компоненты · CustoCRM Design System</title>
|
||||
<title>Компоненты · Chatballs Design System</title>
|
||||
<link rel="stylesheet" href="assets/base.css">
|
||||
<link rel="stylesheet" href="assets/docs.css">
|
||||
<link rel="stylesheet" href="assets/components.css">
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Данные и статусы · CustoCRM Design System</title>
|
||||
<title>Данные и статусы · Chatballs Design System</title>
|
||||
<link rel="stylesheet" href="assets/base.css">
|
||||
<link rel="stylesheet" href="assets/docs.css">
|
||||
<link rel="stylesheet" href="assets/components.css">
|
||||
@@ -77,7 +77,7 @@
|
||||
<div class="ds-specimen-header"><strong>ProductTag</strong><code>productAccent()</code></div>
|
||||
<div class="ds-specimen-body">
|
||||
<span class="product-tag" style="color:#722ed1;background:#f9f0ff"><i style="background:#722ed1"></i>FoxRay</span>
|
||||
<span class="product-tag" style="color:#0958d9;background:#e6f4ff"><i style="background:#0958d9"></i>CustoCRM</span>
|
||||
<span class="product-tag" style="color:#0958d9;background:#e6f4ff"><i style="background:#0958d9"></i>Chatballs</span>
|
||||
<span class="product-tag" style="color:#0958d9;background:#e6f4ff"><i style="background:#0958d9"></i>FirePage</span>
|
||||
</div>
|
||||
</article>
|
||||
@@ -85,7 +85,7 @@
|
||||
<div class="ds-specimen-header"><strong>ProductMark</strong><code>ProductMark</code></div>
|
||||
<div class="ds-specimen-body">
|
||||
<span class="product-mark"><i style="background:#722ed1"></i>FoxRay</span>
|
||||
<span class="product-mark"><i style="background:#0958d9"></i>CustoCRM</span>
|
||||
<span class="product-mark"><i style="background:#0958d9"></i>Chatballs</span>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Токены · CustoCRM Design System</title>
|
||||
<title>Токены · Chatballs Design System</title>
|
||||
<link rel="stylesheet" href="assets/base.css">
|
||||
<link rel="stylesheet" href="assets/docs.css">
|
||||
<link rel="stylesheet" href="assets/components.css">
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>CustoCRM Design System</title>
|
||||
<title>Chatballs Design System</title>
|
||||
<link rel="stylesheet" href="assets/base.css">
|
||||
<link rel="stylesheet" href="assets/docs.css">
|
||||
<link rel="stylesheet" href="assets/components.css">
|
||||
@@ -23,9 +23,9 @@
|
||||
<main class="ds-content">
|
||||
<header class="ds-page-header">
|
||||
<div>
|
||||
<div class="ds-eyebrow">CustoCRM UI inventory</div>
|
||||
<div class="ds-eyebrow">Chatballs UI inventory</div>
|
||||
<h1>Дизайн-система текущего фронтенда</h1>
|
||||
<p>Статический справочник существующих токенов, компонентов, паттернов и компоновок CustoCRM. Примеры повторяют действующие CSS-классы и визуальные решения из <code>apps/internal-ui/src</code>.</p>
|
||||
<p>Статический справочник существующих токенов, компонентов, паттернов и компоновок Chatballs. Примеры повторяют действующие CSS-классы и визуальные решения из <code>apps/internal-ui/src</code>.</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Инвентарь · CustoCRM Design System</title>
|
||||
<title>Инвентарь · Chatballs Design System</title>
|
||||
<link rel="stylesheet" href="assets/base.css">
|
||||
<link rel="stylesheet" href="assets/docs.css">
|
||||
<link rel="stylesheet" href="assets/components.css">
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Макеты страниц · CustoCRM Design System</title>
|
||||
<title>Макеты страниц · Chatballs Design System</title>
|
||||
<link rel="stylesheet" href="assets/base.css">
|
||||
<link rel="stylesheet" href="assets/docs.css">
|
||||
<link rel="stylesheet" href="assets/components.css">
|
||||
@@ -36,7 +36,7 @@
|
||||
</div>
|
||||
<div class="layout-preview mini-shell">
|
||||
<aside class="mini-sidebar">
|
||||
<div class="mini-brand"><i>C</i>CustoCRM</div>
|
||||
<div class="mini-brand"><i>C</i>Chatballs</div>
|
||||
<nav class="mini-nav">
|
||||
<span><svg class="icon"><use href="#i-grid"></use></svg>Обзор</span>
|
||||
<span><svg class="icon"><use href="#i-message"></use></svg>Диалоги</span>
|
||||
@@ -122,7 +122,7 @@
|
||||
<div class="thread-messages"><div class="message-bubble">Здравствуйте! Подскажите, какой тариф подходит для двух агентов?</div><div class="message-bubble own">Для двух активных ИИ-агентов подойдёт тариф Startup.</div></div>
|
||||
<footer class="thread-composer"><i></i><button class="ui-icon-button" aria-label="Отправить"><svg class="icon"><use href="#i-message"></use></svg></button></footer>
|
||||
</section>
|
||||
<aside class="conversation-context"><h4 style="margin:0 0 14px;font-size:11px">Контекст</h4><div class="key-value" style="margin-bottom:12px"><span>Продукт</span><strong>CustoCRM</strong></div><div class="key-value" style="margin-bottom:12px"><span>Канал</span><strong>Telegram</strong></div><div class="key-value"><span>Статус</span><strong>Открыт</strong></div></aside>
|
||||
<aside class="conversation-context"><h4 style="margin:0 0 14px;font-size:11px">Контекст</h4><div class="key-value" style="margin-bottom:12px"><span>Продукт</span><strong>Chatballs</strong></div><div class="key-value" style="margin-bottom:12px"><span>Канал</span><strong>Telegram</strong></div><div class="key-value"><span>Статус</span><strong>Открыт</strong></div></aside>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Паттерны · CustoCRM Design System</title>
|
||||
<title>Паттерны · Chatballs Design System</title>
|
||||
<link rel="stylesheet" href="assets/base.css">
|
||||
<link rel="stylesheet" href="assets/docs.css">
|
||||
<link rel="stylesheet" href="assets/components.css">
|
||||
@@ -63,10 +63,10 @@
|
||||
<thead><tr><th>Сотрудник</th><th>Роль</th><th>Статус</th><th>Продукты</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><div class="person-cell"><span class="avatar">АЕ</span><div><a class="link is-neutral is-strong" href="#">Андрей Ермолаев</a><small>andrey@edevs.tech</small></div></div></td>
|
||||
<td><div class="person-cell"><span class="avatar">АЕ</span><div><a class="link is-neutral is-strong" href="#">Андрей Ермолаев</a><small>andrey@example.com</small></div></div></td>
|
||||
<td><span class="role-badge owner">Владелец</span></td>
|
||||
<td><span class="status-pill is-active"><i></i>Активен</span></td>
|
||||
<td><span class="product-mark"><i style="background:#0958d9"></i>CustoCRM</span></td>
|
||||
<td><span class="product-mark"><i style="background:#0958d9"></i>Chatballs</span></td>
|
||||
<td><button class="row-menu-button" aria-label="Меню"><svg class="icon"><use href="#i-more"></use></svg></button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
File renamed without changes.
Reference in new issue
Block a user