Merge branch 'main' into dev
This commit is contained in:
commit
adb1c7cb87
|
|
@ -458,6 +458,8 @@ async function executeApproval(docId: string, approvalId: string) {
|
||||||
replyTo: agentReplyTo,
|
replyTo: agentReplyTo,
|
||||||
subject: approval.subject,
|
subject: approval.subject,
|
||||||
text: approval.bodyText,
|
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) {
|
if (approval.ccAddresses.length > 0) {
|
||||||
|
|
|
||||||
|
|
@ -607,10 +607,19 @@ export function renderShell(opts: ShellOptions): string {
|
||||||
var enabledModules = detail.enabledModules;
|
var enabledModules = detail.enabledModules;
|
||||||
window.__rspaceEnabledModules = enabledModules;
|
window.__rspaceEnabledModules = enabledModules;
|
||||||
|
|
||||||
// Update tab bar's module list
|
// Recompute visible + allModules with updated enabled flags
|
||||||
var allMods = window.__rspaceAllModules || [];
|
var allMods = window.__rspaceAllModules || [];
|
||||||
var enabledSet = new Set(enabledModules);
|
var enabledSet = new Set(enabledModules);
|
||||||
var visible = allMods.filter(function(m) { return m.id === 'rspace' || enabledSet.has(m.id); });
|
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');
|
var tb = document.querySelector('rstack-tab-bar');
|
||||||
if (tb) tb.setModules(visible);
|
if (tb) tb.setModules(visible);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2199,11 +2199,14 @@ spaces.post("/:slug/invite", async (c) => {
|
||||||
metadata: { inviteToken: invite.token, role },
|
metadata: { inviteToken: invite.token, role },
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
|
|
||||||
// Send invite email
|
// Send invite email from {slug}-agent@rspace.online
|
||||||
if (inviteTransport) {
|
if (inviteTransport) {
|
||||||
try {
|
try {
|
||||||
|
const agentAddr = `${slug}-agent@rspace.online`;
|
||||||
await inviteTransport.sendMail({
|
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,
|
to: body.email,
|
||||||
subject: `${inviterName} invited you to "${slug}" on rSpace`,
|
subject: `${inviterName} invited you to "${slug}" on rSpace`,
|
||||||
html: `
|
html: `
|
||||||
|
|
@ -2326,11 +2329,14 @@ spaces.post("/:slug/members/add", async (c) => {
|
||||||
metadata: { inviteToken: invite.token, role },
|
metadata: { inviteToken: invite.token, role },
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
|
|
||||||
// Send invite email (non-fatal)
|
// Send invite email from {slug}-agent@rspace.online (non-fatal)
|
||||||
if (inviteTransport && targetEmail) {
|
if (inviteTransport && targetEmail) {
|
||||||
try {
|
try {
|
||||||
|
const agentAddr = `${slug}-agent@rspace.online`;
|
||||||
await inviteTransport.sendMail({
|
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,
|
to: targetEmail,
|
||||||
subject: `${inviterName} invited you to "${slug}" on rSpace`,
|
subject: `${inviterName} invited you to "${slug}" on rSpace`,
|
||||||
html: `
|
html: `
|
||||||
|
|
|
||||||
|
|
@ -243,34 +243,37 @@ export class RStackAppSwitcher extends HTMLElement {
|
||||||
const disabledModules = this.#allModules.filter(
|
const disabledModules = this.#allModules.filter(
|
||||||
m => m.enabled === false && m.id !== 'rspace'
|
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 += `
|
html += `
|
||||||
<div class="catalog-divider">
|
<div class="catalog-divider">
|
||||||
<button class="catalog-toggle" id="catalog-toggle">
|
<button class="catalog-toggle" id="catalog-toggle">
|
||||||
${this.#catalogOpen ? '▾' : '▸'} Manage rApps
|
${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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
if (this.#catalogOpen) {
|
if (this.#catalogOpen) {
|
||||||
html += `<div class="catalog-panel" id="catalog-panel">`;
|
html += `<div class="catalog-panel" id="catalog-panel">`;
|
||||||
// Show enabled modules with toggle-off option
|
// Show disabled modules with add 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
|
|
||||||
if (disabledModules.length > 0) {
|
if (disabledModules.length > 0) {
|
||||||
html += `<div class="catalog-section-label">Available to Add</div>`;
|
html += `<div class="catalog-section-label">Available to Add</div>`;
|
||||||
for (const m of disabledModules) {
|
for (const m of disabledModules) {
|
||||||
html += this.#renderCatalogItem(m, false);
|
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>`;
|
html += `</div>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5462,8 +5462,11 @@ app.post('/api/invites/identity', async (c) => {
|
||||||
const subjectLine = spaceSlug
|
const subjectLine = spaceSlug
|
||||||
? `${payload.username} invited you to join "${spaceSlug}" on rSpace`
|
? `${payload.username} invited you to join "${spaceSlug}" on rSpace`
|
||||||
: `${payload.username} invited you to join rSpace`;
|
: `${payload.username} invited you to join rSpace`;
|
||||||
|
const agentAddr = spaceSlug ? `${spaceSlug}-agent@rspace.online` : null;
|
||||||
await smtpTransport.sendMail({
|
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,
|
to: email,
|
||||||
subject: subjectLine,
|
subject: subjectLine,
|
||||||
html: `
|
html: `
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ body {
|
||||||
.rspace-banner {
|
.rspace-banner {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0; left: 0; right: 0;
|
top: 0; left: 0; right: 0;
|
||||||
z-index: 10002;
|
z-index: 10000; /* above header (9999) */
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
@ -68,7 +68,7 @@ body {
|
||||||
.rspace-banner__close:hover {
|
.rspace-banner__close:hover {
|
||||||
color: #fff;
|
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 {
|
body.rspace-banner-visible .rstack-header {
|
||||||
top: 36px;
|
top: 36px;
|
||||||
}
|
}
|
||||||
|
|
@ -628,13 +628,13 @@ body.rspace-headers-minimized .rapp-subnav {
|
||||||
|
|
||||||
/* Smooth transitions for header minimize/restore */
|
/* Smooth transitions for header minimize/restore */
|
||||||
.rstack-header {
|
.rstack-header {
|
||||||
transition: transform 0.25s ease;
|
transition: transform 0.25s ease, top 0.3s ease-out;
|
||||||
}
|
}
|
||||||
.rstack-tab-row {
|
.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 {
|
#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) */
|
/* Mobile: minimized state adjustments (sticky, not fixed) */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue