(core) Adding a flag for the UI to check if emails are enabled

Summary:
Front-end code can now test if emails are enabled
and hide some parts of UI based on it.

Test Plan:
Only secondery text was hidden on add users dialog.
Tested manually.

Reviewers: georgegevoian

Reviewed By: georgegevoian

Subscribers: georgegevoian

Differential Revision: https://phab.getgrist.com/D4221
This commit is contained in:
Jarosław Sadziński 2024-04-02 13:22:58 +02:00
parent c87d835533
commit 03ead0d1ca
7 changed files with 23 additions and 12 deletions

View File

@ -16,6 +16,7 @@ import {
cssMemberText, cssMemberText,
} from "app/client/ui/UserItem"; } from "app/client/ui/UserItem";
import {createUserImage, cssUserImage} from "app/client/ui/UserImage"; import {createUserImage, cssUserImage} from "app/client/ui/UserImage";
import {getGristConfig} from 'app/common/urlUtils';
import {Computed, computed, dom, DomElementArg, Holder, IDisposableOwner, Observable, styled} from "grainjs"; import {Computed, computed, dom, DomElementArg, Holder, IDisposableOwner, Observable, styled} from "grainjs";
import {cssMenuItem} from "popweasel"; import {cssMenuItem} from "popweasel";
@ -111,10 +112,9 @@ export function buildACMemberEmail(
)), )),
cssMemberText( cssMemberText(
cssMemberPrimaryPlus(t("Invite new member")), cssMemberPrimaryPlus(t("Invite new member")),
cssMemberSecondaryPlus( getGristConfig().notifierEnabled ? cssMemberSecondaryPlus(
// dom.text(use => `We'll email an invite to ${use(emailObs)}`) dom.text(use => t("We'll email an invite to {{email}}", {email: use(emailObs)}))
dom.text(use => t("We'll email an invite to {{email}}", {email: use(emailObs)})) // TODO i18next ) : null,
)
), ),
testId("um-add-email") testId("um-add-email")
) )

View File

