Skip to content

Feat/mocks for demo#836

Open
talyguryn wants to merge 44 commits intomasterfrom
feat/mocks-for-demo
Open

Feat/mocks for demo#836
talyguryn wants to merge 44 commits intomasterfrom
feat/mocks-for-demo

Conversation

@talyguryn
Copy link
Copy Markdown
Member

@talyguryn talyguryn commented Feb 7, 2026

Demo mode feature on /?demo=1 url

Mock api requests, show defined data

Introduces demo mode support by adding mock API responses for events, projects, user, and workspaces. Refactors API modules to use a withDemoMock utility for conditional mock injection. Updates EventsList and store modules for improved debug logging and error handling. Demo mode can be enabled automatically or via browser console for local development.
@codex-assistant

This comment was marked as outdated.

@codex-assistant

This comment was marked as outdated.

@codex-assistant

This comment was marked as outdated.

@codex-assistant codex-assistant bot marked this pull request as ready for review February 7, 2026 10:19
@codex-assistant
Copy link
Copy Markdown

Thanks for adding a description — the PR is now marked as Ready for Review.

Copilot AI review requested due to automatic review settings February 7, 2026 10:20

This comment was marked as outdated.

Introduce a demo mode backed by a mock database and organized mock API modules. Added a demo Vuex module (store/modules/demo), wired demo state into the root store and persisted state, and updated the router to support /demo paths and set demo tokens. Replaced the old withDemoMock utility with withMockDemo and updated API wrappers (events, projects, workspaces, user) to load mocks from new ./mocks/* locations. Created a central mock-db (users, workspaces, events) with demo data and multiple new mock responses for charts, releases, project visits, and current user. UI changes include a demo button on the login page and i18n strings for demo mode. Removed legacy mock files and simplified mock loading logic.
Introduce a centralized mock-db and refactor demo mocks to use shared DEMO_* data. Add new mock-db files (charts.ts, releases.ts) and re-export them from src/api/mock-db/index.ts. Simplify and standardize event/project/user mock modules to return values or factory functions from the mock-db. Rewrite withMockDemo to accept either a mock name (string) or factory, preload mock modules via import.meta.glob, resolve mock paths, support debug options, and fallback to the real API on errors. Update API call sites to the new withMockDemo signature and enable debug or options where appropriate. Misc: add ImportMeta.glob typing in shims, make router demo activation asynchronous and handle demo auth flow, and tweak demo event data (visitedBy handling) in the mock DB.
Add a centralized utils/time.ts with common time constants (ms/sec and day offsets) and replace scattered magic numbers across mock data and mock-db with these constants. Update mocks to include explicit TypeScript return types and more consistent timestamp calculations (daily/hour offsets), refine repetitions generation (ID offset and hour constants), and import project release types for DEMO_RELEASES/DEMO_RELEASE_DETAILS. Also minor cleanup: nullish return in getEvent and reshaped GraphQL-like mock return objects for project/user/workspace endpoints to improve type safety and clarity.
Apply consistent formatting and minor type/JSdoc adjustments across the codebase. Changes include: aligned object/argument indentation in API calls, split long lines, replaced inline numeric literals with named constants in time utilities, tightened imports (use `import type`), added a few JSDoc param tags, replaced broad `Function` types with `Commit` where appropriate, removed trailing empty lines, and small mock file tweaks (array mapping arrow style and mock data structure spacing). No intended behavioral changes — primarily styling, typing and readability improvements.
Replace short mock identifiers with absolute '@/...' mock paths across API modules (events, projects, user, workspaces) to ensure consistent mock loading. Enhance resolveMockPath to handle /src/ and @/ prefixes and try .ts/.js variants when resolving mock modules. Also enable debug option for projects.fetchChartData with withMockDemo.
Introduce a useDemo composable to centralize demo-mode checks and actions (isDemoActive, enableDemo, disableDemo, toggleDemo). Update router to use the composable instead of direct store calls when enabling demo mode and when preserving /demo routes. Switch i18n to composition API usage (legacy: false, globalInjection: true) and set locale via i18n.global.locale.value.

Refactor withMockDemo to remove the preloaded import.meta.glob approach and instead dynamically import mock modules at runtime. Require explicit mock paths (supporting @/ and /src/ prefixes), normalize candidates, and throw clear errors when mocks can't be resolved. Also switch demo-mode checks in withMockDemo to use isDemoActive from the new composable and improve logging and error handling during mock loading.
Switch local type imports to the centralized @hawk.so/types package and standardize demo/mock timestamps to use seconds (and seconds-based constants) instead of milliseconds. Update time calculations and constants across mock-db and mock API files, convert event/repetition timestamps to seconds, and simplify a couple of project release mocks to return raw ReleaseData/ReleaseDetails (remove GraphQL wrapper shape). Affects events, projects, user, workspaces and mock-db release/user/chart files.
Introduce a refactored demo-mode system and UI banner. Add a composable (useDemo) exposing isEnabled ref and demo controls, handle ?demo=1 query param, set demo tokens, and register demo module for persistence. Update router and App/AppShell to use the new demo state, show a demo banner with a Disable Demo button, and avoid redirecting to login when demo is enabled. Simplify withMockDemo to load explicit mock paths and rely on isEnabled.value; update many API calls to point to explicit mock files. Minor UX/text updates to i18n (disable button) and Login link to trigger demo via query. Remove various debug/console logs and a removed ImportMeta extension in shims.
Fix setLanguage to assign i18n.global.locale directly (remove incorrect .value usage) to properly update the locale. Also remove an extraneous blank line in src/store/modules/events/index.ts to tidy up the module.
Prefix store.dispatch and router.replace calls with `void` in src/composables/useDemo.ts to explicitly ignore their returned promises and satisfy linting (no-floating-promises) / avoid unused Promise warnings. This is a non-functional change to address static checks.
talyguryn and others added 9 commits February 21, 2026 13:56
Convert useDemo to a shared composable (createSharedComposable) and centralize demo state management. The previous top-level isEnabled ref was removed and is now returned from useDemo as a Ref along with typed controls (isDemoActive, enableDemo, disableDemo, toggleDemo). The demo URL watcher and setDemoState logic were improved to avoid duplicate initialization and to synchronize Vuex tokens/state. Update callsites (App.vue, AppShell.vue, router.ts, withMockDemo.ts) to consume useDemo and use the returned isEnabled (exposed as isDemoEnabled in components). Also bump @hawk.so/types version in package.json.
Switch demo checks from ref.value to the new demo API and store-based flow. App and AppShell now use isDemoEnabled (non-ref), account settings logout uses useDemo to disable an active demo, and withMockDemo calls useDemo(). Router now handles ?demo=1 by dispatching demo/enableDemo and seeding demo tokens, and auth guard checks store.state.demo?.isActive instead of the removed composable import. Also simplified i18n initialization by removing legacy/globalInjection and setting i18n.global.locale directly.
Add demo-mode detection and friendly messaging for unauthenticated GraphQL responses (DEMO_ACCESS_TOKEN and isDemoModeEnabled) in the API. Update error handling when loading notification settings: store action now validates fetched notifications and throws a demo-specific or generic error when missing, and the Notifications component wraps the fetch in try/catch to report errors to Hawk and show a notifier. Also enable legacy mode in i18n configuration.
Replace hardcoded Russian demo-mode message with i18n lookup in API error handling. Import i18n in src/api/index.ts and call i18n.global.t('demo.functionUnavailable') for UNAUTHENTICATED demo responses. Add corresponding "functionUnavailable" keys to English and Russian message files so the message is localized.
Refactor user notification API calls to use api.call and to expose request helpers wrapped with withMockDemo for demo mocks. Added mock implementations and in-memory notification state (fetchNotificationsSettings.mock.ts, updateNotificationsChannel.mock.ts, updateNotificationsReceiveType.mock.ts, notificationsState.ts) and updated exports in src/api/user/index.js to use these mocks. Also updated fetchBankCards to use api.call and optional chaining, and changed withMockDemo to forward arguments to mock functions so mocks can react to input.
Enhance the mock fetchDailyEventsPortion API to accept sort, filters and search parameters (with defaults) and normalize the search string. Events are now filtered by starred/resolved/ignored marks and title, and can be sorted by date, count or affected users. Update mapping to use the filtered/sorted list. Also extend createDemoEvent in the mock DB to accept isResolved/isIgnored flags and apply them to event marks, and mark a couple of demo events accordingly.
Wrap several API calls with withMockDemo and add mock implementations + mock DB data for demo mode. Added mocks for plans, business operations, workspace list/balance and admin/remove actions, and exported business-operations from mock-db. Updated demo workspace plan data (free/RUB/limits). Adjusted UI: simplified ChooseTariffPlanPopup layout to vertical plans, removed TariffPlan horizontal prop and updated its styles, and block payment actions in PaymentDetailsDialog when demo mode is active with a notification.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 58 out of 59 changed files in this pull request and generated 9 comments.

Comments suppressed due to low confidence (1)

src/components/modals/ChooseTariffPlanPopup.vue:266

  • The choose-plan__plans--horizontal modifier class is no longer applied in the template, so this CSS block is now dead code (and currently duplicates the base flex-direction: column). It should be removed to avoid confusion, or the template logic should be restored if it’s still needed.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +9 to +14
export default function mockGetBusinessOperations(ids: string[]): BusinessOperation[] {
// Return demo operations if requesting for demo workspace
if (ids.includes('6213b6a01e6281087467cc7a')) {
return DEMO_BUSINESS_OPERATIONS;
}
return [];
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mock hard-codes the demo workspace id string. Since DEMO_WORKSPACE_ID is already defined in @/api/mock-db, using the shared constant here would prevent drift if the demo ids ever change.

Copilot uses AI. Check for mistakes.
* Returns success status for updating last project visit timestamp
* @param projectId
*/
export default async function updateLastProjectVisitMock(projectId: string): Promise<boolean> {
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

projectId is unused in this mock; with the repo’s unused-vars rules it’s better to prefix it with _ (or remove it) to avoid lint warnings and make intent explicit.

Suggested change
export default async function updateLastProjectVisitMock(projectId: string): Promise<boolean> {
export default async function updateLastProjectVisitMock(_projectId: string): Promise<boolean> {

Copilot uses AI. Check for mistakes.
Comment on lines +29 to +34
async function loadMockModule(mockPath: string): Promise<any> {
try {
return await import(/* @vite-ignore */ mockPath);
} catch (error) {
throw new Error(`Mock module not found: ${mockPath}`);
}
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loadMockModule() uses import(/* @vite-ignore */ mockPath) with a runtime string path. In Vite production builds this typically won’t include the mock modules in the bundle, so demo mode can break at runtime when the import can’t be resolved. Consider switching to an import.meta.glob() registry (or passing the mock factory directly) so the mocks are statically discoverable and bundled.

Copilot uses AI. Check for mistakes.
Rename the demo mock utility and its usages: src/utils/withMockDemo.ts -> src/utils/withDemoMock.ts and change the exported function name from withMockDemo to withDemoMock. Update imports/usages across API modules (billing, events, plans, projects, user, workspaces) to reference the new name/path. No functional changes — only a rename for clearer naming and consistency.
export default function mockGetEvent(): HawkEvent | null {
// In demo mode, we just return the first demo event
// In a real scenario, we could match by eventId from args
const event = DEMO_EVENTS[0];
Copy link
Copy Markdown
Member

@neSpecc neSpecc Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is not the best solution. Its better to create a list of mocked events and find a particular event in there

export const getPlans = withMockDemo(
getPlansRequest,
'/src/api/plans/mocks/getPlans.mock.ts'
);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest to get rid of mock here and allowlist this query for anons on the API side.

It can be done easily by adding @allowAnon directive here https://github.com/codex-team/hawk.api.nodejs/blob/3d9de276b2c001e0111c564aa8c9cdb857a45ff7/src/typeDefs/plans.ts#L43

This will ensure plans list is actual. It may be important for users who discover Hawk by demo mode.

src/api/index.ts Outdated
* Hawk API endpoint URL
*/
export const API_ENDPOINT: string = import.meta.env.VITE_API_ENDPOINT || '';
const DEMO_ACCESS_TOKEN = 'demo-access-token';
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this constant is declared several times. It's better to reuse the single one.

Comment on lines +14 to +18
function isDemoModeEnabled(): boolean {
const authHeader = axios.defaults.headers.common.Authorization;

return typeof authHeader === 'string' && authHeader.includes(DEMO_ACCESS_TOKEN);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please describe the logic in jsdoc. Why this way is used?

try {
return isEnabled.value || (store?.state?.demo?.isActive ?? false);
} catch (error) {
console.warn('[useDemo] Could not access store, demo mode disabled:', error);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its better to throw error in this case so we'll see it in Hawk and start debugging.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same in other similar places below

Comment on lines +175 to +176
isEnabled,
isDemoActive,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the difference between these two? It's better to leave a single one (ref or computed ref is preferable)

Copy link
Copy Markdown
Member

@neSpecc neSpecc Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these changes are redundant sinсe useDemo already contains this logic.

talyguryn and others added 14 commits February 21, 2026 23:56
Replace static DEMO_CHART_DATA with dynamic chart generation driven by DEMO_EVENTS in both events and projects mocks. Added timestamp helpers (alignToDay, toUnixSeconds, getBucketStart), timezoneOffset support, bucketization (days or groupBy), and rate-limited event detection. Updated mock DB to include NOW_SECONDS, set timestamps on existing events, and bulk-generate many synthetic events with varied minute offsets to produce realistic time series. Mocks now return per-day/per-bucket 'accepted' (and 'rate-limited' for projects) chart lines for the requested range or originalEventId.
Introduce project-scoped demo events and a second demo project. Add getDemoEventsByProjectId and DEMO_SECOND_PROJECT/DEMO_PROJECTS, assign generated events to the second project, and update createDemoEvent to accept projectId (used in payload URLs). Update mocks (events, projects, workspaces) to accept projectId arguments and filter DEMO_EVENTS by project: fetchChartData, fetchDailyEventsPortion, getEvent, getRepetitionsPortion, and workspace mock now return project-specific daily events. Also add safe handling when no base event is found for repetitions and extend the demo events set with additional mobile-oriented samples.
Replace the previous isEnabled / isDemoActive function API with a single computed isDemoActive ref from the useDemo composable. Update imports, types and all consumers to use the new computed ref (.value where needed), and remove the old isEnabled return value. Files updated: src/composables/useDemo.ts (API/type changes and implementation), src/App.vue, src/components/AppShell.vue, src/components/account/settings/Layout.vue, and src/utils/withDemoMock.ts to use the new isDemoActive computed ref. This centralizes demo-mode state handling and simplifies consumer logic.
Export DEMO_ACCESS_TOKEN and DEMO_REFRESH_TOKEN from the demo composable and remove duplicate local constants. Update src/api/index.ts and src/router.ts to import and use the exported tokens (replace hardcoded string literals). This centralizes demo auth tokens, reduces duplication, and adds brief JSDoc comments for the exported constants.
Exported getBalance directly (replacing getBalanceRequest) and removed the withDemoMock wrapper and its mock file. The implementation now calls the API directly and the mock at src/api/workspaces/mocks/getBalance.mock.ts was deleted. Note: the return type was adjusted from Workspace[] to Workspace, which may be a breaking change for callers expecting an array.
Replace the previous getPlansRequest + withDemoMock wrapper by exporting getPlans directly from src/api/plans/index.ts. Remove the withDemoMock import and delete the demo mock file src/api/plans/mocks/getPlans.mock.ts. getPlans now returns (await api.callOld(QUERY_PLANS)).plans, removing the demo/mock fallback.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants