feat: עיצוב מחדש של מסך הגדרות הניהול + captain-definition#23
Open
27180781 wants to merge 16 commits into
Open
feat: עיצוב מחדש של מסך הגדרות הניהול + captain-definition#2327180781 wants to merge 16 commits into
27180781 wants to merge 16 commits into
Conversation
Replace the generic key/value table with a structured form: settings are grouped by category (general, auth, ads, webhook, notifications, FCM), each with Hebrew labels and descriptions. Booleans are toggles, regex rules have separate pattern/replace fields, and a paste-JSON helper auto-fills FCM service account fields. A collapsible "advanced" section preserves manual key/value entry for unknown settings. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a dedicated admin tab "שילוב פרסומות ממגנט" where admins paste an HTML/JS embed snippet from the Magnet ad platform. Ads render between chat messages according to configurable rules: either every N messages (with optional minimum time gap) or every N seconds (with optional minimum new-messages gap). Each ad slot is lazy-loaded with IntersectionObserver — the external embed only fires when the user scrolls near it, and re-fires on every re-mount so each viewer (and each scroll) gets a live ad. If the embed produces no DOM content within 5 seconds, the slot collapses silently. Backend exposes a new public GET /api/ads/magnet endpoint and persists the seven magnet_* keys in the existing settings:list store. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a publisher API key field and a stats viewer in the Magnet admin tab. A new admin-protected endpoint GET /api/admin/magnet/stats proxies the request to Magnet's publisher-stats function so the API key never reaches the browser. The stats panel shows clicks and earnings (today / week / month) in two columns with currency formatting, displays the site domain, and has a refresh button with a last-updated timestamp. Errors from Magnet (400 invalid key, 404 unapproved site) are surfaced in Hebrew. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add defensive fallbacks so a regression in the Magnet ad-injection logic can never prevent regular chat messages from rendering: - rebuildItems() now wraps buildItems() in try/catch and falls back to plain message items if it throws or returns an empty list while there are messages. - Template renders directly from messages[] when items[] is empty, bypassing the ad-injection layer entirely as a safety net. - ngOnInit catches a rejected loadSettings() promise so it cannot block the subsequent rebuildItems call. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous approach replaced the @for over messages with a @for over a new ChatItem[] union type. That introduced a subtle regression where messages stopped rendering for some users. Restore the original @for (message of messages; track message) loop and inject the magnet ad slot as a sibling <nb-list-item> right after each message that should have an ad — driven by an adSlotsAfter Set<number> of message IDs. Service no longer builds an items array; it returns the Set directly via computeAdSlots(). The chat component owns adSlotsAfter and recomputes it on every message-list mutation. If computation throws, the Set stays empty and messages render unaffected. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dering Despite restoring the @for messages template loop, deployed builds were still rendering an empty chat list with no messages, no loading spinner, and no "no messages" placeholder — a state inconsistent with what the template should produce. To unblock users, fully revert chat.component.ts and chat.component.html to the pre-magnet snapshot. The magnet ads service, slot component, admin tab, and backend endpoints remain in place; ad injection into the chat list will be re-introduced separately once the regression is understood. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Step 1 of incremental re-introduction: add the MagnetAdsService injection, the adSlotsAfter Set, the rebuildItems() helper, and the ngOnInit loadSettings() call. The template is left unchanged from the known-working revert. If the chat still renders, we know the regression came from the template @if injection rather than the service wiring. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Step 2 of incremental re-introduction: add the @if (adSlotsAfter.has(...)) template block, but render a plain <div> placeholder instead of the real <app-magnet-ad-slot> component. If messages still render with this in place, the regression was tied to the magnet-ad-slot component (DI, ngAfterViewInit, IntersectionObserver, etc.) rather than to the @if template structure itself. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Step 3 of incremental re-introduction: instead of adding a sibling <nb-list-item> after the message item, place the ad placeholder inside the same <nb-list-item> as the message. This avoids creating a second projected list-item child of <nb-list> via @if, which appears to be what blocks rendering — Nebular's <nb-list> may rely on a content-child query that does not survive a conditional second item. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Now that the regression is understood (creating a sibling <nb-list-item> via @if inside @for breaks Nebular's <nb-list> rendering), wire the real <app-magnet-ad-slot> component back in — but place it inside the existing <nb-list-item> rather than as a sibling. This keeps every iteration of @for producing exactly one <nb-list-item>, which is what <nb-list> expects. Also re-add MagnetAdSlotComponent to ChatComponent's imports. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wrap the magnet ad slot in the same visual structure as a regular admin message: channel logo on the side, channel name + 'פרסומת' label above, and the embed itself rendered inside the same .message-card bubble used for chat messages. Inject ChatService into the slot component to read channelInfo for the logo and name. The collapsed state now toggles a CSS class on the wrapper (display: none) instead of rebuilding the DOM, which keeps the #host ViewChild stable across renders. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a new "אנליטיקס וטראקינג" category in the admin settings UI with a textarea field for pasting any HTML/JS analytics snippet (Google Analytics, GTM, Meta Pixel, etc.). The backend stores it under the analytics_head settings key and serveSpaFile injects it into the served index.html immediately before the closing </head> tag, so the snippet runs on every page load. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Update SET.md with the changes introduced over this work session: - The new visual settings UI with categorized cards. - The analytics_head setting and its head injection. - The full Magnet ad integration (frequency rules, lazy loading, ad bubble rendering, stats panel) and the architectural note about why ads are nested inside the existing <nb-list-item> rather than as siblings. - The new /api/ads/magnet and /api/admin/magnet/stats endpoints. - A complete refreshed settings table including all magnet_* keys and analytics_head. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
regex-replace(שדות pattern/replace נפרדים), הדבקת JSON של Service Account שמפצל אוטומטית לכל שדותfcm_json_*, ומקטע "הגדרות מתקדמות" מתקפל בתחתית שמאפשר עדיין הוספת key/value חופשי (גם מציג הגדרות לא מוכרות שכבר קיימות).[{key, value}]בעת שמירה (בוליאנים נשמרים כ-'1', regex כ-pattern#replace).captain-definitionלהגדרת פריסה ב-CapRover.Files changed
frontend/src/app/components/admin/settings/settings.schema.ts(חדש) — schema עם קטגוריות, סוגי שדות, ותיאורים בעברית.frontend/src/app/components/admin/settings/settings.component.ts— נכתב מחדש לטעון/לשמור לפי ה-schema.frontend/src/app/components/admin/settings/settings.component.html— UI חדש לחלוטין.frontend/src/app/components/admin/settings/settings.component.scss— סגנונות חדשים.captain-definition— קובץ פריסה.Test plan
1/לא קיים).regex-replaceולוודא שהם נשמרים בפורמטpattern#replaceופועלים בפרסום הודעות.fcm_json_*מתמלאים.🤖 Generated with Claude Code