mirror of
				https://github.com/gristlabs/grist-core.git
				synced 2025-06-13 20:53:59 +00:00 
			
		
		
		
	(core) Welcome intro for viewers on a team site.
Summary: Adding intro for a viewer on a teamsite. Showing upgrade button for owners only. Test Plan: new test Reviewers: georgegevoian Reviewed By: georgegevoian Differential Revision: https://phab.getgrist.com/D3557
This commit is contained in:
		
							parent
							
								
									b7686fa664
								
							
						
					
					
						commit
						c359547f6b
					
				| @ -150,10 +150,9 @@ export class HomeModelImpl extends Disposable implements HomeModel, ViewSettings | ||||
|     return destWS && roles.canEdit(destWS.access) ? destWS : null; | ||||
|   }); | ||||
| 
 | ||||
|   // Whether to show intro: no docs (other than examples) and user may create docs.
 | ||||
|   // Whether to show intro: no docs (other than examples).
 | ||||
|   public readonly showIntro = Computed.create(this, this.workspaces, (use, wss) => ( | ||||
|     wss.every((ws) => ws.isSupportWorkspace || ws.docs.length === 0) && | ||||
|     Boolean(use(this.newDocWorkspace)))); | ||||
|     wss.every((ws) => ws.isSupportWorkspace || ws.docs.length === 0))); | ||||
| 
 | ||||
|   private _userOrgPrefs = Observable.create<UserOrgPrefs|undefined>(this, this._app.currentOrg?.userOrgPrefs); | ||||
| 
 | ||||
|  | ||||
| @ -11,30 +11,69 @@ import {cssLink} from 'app/client/ui2018/links'; | ||||
| import {commonUrls, shouldHideUiElement} from 'app/common/gristUrls'; | ||||
| import {FullUser} from 'app/common/LoginSessionAPI'; | ||||
| import * as roles from 'app/common/roles'; | ||||
| import {dom, DomContents, styled} from 'grainjs'; | ||||
| import {Computed, dom, DomContents, styled} from 'grainjs'; | ||||
| 
 | ||||
| 
 | ||||
