2020-10-02 15:10:00 +00:00
|
|
|
import { GristDoc } from "app/client/components/GristDoc";
|
|
|
|
import { urlState } from "app/client/models/gristUrlState";
|
|
|
|
import { showExampleCard } from 'app/client/ui/ExampleCard';
|
|
|
|
import { examples } from 'app/client/ui/ExampleInfo';
|
|
|
|
import { createHelpTools, cssSectionHeader, cssSpacer, cssTools } from 'app/client/ui/LeftPanelCommon';
|
2021-03-08 21:08:13 +00:00
|
|
|
import { cssLinkText, cssPageEntry, cssPageIcon, cssPageLink } from 'app/client/ui/LeftPanelCommon';
|
|
|
|
import { hoverTooltip, tooltipCloseButton } from 'app/client/ui/tooltips';
|
2020-10-02 15:10:00 +00:00
|
|
|
import { colors } from 'app/client/ui2018/cssVars';
|
|
|
|
import { icon } from 'app/client/ui2018/icons';
|
2021-03-08 21:08:13 +00:00
|
|
|
import { cssLink } from 'app/client/ui2018/links';
|
2021-03-25 19:17:25 +00:00
|
|
|
import { menuAnnotate } from 'app/client/ui2018/menus';
|
2021-03-08 21:08:13 +00:00
|
|
|
import { userOverrideParams } from 'app/common/gristUrls';
|
2021-03-25 17:37:09 +00:00
|
|
|
import { Disposable, dom, makeTestId, Observable, observable, styled } from "grainjs";
|
2020-10-02 15:10:00 +00:00
|
|
|
|
|
|
|
const testId = makeTestId('test-tools-');
|
|
|
|
|
|
|
|
export function tools(owner: Disposable, gristDoc: GristDoc, leftPanelOpen: Observable<boolean>): Element {
|
2021-03-01 16:51:30 +00:00
|
|
|
const isOwner = gristDoc.docPageModel.currentDoc.get()?.access === 'owners';
|
2021-03-02 21:11:37 +00:00
|
|
|
const isOverridden = Boolean(gristDoc.docPageModel.userOverride.get());
|
2021-03-25 17:37:09 +00:00
|
|
|
const canViewAccessRules = observable(false);
|
|
|
|
function updateCanViewAccessRules() {
|
|
|
|
canViewAccessRules.set((isOwner && !isOverridden) ||
|
|
|
|
gristDoc.docModel.rules.getNumRows() > 0);
|
|
|
|
}
|
|
|
|
owner.autoDispose(gristDoc.docModel.rules.tableData.tableActionEmitter.addListener(updateCanViewAccessRules));
|
|
|
|
updateCanViewAccessRules();
|
2020-10-02 15:10:00 +00:00
|
|
|
return cssTools(
|
|
|
|
cssTools.cls('-collapsed', (use) => !use(leftPanelOpen)),
|
|
|
|
cssSectionHeader("TOOLS"),
|
|
|
|
|
2021-03-25 19:17:25 +00:00
|
|
|
cssPageEntry(
|
|
|
|
cssPageEntry.cls('-selected', (use) => use(gristDoc.activeViewId) === 'acl'),
|
|
|
|
cssPageEntry.cls('-disabled', (use) => !use(canViewAccessRules)),
|
|
|
|
dom.domComputed(canViewAccessRules, (_canViewAccessRules) => {
|
|
|
|
return cssPageLink(
|
|
|
|
cssPageIcon('EyeShow'),
|
|
|
|
cssLinkText('Access Rules',
|
|
|
|
menuAnnotate('Beta', cssBetaTag.cls(''))
|
|
|
|
),
|
|
|
|
_canViewAccessRules ? urlState().setLinkUrl({docPage: 'acl'}) : null,
|
|
|
|
isOverridden ? addRevertViewAsUI() : null,
|
|
|
|
);
|
|
|
|
}),
|
|
|
|
testId('access-rules'),
|
2020-12-04 23:29:29 +00:00
|
|
|
),
|
2021-03-25 19:17:25 +00:00
|
|
|
|
2020-10-02 15:10:00 +00:00
|
|
|
cssPageEntry(
|
|
|
|
cssPageLink(cssPageIcon('Log'), cssLinkText('Document History'), testId('log'),
|
|
|
|
dom.on('click', () => gristDoc.showTool('docHistory')))
|
|
|
|
),
|
|
|
|
// TODO: polish validation and add it back
|
|
|
|
dom.maybe((use) => use(gristDoc.app.features).validationsTool, () =>
|
|
|
|
cssPageEntry(
|
|
|
|
cssPageLink(cssPageIcon('Validation'), cssLinkText('Validate Data'), testId('validate'),
|
|
|
|
dom.on('click', () => gristDoc.showTool('validations'))))
|
|
|
|
),
|
|
|
|
cssPageEntry(
|
|
|
|
cssPageEntry.cls('-selected', (use) => use(gristDoc.activeViewId) === 'code'),
|
|
|
|
cssPageLink(cssPageIcon('Code'),
|
|
|
|
cssLinkText('Code View'),
|
|
|
|
urlState().setLinkUrl({docPage: 'code'})
|
|
|
|
),
|
|
|
|
testId('code'),
|
|
|
|
),
|
|
|
|
cssSpacer(),
|
|
|
|
dom.maybe(gristDoc.docPageModel.currentDoc, (doc) => {
|
|
|
|
if (!doc.workspace.isSupportWorkspace) { return null; }
|
|
|
|
const ex = examples.find((e) => e.matcher.test(doc.name));
|
|
|
|
if (!ex || !ex.tutorialUrl) { return null; }
|
|
|
|
const appModel = gristDoc.docPageModel.appModel;
|
|
|
|
return cssPageEntry(
|
|
|
|
cssPageLink(cssPageIcon('Page'), cssLinkText('How-to Tutorial'), testId('tutorial'),
|
|
|
|
{href: ex.tutorialUrl, target: '_blank'},
|
|
|
|
cssExampleCardOpener(
|
|
|
|
icon('TypeDetails'),
|
|
|
|
dom.on('click', (ev, elem) => {
|
|
|
|
ev.preventDefault();
|
|
|
|
showExampleCard(ex, appModel, elem, true);
|
|
|
|
}),
|
|
|
|
testId('welcome-opener'),
|
|
|
|
(elem) => {
|
|
|
|
// Once the trigger element is attached to DOM, show the card.
|
|
|
|
setTimeout(() => showExampleCard(ex, appModel, elem), 0);
|
|
|
|
},
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}),
|
|
|
|
createHelpTools(gristDoc.docPageModel.appModel, false)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-03-08 21:08:13 +00:00
|
|
|
// When viewing a page as another user, the "Access Rules" page link includes a button to revert
|
|
|
|
// the user and open the page, and a click on the page link shows a tooltip to revert.
|
|
|
|
function addRevertViewAsUI() {
|
|
|
|
return [
|
|
|
|
// A button that allows reverting back to yourself.
|
|
|
|
dom('a',
|
|
|
|
cssExampleCardOpener.cls(''),
|
|
|
|
cssRevertViewAsButton.cls(''),
|
|
|
|
icon('Convert'),
|
|
|
|
urlState().setHref(userOverrideParams(null, {docPage: 'acl'})),
|
|
|
|
dom.on('click', (ev) => ev.stopPropagation()), // Avoid refreshing the tooltip.
|
|
|
|
testId('revert-view-as'),
|
|
|
|
),
|
|
|
|
|
|
|
|
// A tooltip that allows reverting back to yourself.
|
|
|
|
hoverTooltip((ctl) =>
|
|
|
|
cssConvertTooltip(icon('Convert'),
|
|
|
|
cssLink('Return to viewing as yourself',
|
|
|
|
urlState().setHref(userOverrideParams(null, {docPage: 'acl'})),
|
|
|
|
),
|
|
|
|
tooltipCloseButton(ctl),
|
|
|
|
),
|
|
|
|
{openOnClick: true}
|
|
|
|
),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
const cssConvertTooltip = styled('div', `
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
--icon-color: ${colors.lightGreen};
|
|
|
|
|
|
|
|
& > .${cssLink.className} {
|
|
|
|
margin-left: 8px;
|
|
|
|
}
|
|
|
|
`);
|
|
|
|
|
2020-10-02 15:10:00 +00:00
|
|
|
const cssExampleCardOpener = styled('div', `
|
|
|
|
cursor: pointer;
|
|
|
|
margin-right: 4px;
|
|
|
|
margin-left: auto;
|
|
|
|
border-radius: 16px;
|
|
|
|
border-radius: 3px;
|
|
|
|
height: 24px;
|
|
|
|
width: 24px;
|
|
|
|
padding: 4px;
|
|
|
|
line-height: 0px;
|
|
|
|
--icon-color: ${colors.light};
|
|
|
|
background-color: ${colors.lightGreen};
|
|
|
|
&:hover {
|
|
|
|
background-color: ${colors.darkGreen};
|
|
|
|
}
|
2021-03-08 21:08:13 +00:00
|
|
|
.${cssTools.className}-collapsed & {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
`);
|
|
|
|
|
|
|
|
const cssRevertViewAsButton = styled(cssExampleCardOpener, `
|
|
|
|
background-color: ${colors.darkGrey};
|
|
|
|
&:hover {
|
|
|
|
background-color: ${colors.slate};
|
|
|
|
}
|
2020-10-02 15:10:00 +00:00
|
|
|
`);
|
2021-03-25 19:17:25 +00:00
|
|
|
|
|
|
|
const cssBetaTag = styled('div', `
|
|
|
|
.${cssPageEntry.className}-disabled & {
|
|
|
|
opacity: 0.4;
|
|
|
|
}
|
|
|
|
`);
|