mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Update design of empty docs home page, and add a "Manage Team" button.
Summary: - Remove the empty-folder icon - Add an "Invite team members" button for owners on empty team sites - Add a "Browse Templates" button for all other cases on empty sites - Update intro text for team, including a link to Sprouts - Update intro text for personal/anon. - Include a Free/Pro tag for team sites (for now, only "Free") - Add a "Manage Team" button for owners on home page of all team sites. - Polished the UI of UserManager: add a transition for the background, and delay the appearance of the spinner for fast loads. Test Plan: Fixed up the HomeIntro tests; added test case for Manage Team button Reviewers: georgegevoian Reviewed By: georgegevoian Differential Revision: https://phab.getgrist.com/D3459
This commit is contained in:
@@ -6,14 +6,25 @@ import {shouldHideUiElement} from 'app/common/gristUrls';
|
||||
import * as version from 'app/common/version';
|
||||
import {BindableValue, Disposable, dom, styled} from "grainjs";
|
||||
import {menu, menuItem, menuItemLink, menuSubHeader} from 'app/client/ui2018/menus';
|
||||
import {Organization, SUPPORT_EMAIL} from 'app/common/UserAPI';
|
||||
import {isTemplatesOrg, Organization, SUPPORT_EMAIL} from 'app/common/UserAPI';
|
||||
import {AppModel} from 'app/client/models/AppModel';
|
||||
import {icon} from 'app/client/ui2018/icons';
|
||||
import {DocPageModel} from 'app/client/models/DocPageModel';
|
||||
import * as roles from 'app/common/roles';
|
||||
import {loadUserManager} from 'app/client/lib/imports';
|
||||
import {manageTeamUsersApp} from 'app/client/ui/OpenUserManager';
|
||||
import {maybeAddSiteSwitcherSection} from 'app/client/ui/SiteSwitcher';
|
||||
import {DomContents} from 'grainjs';
|
||||
|
||||
// Maps a name of a Product (from app/gen-server/entity/Product.ts) to a tag (pill) to show next
|
||||
// to the org name.
|
||||
const productPills: {[name: string]: string|null} = {
|
||||
// TODO We don't label paid team plans with a tag yet, but we should label as "Pro" once we
|
||||
// update our pricing pages to refer to paid team plans as Pro plans.
|
||||
"professional": null, // Deprecated but used in development.
|
||||
"team": null, // Used for the paid team plans.
|
||||
"teamFree": "Free", // The new free team plan.
|
||||
// Other plans are either personal, or grandfathered, or for testing.
|
||||
};
|
||||
|
||||
export class AppHeader extends Disposable {
|
||||
constructor(private _orgName: BindableValue<string>, private _appModel: AppModel,
|
||||
@@ -26,22 +37,9 @@ export class AppHeader extends Disposable {
|
||||
|
||||
const user = this._appModel.currentValidUser;
|
||||
const currentOrg = this._appModel.currentOrg;
|
||||
const isTeamSite = Boolean(currentOrg && !currentOrg.owner);
|
||||
const isBillingManager = Boolean(currentOrg && currentOrg.billingAccount &&
|
||||
(currentOrg.billingAccount.isManager || user?.email === SUPPORT_EMAIL));
|
||||
|
||||
// Opens the user-manager for the org.
|
||||
const manageUsers = async (org: Organization) => {
|
||||
const api = this._appModel.api;
|
||||
(await loadUserManager()).showUserManagerModal(api, {
|
||||
permissionData: api.getOrgAccess(org.id),
|
||||
activeUser: user,
|
||||
resourceType: 'organization',
|
||||
resourceId: org.id,
|
||||
resource: org
|
||||
});
|
||||
};
|
||||
|
||||
return cssAppHeader(
|
||||
cssAppHeader.cls('-widelogo', theme.wideLogo || false),
|
||||
// Show version when hovering over the application icon.
|
||||
@@ -51,15 +49,17 @@ export class AppHeader extends Disposable {
|
||||
testId('dm-logo')
|
||||
),
|
||||
cssOrg(
|
||||
cssOrgName(dom.text(this._orgName)),
|
||||
cssOrgName(dom.text(this._orgName), testId('dm-orgname')),
|
||||
productPill(currentOrg),
|
||||
this._orgName && cssDropdownIcon('Dropdown'),
|
||||
menu(() => [
|
||||
menuSubHeader(`${isTeamSite ? 'Team' : 'Personal'} Site`, testId('orgmenu-title')),
|
||||
menuSubHeader(`${this._appModel.isTeamSite ? 'Team' : 'Personal'} Site`, testId('orgmenu-title')),
|
||||
menuItemLink(urlState().setLinkUrl({}), 'Home Page', testId('orgmenu-home-page')),
|
||||
|
||||
// Show 'Organization Settings' when on a home page of a valid org.
|
||||
(!this._docPageModel && currentOrg && !currentOrg.owner ?
|
||||
menuItem(() => manageUsers(currentOrg), 'Manage Team', testId('orgmenu-manage-team'),
|
||||
menuItem(() => manageTeamUsersApp(this._appModel),
|
||||
'Manage Team', testId('orgmenu-manage-team'),
|
||||
dom.cls('disabled', !roles.canEditAccess(currentOrg.access))) :
|
||||
// Don't show on doc pages, or for personal orgs.
|
||||
null),
|
||||
@@ -82,6 +82,22 @@ export class AppHeader extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
export function productPill(org: Organization|null, options: {large?: boolean} = {}): DomContents {
|
||||
if (!org || isTemplatesOrg(org)) {
|
||||
return null;
|
||||
}
|
||||
const product = org?.billingAccount?.product.name;
|
||||
const pillTag = product && productPills[product];
|
||||
if (!pillTag) {
|
||||
return null;
|
||||
}
|
||||
return cssProductPill(cssProductPill.cls('-' + pillTag),
|
||||
options.large ? cssProductPill.cls('-large') : null,
|
||||
pillTag,
|
||||
testId('appheader-product-pill'));
|
||||
}
|
||||
|
||||
|
||||
const cssAppHeader = styled('div', `
|
||||
display: flex;
|
||||
width: 100%;
|
||||
@@ -126,6 +142,11 @@ const cssOrg = styled('div', `
|
||||
max-width: calc(100% - 48px);
|
||||
cursor: pointer;
|
||||
height: 100%;
|
||||
font-weight: 500;
|
||||
|
||||
&:hover {
|
||||
background-color: ${colors.mediumGrey};
|
||||
}
|
||||
`);
|
||||
|
||||
const cssOrgName = styled('div', `
|
||||
@@ -138,3 +159,25 @@ const cssOrgName = styled('div', `
|
||||
display: none;
|
||||
}
|
||||
`);
|
||||
|
||||
const cssProductPill = styled('div', `
|
||||
border-radius: 4px;
|
||||
font-size: ${vars.smallFontSize};
|
||||
padding: 2px 4px;
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
|
||||
&-Free {
|
||||
background-color: ${colors.orange};
|
||||
color: white;
|
||||
}
|
||||
&-Pro {
|
||||
background-color: ${colors.lightGreen};
|
||||
color: white;
|
||||
}
|
||||
&-large {
|
||||
padding: 4px 8px;
|
||||
margin-left: 16px;
|
||||
font-size: ${vars.mediumFontSize};
|
||||
}
|
||||
`);
|
||||
|
||||
Reference in New Issue
Block a user