Fix sidebar showing all modules: hide Manage panel when none disabled
- App switcher: only show "Manage rApps" when there are actually disabled modules or active restrictions. Move "Available to Add" above "Remove" to prioritize adding. Eliminates duplicate module listing when all modules are enabled. - Shell: update app switcher on modules-changed event (was only updating tab bar and folk-rapp, not the sidebar itself). - SMTP: use space-agent@rspace.online as From for invite/approval emails with proper envelope sender for DKIM alignment. - Shell CSS: fix banner z-index, smooth header transition on banner. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b54ad4b36c
commit
45372c6681
|
|
@ -458,6 +458,8 @@ async function executeApproval(docId: string, approvalId: string) {
|
|||
replyTo: agentReplyTo,
|
||||
subject: approval.subject,
|
||||
text: approval.bodyText,
|
||||
// Envelope override: authenticate as SMTP_USER but show mailboxEmail in From header
|
||||
envelope: { from: SMTP_USER || 'noreply@rmail.online', to: approval.toAddresses },
|
||||
};
|
||||
|
||||
if (approval.ccAddresses.length > 0) {
|
||||
|
|
|
|||
|
|
@ -607,10 +607,19 @@ export function renderShell(opts: ShellOptions): string {
|
|||
var enabledModules = detail.enabledModules;
|
||||
window.__rspaceEnabledModules = enabledModules;
|
||||
|
||||
// Update tab bar's module list
|
||||
// Recompute visible + allModules with updated enabled flags
|
||||
var allMods = window.__rspaceAllModules || [];
|
||||
var enabledSet = new Set(enabledModules);
|
||||
var visible = allMods.filter(function(m) { return m.id === 'rspace' || enabledSet.has(m.id); });
|
||||
var updatedAll = allMods.map(function(m) { return Object.assign({}, m, { enabled: m.id === 'rspace' || enabledSet.has(m.id) }); });
|
||||
window.__rspaceModuleList = visible;
|
||||
window.__rspaceAllModules = updatedAll;
|
||||
|
||||
// Update app switcher's main navigation + catalog
|
||||
var switcher = document.querySelector('rstack-app-switcher');
|
||||
if (switcher) { switcher.setModules(visible); switcher.setAllModules(updatedAll); }
|
||||
|
||||
// Update tab bar's module list
|
||||
var tb = document.querySelector('rstack-tab-bar');
|
||||
if (tb) tb.setModules(visible);
|
||||
|
||||
|
|
|
|||
|
|
@ -2199,11 +2199,14 @@ spaces.post("/:slug/invite", async (c) => {
|
|||
metadata: { inviteToken: invite.token, role },
|
||||
}).catch(() => {});
|
||||
|
||||
// Send invite email
|
||||
// Send invite email from {slug}-agent@rspace.online
|
||||
if (inviteTransport) {
|
||||
try {
|
||||
const agentAddr = `${slug}-agent@rspace.online`;
|
||||
await inviteTransport.sendMail({
|
||||
from: process.env.SMTP_FROM || "rSpace <noreply@rmail.online>",
|
||||
from: `${slug} <${agentAddr}>`,
|
||||
replyTo: agentAddr,
|
||||
envelope: { from: process.env.SMTP_USER || "noreply@rmail.online", to: body.email },
|
||||
to: body.email,
|
||||
subject: `${inviterName} invited you to "${slug}" on rSpace`,
|
||||
html: `
|
||||
|
|
@ -2326,11 +2329,14 @@ spaces.post("/:slug/members/add", async (c) => {
|
|||
metadata: { inviteToken: invite.token, role },
|
||||
}).catch(() => {});
|
||||
|
||||
// Send invite email (non-fatal)
|
||||
// Send invite email from {slug}-agent@rspace.online (non-fatal)
|
||||
if (inviteTransport && targetEmail) {
|
||||
try {
|
||||
const agentAddr = `${slug}-agent@rspace.online`;
|
||||
await inviteTransport.sendMail({
|
||||
from: process.env.SMTP_FROM || "rSpace <noreply@rmail.online>",
|
||||
from: `${slug} <${agentAddr}>`,
|
||||
replyTo: agentAddr,
|
||||
envelope: { from: process.env.SMTP_USER || "noreply@rmail.online", to: targetEmail },
|
||||
to: targetEmail,
|
||||
subject: `${inviterName} invited you to "${slug}" on rSpace`,
|
||||
html: `
|
||||
|
|
|
|||
|
|
@ -243,34 +243,37 @@ export class RStackAppSwitcher extends HTMLElement {
|
|||
const disabledModules = this.#allModules.filter(
|
||||
m => m.enabled === false && m.id !== 'rspace'
|
||||
);
|
||||
if (disabledModules.length > 0 || this.#allModules.length > 0) {
|
||||
// Only show the Manage section when there are disabled modules to add,
|
||||
// or when enabledModules is actively configured (not null/all-enabled)
|
||||
const hasRestrictions = disabledModules.length > 0;
|
||||
if (hasRestrictions || this.#allModules.length > this.#modules.length) {
|
||||
html += `
|
||||
<div class="catalog-divider">
|
||||
<button class="catalog-toggle" id="catalog-toggle">
|
||||
${this.#catalogOpen ? '▾' : '▸'} Manage rApps
|
||||
${disabledModules.length > 0 ? `<span class="catalog-count">${disabledModules.length} available</span>` : ''}
|
||||
${disabledModules.length > 0 ? `<span class="catalog-count">${disabledModules.length} more</span>` : ''}
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
if (this.#catalogOpen) {
|
||||
html += `<div class="catalog-panel" id="catalog-panel">`;
|
||||
// Show enabled modules with toggle-off option
|
||||
const enabledNonCore = this.#allModules.filter(
|
||||
m => m.enabled !== false && m.id !== 'rspace'
|
||||
);
|
||||
if (enabledNonCore.length > 0) {
|
||||
html += `<div class="catalog-section-label">Enabled</div>`;
|
||||
for (const m of enabledNonCore) {
|
||||
html += this.#renderCatalogItem(m, true);
|
||||
}
|
||||
}
|
||||
// Show disabled modules with toggle-on option
|
||||
// Show disabled modules with add option
|
||||
if (disabledModules.length > 0) {
|
||||
html += `<div class="catalog-section-label">Available to Add</div>`;
|
||||
for (const m of disabledModules) {
|
||||
html += this.#renderCatalogItem(m, false);
|
||||
}
|
||||
}
|
||||
// Show enabled modules with remove option (compact section below)
|
||||
const enabledNonCore = this.#allModules.filter(
|
||||
m => m.enabled !== false && m.id !== 'rspace'
|
||||
);
|
||||
if (enabledNonCore.length > 0) {
|
||||
html += `<div class="catalog-section-label">Remove from Space</div>`;
|
||||
for (const m of enabledNonCore) {
|
||||
html += this.#renderCatalogItem(m, true);
|
||||
}
|
||||
}
|
||||
html += `</div>`;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5462,8 +5462,11 @@ app.post('/api/invites/identity', async (c) => {
|
|||
const subjectLine = spaceSlug
|
||||
? `${payload.username} invited you to join "${spaceSlug}" on rSpace`
|
||||
: `${payload.username} invited you to join rSpace`;
|
||||
const agentAddr = spaceSlug ? `${spaceSlug}-agent@rspace.online` : null;
|
||||
await smtpTransport.sendMail({
|
||||
from: CONFIG.smtp.from,
|
||||
from: agentAddr ? `${spaceSlug} <${agentAddr}>` : CONFIG.smtp.from,
|
||||
...(agentAddr ? { replyTo: agentAddr } : {}),
|
||||
...(agentAddr ? { envelope: { from: CONFIG.smtp.user, to: email } } : {}),
|
||||
to: email,
|
||||
subject: subjectLine,
|
||||
html: `
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ body {
|
|||
.rspace-banner {
|
||||
position: fixed;
|
||||
top: 0; left: 0; right: 0;
|
||||
z-index: 10002;
|
||||
z-index: 10000; /* above header (9999) */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
|
@ -68,7 +68,7 @@ body {
|
|||
.rspace-banner__close:hover {
|
||||
color: #fff;
|
||||
}
|
||||
/* Push header down when a banner is visible */
|
||||
/* Push header + content down when a banner is visible */
|
||||
body.rspace-banner-visible .rstack-header {
|
||||
top: 36px;
|
||||
}
|
||||
|
|
@ -628,13 +628,13 @@ body.rspace-headers-minimized .rapp-subnav {
|
|||
|
||||
/* Smooth transitions for header minimize/restore */
|
||||
.rstack-header {
|
||||
transition: transform 0.25s ease;
|
||||
transition: transform 0.25s ease, top 0.3s ease-out;
|
||||
}
|
||||
.rstack-tab-row {
|
||||
transition: margin-left 0.25s ease, left 0.25s ease, transform 0.25s ease;
|
||||
transition: margin-left 0.25s ease, left 0.25s ease, transform 0.25s ease, top 0.3s ease-out;
|
||||
}
|
||||
#app {
|
||||
transition: margin-left 0.25s ease, left 0.25s ease, padding-top 0.25s ease;
|
||||
transition: margin-left 0.25s ease, left 0.25s ease, padding-top 0.3s ease-out;
|
||||
}
|
||||
|
||||
/* Mobile: minimized state adjustments (sticky, not fixed) */
|
||||
|
|
|
|||
Loading…
Reference in New Issue