@ -786,6 +786,9 @@ export interface GristLoadConfig {
canCloseAccount?: boolean; canCloseAccount?: boolean;
experimentalPlugins?: boolean; experimentalPlugins?: boolean;
// If backend has an email service for sending notifications.
notifierEnabled?: boolean;
} }
export const Features = StringUnion( export const Features = StringUnion(

View File

@ -47,7 +47,7 @@ import {initGristSessions, SessionStore} from 'app/server/lib/gristSessions';
import {HostedStorageManager} from 'app/server/lib/HostedStorageManager'; import {HostedStorageManager} from 'app/server/lib/HostedStorageManager';
import {IBilling} from 'app/server/lib/IBilling'; import {IBilling} from 'app/server/lib/IBilling';
import {IDocStorageManager} from 'app/server/lib/IDocStorageManager'; import {IDocStorageManager} from 'app/server/lib/IDocStorageManager';
import {INotifier} from 'app/server/lib/INotifier'; import {EmptyNotifier, INotifier} from 'app/server/lib/INotifier';
import {InstallAdmin} from 'app/server/lib/InstallAdmin'; import {InstallAdmin} from 'app/server/lib/InstallAdmin';
import log from 'app/server/lib/log'; import log from 'app/server/lib/log';
import {getLoginSystem} from 'app/server/lib/logins'; import {getLoginSystem} from 'app/server/lib/logins';
@ -384,7 +384,7 @@ export class FlexServer implements GristServer {
} }
public hasNotifier(): boolean { public hasNotifier(): boolean {
return Boolean(this._notifier); return Boolean(this._notifier) && this._notifier !== EmptyNotifier;
} }
public getNotifier(): INotifier { public getNotifier(): INotifier {

View File

@ -52,6 +52,7 @@ export interface GristServer {
getHomeDBManager(): HomeDBManager; getHomeDBManager(): HomeDBManager;
getStorageManager(): IDocStorageManager; getStorageManager(): IDocStorageManager;
getTelemetry(): ITelemetry; getTelemetry(): ITelemetry;
hasNotifier(): boolean;
getNotifier(): INotifier; getNotifier(): INotifier;
getDocTemplate(): Promise<DocTemplate>; getDocTemplate(): Promise<DocTemplate>;
getTag(): string; getTag(): string;
@ -142,6 +143,7 @@ export function createDummyGristServer(): GristServer {
getStorageManager() { throw new Error('no storage manager'); }, getStorageManager() { throw new Error('no storage manager'); },
getTelemetry() { return createDummyTelemetry(); }, getTelemetry() { return createDummyTelemetry(); },
getNotifier() { throw new Error('no notifier'); }, getNotifier() { throw new Error('no notifier'); },
hasNotifier() { return false; },
getDocTemplate() { throw new Error('no doc template'); }, getDocTemplate() { throw new Error('no doc template'); },
getTag() { return 'tag'; }, getTag() { return 'tag'; },
sendAppPage() { return Promise.resolve(); }, sendAppPage() { return Promise.resolve(); },

View File

@ -5,7 +5,7 @@ import {HomeDBManager} from 'app/gen-server/lib/HomeDBManager';
import {ExternalStorage} from 'app/server/lib/ExternalStorage'; import {ExternalStorage} from 'app/server/lib/ExternalStorage';
import {createDummyTelemetry, GristServer} from 'app/server/lib/GristServer'; import {createDummyTelemetry, GristServer} from 'app/server/lib/GristServer';
import {IBilling} from 'app/server/lib/IBilling'; import {IBilling} from 'app/server/lib/IBilling';
import {INotifier} from 'app/server/lib/INotifier'; import {EmptyNotifier, INotifier} from 'app/server/lib/INotifier';
import {InstallAdmin, SimpleInstallAdmin} from 'app/server/lib/InstallAdmin'; import {InstallAdmin, SimpleInstallAdmin} from 'app/server/lib/InstallAdmin';
import {ISandbox, ISandboxCreationOptions} from 'app/server/lib/ISandbox'; import {ISandbox, ISandboxCreationOptions} from 'app/server/lib/ISandbox';
import {IShell} from 'app/server/lib/IShell'; import {IShell} from 'app/server/lib/IShell';
@ -99,11 +99,7 @@ export function makeSimpleCreator(opts: {
}; };
}, },
Notifier(dbManager, gristConfig) { Notifier(dbManager, gristConfig) {
return notifier?.create(dbManager, gristConfig) ?? { return notifier?.create(dbManager, gristConfig) ?? EmptyNotifier;
get testPending() { return false; },
async deleteUser() { /* do nothing */ },
testSetSendMessageCallback() { return undefined; },
};
}, },
ExternalStorage(purpose, extraPrefix) { ExternalStorage(purpose, extraPrefix) {
for (const s of storage || []) { for (const s of storage || []) {

View File

@ -10,3 +10,12 @@ export interface INotifier {
// Return undefined if no notification system is available. // Return undefined if no notification system is available.
testSetSendMessageCallback(op: (body: SendGridMail, description: string) => Promise<void>): SendGridConfig|undefined; testSetSendMessageCallback(op: (body: SendGridMail, description: string) => Promise<void>): SendGridConfig|undefined;
} }
/**
* A notifier that does nothing. Used when no email notifications are configured.
*/
export const EmptyNotifier: INotifier = {
get testPending() { return false; },
async deleteUser() { /* do nothing */ },
testSetSendMessageCallback() { return undefined; },
} as const;

View File

@ -97,6 +97,7 @@ export function makeGristConfig(options: MakeGristConfigOptions): GristLoadConfi
templateOrg: getTemplateOrg(), templateOrg: getTemplateOrg(),
canCloseAccount: isAffirmative(process.env.GRIST_ACCOUNT_CLOSE), canCloseAccount: isAffirmative(process.env.GRIST_ACCOUNT_CLOSE),
experimentalPlugins: isAffirmative(process.env.GRIST_EXPERIMENTAL_PLUGINS), experimentalPlugins: isAffirmative(process.env.GRIST_EXPERIMENTAL_PLUGINS),
notifierEnabled: server?.hasNotifier(),
...extra, ...extra,
}; };
} }