diff --git a/.gitignore b/.gitignore index b18af88..ae39989 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,6 @@ # runtime-данные приложения (вложения и пр.) backend/data/ + +# ZIP расширения — генерится pack-скриптом extension/ или Docker-сборкой +frontend/public/extension/ diff --git a/extension/README.md b/extension/README.md index dd342cd..4ed1ca5 100644 --- a/extension/README.md +++ b/extension/README.md @@ -33,11 +33,16 @@ cd extension npm install # кит — git-зависимость (см. .npmrc) npm run build # vue-tsc + vite build → dist/ +npm run pack # ZIP dist → frontend/public/extension/ (для страницы /extension) ``` npm 12 блокирует postinstall-скрипт esbuild — при первом `npm install` согласуйте его (`npm install-scripts approve esbuild`). +В прод-образе фронта ZIP собирается сам (frontend/Dockerfile): страница +`/extension` в сервисе раздаёт его и показывает инструкцию по установке +(пункт меню — только из веб-версии, не в PWA). + ## Загрузка unpacked - **Chrome/Chromium**: `chrome://extensions` → «Developer mode» → «Load diff --git a/extension/package.json b/extension/package.json index 6f34c0d..89be532 100644 --- a/extension/package.json +++ b/extension/package.json @@ -5,7 +5,8 @@ "type": "module", "scripts": { "build": "vue-tsc -b && vite build", - "dev": "vite build --watch" + "dev": "vite build --watch", + "pack": "mkdir -p ../frontend/public/extension && cd dist && zip -qr ../../frontend/public/extension/gntodo-extension.zip ." }, "dependencies": { "gnexus-ui-kit": "git+https://git.gnexus.space/git/root/gnexus-ui-kit.git", diff --git a/frontend/src/App.vue b/frontend/src/App.vue index f58c55a..1c6dcc6 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -16,6 +16,9 @@ const { t } = useI18n() const user = ref(null) const accountUrl = ref('') +// Страница расширения — только из веб-версии: в установленном PWA пункт скрыт +const isStandalone = window.matchMedia('(display-mode: standalone)').matches + const navItems = computed(() => [ { id: 'home', label: t('nav.home'), icon: 'ph-house', to: '/' }, { id: 'options', label: t('nav.options'), icon: 'ph-shuffle', to: '/options' }, @@ -26,6 +29,10 @@ // архив — редко используемый раздел, предпоследний пункт { id: 'archive', label: t('nav.archive'), icon: 'ph-archive', to: '/archive' }, { id: 'settings', label: t('nav.settings'), icon: 'ph-gear-six', to: '/settings' }, + // страница-инструкция расширения — из веб-версии (не в PWA, ТЗ 3.18) + ...(isStandalone + ? [] + : [{ id: 'extension', label: t('nav.extension'), icon: 'ph-puzzle-piece', to: '/extension' }]), ]) const currentLabel = computed(() => { diff --git a/frontend/src/locales/en.ts b/frontend/src/locales/en.ts index 2a20645..aeb2096 100644 --- a/frontend/src/locales/en.ts +++ b/frontend/src/locales/en.ts @@ -49,6 +49,7 @@ archive: 'Archive', options: 'Task handout', settings: 'Settings', + extension: 'Extension', }, garden: { title: 'Garden', @@ -454,6 +455,30 @@ mcpTokenCreate: 'Generate', mcpOpen: 'How to connect', }, + ext: { + title: 'Quick-capture extension', + whatTitle: 'What it is', + whatText: + 'Click the extension icon in the browser toolbar — the task is in your inbox without opening the service. The popup has two tabs: "Add" (first line — title, the rest — description; a project is optional) and "Active" — view-only, clicking a task opens it in the service.', + tokenTitle: 'Step 1. Access token', + tokenText: + 'The extension connects with a personal MCP token (like AI agents): create it in "Settings → MCP tokens" — the value is shown once.', + tokenButton: 'Open Settings', + downloadTitle: 'Step 2. Download and unpack', + downloadButton: 'Download ZIP', + downloadHint: 'Unpack the archive into any folder.', + installTitle: 'Step 3. Load the extension into the browser', + chromeText: + 'Chrome/Chromium: open chrome://extensions, enable "Developer mode" → "Load unpacked" → pick the unpacked folder.', + firefoxText: + 'Firefox: open about:debugging#/runtime/this-firefox → "Load Temporary Add-on…" → the manifest.json file from the archive.', + connectTitle: 'Step 4. Connect', + connectText: + 'Click the extension icon, paste the token from step 1 and press "Connect". Revoking the token in "Settings" disables the extension.', + pwaTitle: 'Available in the web version', + pwaNote: + 'This page is hidden in the installed app (PWA) — open the service in a regular browser tab.', + }, mcp: { title: 'MCP for AI agents', whatTitle: 'What it is', diff --git a/frontend/src/locales/ru.ts b/frontend/src/locales/ru.ts index e2a945d..e380e09 100644 --- a/frontend/src/locales/ru.ts +++ b/frontend/src/locales/ru.ts @@ -50,6 +50,7 @@ archive: 'Архив', options: 'Выдача задачи', settings: 'Настройки', + extension: 'Расширение', }, garden: { title: 'Сад', @@ -455,6 +456,30 @@ mcpTokenCreate: 'Сгенерировать', mcpOpen: 'Как подключить', }, + ext: { + title: 'Расширение быстрого захвата', + whatTitle: 'Что это такое', + whatText: + 'Клик по иконке расширения в трее браузера — и задача в стеке, не открывая сервис. В попапе две вкладки: «Добавить» (первая строка — название, остальное — описание; можно выбрать проект) и «Активные» — только просмотр, клик по задаче открывает её в сервисе.', + tokenTitle: 'Шаг 1. Токен доступа', + tokenText: + 'Расширение подключается персональным MCP-токеном (как ИИ-агенты): создайте его в «Настройках → Токены MCP» — значение показывается один раз.', + tokenButton: 'Открыть Настройки', + downloadTitle: 'Шаг 2. Скачать и распаковать', + downloadButton: 'Скачать ZIP', + downloadHint: 'Распакуйте архив в любую папку.', + installTitle: 'Шаг 3. Загрузить расширение в браузер', + chromeText: + 'Chrome/Chromium: откройте chrome://extensions, включите «Developer mode» → «Load unpacked» → выберите распакованную папку.', + firefoxText: + 'Firefox: откройте about:debugging#/runtime/this-firefox → «Load Temporary Add-on…» → файл manifest.json из архива.', + connectTitle: 'Шаг 4. Подключить', + connectText: + 'Кликните по иконке расширения, вставьте токен из шага 1 и нажмите «Подключить». Отзыв токена в «Настройках» отключает расширение.', + pwaTitle: 'Доступно из веб-версии', + pwaNote: + 'Страница скрыта в установленном приложении (PWA) — откройте сервис в обычной вкладке браузера.', + }, mcp: { title: 'MCP для ИИ-агентов', whatTitle: 'Что это такое', diff --git a/frontend/src/locales/uk.ts b/frontend/src/locales/uk.ts index e031e5a..975ad04 100644 --- a/frontend/src/locales/uk.ts +++ b/frontend/src/locales/uk.ts @@ -49,6 +49,7 @@ archive: 'Архів', options: 'Видача завдання', settings: 'Налаштування', + extension: 'Розширення', }, garden: { title: 'Сад', @@ -454,6 +455,30 @@ mcpTokenCreate: 'Згенерувати', mcpOpen: 'Як підключити', }, + ext: { + title: 'Розширення швидкого захоплення', + whatTitle: 'Що це таке', + whatText: + 'Клік по іконці розширення в треї браузера — і задача в стеку, не відкриваючи сервіс. У попапі дві вкладки: «Додати» (перший рядок — назва, решта — опис; можна вибрати проєкт) і «Активні» — лише перегляд, клік по задачі відкриває її в сервісі.', + tokenTitle: 'Крок 1. Токен доступу', + tokenText: + 'Розширення підключається персональним MCP-токеном (як ІІІ-агенти): створіть його в «Налаштуваннях → Токени MCP» — значення показується один раз.', + tokenButton: 'Відкрити Налаштування', + downloadTitle: 'Крок 2. Завантажити та розпакувати', + downloadButton: 'Завантажити ZIP', + downloadHint: 'Розпакуйте архів у будь-яку папку.', + installTitle: 'Крок 3. Завантажити розширення в браузер', + chromeText: + 'Chrome/Chromium: відкрийте chrome://extensions, увімкніть «Developer mode» → «Load unpacked» → виберіть розпаковану папку.', + firefoxText: + 'Firefox: відкрийте about:debugging#/runtime/this-firefox → «Load Temporary Add-on…» → файл manifest.json з архіву.', + connectTitle: 'Крок 4. Підключити', + connectText: + 'Клікніть по іконці розширення, вставте токен із кроку 1 і натисніть «Підключити». Відкликання токена в «Налаштуваннях» вимикає розширення.', + pwaTitle: 'Доступно з веб-версії', + pwaNote: + 'Сторінка прихована у встановленому застосунку (PWA) — відкрийте сервіс у звичайній вкладці браузера.', + }, mcp: { title: 'MCP для ІІ-агентів', whatTitle: 'Що це таке', diff --git a/frontend/src/main.ts b/frontend/src/main.ts index 9442b9c..c06e424 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -23,6 +23,7 @@ import TaskView from './views/TaskView.vue' import McpView from './views/McpView.vue' import LoginView from './views/LoginView.vue' +import ExtensionView from './views/ExtensionView.vue' const router = createRouter({ history: createWebHistory(), @@ -42,6 +43,8 @@ { path: '/tasks/:id', component: TaskView, meta: { title: 'nav.task' } }, { path: '/options', component: OptionsView, meta: { title: 'nav.options' } }, { path: '/settings', component: SettingsView, meta: { title: 'nav.settings' } }, + // страница-инструкция расширения (ТЗ 3.18): скачивание ZIP + загрузка unpacked + { path: '/extension', component: ExtensionView, meta: { title: 'nav.extension' } }, // инструкция по MCP для агентов — ссылка из «Настроек» (ТЗ 3.10). // Путь /mcp занят самим MCP-сервером — страница живёт на /mcp-help { path: '/mcp-help', component: McpView, meta: { title: 'mcp.title' } }, diff --git a/frontend/src/views/ExtensionView.vue b/frontend/src/views/ExtensionView.vue new file mode 100644 index 0000000..3fecc0b --- /dev/null +++ b/frontend/src/views/ExtensionView.vue @@ -0,0 +1,77 @@ + + + + + \ No newline at end of file