mirror of
				https://github.com/gristlabs/grist-core.git
				synced 2025-06-13 20:53:59 +00:00 
			
		
		
		
	(core) Use new Banner component for activation messages
Summary: Use new Banner component for activation messages. Test Plan: Existing tests. Reviewers: paulfitz Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D3483
This commit is contained in:
		
							parent
							
								
									02dd96daf2
								
							
						
					
					
						commit
						7176b7efb6
					
				| @ -1,93 +0,0 @@ | ||||
| import {Banner, buildBannerMessage} from 'app/client/components/Banner'; | ||||
| import {buildUpgradeMessage} from 'app/client/components/DocumentUsage'; | ||||
| import {sessionStorageBoolObs} from 'app/client/lib/localStorageObs'; | ||||
| import {AppModel} from 'app/client/models/AppModel'; | ||||
| import {isFreeProduct} from 'app/common/Features'; | ||||
| import {isOwner} from 'app/common/roles'; | ||||
| import {Disposable, dom, makeTestId, Observable} from 'grainjs'; | ||||
| 
 | ||||
| const testId = makeTestId('test-site-usage-banner-'); | ||||
| 
 | ||||
| export class SiteUsageBanner extends Disposable { | ||||
|   private readonly _currentOrg = this._app.currentOrg; | ||||
|   private readonly _currentOrgUsage = this._app.currentOrgUsage; | ||||
|   private readonly _product = this._currentOrg?.billingAccount?.product; | ||||
|   private readonly _currentUser = this._app.currentValidUser; | ||||
| 
 | ||||
|   // Session storage observable. Set to false to dismiss the banner for the session.
 | ||||
|   private _showApproachingLimitBannerPref?: Observable<boolean>; | ||||
| 
 | ||||
|   constructor(private _app: AppModel) { | ||||
|     super(); | ||||
| 
 | ||||
|     if (this._currentUser && isOwner(this._currentOrg)) { | ||||
|       this._showApproachingLimitBannerPref = this.autoDispose(sessionStorageBoolObs( | ||||
|         `u=${this._currentUser.id}:org=${this._currentOrg.id}:showApproachingLimitBanner`, | ||||
|         true, | ||||
|       )); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   public buildDom() { | ||||
|     return dom.maybe(this._currentOrgUsage, (usage) => { | ||||
|       const {approachingLimit, gracePeriod, deleteOnly} = usage; | ||||
|       if (deleteOnly > 0 || gracePeriod > 0) { | ||||
|         return this._buildExceedingLimitsBanner(deleteOnly + gracePeriod); | ||||
|       } else if (approachingLimit > 0) { | ||||
|         return this._buildApproachingLimitsBanner(approachingLimit); | ||||
|       } else { | ||||
|         return null; | ||||
|       } | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   private _buildApproachingLimitsBanner(numDocs: number) { | ||||
|     return dom.domComputed(use => { | ||||
|       if (this._showApproachingLimitBannerPref && !use(this._showApproachingLimitBannerPref)) { | ||||
|         return null; | ||||
|       } | ||||
| 
 | ||||
|       const limitsMessage = numDocs > 1 | ||||
|         ? `${numDocs} documents are approaching their limits.` | ||||
|         : `${numDocs} document is approaching its limits.`; | ||||
|       return dom.create(Banner, { | ||||
|         content: buildBannerMessage( | ||||
|           limitsMessage, | ||||
|           (this._product && isFreeProduct(this._product) | ||||
|             ? [' ', buildUpgradeMessage(true)] | ||||
|             : null | ||||
|           ), | ||||
|           testId('text'), | ||||
|         ), | ||||
|         style: 'warning', | ||||
|         showCloseButton: true, | ||||
|         onClose: () => this._showApproachingLimitBannerPref?.set(false), | ||||
|       }); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   private _buildExceedingLimitsBanner(numDocs: number) { | ||||
|     const limitsMessage = numDocs > 1 | ||||
|       ? `${numDocs} documents have exceeded their limits.` | ||||
|       : `${numDocs} document has exceeded its limits.`; | ||||
|     return dom.create(Banner, { | ||||
|       content: buildBannerMessage( | ||||
|         limitsMessage, | ||||
|         (this._product && isFreeProduct(this._product) | ||||
|           ? [' ', buildUpgradeMessage(true)] | ||||
|           : null | ||||
|         ), | ||||
|         testId('text'), | ||||
|       ), | ||||
|       contentSmall: buildBannerMessage( | ||||
|         (this._product && isFreeProduct(this._product) | ||||
|           ? buildUpgradeMessage(true, 'short') | ||||
|           : limitsMessage | ||||
|         ), | ||||
|       ), | ||||
|       style: 'error', | ||||
|       showCloseButton: false, | ||||
|       showExpandButton: true, | ||||
|     }); | ||||
|   } | ||||
| } | ||||
| @ -1,5 +1,4 @@ | ||||
| import {DocUsageBanner} from 'app/client/components/DocUsageBanner'; | ||||
| import {SiteUsageBanner} from 'app/client/components/SiteUsageBanner'; | ||||
| import {buildDocumentBanners, buildHomeBanners} from 'app/client/components/Banners'; | ||||
| import {domAsync} from 'app/client/lib/domAsync'; | ||||
| import {loadBillingPage} from 'app/client/lib/imports'; | ||||
| import {createSessionObs, isBoolean, isNumber} from 'app/client/lib/sessionObs'; | ||||
| @ -105,7 +104,7 @@ function pagePanelsHome(owner: IDisposableOwner, appModel: AppModel, app: App) { | ||||
|     }, | ||||
|     headerMain: createTopBarHome(appModel), | ||||
|     contentMain: createDocMenu(pageModel), | ||||
|     contentTop: dom.create(SiteUsageBanner, appModel), | ||||
|     contentTop: buildHomeBanners(appModel), | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| @ -155,7 +154,7 @@ function pagePanelsDoc(owner: IDisposableOwner, appModel: AppModel, appObj: App) | ||||
|     contentMain: dom.maybe(pageModel.gristDoc, (gristDoc) => gristDoc.buildDom()), | ||||
|     onResize, | ||||
|     testId, | ||||
|     contentTop: dom.create(DocUsageBanner, pageModel), | ||||
|     contentTop: buildDocumentBanners(pageModel), | ||||
|     contentBottom: dom.create(createBottomBarDoc, pageModel, leftPanelOpen, rightPanelOpen), | ||||
|   }); | ||||
| } | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import {SiteUsageBanner} from 'app/client/components/SiteUsageBanner'; | ||||
| import {buildHomeBanners} from 'app/client/components/Banners'; | ||||
| import {beaconOpenMessage} from 'app/client/lib/helpScout'; | ||||
| import {AppModel, reportError} from 'app/client/models/AppModel'; | ||||
| import {BillingModel, BillingModelImpl, ISubscriptionModel} from 'app/client/models/BillingModel'; | ||||
| @ -66,7 +66,7 @@ export class BillingPage extends Disposable { | ||||
|             content: leftPanelBasic(this._appModel, panelOpen), | ||||
|           }, | ||||
|           headerMain: this._createTopBarBilling(), | ||||
|           contentTop: dom.create(SiteUsageBanner, this._appModel), | ||||
|           contentTop: buildHomeBanners(this._appModel), | ||||
|           contentMain: this._buildCurrentPageDom() | ||||
|         }); | ||||
|       } | ||||
|  | ||||
| @ -94,22 +94,7 @@ export function makeSendAppPage(opts: { | ||||
|     const staticOrigin = process.env.APP_STATIC_URL || ""; | ||||
|     const staticBaseUrl = `${staticOrigin}/v/${options.tag || tag}/`; | ||||
|     const customHeadHtmlSnippet = server?.create.getExtraHeadHtml?.() ?? ""; | ||||
|     // TODO: Temporary changes until there is a handy banner to put this in.
 | ||||
|     let warning = testLogin ? "<div class=\"dev_warning\">Authentication is not enforced</div>" : ""; | ||||
|     const activation = config.activation; | ||||
|     if (!warning && activation) { | ||||
|       if (activation.trial) { | ||||
|         warning = `Trial: ${activation.trial.daysLeft} day(s) left`; | ||||
|       } else if (activation.needKey) { | ||||
|         warning = 'Activation key needed. Documents in read-only mode.'; | ||||
|       } else if (activation.key?.daysLeft && activation.key.daysLeft < 30) { | ||||
|         warning = `Need reactivation in ${activation.key.daysLeft} day(s)`; | ||||
|       } | ||||
|       if (warning) { | ||||
|         warning = `<div class="dev_warning activation-msg">${warning}</div>`; | ||||
|       } | ||||
|     } | ||||
|     // Temporary changes end.
 | ||||
|     const warning = testLogin ? "<div class=\"dev_warning\">Authentication is not enforced</div>" : ""; | ||||
|     const content = fileContent | ||||
|       .replace("<!-- INSERT WARNING -->", warning) | ||||
|       .replace("<!-- INSERT TITLE SUFFIX -->", getPageTitleSuffix(server?.getGristConfig())) | ||||
|  | ||||
							
								
								
									
										10
									
								
								stubs/app/client/components/Banners.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								stubs/app/client/components/Banners.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| import {AppModel} from 'app/client/models/AppModel'; | ||||
| import {DocPageModel} from 'app/client/models/DocPageModel'; | ||||
| 
 | ||||
| export function buildHomeBanners(_app: AppModel) { | ||||
|   return null; | ||||
| } | ||||
| 
 | ||||
| export function buildDocumentBanners(_docPageModel: DocPageModel) { | ||||
|   return null; | ||||
| } | ||||
| @ -1,10 +0,0 @@ | ||||
| import {DocPageModel} from 'app/client/models/DocPageModel'; | ||||
| import {Disposable} from 'grainjs'; | ||||
| 
 | ||||
| export class DocUsageBanner extends Disposable { | ||||
|   constructor(_docPageModel: DocPageModel) { super(); } | ||||
| 
 | ||||
|   public buildDom() { | ||||
|     return null; | ||||
|   } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user