Enforce module disabling on canvas folk-rapp shapes
CI/CD / deploy (push) Failing after 9s
Details
CI/CD / deploy (push) Failing after 9s
Details
Disabled rApp modules now show a grayed lock overlay on the canvas instead of loading their iframe/widget. Uses a static instance registry so setEnabledModules() broadcasts to all live shapes immediately. Re-enabling a module reloads its content. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
29cd6168f9
commit
7dc4e9b3e9
|
|
@ -195,6 +195,29 @@ const styles = css`
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rapp-disabled {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
gap: 8px;
|
||||||
|
color: var(--rs-text-muted);
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 16px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rapp-disabled-icon {
|
||||||
|
font-size: 28px;
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([data-module-disabled]) .rapp-header {
|
||||||
|
filter: grayscale(0.6);
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
/* Module picker (shown when no moduleId set) */
|
/* Module picker (shown when no moduleId set) */
|
||||||
.rapp-picker {
|
.rapp-picker {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -598,9 +621,13 @@ export class FolkRApp extends FolkShape {
|
||||||
/** Enabled module IDs for picker/switcher filtering (null = all enabled) */
|
/** Enabled module IDs for picker/switcher filtering (null = all enabled) */
|
||||||
static enabledModuleIds: Set<string> | null = null;
|
static enabledModuleIds: Set<string> | null = null;
|
||||||
|
|
||||||
|
/** Live instance registry for broadcasting enabled-state changes */
|
||||||
|
static #instances = new Set<FolkRApp>();
|
||||||
|
|
||||||
/** Update which modules appear in the picker and switcher dropdowns */
|
/** Update which modules appear in the picker and switcher dropdowns */
|
||||||
static setEnabledModules(ids: string[] | null) {
|
static setEnabledModules(ids: string[] | null) {
|
||||||
FolkRApp.enabledModuleIds = ids ? new Set(ids) : null;
|
FolkRApp.enabledModuleIds = ids ? new Set(ids) : null;
|
||||||
|
for (const inst of FolkRApp.#instances) inst.#syncDisabledState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Port descriptors for data pipe integration (AC#3) */
|
/** Port descriptors for data pipe integration (AC#3) */
|
||||||
|
|
@ -813,6 +840,9 @@ export class FolkRApp extends FolkShape {
|
||||||
} catch { /* iframe not ready */ }
|
} catch { /* iframe not ready */ }
|
||||||
}) as EventListener);
|
}) as EventListener);
|
||||||
|
|
||||||
|
// Register for enabled-state broadcasts
|
||||||
|
FolkRApp.#instances.add(this);
|
||||||
|
|
||||||
// Load content
|
// Load content
|
||||||
if (this.#moduleId) {
|
if (this.#moduleId) {
|
||||||
this.#renderContent();
|
this.#renderContent();
|
||||||
|
|
@ -825,6 +855,7 @@ export class FolkRApp extends FolkShape {
|
||||||
|
|
||||||
disconnectedCallback() {
|
disconnectedCallback() {
|
||||||
super.disconnectedCallback?.();
|
super.disconnectedCallback?.();
|
||||||
|
FolkRApp.#instances.delete(this);
|
||||||
if (this.#messageHandler) {
|
if (this.#messageHandler) {
|
||||||
window.removeEventListener("message", this.#messageHandler);
|
window.removeEventListener("message", this.#messageHandler);
|
||||||
this.#messageHandler = null;
|
this.#messageHandler = null;
|
||||||
|
|
@ -964,10 +995,56 @@ export class FolkRApp extends FolkShape {
|
||||||
return onSubdomain ? `/${this.#moduleId}` : `/${space}/${this.#moduleId}`;
|
return onSubdomain ? `/${this.#moduleId}` : `/${space}/${this.#moduleId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Check if this shape's module is currently disabled */
|
||||||
|
#isModuleDisabled(): boolean {
|
||||||
|
const enabled = FolkRApp.enabledModuleIds;
|
||||||
|
if (!enabled) return false; // null = all enabled
|
||||||
|
return this.#moduleId !== "" && !enabled.has(this.#moduleId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Show the disabled overlay and tear down any active iframe/timer */
|
||||||
|
#showDisabled() {
|
||||||
|
if (!this.#contentEl) return;
|
||||||
|
|
||||||
|
// Clear iframe and timer
|
||||||
|
this.#iframe = null;
|
||||||
|
if (this.#refreshTimer) {
|
||||||
|
clearInterval(this.#refreshTimer);
|
||||||
|
this.#refreshTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setAttribute("data-module-disabled", "");
|
||||||
|
|
||||||
|
const meta = MODULE_META[this.#moduleId];
|
||||||
|
this.#contentEl.innerHTML = `
|
||||||
|
<div class="rapp-disabled">
|
||||||
|
<span class="rapp-disabled-icon">🔒</span>
|
||||||
|
<span>${meta?.name || this.#moduleId} is disabled</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sync this instance's visual state with the current enabled set */
|
||||||
|
#syncDisabledState() {
|
||||||
|
if (!this.#contentEl || !this.#moduleId) return;
|
||||||
|
const disabled = this.#isModuleDisabled();
|
||||||
|
const wasDisabled = this.hasAttribute("data-module-disabled");
|
||||||
|
|
||||||
|
if (disabled && !wasDisabled) {
|
||||||
|
this.#showDisabled();
|
||||||
|
} else if (!disabled && wasDisabled) {
|
||||||
|
this.removeAttribute("data-module-disabled");
|
||||||
|
this.#renderContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Route to the right render method based on current mode */
|
/** Route to the right render method based on current mode */
|
||||||
#renderContent() {
|
#renderContent() {
|
||||||
if (!this.#contentEl || !this.#moduleId) return;
|
if (!this.#contentEl || !this.#moduleId) return;
|
||||||
|
|
||||||
|
// Block rendering if module is disabled
|
||||||
|
if (this.#isModuleDisabled()) { this.#showDisabled(); return; }
|
||||||
|
|
||||||
// Clear refresh timer
|
// Clear refresh timer
|
||||||
if (this.#refreshTimer) {
|
if (this.#refreshTimer) {
|
||||||
clearInterval(this.#refreshTimer);
|
clearInterval(this.#refreshTimer);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue