mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) Focusing the creator panel on the table wiget for charts and custom views
Summary: When a chart page/section is added and the creator panel is already open, focus is set to a "table" tab. When a custom view is added as a page/section, the same thing happens, but there is also a behavioral tooltip shown for the custom URL. Test Plan: Updated and added. Reviewers: georgegevoian Reviewed By: georgegevoian Differential Revision: https://phab.getgrist.com/D3857
This commit is contained in:
parent
cc0e1154d0
commit
40ea6bb2bc
@ -77,6 +77,11 @@ export class BehavioralPromptsManager extends Disposable {
|
|||||||
this._isDisabled = true;
|
this._isDisabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public reset() {
|
||||||
|
this._prefs.set({...this._prefs.get(), dismissedTips: [], dontShowTips: false});
|
||||||
|
this.enable();
|
||||||
|
}
|
||||||
|
|
||||||
private _queueTip(refElement: Element, prompt: BehavioralPrompt, options: AttachOptions) {
|
private _queueTip(refElement: Element, prompt: BehavioralPrompt, options: AttachOptions) {
|
||||||
if (
|
if (
|
||||||
this._isDisabled ||
|
this._isDisabled ||
|
||||||
|
@ -513,6 +513,24 @@ export class GristDoc extends DisposableWithEvents {
|
|||||||
this.draftMonitor = Drafts.create(this, this);
|
this.draftMonitor = Drafts.create(this, this);
|
||||||
this.cursorMonitor = CursorMonitor.create(this, this);
|
this.cursorMonitor = CursorMonitor.create(this, this);
|
||||||
this.editorMonitor = EditorMonitor.create(this, this);
|
this.editorMonitor = EditorMonitor.create(this, this);
|
||||||
|
|
||||||
|
// When active section is changed to a chart or custom widget, change the tab in the creator
|
||||||
|
// panel to the table.
|
||||||
|
this.autoDispose(this.viewModel.activeSection.subscribe((section) => {
|
||||||
|
if (section.isDisposed() || section._isDeleted.peek()) { return; }
|
||||||
|
if ('chart' === section.parentKey.peek()) {
|
||||||
|
commands.allCommands.viewTabFocus.run();
|
||||||
|
} else if ('custom' === section.parentKey.peek()) {
|
||||||
|
// Check if user has seen custom URL tooltip.
|
||||||
|
const seenTooltip = this.behavioralPromptsManager.hasSeenTip('customURL');
|
||||||
|
// If yes, just focus on the table if it is opened
|
||||||
|
if (seenTooltip) {
|
||||||
|
commands.allCommands.viewTabFocus.run();
|
||||||
|
} else {
|
||||||
|
commands.allCommands.viewTabOpen.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,6 +73,11 @@ exports.groups = [{
|
|||||||
keys: [],
|
keys: [],
|
||||||
desc: 'Shortcut to open view tab'
|
desc: 'Shortcut to open view tab'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'viewTabFocus',
|
||||||
|
keys: [],
|
||||||
|
desc: 'Shortcut to focus view tab if creator panel is open'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'fieldTabOpen',
|
name: 'fieldTabOpen',
|
||||||
keys: [],
|
keys: [],
|
||||||
|
@ -282,6 +282,7 @@ export class AppModelImpl extends Disposable implements AppModel {
|
|||||||
|
|
||||||
G.window.resetSeenPopups = (seen = false) => {
|
G.window.resetSeenPopups = (seen = false) => {
|
||||||
this.dismissedPopups.set(seen ? DismissedPopup.values : []);
|
this.dismissedPopups.set(seen ? DismissedPopup.values : []);
|
||||||
|
this.behavioralPromptsManager.reset();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ export class CustomSectionConfig extends Disposable {
|
|||||||
// Does widget has custom configuration.
|
// Does widget has custom configuration.
|
||||||
private _hasConfiguration: Computed<boolean>;
|
private _hasConfiguration: Computed<boolean>;
|
||||||
|
|
||||||
constructor(private _section: ViewSectionRec, _gristDoc: GristDoc) {
|
constructor(private _section: ViewSectionRec, private _gristDoc: GristDoc) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
const api = _gristDoc.app.topAppModel.api;
|
const api = _gristDoc.app.topAppModel.api;
|
||||||
@ -411,7 +411,12 @@ export class CustomSectionConfig extends Disposable {
|
|||||||
async value => this._url.set(value),
|
async value => this._url.set(value),
|
||||||
dom.attr('placeholder', t("Enter Custom URL")),
|
dom.attr('placeholder', t("Enter Custom URL")),
|
||||||
testId('url')
|
testId('url')
|
||||||
)
|
),
|
||||||
|
this._gristDoc.behavioralPromptsManager.attachTip('customURL', {
|
||||||
|
popupOptions: {
|
||||||
|
placement: 'left-start',
|
||||||
|
}
|
||||||
|
})
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
dom.maybe(prompt, () =>
|
dom.maybe(prompt, () =>
|
||||||
|
@ -217,5 +217,18 @@ export const GristBehavioralPrompts: Record<BehavioralPrompt, BehavioralPromptCo
|
|||||||
),
|
),
|
||||||
...args,
|
...args,
|
||||||
),
|
),
|
||||||
}
|
},
|
||||||
|
customURL: {
|
||||||
|
title: () => t('Custom Widgets'),
|
||||||
|
content: (...args: DomElementArg[]) => cssTooltipContent(
|
||||||
|
dom('div',
|
||||||
|
t(
|
||||||
|
'You can choose one of our pre-made widgets or embed your own ' +
|
||||||
|
'by providing its full URL.'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dom('div', cssLink({href: commonUrls.helpCustomWidgets, target: '_blank'}, t('Learn more.'))),
|
||||||
|
...args,
|
||||||
|
),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -104,6 +104,7 @@ export class RightPanel extends Disposable {
|
|||||||
this.autoDispose(commands.createGroup({
|
this.autoDispose(commands.createGroup({
|
||||||
fieldTabOpen: () => this._openFieldTab(),
|
fieldTabOpen: () => this._openFieldTab(),
|
||||||
viewTabOpen: () => this._openViewTab(),
|
viewTabOpen: () => this._openViewTab(),
|
||||||
|
viewTabFocus: () => this._viewTabFocus(),
|
||||||
sortFilterTabOpen: () => this._openSortFilter(),
|
sortFilterTabOpen: () => this._openSortFilter(),
|
||||||
dataSelectionTabOpen: () => this._openDataSelection()
|
dataSelectionTabOpen: () => this._openDataSelection()
|
||||||
}, this, true));
|
}, this, true));
|
||||||
@ -117,6 +118,11 @@ export class RightPanel extends Disposable {
|
|||||||
this._open('pageWidget', 'widget');
|
this._open('pageWidget', 'widget');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _viewTabFocus() {
|
||||||
|
// If the view tab is already open, focus on the first input.
|
||||||
|
this._focus('pageWidget');
|
||||||
|
}
|
||||||
|
|
||||||
private _openSortFilter() {
|
private _openSortFilter() {
|
||||||
this._open('pageWidget', 'sortAndFilter');
|
this._open('pageWidget', 'sortAndFilter');
|
||||||
}
|
}
|
||||||
@ -135,6 +141,14 @@ export class RightPanel extends Disposable {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _focus(topTab: typeof TopTab.type) {
|
||||||
|
bundleChanges(() => {
|
||||||
|
if (!this._isOpen.get()) { return; }
|
||||||
|
this._isOpen.set(true);
|
||||||
|
this._topTab.set(topTab);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private _buildHeaderDom() {
|
private _buildHeaderDom() {
|
||||||
return dom.domComputed((use) => {
|
return dom.domComputed((use) => {
|
||||||
if (!use(this._isOpen)) { return null; }
|
if (!use(this._isOpen)) { return null; }
|
||||||
|
@ -86,6 +86,7 @@ export const BehavioralPrompt = StringUnion(
|
|||||||
'editCardLayout',
|
'editCardLayout',
|
||||||
'addNew',
|
'addNew',
|
||||||
'rickRow',
|
'rickRow',
|
||||||
|
'customURL',
|
||||||
);
|
);
|
||||||
export type BehavioralPrompt = typeof BehavioralPrompt.type;
|
export type BehavioralPrompt = typeof BehavioralPrompt.type;
|
||||||
|
|
||||||
|
@ -70,6 +70,7 @@ export const commonUrls = {
|
|||||||
helpUnderstandingReferenceColumns: "https://support.getgrist.com/col-refs/#understanding-reference-columns",
|
helpUnderstandingReferenceColumns: "https://support.getgrist.com/col-refs/#understanding-reference-columns",
|
||||||
helpTriggerFormulas: "https://support.getgrist.com/formulas/#trigger-formulas",
|
helpTriggerFormulas: "https://support.getgrist.com/formulas/#trigger-formulas",
|
||||||
helpTryingOutChanges: "https://support.getgrist.com/copying-docs/#trying-out-changes",
|
helpTryingOutChanges: "https://support.getgrist.com/copying-docs/#trying-out-changes",
|
||||||
|
helpCustomWidgets: "https://support.getgrist.com/widget-custom",
|
||||||
plans: "https://www.getgrist.com/pricing",
|
plans: "https://www.getgrist.com/pricing",
|
||||||
createTeamSite: "https://www.getgrist.com/create-team-site",
|
createTeamSite: "https://www.getgrist.com/create-team-site",
|
||||||
sproutsProgram: "https://www.getgrist.com/sprouts-program",
|
sproutsProgram: "https://www.getgrist.com/sprouts-program",
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf8">
|
<meta charset="utf8">
|
||||||
<link rel="icon" type="image/x-icon" href="icons/favicon.png" />
|
|
||||||
<link rel="stylesheet" href="icons/icons.css">
|
|
||||||
<title>Custom widget</title>
|
<title>Custom widget</title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
|
@ -4,10 +4,76 @@ import {server, setupTestSuite} from 'test/nbrowser/testUtils';
|
|||||||
|
|
||||||
describe('RightPanel', function() {
|
describe('RightPanel', function() {
|
||||||
this.timeout(20000);
|
this.timeout(20000);
|
||||||
setupTestSuite();
|
const cleanup = setupTestSuite();
|
||||||
|
|
||||||
afterEach(() => gu.checkForErrors());
|
afterEach(() => gu.checkForErrors());
|
||||||
|
|
||||||
|
it('should focus on the creator panel when chart/custom section is added', async () => {
|
||||||
|
const mainSession = await gu.session().teamSite.login();
|
||||||
|
await mainSession.tempNewDoc(cleanup);
|
||||||
|
|
||||||
|
// Close panel and make sure it stays closed.
|
||||||
|
await gu.toggleSidePanel('right', 'close');
|
||||||
|
|
||||||
|
// Add a chart section.
|
||||||
|
await gu.addNewSection('Chart', 'Table1');
|
||||||
|
assert.isFalse(await gu.isSidePanelOpen('right'));
|
||||||
|
await gu.undo();
|
||||||
|
|
||||||
|
// Add a chart page.
|
||||||
|
await gu.addNewPage('Chart', 'Table1');
|
||||||
|
assert.isFalse(await gu.isSidePanelOpen('right'));
|
||||||
|
await gu.undo();
|
||||||
|
|
||||||
|
// Add a custom section.
|
||||||
|
await gu.addNewSection('Custom', 'Table1');
|
||||||
|
assert.isFalse(await gu.isSidePanelOpen('right'));
|
||||||
|
await gu.undo();
|
||||||
|
|
||||||
|
// Add a custom page.
|
||||||
|
await gu.addNewPage('Custom', 'Table1');
|
||||||
|
assert.isFalse(await gu.isSidePanelOpen('right'));
|
||||||
|
await gu.undo();
|
||||||
|
|
||||||
|
// Now open the panel on the column tab.
|
||||||
|
const columnTab = async () => {
|
||||||
|
await gu.toggleSidePanel('right', 'open');
|
||||||
|
await driver.find('.test-right-tab-field').click();
|
||||||
|
};
|
||||||
|
|
||||||
|
await columnTab();
|
||||||
|
|
||||||
|
// Add a chart section.
|
||||||
|
await gu.addNewSection('Chart', 'Table1');
|
||||||
|
assert.isTrue(await gu.isSidePanelOpen('right'));
|
||||||
|
assert.isTrue(await driver.find('.test-right-widget-title').isDisplayed());
|
||||||
|
await gu.undo();
|
||||||
|
|
||||||
|
await columnTab();
|
||||||
|
|
||||||
|
// Add a chart page.
|
||||||
|
await gu.addNewPage('Chart', 'Table1');
|
||||||
|
assert.isTrue(await gu.isSidePanelOpen('right'));
|
||||||
|
assert.isTrue(await driver.find('.test-right-widget-title').isDisplayed());
|
||||||
|
await gu.undo();
|
||||||
|
|
||||||
|
await columnTab();
|
||||||
|
|
||||||
|
// Add a custom section.
|
||||||
|
await gu.addNewSection('Custom', 'Table1');
|
||||||
|
assert.isTrue(await gu.isSidePanelOpen('right'));
|
||||||
|
assert.isTrue(await driver.find('.test-right-widget-title').isDisplayed());
|
||||||
|
await gu.undo();
|
||||||
|
|
||||||
|
await columnTab();
|
||||||
|
|
||||||
|
// Add a custom page.
|
||||||
|
await gu.addNewPage('Custom', 'Table1');
|
||||||
|
assert.isTrue(await gu.isSidePanelOpen('right'));
|
||||||
|
assert.isTrue(await driver.find('.test-right-widget-title').isDisplayed());
|
||||||
|
await gu.undo();
|
||||||
|
});
|
||||||
|
|
||||||
it('should open/close panel, and reflect the current section', async function() {
|
it('should open/close panel, and reflect the current section', async function() {
|
||||||
// Open a document with multiple views and multiple sections.
|
// Open a document with multiple views and multiple sections.
|
||||||
await server.simulateLogin("Chimpy", "chimpy@getgrist.com", 'nasa');
|
await server.simulateLogin("Chimpy", "chimpy@getgrist.com", 'nasa');
|
||||||
@ -19,7 +85,7 @@ describe('RightPanel', function() {
|
|||||||
assert.equal(await driver.find('.test-bc-page').getAttribute('value'), 'City');
|
assert.equal(await driver.find('.test-bc-page').getAttribute('value'), 'City');
|
||||||
|
|
||||||
// Open side pane, and check it shows the right section.
|
// Open side pane, and check it shows the right section.
|
||||||
await gu.toggleSidePanel('right');
|
await gu.toggleSidePanel('right', 'open');
|
||||||
await driver.find('.test-config-widget').click();
|
await driver.find('.test-config-widget').click();
|
||||||
assert.equal(await gu.isSidePanelOpen('right'), true);
|
assert.equal(await gu.isSidePanelOpen('right'), true);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user