| export function buildHomeIntro(homeModel: HomeModel): DomContents { | ||||
|   const isViewer = homeModel.app.currentOrg?.access === roles.VIEWER; | ||||
|   const user = homeModel.app.currentValidUser; | ||||
|   if (user) { | ||||
|     return homeModel.app.isTeamSite ? makeTeamSiteIntro(homeModel) : makePersonalIntro(homeModel, user); | ||||
|   } else { | ||||
|   const isAnonym = !user; | ||||
|   const isPersonal = !homeModel.app.isTeamSite; | ||||
|   if (isAnonym) { | ||||
|     return makeAnonIntro(homeModel); | ||||
|   } else if (isPersonal) { | ||||
|     return makePersonalIntro(homeModel, user); | ||||
|   } else { // isTeamSite
 | ||||
|     if (isViewer) { | ||||
|       return makeViewerTeamSiteIntro(homeModel); | ||||
|     } else { | ||||
|       return makeTeamSiteIntro(homeModel); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function makeViewerTeamSiteIntro(homeModel: HomeModel) { | ||||
|   const personalOrg = Computed.create(null, use => use(homeModel.app.topAppModel.orgs).find(o => o.owner)); | ||||
|   const docLink = (dom.maybe(personalOrg, org => { | ||||
|     return cssLink( | ||||
|       urlState().setLinkUrl({org: org.domain ?? undefined}), | ||||
|       'free, personal site', | ||||
|       testId('welcome-personal-url')); | ||||
|   })); | ||||
|   return [ | ||||
|     css.docListHeader( | ||||
|       dom.autoDispose(personalOrg), | ||||
|       `Welcome to ${homeModel.app.currentOrgName}`, | ||||
|       productPill(homeModel.app.currentOrg, {large: true}), | ||||
|       testId('welcome-title') | ||||
|     ), | ||||
|     cssIntroLine( | ||||
|       testId('welcome-info'), | ||||
|       "You have read-only access to this site. Currently there are no documents.", dom('br'), | ||||
|       "Any documents created in this site will appear here."), | ||||
|     cssIntroLine( | ||||
|       'Interested in using Grist outside of your team? Visit your ', docLink, '.', | ||||
|       testId('welcome-text') | ||||
|     ) | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| function makeTeamSiteIntro(homeModel: HomeModel) { | ||||
|   const sproutsProgram = cssLink({href: commonUrls.sproutsProgram, target: '_blank'}, 'Sprouts Program'); | ||||
|   return [ | ||||
|     css.docListHeader(`Welcome to ${homeModel.app.currentOrgName}`, | ||||
|     css.docListHeader( | ||||
|       `Welcome to ${homeModel.app.currentOrgName}`, | ||||
|       productPill(homeModel.app.currentOrg, {large: true}), | ||||
|       testId('welcome-title')), | ||||
|       testId('welcome-title') | ||||
|     ), | ||||
|     cssIntroLine('Get started by inviting your team and creating your first Grist document.'), | ||||
|     (shouldHideUiElement('helpCenter') ? null : | ||||
|       cssIntroLine('Learn more in our ', helpCenterLink(), ', or find an expert via our ', sproutsProgram, '.', | ||||
|         testId('welcome-text')) | ||||
|       cssIntroLine( | ||||
|         'Learn more in our ', helpCenterLink(), ', or find an expert via our ', sproutsProgram, '.', | ||||
|         testId('welcome-text') | ||||
|       ) | ||||
|     ), | ||||
|     makeCreateButtons(homeModel), | ||||
|     makeCreateButtons(homeModel) | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
|  * page, both for anonymous and logged-in users. | ||||
|  */ | ||||
| 
 | ||||
| import {assert, driver, stackWrapFunc, WebElement} from 'mocha-webdriver'; | ||||
| import {assert, driver, Key, stackWrapFunc, WebElement} from 'mocha-webdriver'; | ||||
| import * as gu from 'test/nbrowser/gristUtils'; | ||||
| import {server, setupTestSuite} from 'test/nbrowser/testUtils'; | ||||
| 
 | ||||
| @ -42,6 +42,42 @@ describe('HomeIntro', function() { | ||||
|     it('should render selected Examples workspace specially', testSelectedExamplesPage); | ||||
|   }); | ||||
| 
 | ||||
|   describe("Viewer on a team site", function() { | ||||
|     it('should show welcome for viewers', async function() { | ||||
|       // Sign in as to a team that has no docs.
 | ||||
|       await server.simulateLogin("Chimpy", "chimpy@getgrist.com", "FreeTeam"); | ||||
|       await driver.get(server.getUrl('freeteam', '')); | ||||
|       await gu.editOrgAcls(); | ||||
|       const orgInput = await driver.find('.test-um-member-new input'); | ||||
|       await orgInput.sendKeys('charon@getgrist.com', Key.ENTER); | ||||
|       await gu.saveAcls(); | ||||
|       await gu.removeLogin(); | ||||
|       await server.simulateLogin("Charon", "charon@getgrist.com", "abyss"); | ||||
|       await driver.get(server.getUrl('freeteam', '')); | ||||
| 
 | ||||
|       // Check message specific to logged-in user and an empty team site.
 | ||||
|       assert.match(await driver.findWait('.test-welcome-title', 1000).getText(), new RegExp(`Welcome.* FreeTeam`)); | ||||
|       assert.match(await driver.find('.test-welcome-info').getText(), | ||||
|         /You have read-only access to this site.*/); | ||||
|       assert.match(await driver.find('.test-welcome-text').getText(), | ||||
|         /Interested in using Grist outside of your team\? Visit your free, personal site\./); | ||||
|       assert.notMatch(await driver.find('.test-welcome-text').getText(), /sign up/); | ||||
|       await driver.find(".test-welcome-personal-url").click(); | ||||
|       await gu.waitForDocMenuToLoad(); | ||||
|       assert.equal( | ||||
|         await driver.find('.test-dm-other-sites-message').getText(), | ||||
|         'You are on your personal site. You also have access to the following sites:' | ||||
|       ); | ||||
|       await driver.get(server.getUrl('freeteam', '')); | ||||
|       await gu.waitForDocMenuToLoad(); | ||||
|     }); | ||||
| 
 | ||||
|     it('should not show Other Sites section', testOtherSitesSection); | ||||
|     it('should not show welcome buttons', testNoButtonsOnHome); | ||||
|     it('should show examples workspace with the intro', testExamplesSection); | ||||
|     it('should render selected Examples workspace specially', testSelectedExamplesPage); | ||||
|   }); | ||||
| 
 | ||||
|   describe("Logged-in on merged-org", function() { | ||||
|     it('should show welcome for logged-in user', async function() { | ||||
|       // Sign in as a new user who has no docs.
 | ||||
| @ -117,6 +153,13 @@ describe('HomeIntro', function() { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   async function testNoButtonsOnHome() { | ||||
|     const buttons = ['test-intro-templates', 'test-intro-import-doc', 'test-intro-create-doc']; | ||||
|     for (const button of buttons) { | ||||
|       assert.isFalse(await driver.find(`.${button}`).isPresent()); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   async function testCreateImport(isLoggedIn: boolean) { | ||||
|     // Create doc from intro button
 | ||||
|     await driver.find('.test-intro-create-doc').click(); | ||||
| @ -160,7 +203,7 @@ describe('HomeIntro', function() { | ||||
| 
 | ||||
|   // Wait for doc to load, check it, then return to home page, and remove the doc so that we
 | ||||
|   // can see the intro again.
 | ||||
|   const checkDocAndRestore = stackWrapFunc(async function(isLoggedIn: boolean, docChecker: () => Promise<void>, | ||||
|   const checkDocAndRestore = async function(isLoggedIn: boolean, docChecker: () => Promise<void>, | ||||
|                                                           stepsBackToDocMenu: number = 1) { | ||||
|     await gu.waitForDocToLoad(); | ||||
|     await gu.dismissWelcomeTourIfNeeded(); | ||||
| @ -180,7 +223,7 @@ describe('HomeIntro', function() { | ||||
|       await driver.wait(async () => !(await driver.find('.test-modal-dialog').isPresent()), 3000); | ||||
|     } | ||||
|     assert.equal(await driver.find('.test-dm-doc').isPresent(), false); | ||||
|   }); | ||||
|   }; | ||||
| 
 | ||||
|   async function testExamplesCollapsing() { | ||||
|     assert.equal(await driver.find('.test-dm-pinned-doc-name').isDisplayed(), true); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user