From 192497ead09b33620169a4f274d727eba14e69dc Mon Sep 17 00:00:00 2001 From: Andrey Date: Sun, 12 Jul 2026 19:49:02 +0300 Subject: [PATCH] :lipstick: rebrand(ui): CustoCRM logo and product name instead of Edevs Hub - New logo: favicon.svg and LogoIcon (replaces PulseIcon) in sidebar and auth screens - Source logo asset saved to resources/icon.svg - Replace "Edevs Hub" with "CustoCRM" across internal-ui, web-chat, backend strings (email sender/subject, TOTP issuer, notification bot texts, OpenAPI title), env examples and README - Add .claude/launch.json for internal-ui dev server (bind 127.0.0.1) Co-Authored-By: Claude Fable 5 --- .env.example | 2 +- .env.production.example | 2 +- README.md | 2 +- apps/backend/hub_backend/settings.py | 2 +- apps/backend/hub_backend/urls.py | 2 +- apps/backend/hub_platform/identity/auth/totp_utils.py | 2 +- apps/backend/hub_platform/identity/emails.py | 4 ++-- apps/backend/hub_platform/notifications/binding.py | 4 ++-- apps/internal-ui/index.html | 2 +- apps/internal-ui/public/favicon.svg | 6 +++--- apps/internal-ui/src/features/auth/AuthFrame.tsx | 4 ++-- apps/internal-ui/src/features/auth/AuthLogin.tsx | 2 +- apps/internal-ui/src/features/auth/AuthResetPassword.tsx | 2 +- apps/internal-ui/src/features/auth/qr.ts | 2 +- apps/internal-ui/src/layout/Sidebar.tsx | 6 +++--- apps/internal-ui/src/shared/icons.tsx | 6 +++--- apps/web-chat/call.html | 2 +- apps/web-chat/index.html | 2 +- 18 files changed, 27 insertions(+), 27 deletions(-) diff --git a/.env.example b/.env.example index dde9981..953468f 100644 --- a/.env.example +++ b/.env.example @@ -30,7 +30,7 @@ HUB_OPENROUTER_API_KEY= # EMAIL_HOST= # EMAIL_HOST_USER= # EMAIL_HOST_PASSWORD= -# DEFAULT_FROM_EMAIL=Edevs Hub +# DEFAULT_FROM_EMAIL=CustoCRM INTERNAL_UI_BASE_URL=http://localhost:5173 POSTGRES_DB=edevs_hub diff --git a/.env.production.example b/.env.production.example index 2de071a..fae7015 100644 --- a/.env.production.example +++ b/.env.production.example @@ -66,7 +66,7 @@ EMAIL_PORT=587 EMAIL_HOST_USER= EMAIL_HOST_PASSWORD= EMAIL_USE_TLS=true -DEFAULT_FROM_EMAIL=Edevs Hub +DEFAULT_FROM_EMAIL=CustoCRM # Required only for the first production seed when no OWNER exists yet. # The seed command never resets an existing user's password. diff --git a/README.md b/README.md index 3cfc8e8..82eb523 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Edevs Hub +# CustoCRM Canonical implementation workspace for `hub.edevs.tech`. diff --git a/apps/backend/hub_backend/settings.py b/apps/backend/hub_backend/settings.py index 43d8f45..fd4e8f6 100644 --- a/apps/backend/hub_backend/settings.py +++ b/apps/backend/hub_backend/settings.py @@ -150,7 +150,7 @@ EMAIL_PORT = int(os.environ.get("EMAIL_PORT", "587")) EMAIL_HOST_USER = os.environ.get("EMAIL_HOST_USER", "") EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD", "") EMAIL_USE_TLS = os.environ.get("EMAIL_USE_TLS", "true").lower() == "true" -DEFAULT_FROM_EMAIL = os.environ.get("DEFAULT_FROM_EMAIL", "Edevs Hub ") +DEFAULT_FROM_EMAIL = os.environ.get("DEFAULT_FROM_EMAIL", "CustoCRM ") # Base URL of the internal UI, used to build links inside transactional emails. INTERNAL_UI_BASE_URL = os.environ.get("INTERNAL_UI_BASE_URL", "http://localhost:5173") diff --git a/apps/backend/hub_backend/urls.py b/apps/backend/hub_backend/urls.py index 96c0d45..22d7f7e 100644 --- a/apps/backend/hub_backend/urls.py +++ b/apps/backend/hub_backend/urls.py @@ -7,7 +7,7 @@ from hub_platform.webchat.views import WidgetLoaderView urlpatterns = [ path("admin/", admin.site.urls), path("chat-widget.js", WidgetLoaderView.as_view(), name="chat-widget-loader"), - path("api/v1/schema/", get_schema_view(title="Edevs Hub API", version="0.1.0"), name="openapi-schema"), + path("api/v1/schema/", get_schema_view(title="CustoCRM API", version="0.1.0"), name="openapi-schema"), path("api/v1/auth/", include("hub_platform.identity.auth_urls")), path("api/v1/company/", include("hub_platform.identity.company_urls")), path("api/v1/company/", include("hub_platform.products.urls")), diff --git a/apps/backend/hub_platform/identity/auth/totp_utils.py b/apps/backend/hub_platform/identity/auth/totp_utils.py index 880568e..70f303f 100644 --- a/apps/backend/hub_platform/identity/auth/totp_utils.py +++ b/apps/backend/hub_platform/identity/auth/totp_utils.py @@ -8,7 +8,7 @@ import time from hub_platform.identity.models import HumanUser TOTP_SESSION_KEY = "identity_pending_totp_user_id" -TOTP_ISSUER = "Edevs Hub" +TOTP_ISSUER = "CustoCRM" TOTP_PERIOD_SECONDS = 30 diff --git a/apps/backend/hub_platform/identity/emails.py b/apps/backend/hub_platform/identity/emails.py index d166870..d640b74 100644 --- a/apps/backend/hub_platform/identity/emails.py +++ b/apps/backend/hub_platform/identity/emails.py @@ -12,10 +12,10 @@ def send_password_reset_email(user: HumanUser) -> None: token = default_token_generator.make_token(user) reset_url = f"{settings.INTERNAL_UI_BASE_URL.rstrip('/')}/reset-password?uid={uid}&token={token}" send_mail( - subject="Восстановление доступа к Edevs Hub", + subject="Восстановление доступа к CustoCRM", message=( f"Здравствуйте, {user.full_name or user.email}.\n\n" - "Вы запросили сброс пароля для Edevs Hub. Чтобы задать новый пароль, перейдите по ссылке:\n" + "Вы запросили сброс пароля для CustoCRM. Чтобы задать новый пароль, перейдите по ссылке:\n" f"{reset_url}\n\n" "Ссылка действует 30 минут. Если вы не запрашивали сброс, просто проигнорируйте это письмо." ), diff --git a/apps/backend/hub_platform/notifications/binding.py b/apps/backend/hub_platform/notifications/binding.py index b376d13..dc48758 100644 --- a/apps/backend/hub_platform/notifications/binding.py +++ b/apps/backend/hub_platform/notifications/binding.py @@ -24,8 +24,8 @@ logger = logging.getLogger(__name__) CODE_TTL = timedelta(minutes=10) NOTIFIER_PURPOSE = "notifications" -CONFIRMATION_TEXT = "Готово! Уведомления Edevs Hub подключены. Отключить можно в профиле." -HINT_TEXT = "Это сервисный бот уведомлений Edevs Hub. Чтобы подключить уведомления, откройте профиль в Hub и нажмите «Подключить»." +CONFIRMATION_TEXT = "Готово! Уведомления CustoCRM подключены. Отключить можно в профиле." +HINT_TEXT = "Это сервисный бот уведомлений CustoCRM. Чтобы подключить уведомления, откройте профиль в Hub и нажмите «Подключить»." # База deep-link по провайдеру: и TG, и MAX поддерживают ?start=<код>. _DEEP_LINK_BASE = { diff --git a/apps/internal-ui/index.html b/apps/internal-ui/index.html index 94d8fb8..db6d54e 100644 --- a/apps/internal-ui/index.html +++ b/apps/internal-ui/index.html @@ -4,7 +4,7 @@ - Edevs Hub + CustoCRM
diff --git a/apps/internal-ui/public/favicon.svg b/apps/internal-ui/public/favicon.svg index 1a44b7a..4ea6134 100644 --- a/apps/internal-ui/public/favicon.svg +++ b/apps/internal-ui/public/favicon.svg @@ -1,4 +1,4 @@ - - - + + + diff --git a/apps/internal-ui/src/features/auth/AuthFrame.tsx b/apps/internal-ui/src/features/auth/AuthFrame.tsx index fe551d8..735716c 100644 --- a/apps/internal-ui/src/features/auth/AuthFrame.tsx +++ b/apps/internal-ui/src/features/auth/AuthFrame.tsx @@ -1,13 +1,13 @@ import type { ReactNode } from "react"; -import { PulseIcon, ShieldIcon } from "../../shared/icons"; +import { LogoIcon, ShieldIcon } from "../../shared/icons"; export function AuthFrame({ title, subtitle, logo, width = 400, children, note }: { title: string; subtitle: ReactNode; logo: "pulse" | "shield"; width?: number; children: ReactNode; note?: ReactNode }) { return (
-
{logo === "shield" ? : }
+
{logo === "shield" ? : }

{title}

{subtitle}

diff --git a/apps/internal-ui/src/features/auth/AuthLogin.tsx b/apps/internal-ui/src/features/auth/AuthLogin.tsx index 903e74c..3b41eaa 100644 --- a/apps/internal-ui/src/features/auth/AuthLogin.tsx +++ b/apps/internal-ui/src/features/auth/AuthLogin.tsx @@ -36,7 +36,7 @@ export function AuthLogin({ onLogin, onTotpChallenge, onRecover }: { onLogin: (u } return ( - +
{error &&
!Неверный email или пароль. Проверьте данные и попробуйте снова.
} diff --git a/apps/internal-ui/src/features/auth/AuthResetPassword.tsx b/apps/internal-ui/src/features/auth/AuthResetPassword.tsx index f7bd6e2..4c597b6 100644 --- a/apps/internal-ui/src/features/auth/AuthResetPassword.tsx +++ b/apps/internal-ui/src/features/auth/AuthResetPassword.tsx @@ -94,7 +94,7 @@ export function AuthResetPassword({ onDone }: { onDone: () => void }) { } return ( - + {error &&
!{error}
} diff --git a/apps/internal-ui/src/features/auth/qr.ts b/apps/internal-ui/src/features/auth/qr.ts index d32d35f..8ddf524 100644 --- a/apps/internal-ui/src/features/auth/qr.ts +++ b/apps/internal-ui/src/features/auth/qr.ts @@ -11,7 +11,7 @@ export type QrMatrix = { }; export function createQrMatrix(text: string): QrMatrix { - const bytes = Array.from(new TextEncoder().encode(text || "Edevs Hub")); + const bytes = Array.from(new TextEncoder().encode(text || "CustoCRM")); const version = chooseVersion(bytes.length); const size = version * 4 + 17; const dataCodewords = encodeData(bytes, version); diff --git a/apps/internal-ui/src/layout/Sidebar.tsx b/apps/internal-ui/src/layout/Sidebar.tsx index d1315d8..05a194a 100644 --- a/apps/internal-ui/src/layout/Sidebar.tsx +++ b/apps/internal-ui/src/layout/Sidebar.tsx @@ -1,5 +1,5 @@ import type { RouteKey, SessionUser } from "../types"; -import { Icon, PulseIcon } from "../shared/icons"; +import { Icon, LogoIcon } from "../shared/icons"; import { Avatar } from "../shared/ui"; export function Sidebar({ route, user, setRoute }: { route: RouteKey; user: SessionUser; setRoute: (route: RouteKey) => void }) { @@ -20,8 +20,8 @@ export function Sidebar({ route, user, setRoute }: { route: RouteKey; user: Sess return (