(core) Preserves docPage upon viewAs mode activation, except for acl page

Summary:
Switching to view-as should not change current page. Except when using
the `View As` dropdown in the acl page, in which case we do want to
revert to the default page.
This is a follow up task for: D3732

Test Plan: Updated acl nbrowser test.

Reviewers: jarek

Reviewed By: jarek

Differential Revision: https://phab.getgrist.com/D3773
This commit is contained in:
Cyprien P 2023-01-19 11:29:52 +01:00
parent c2b7027633
commit abea735470
2 changed files with 15 additions and 11 deletions

View File

@ -6,7 +6,7 @@ import {cssMemberImage, cssMemberListItem, cssMemberPrimary,
import {testId, theme, vars} from 'app/client/ui2018/cssVars'; import {testId, theme, vars} from 'app/client/ui2018/cssVars';
import {PermissionDataWithExtraUsers} from 'app/common/ActiveDocAPI'; import {PermissionDataWithExtraUsers} from 'app/common/ActiveDocAPI';
import {menu, menuCssClass, menuItemLink} from 'app/client/ui2018/menus'; import {menu, menuCssClass, menuItemLink} from 'app/client/ui2018/menus';
import {userOverrideParams} from 'app/common/gristUrls'; import {IGristUrlState, userOverrideParams} from 'app/common/gristUrls';
import {FullUser} from 'app/common/LoginSessionAPI'; import {FullUser} from 'app/common/LoginSessionAPI';
import {ANONYMOUS_USER_EMAIL, EVERYONE_EMAIL} from 'app/common/UserAPI'; import {ANONYMOUS_USER_EMAIL, EVERYONE_EMAIL} from 'app/common/UserAPI';
import {getRealAccess, UserAccessData} from 'app/common/UserAPI'; import {getRealAccess, UserAccessData} from 'app/common/UserAPI';
@ -66,12 +66,14 @@ export class ACLUsersPopup extends Disposable {
} }
} }
public attachPopup(elem: Element, options: IPopupOptions) { // Optionnally have document page reverts to the default page upon activation of the view as mode
// by setting `options.resetDocPage` to true.
public attachPopup(elem: Element, options: IPopupOptions & {resetDocPage?: boolean}) {
setPopupToCreateDom(elem, (ctl) => { setPopupToCreateDom(elem, (ctl) => {
const buildRow = const buildRow =
(user: UserAccessData) => this._buildUserRow(user); (user: UserAccessData) => this._buildUserRow(user, options);
const buildExampleUserRow = const buildExampleUserRow =
(user: UserAccessData) => this._buildUserRow(user, {isExampleUser: true}); (user: UserAccessData) => this._buildUserRow(user, {isExampleUser: true, ...options});
return cssMenuWrap(cssMenu( return cssMenuWrap(cssMenu(
dom.cls(menuCssClass), dom.cls(menuCssClass),
cssUsers.cls(''), cssUsers.cls(''),
@ -92,6 +94,7 @@ export class ACLUsersPopup extends Disposable {
}, {...defaultMenuOptions, ...options}); }, {...defaultMenuOptions, ...options});
} }
// See 'attachPopup' for more info on the 'resetDocPage' option.
public menu(options: IMenuOptions) { public menu(options: IMenuOptions) {
return menu(() => { return menu(() => {
this.load().catch(noop); this.load().catch(noop);
@ -116,7 +119,7 @@ export class ACLUsersPopup extends Disposable {
return this._shareUsers.length + this._attributeTableUsers.length < 5; return this._shareUsers.length + this._attributeTableUsers.length < 5;
} }
private _buildUserRow(user: UserAccessData, opt: {isExampleUser?: boolean} = {}) { private _buildUserRow(user: UserAccessData, opt: {isExampleUser?: boolean, resetDocPage?: boolean} = {}) {
return dom('a', return dom('a',
{class: cssMemberListItem.className + ' ' + cssUserItem.className}, {class: cssMemberListItem.className + ' ' + cssUserItem.className},
cssMemberImage( cssMemberImage(
@ -128,12 +131,14 @@ export class ACLUsersPopup extends Disposable {
), ),
user.name ? cssMemberSecondary(user.email) : null user.name ? cssMemberSecondary(user.email) : null
), ),
this._viewAs(user), this._viewAs(user, opt.resetDocPage),
testId('acl-user-item'), testId('acl-user-item'),
); );
} }
private _viewAs(user: UserAccessData) { private _viewAs(user: UserAccessData, resetDocPage: boolean = false) {
const extraState: IGristUrlState = {};
if (resetDocPage) { extraState.docPage = undefined; }
if (this.pageModel?.isPrefork.get() && if (this.pageModel?.isPrefork.get() &&
this.pageModel?.currentDoc.get()?.access !== 'owners') { this.pageModel?.currentDoc.get()?.access !== 'owners') {
// "View As" is restricted to document owners on the back-end. Non-owners can be // "View As" is restricted to document owners on the back-end. Non-owners can be
@ -145,13 +150,12 @@ export class ACLUsersPopup extends Disposable {
const forkResult = await this.pageModel?.gristDoc.get()?.docComm.fork(); const forkResult = await this.pageModel?.gristDoc.get()?.docComm.fork();
if (!forkResult) { throw new Error('Failed to create fork'); } if (!forkResult) { throw new Error('Failed to create fork'); }
window.location.assign(urlState().makeUrl(userOverrideParams(user.email, window.location.assign(urlState().makeUrl(userOverrideParams(user.email,
{doc: forkResult.urlId, {...extraState, doc: forkResult.urlId})));
docPage: undefined})));
}); });
} else { } else {
// When forking isn't needed, we return a direct link to be maximally transparent // When forking isn't needed, we return a direct link to be maximally transparent
// about where button will go. // about where button will go.
return urlState().setHref(userOverrideParams(user.email, {docPage: undefined})); return urlState().setHref(userOverrideParams(user.email, extraState));
} }
} }
} }

View File

@ -381,7 +381,7 @@ export class AccessRules extends Disposable {
), ),
bigBasicButton(t('Add User Attributes'), dom.on('click', () => this._addUserAttributes())), bigBasicButton(t('Add User Attributes'), dom.on('click', () => this._addUserAttributes())),
bigBasicButton(t('View As'), cssDropdownIcon('Dropdown'), bigBasicButton(t('View As'), cssDropdownIcon('Dropdown'),
elem => this._aclUsersPopup.attachPopup(elem, {placement: 'bottom-end'}), elem => this._aclUsersPopup.attachPopup(elem, {placement: 'bottom-end', resetDocPage: true}),
dom.style('visibility', use => use(this._aclUsersPopup.isInitialized) ? '' : 'hidden')), dom.style('visibility', use => use(this._aclUsersPopup.isInitialized) ? '' : 'hidden')),
), ),
cssConditionError({style: 'margin-left: 16px'}, cssConditionError({style: 'margin-left: 16px'},