@@ -83,30 +83,28 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
@@ -115,7 +113,6 @@
-
\ No newline at end of file
+
+.modal {
+ background: #fff;
+ border-radius: 6px;
+ box-shadow: 0 4px 16px rgba(0,0,0,0.10);
+ padding: 18px 16px 14px 16px;
+ min-width: 320px;
+ max-width: 98vw;
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+}
+
+.modal h4 {
+ margin: 0 0 6px 0;
+ font-size: 1.08rem;
+ font-weight: 600;
+}
+
+.modal label {
+ font-size: 0.98rem;
+ color: #374151;
+ margin-bottom: 1px;
+}
+
+.modal-actions {
+ display: flex;
+ gap: 8px;
+ margin-top: 8px;
+}
+
+.notion-table td:empty::after {
+ content: '—';
+ color: #b0b0b0;
+ font-style: italic;
+}
+
+@media (max-width: 700px) {
+ .notion-table-wrapper, .table-filters-el {
+ padding: 4px 1vw;
+ max-width: 100vw;
+ }
+ .modal {
+ min-width: 90vw;
+ padding: 10px 2vw;
+ }
+ .notion-table th, .notion-table td {
+ padding: 4px 2px;
+ font-size: 0.95rem;
+ }
+}
+
\ No newline at end of file
diff --git a/frontend/src/components/tables/UserTablesList.vue b/frontend/src/components/tables/UserTablesList.vue
index 46880c1..32e7805 100644
--- a/frontend/src/components/tables/UserTablesList.vue
+++ b/frontend/src/components/tables/UserTablesList.vue
@@ -6,7 +6,7 @@
-
-
+
-
@@ -40,9 +40,6 @@ function selectTable(table) {
function createTable() {
router.push({ name: 'create-table' });
}
-function goToTagsTable() {
- router.push({ name: 'tags-table-view' });
-}
\ No newline at end of file
diff --git a/frontend/src/views/tables/EditTableView.vue b/frontend/src/views/tables/EditTableView.vue
index 2bf493c..3758dc3 100644
--- a/frontend/src/views/tables/EditTableView.vue
+++ b/frontend/src/views/tables/EditTableView.vue
@@ -24,7 +24,7 @@
import { ref, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import BaseLayout from '../../components/BaseLayout.vue';
-import axios from 'axios';
+import tablesService from '@/services/tablesService';
const $route = useRoute();
const router = useRouter();
const name = ref('');
@@ -32,14 +32,14 @@ const description = ref('');
const isRagSourceId = ref(2);
onMounted(async () => {
- const { data } = await axios.get(`/tables/${$route.params.id}`);
+ const data = await tablesService.getTable($route.params.id);
name.value = data.name;
description.value = data.description;
isRagSourceId.value = data.is_rag_source_id || 2;
});
async function save() {
- await axios.patch(`/api/tables/${$route.params.id}`, {
+ await tablesService.updateTable($route.params.id, {
name: name.value,
description: description.value,
isRagSourceId: isRagSourceId.value
diff --git a/frontend/src/views/tables/TablesListView.vue b/frontend/src/views/tables/TablesListView.vue
index 60561b2..79bffbf 100644
--- a/frontend/src/views/tables/TablesListView.vue
+++ b/frontend/src/views/tables/TablesListView.vue
@@ -14,7 +14,6 @@ import BaseLayout from '../../components/BaseLayout.vue';
import UserTablesList from '../../components/tables/UserTablesList.vue';
import { useRouter } from 'vue-router';
import { useAuthContext } from '@/composables/useAuth';
-// import TagsTableView from '../../components/tables/TagsTableView.vue'; // больше не используется
const router = useRouter();
const { isAdmin } = useAuthContext();
function goBack() {
diff --git a/frontend/src/views/tables/TagsTableViewPage.vue b/frontend/src/views/tables/TagsTableViewPage.vue
deleted file mode 100644
index f6e5cc1..0000000
--- a/frontend/src/views/tables/TagsTableViewPage.vue
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
index 46a07df..011ace3 100644
--- a/frontend/vite.config.js
+++ b/frontend/vite.config.js
@@ -47,6 +47,15 @@ export default defineConfig({
secure: false,
credentials: true,
rewrite: (path) => path,
+ ws: true,
+ },
+ '/ws': {
+ target: 'ws://dapp-backend:8000',
+ ws: true,
+ changeOrigin: true,
+ secure: false,
+ credentials: true,
+ rewrite: (path) => path,
},
},
watch: {
diff --git a/md/rag-assistant-details.md b/md/rag-assistant-details.md
new file mode 100644
index 0000000..d40b1c8
--- /dev/null
+++ b/md/rag-assistant-details.md
@@ -0,0 +1,95 @@
+# VC HB3 - Accelerator: Детали задания для ИИ-ассистента
+
+## 1. Описание проекта
+VC HB3 - Accelerator — это венчурный фонд и поставщик софта, который с помощью акселерационных программ помогает предпринимателям создавать токенизированные стартапы во всех отраслях. Фонд объединяет предпринимателей из разных юрисдикций, предоставляет инструменты для токенизации, прозрачных инвестиций и управления цифровыми юридическими лицами.
+
+## 2. Цели и задачи ИИ-ассистента
+- Помогать клиентам быстро находить ответы на вопросы о продуктах, услугах и условиях фонда.
+- Предлагать релевантные продукты и услуги на основе сегментации клиентов.
+- Автоматизировать консультации, обработку типовых запросов и навигацию по возможностям фонда.
+- Содействовать формированию групп акселератора и информировать о возможностях участия.
+
+## 3. Сегментация клиентов
+ИИ-ассистент должен различать следующие основные сегменты клиентов:
+
+### 3.1. Предприниматели
+- Интересуются запуском стартапа, токенизацией бизнеса, участием в акселераторе.
+- Могут быть из разных юрисдикций и отраслей.
+- Ищут инструменты для управления, учета, приема платежей, автоматизации.
+
+### 3.2. LP (Liquidity Providers)
+- Инвесторы, желающие получить доступ к метрикам DLE, ранним инвестициям, доле в фонде.
+- Интересуются прозрачностью, возвратом инвестиций, управлением токенами.
+
+### 3.3. Стартапы-участники акселератора
+- Уже приобрели софт, участвуют в акселерационных программах.
+- Ищут финансирование, экспертизу, партнерство.
+
+### 3.4. Холдеры админ токенов
+- Заинтересованы в управлении фондом, получении обновлений, возврате средств.
+
+### 3.5. Регуляторы и партнеры
+- Интересуются прозрачностью, юридическими аспектами, сотрудничеством.
+
+## 4. Примеры типовых запросов и сценариев
+- Как установить и настроить софт?
+- Как получить финансирование для стартапа?
+- Как стать участником акселератора?
+- Как LP может получить доступ к метрикам?
+- Как вернуть средства за админ токены?
+
+---
+
+## 5. RAG-таблица (для дальнейшего наполнения)
+| Вопрос | Ответ | Категория |
+|--------|-------|-----------|
+| | | |
+
+## 6. Сценарии взаимодействия
+(заполняется по мере детализации бизнес-процессов)
+
+## 7. Использование тегов для сегментации и персонализации
+Для каждого вопроса и ответа в RAG-таблице добавляется столбец с мультивыбором тегов клиентов. Это позволяет:
+- Связывать вопросы и ответы с определёнными сегментами пользователей (например, предприниматель, LP, стартап, холдер, регулятор, отрасль, регион и т.д.).
+- Персонализировать рекомендации ассистента на основе тегов пользователя.
+- Масштабировать базу знаний, добавляя новые теги и сегменты по мере развития проекта.
+
+**Пример расширенной структуры RAG-таблицы:**
+| Вопрос | Ответ | Категория | Теги клиентов |
+|--------|-------|-----------|--------------|
+| Как получить финансирование? | ... | Инвестиции | предприниматель, стартап, акселератор |
+| Как вернуть средства за токены? | ... | Тарифы | холдер, LP |
+| Как установить софт? | ... | Продукт | предприниматель, стартап |
+
+## 8. Фильтры для работы с таблицами
+Для удобства редактирования и поиска в таблицах реализуются фильтры:
+- По тегам клиентов (мультивыбор).
+- По категориям вопросов/ответов.
+- По продуктам и услугам.
+- По статусу (активен, архив и др.).
+
+Фильтры позволяют быстро находить, редактировать и анализировать релевантные записи, а также персонализировать отображение данных для разных ролей пользователей.
+
+## 9. Пользовательские таблицы, multiselect-столбцы и связи
+
+### 9.1. Гибкая структура пользовательских таблиц
+- Пользователь может создавать собственные таблицы (user_tables), столбцы (user_columns) и строки (user_rows).
+- Для каждого столбца можно выбрать тип: text, select, multiselect, relation и др.
+- Для multiselect/select-столбцов значения (опции) хранятся в поле options столбца и могут добавляться/удаляться прямо из интерфейса.
+
+### 9.2. Хранение и настройка связей
+- Для связи между сущностями (например, пользователь — партнеры, вопрос — продукты) используется отдельная таблица связей (например, user_multiselect_values: id, user_id, column_id, value).
+- Это позволяет хранить любые связи "многие-ко-многим" между пользователями, вопросами, продуктами и т.д.
+- Для multiselect-столбцов в RAG-таблице вопросы/ответы можно выбирать продукты/услуги, к которым относится запись.
+
+### 9.3. Фильтрация и производительность
+- Фильтрация реализуется через SQL-запросы с JOIN по user_tables, user_columns, user_rows, user_cell_values и таблице связей.
+- Для multiselect-столбцов фильтрация по значениям возможна через LIKE или jsonb-операторы (при хранении массивов).
+- Производительность обеспечивается индексами по row_id, column_id и, при необходимости, по value (jsonb gin-индекс).
+- Такая архитектура масштабируется и используется в современных low-code/CRM системах (Notion, Airtable и др.).
+
+### 9.4. Пример использования
+- Пользователь создает таблицу "Партнеры" с multiselect-столбцом.
+- В интерфейсе контакта можно выбрать партнеров для пользователя — значения сохраняются в user_multiselect_values.
+- В RAG-таблице вопросы/ответы можно связать с продуктами/услугами через multiselect-столбец.
+- ИИ-ассистент может фильтровать и персонализировать ответы по этим связям.
\ No newline at end of file
diff --git a/md/user-tables-relation-task.md b/md/user-tables-relation-task.md
new file mode 100644
index 0000000..0aeee36
--- /dev/null
+++ b/md/user-tables-relation-task.md
@@ -0,0 +1,150 @@
+# Техническое задание: Пользовательские таблицы с настраиваемыми связями
+
+## Цель
+Реализовать систему пользовательских таблиц, в которых при создании столбца можно настраивать нужные связи (relation/reference/lookup) с другими таблицами.
+
+---
+
+## Основные требования
+
+1. **Пользователь может создавать любые таблицы** (например, "Клиенты", "Теги", "Продукты", "RAG-таблица" и т.д.).
+2. **Для каждой таблицы можно добавлять столбцы разных типов:**
+ - text, number, date, select, multiselect
+ - relation/reference (связь с другой таблицей)
+ - lookup (вывод связанных данных из другой таблицы)
+3. **Для столбцов типа relation/reference:**
+ - Можно выбрать, с какой таблицей и каким полем устанавливается связь
+ - Можно выбрать тип связи: один-к-одному, один-ко-многим, многие-ко-многим
+ - В ячейке такого столбца пользователь может выбрать одну или несколько строк из связанной таблицы
+4. **Связи хранятся в отдельной таблице связей или в value ячейки (массив id)**
+5. **В интерфейсе:**
+ - При создании/редактировании столбца типа relation пользователь выбирает таблицу и поле для связи
+ - В таблице, в ячейке relation-столбца, отображается выпадающий список/мультивыбор с данными из связанной таблицы
+6. **Фильтрация и поиск:**
+ - Можно фильтровать строки по связанным значениям (например, все вопросы, относящиеся к определённому тегу или продукту)
+7. **Масштабируемость:**
+ - Архитектура должна поддерживать создание большого количества таблиц, столбцов и связей без потери производительности
+
+---
+
+## Примеры сценариев
+
+### 1. Связь "Клиент — Теги"
+- Пользователь создаёт таблицу "Клиенты" и таблицу "Теги"
+- В таблице "Клиенты" добавляет столбец типа relation, связывающий клиента с одним или несколькими тегами
+- В каждой строке можно выбрать теги из справочника
+
+### 2. Связь "Вопрос — Продукты"
+- В RAG-таблице добавляется столбец типа relation к таблице "Продукты"
+- Для каждого вопроса можно выбрать, к каким продуктам он относится
+
+### 3. Lookup-столбец
+- В таблице "Клиенты" можно добавить lookup-столбец, который автоматически подтягивает связанные значения из другой таблицы (например, список продуктов, которыми пользуется клиент)
+
+---
+
+## Требования к backend
+- Расширить модели user_tables, user_columns, user_rows, user_cell_values
+- Добавить таблицу связей (например, table_relations: id, from_row_id, column_id, to_table, to_row_id)
+- API для создания/редактирования столбцов с типом relation
+- API для получения и сохранения связей
+
+## Требования к frontend
+- UI для выбора типа столбца (relation/reference/lookup)
+- UI для выбора связанной таблицы и поля
+- UI для выбора значений в ячейке relation-столбца (выпадающий список, мультивыбор)
+- Фильтрация и отображение связанных данных
+
+---
+
+## Преимущества
+- Максимальная гибкость и масштабируемость
+- Возможность строить сложные взаимосвязанные базы знаний, CRM, RAG-ассистентов
+- Удобство для ИИ и аналитики
+
+## Типы столбцов для пользовательских таблиц
+
+1. **text** — однострочный текст
+2. **textarea** — многострочный текст (заметки, описания)
+3. **number** — число (целое или дробное)
+4. **date** — дата
+5. **datetime** — дата и время
+6. **time** — только время
+7. **boolean/checkbox** — булево значение (чекбокс)
+8. **select** — выпадающий список (одиночный выбор)
+9. **multiselect** — выпадающий список (множественный выбор)
+10. **file/image** — файл или изображение (загрузка и хранение)
+11. **relation/reference** — связь с другой таблицей (выбор одной или нескольких строк из другой таблицы)
+12. **lookup** — автоматический вывод связанных данных из другой таблицы по relation
+13. **email** — email-адрес с валидацией
+14. **phone** — телефон с валидацией
+15. **url** — ссылка/URL с валидацией
+16. **currency** — число с символом валюты
+17. **percent** — число с отображением в процентах
+18. **color** — выбор цвета (colorpicker)
+19. **user/assignee** — ссылка на пользователя системы (ответственный)
+20. **status** — список статусов (например, “В работе”, “Готово”)
+21. **formula** — вычисляемое поле на основе других столбцов
+22. **progress/rating** — визуальное отображение прогресса, рейтинга (шкала, звёзды)
+23. **json/object** — хранение структурированных данных (JSON)
+
+## Плейсхолдеры для интеграции с ИИ-ассистентом
+
+- Для каждого столбца при создании автоматически генерируется плейсхолдер (placeholder), который можно использовать в промтах и шаблонах для ИИ-ассистента.
+- Плейсхолдер формируется на основе названия столбца (транслитерация, нижний регистр, замена пробелов на подчёркивания, например: "Партнеры венчурного фонда" → {partners_venchurnogo_fonda}).
+- Плейсхолдер уникален в рамках таблицы. При совпадении имён добавляется суффикс или используется id столбца.
+- В таблице user_columns рекомендуется добавить поле placeholder (string, unique).
+- В интерфейсе при создании/редактировании столбца отображать сгенерированный плейсхолдер (и, при необходимости, давать возможность его редактировать).
+- В системных промтах и шаблонах для LLM/ассистента значения автоматически подставляются по плейсхолдерам.
+
+**Пример использования в промте:**
+```
+Вопрос: {question}
+Ответ: {answer}
+Партнеры: {partners}
+```
+
+## Использование плейсхолдеров в системном промте ассистента
+
+- На странице настроек ассистента (`/settings/ai/assistant`) под полем для системного промта автоматически отображается список всех плейсхолдеров, созданных пользователем в пользовательских таблицах.
+- Для каждого плейсхолдера показывается:
+ - Сам плейсхолдер (например, `{partners}`)
+ - Название столбца и таблицы, к которому он относится (например, “Партнеры венчурного фонда” — RAG-таблица)
+- Список плейсхолдеров обновляется автоматически при добавлении/удалении столбцов.
+
+**Инструкция для пользователя:**
+> Используйте плейсхолдеры из списка ниже для подстановки значений из пользовательских таблиц в системный промт. Например:
+> ```
+> Вопрос: {question}
+> Ответ: {answer}
+> Партнеры: {partners}
+> ```
+> Плейсхолдеры автоматически заменяются на соответствующие значения при генерации ответа ассистента.
+
+## Сценарий: добавление тегов пользователю через пользовательские таблицы
+
+1. **Добавление тега на странице контакта**
+ - На странице контакта (`/contacts/1`) при нажатии на кнопку "Добавить тег" система автоматически создаёт пользовательскую таблицу "Теги клиентов" (если она ещё не создана).
+ - Пользователь может добавить новый тег (например, "VIP", "B2B", "Startup") — он появляется в этой таблице.
+
+2. **Выпадающий список тегов**
+ - После добавления хотя бы одного тега появляется выпадающий список (или мультивыбор), в котором отображаются все теги из таблицы "Теги клиентов".
+ - Пользователь может выбрать один или несколько тегов для текущего контакта.
+
+3. **Связь пользователя с тегом**
+ - При выборе тега для пользователя создаётся связь между пользователем и тегом.
+ - Эта связь хранится в отдельной пользовательской таблице (например, `user_tag_links` или универсальной таблице связей), где фиксируется, какой пользователь связан с каким тегом.
+ - Пример структуры таблицы связей:
+ | id | user_id | tag_id |
+ |----|---------|--------|
+ | 1 | 1 | 2 |
+ | 2 | 1 | 3 |
+
+4. **Обратная связь (теги → пользователи)**
+ - В таблице "Теги клиентов" можно реализовать обратную связь: для каждого тега показывать список пользователей, у которых он установлен (например, через relation/lookup-столбец).
+
+5. **Итог:**
+ - Пользователь может создавать и редактировать теги.
+ - Для каждого контакта можно выбрать теги из выпадающего списка.
+ - Все связи между пользователями и тегами хранятся в отдельной таблице.
+ - Можно быстро получить список всех пользователей с определённым тегом и наоборот.
\ No newline at end of file