gristlabs_grist-core/app/client/components/modals.ts
Jarosław Sadziński fb16c3de56 (core) Updating flow and UI for shortcut warnings
Summary:
- Popup looks different (better shadow, order and alignment)
- Warnings need to be dismissed by checking "Don't show again" button, pressing
  Esc/Enter or clicking away just hides the popup, but it will be opened once again.
- Dismissing one warning popup (about zoom keys), dismisses them all

Test Plan: Updated

Reviewers: georgegevoian

Reviewed By: georgegevoian

Differential Revision: https://phab.getgrist.com/D3683
2022-10-26 10:23:28 +02:00

150 lines
4.5 KiB
TypeScript

import * as commands from 'app/client/components/commands';
import {GristDoc} from 'app/client/components/GristDoc';
import {FocusLayer} from 'app/client/lib/FocusLayer';
import {reportSuccess} from 'app/client/models/errors';
import {basicButton, primaryButton} from 'app/client/ui2018/buttons';
import {labeledSquareCheckbox} from 'app/client/ui2018/checkbox';
import {testId, theme} from 'app/client/ui2018/cssVars';
import {modalTooltip} from 'app/client/ui2018/modals';
import {dom, DomContents, observable, styled} from 'grainjs';
/**
* This is a file for all custom and pre-configured popups, modals, toasts and tooltips, used
* in more then one component.
*/
/**
* Tooltip or popup to confirm row deletion.
*/
export function buildConfirmDelete(
refElement: Element,
onSave: (remember: boolean) => void,
single = true,
) {
const remember = observable(false);
const tooltip = modalTooltip(refElement, (ctl) =>
cssContainer(
dom.autoDispose(remember),
testId('confirm-deleteRows'),
testId('confirm-popup'),
elem => { FocusLayer.create(ctl, {defaultFocusElem: elem, pauseMousetrap: true}); },
dom.onKeyDown({
Escape: () => ctl.close(),
Enter: () => { onSave(remember.get()); ctl.close(); },
}),
dom('div', `Are you sure you want to delete ${single ? 'this' : 'these'} record${single ? '' : 's'}?`,
dom.style('margin-bottom', '10px'),
),
dom('div',
labeledSquareCheckbox(remember, "Don't ask again.", testId('confirm-remember')),
dom.style('margin-bottom', '10px'),
),
cssButtons(
primaryButton('Delete', testId('confirm-save'), dom.on('click', () => {
onSave(remember.get());
ctl.close();
})),
basicButton('Cancel', testId('confirm-cancel'), dom.on('click', () => ctl.close()))
)
), {}
);
// Attach this tooltip to a cell so that it is automatically closed when the cell is disposed.
// or scrolled out of view (and then disposed).
dom.onDisposeElem(refElement, () => {
if (!tooltip.isDisposed()) {
tooltip.close();
}
});
return tooltip;
}
export function showDeprecatedWarning(
refElement: Element,
content: DomContents,
onClose: (checked: boolean) => void,
) {
const remember = observable(false);
const tooltip = modalTooltip(refElement, (ctl) =>
cssWideContainer(
testId('popup-warning-deprecated'),
elem => { FocusLayer.create(ctl, {defaultFocusElem: elem, pauseMousetrap: true}); },
dom.onKeyDown({
Escape: () => { ctl.close(); onClose(remember.get()); },
Enter: () => { ctl.close(); onClose(remember.get()); },
}),
content,
cssButtons(
dom.style('margin-top', '12px'),
dom.style('justify-content', 'space-between'),
dom.style('align-items', 'center'),
dom('div',
labeledSquareCheckbox(remember, "Don't show again.", testId('confirm-remember')),
),
basicButton('Dismiss', testId('confirm-save'),
dom.on('click', () => { ctl.close(); onClose(remember.get()); })
)
),
)
);
// Attach this warning to a cell so that it is automatically closed when the cell is disposed.
// or scrolled out of view (and then disposed).
dom.onDisposeElem(refElement, () => {
if (!tooltip.isDisposed()) {
tooltip.close();
}
});
return tooltip;
}
/**
* Shows notification with a single button 'Undo' delete.
*/
export function reportUndo(
doc: GristDoc,
messageLabel: string,
buttonLabel = 'Undo to restore'
) {
// First create a notification with a button to undo the delete.
let notification = reportSuccess(messageLabel, {
key: 'undo',
actions: [{
label: buttonLabel,
action: () => {
// When user clicks on the button, undo the last action.
commands.allCommands.undo.run();
// And remove this notification.
close();
},
}]
});
// When we received some actions from the server, cancel this popup,
// as the undo might do something else.
doc.on('onDocUserAction', close);
notification?.onDispose(() => doc.off('onDocUserAction', close));
function close() {
if (notification && !notification?.isDisposed()) {
notification.dispose();
notification = undefined;
}
}
}
const cssTheme = styled('div', `
color: ${theme.text};
`);
const cssButtons = styled('div', `
display: flex;
gap: 6px;
`);
const cssContainer = styled(cssTheme, `
max-width: 270px;
`);
const cssWideContainer = styled(cssTheme, `
max-width: 340px;
`);