Introduce GRIST_ANON_PLAYGROUND variable #642 (#651)

* `GRIST_ANON_PLAYGROUND`: When set to 'false' deny anonymous users access to the home page
 * `GRIST_FORCE_LOGIN`: Much like `GRIST_ANON_PLAYGROUND` but don't support anonymous access at all (features like sharing docs publicly requires authentication)

---------

Co-authored-by: Florent FAYOLLE <florent.fayolle@beta.gouv.fr>
This commit is contained in:
Florent
2023-09-08 15:05:52 +02:00
committed by GitHub
parent dc5ddc27b0
commit 5ff79703b4
11 changed files with 149 additions and 12 deletions

View File

@@ -190,7 +190,7 @@ export class DocPageModelImpl extends Disposable implements DocPageModel {
public createLeftPane(leftPanelOpen: Observable<boolean>) {
return cssLeftPanel(
dom.maybe(this.gristDoc, (activeDoc) => [
addNewButton(leftPanelOpen,
addNewButton({ isOpen: leftPanelOpen },
menu(() => addMenu(this.importSources, activeDoc, this.isReadonly.get()), {
placement: 'bottom-start',
// "Add New" menu should have the same width as the "Add New" button that opens it.

View File

@@ -5,14 +5,27 @@ import {dom, DomElementArg, Observable, styled} from "grainjs";
const t = makeT(`AddNewButton`);
export function addNewButton(isOpen: Observable<boolean> | boolean = true, ...args: DomElementArg[]) {
export function addNewButton(
{
isOpen,
isDisabled = false,
}: {
isOpen: Observable<boolean> | boolean,
isDisabled?: boolean
},
...args: DomElementArg[]
) {
return cssAddNewButton(
cssAddNewButton.cls('-open', isOpen),
cssAddNewButton.cls('-disabled', isDisabled),
// Setting spacing as flex items allows them to shrink faster when there isn't enough space.
cssLeftMargin(),
cssAddText(t("Add New")),
dom('div', {style: 'flex: 1 1 16px'}),
cssPlusButton(cssPlusIcon('Plus')),
cssPlusButton(
cssPlusButton.cls('-disabled', isDisabled),
cssPlusIcon('Plus')
),
dom('div', {style: 'flex: 0 1 16px'}),
...args,
);
@@ -47,6 +60,11 @@ export const cssAddNewButton = styled('div', `
background-color: ${theme.controlPrimaryHoverBg};
--circle-color: ${theme.addNewCircleHoverBg};
}
&-disabled, &-disabled:hover {
color: ${theme.controlDisabledFg};
background-color: ${theme.controlDisabledBg}
}
`);
const cssLeftMargin = styled('div', `
flex: 0 1 24px;
@@ -72,6 +90,9 @@ const cssPlusButton = styled('div', `
border-radius: 14px;
background-color: var(--circle-color);
text-align: center;
&-disabled {
background-color: ${theme.controlDisabledBg};
}
`);
const cssPlusIcon = styled(icon, `
background-color: ${theme.addNewCircleFg};

View File

@@ -1,5 +1,5 @@
import {makeT} from 'app/client/lib/localization';
import {getLoginOrSignupUrl, urlState} from 'app/client/models/gristUrlState';
import {getLoginOrSignupUrl, getLoginUrl, getSignupUrl, urlState} from 'app/client/models/gristUrlState';
import {HomeModel} from 'app/client/models/HomeModel';
import {productPill} from 'app/client/ui/AppHeader';
import * as css from 'app/client/ui/DocMenuCss';
@@ -12,6 +12,7 @@ import {cssLink} from 'app/client/ui2018/links';
import {commonUrls, isFeatureEnabled} from 'app/common/gristUrls';
import {FullUser} from 'app/common/LoginSessionAPI';
import * as roles from 'app/common/roles';
import {getGristConfig} from 'app/common/urlUtils';
import {Computed, dom, DomContents, styled} from 'grainjs';
const t = makeT('HomeIntro');
@@ -112,10 +113,36 @@ function makePersonalIntro(homeModel: HomeModel, user: FullUser) {
];
}
function makeAnonIntroWithoutPlayground(homeModel: HomeModel) {
return [
(!isFeatureEnabled('helpCenter') ? null : cssIntroLine(t("Visit our {{link}} to learn more about Grist.", {
link: helpCenterLink()
}), testId('welcome-text-no-playground'))),
cssIntroLine(t("To use Grist, please either sign up or sign in.")),
cssBtnGroup(
cssBtn(t("Sign up"), cssButton.cls('-primary'), testId('intro-sign-up'),
dom.on('click', () => location.href = getSignupUrl())
),
cssBtn(t("Sign in"), testId('intro-sign-in'),
dom.on('click', () => location.href = getLoginUrl())
)
)
];
}
function makeAnonIntro(homeModel: HomeModel) {
const welcomeToGrist = css.docListHeader(t("Welcome to Grist!"), testId('welcome-title'));
if (!getGristConfig().enableAnonPlayground) {
return [
welcomeToGrist,
...makeAnonIntroWithoutPlayground(homeModel)
];
}
const signUp = cssLink({href: getLoginOrSignupUrl()}, t("Sign up"));
return [
css.docListHeader(t("Welcome to Grist!"), testId('welcome-title')),
welcomeToGrist,
cssIntroLine(t("Get started by exploring templates, or creating your first Grist document.")),
cssIntroLine(t("{{signUp}} to save your work. ", {signUp}),
(!isFeatureEnabled('helpCenter') ? null : t("Visit our {{link}} to learn more.", { link: helpCenterLink() })),

View File

@@ -30,16 +30,17 @@ export function createHomeLeftPane(leftPanelOpen: Observable<boolean>, home: Hom
const creating = observable<boolean>(false);
const renaming = observable<Workspace|null>(null);
const isAnonymous = !home.app.currentValidUser;
const canCreate = !isAnonymous || getGristConfig().enableAnonPlayground;
return cssContent(
dom.autoDispose(creating),
dom.autoDispose(renaming),
addNewButton(leftPanelOpen,
menu(() => addMenu(home, creating), {
addNewButton({ isOpen: leftPanelOpen, isDisabled: !canCreate },
canCreate ? menu(() => addMenu(home, creating), {
placement: 'bottom-start',
// "Add New" menu should have the same width as the "Add New" button that opens it.
stretchToSelector: `.${cssAddNewButton.className}`
}),
}) : null,
dom.cls('behavioral-prompt-add-new'),
testId('dm-add-new'),
),