diff --git a/README.md b/README.md index 0e7582de..345bad6c 100644 --- a/README.md +++ b/README.md @@ -231,6 +231,7 @@ GRIST_SESSION_DOMAIN | if set, associates the cookie with the given domain - oth GRIST_SESSION_SECRET | a key used to encode sessions GRIST_FORCE_LOGIN | when set to 'true' disables anonymous access GRIST_SINGLE_ORG | set to an org "domain" to pin client to that org +GRIST_HELP_CENTER | set the help center link ref GRIST_SUPPORT_ANON | if set to 'true', show UI for anonymous access (not shown by default) GRIST_SUPPORT_EMAIL | if set, give a user with the specified email support powers. The main extra power is the ability to share sites, workspaces, and docs with all users in a listed way. GRIST_THROTTLE_CPU | if set, CPU throttling is enabled diff --git a/app/client/widgets/NTextBox.ts b/app/client/widgets/NTextBox.ts index 807a6ae5..854685f5 100644 --- a/app/client/widgets/NTextBox.ts +++ b/app/client/widgets/NTextBox.ts @@ -9,6 +9,9 @@ import { cssIconBackground, icon } from 'app/client/ui2018/icons'; import { gristLink } from 'app/client/ui2018/links'; import { NewAbstractWidget, Options } from 'app/client/widgets/NewAbstractWidget'; import { Computed, dom, DomArg, DomContents, fromKo, Observable, styled } from 'grainjs'; +import {makeT} from 'app/client/lib/localization'; + +const t = makeT('NTextBox'); /** * TextBox - The most basic widget for displaying text information. @@ -62,7 +65,7 @@ export class NTextBox extends NewAbstractWidget { return dom('div.field_clip', dom.style('text-align', this.alignment), dom.cls('text_wrapping', this.wrapping), - dom.domComputed((use) => use(row._isAddRow) ? null : makeLinks(use(this.valueFormatter).formatAny(use(value)))) + dom.domComputed((use) => use(row._isAddRow) ? null : makeLinks(use(this.valueFormatter).formatAny(use(value), t))) ); } } diff --git a/app/common/ValueFormatter.ts b/app/common/ValueFormatter.ts index 9ff05f27..8216fc60 100644 --- a/app/common/ValueFormatter.ts +++ b/app/common/ValueFormatter.ts @@ -79,19 +79,28 @@ export class BaseFormatter { * Formats using this.format() if a value is of the right type for this formatter, or using * AnyFormatter otherwise. This method the recommended API. There is no need to override it. */ - public formatAny(value: any): string { - return this.isRightType(value) ? this.format(value) : formatUnknown(value); + public formatAny(value: any, translate?: (val: string) => string): string { + return this.isRightType(value) ? this.format(value, translate) : formatUnknown(value); } /** * Formats a value that matches the type of this formatter. This should be overridden by derived * classes to handle values in formatter-specific ways. */ - protected format(value: any): string { + protected format(value: any, _translate?: (val: string) => string): string { return String(value); } } +export class BoolFormatter extends BaseFormatter { + public format(value: boolean | 0 | 1, translate?: (val: string) => string): string { + if (typeof value === 'boolean' && translate) { + return translate(String(value)); + } + return super.format(value, translate); + } +} + class AnyFormatter extends BaseFormatter { public format(value: any): string { return formatUnknown(value); @@ -265,7 +274,7 @@ class ReferenceListFormatter extends ReferenceFormatter { const formatters: { [name: string]: typeof BaseFormatter } = { Numeric: NumericFormatter, Int: IntFormatter, - Bool: BaseFormatter, + Bool: BoolFormatter, Date: DateFormatter, DateTime: DateTimeFormatter, Ref: ReferenceFormatter, diff --git a/app/common/gristUrls.ts b/app/common/gristUrls.ts index 3e4ff508..49450133 100644 --- a/app/common/gristUrls.ts +++ b/app/common/gristUrls.ts @@ -60,7 +60,7 @@ export const MIN_URLID_PREFIX_LENGTH = 12; */ export const commonUrls = { - help: "https://support.getgrist.com", + help: getHelpCenterUrl(), helpAccessRules: "https://support.getgrist.com/access-rules", helpConditionalFormatting: "https://support.getgrist.com/conditional-formatting", helpLinkingWidgets: "https://support.getgrist.com/linking-widgets", @@ -493,6 +493,9 @@ export interface GristLoadConfig { // In single-org mode, this is the single well-known org. Suppress any org selection UI. singleOrg?: string; + + // Url for support for the browser client to use. + helpCenterUrl?: string; // When set, this directs the client to encode org information in path, not in domain. pathOnly?: boolean; @@ -641,6 +644,15 @@ export function getKnownOrg(): string|null { } } +export function getHelpCenterUrl(): string|null { + if(isClient()) { + const gristConfig: GristLoadConfig = (window as any).gristConfig; + return gristConfig && gristConfig.helpCenterUrl || null; + } else { + return process.env.GRIST_HELP_CENTER || null; + } +} + /** * Like getKnownOrg, but respects singleOrg/GRIST_SINGLE_ORG strictly. * The main difference in behavior would be for orgs with custom domains diff --git a/app/server/lib/sendAppPage.ts b/app/server/lib/sendAppPage.ts index 21740d12..3a1bd0d0 100644 --- a/app/server/lib/sendAppPage.ts +++ b/app/server/lib/sendAppPage.ts @@ -41,6 +41,7 @@ export function makeGristConfig(homeUrl: string|null, extra: Partial