(core) Add a Plus button below a rule set when there is no default rule

Summary:
- If you type into the "Everyone" / "Everyone Else" rule, and it stops being
  the default rule, there will now be an extra row with a "+" button to add a
  new default rule
- Switch to ACE-supported auto-resizing (for better scrollbars handling)
- Tweak ACE padding styles for better-looking scrolling.

Test Plan: Added a test case for the extra "+" button.

Reviewers: paulfitz

Reviewed By: paulfitz

Differential Revision: https://phab.getgrist.com/D2796
pull/21/head
Dmitry S 3 years ago
parent 2f26f140c8
commit 18268d7838

@ -18,9 +18,11 @@ export function aclFormulaEditor(options: ACLFormulaOptions) {
// Set various editor options.
editor.setTheme('ace/theme/chrome');
editor.setOptions({enableLiveAutocompletion: true});
// ACE editor resizes automatically when maxLines is set.
editor.setOptions({enableLiveAutocompletion: true, maxLines: 10});
editor.renderer.setShowGutter(false); // Default line numbers to hidden
editor.renderer.setPadding(0);
editor.renderer.setPadding(5);
editor.renderer.setScrollMargin(4, 4, 0, 0);
editor.$blockScrolling = Infinity;
editor.setReadOnly(options.readOnly);
editor.setFontSize('12');
@ -64,23 +66,9 @@ export function aclFormulaEditor(options: ACLFormulaOptions) {
// Disable Tab/Shift+Tab commands to restore their regular behavior.
(editor.commands as any).removeCommands(['indent', 'outdent']);
function resize() {
if (editor.renderer.lineHeight === 0) {
// Reschedule the resize, since it's not ready yet. Seems to happen occasionally.
setTimeout(resize, 50);
}
editorElem.style.width = 'auto';
editorElem.style.height = (Math.max(1, session.getScreenLength()) * editor.renderer.lineHeight) + 'px';
editor.resize();
}
// Set the editor's initial value.
editor.setValue(options.initialValue);
// Resize the editor on change, and initially once it's attached to the page.
editor.on('change', resize);
setTimeout(resize, 0);
return cssConditionInputAce(
cssConditionInputAce.cls('-disabled', options.readOnly),
dom.onDispose(() => editor.destroy()),
@ -91,7 +79,7 @@ export function aclFormulaEditor(options: ACLFormulaOptions) {
const cssConditionInputAce = styled('div', `
width: 100%;
min-height: 28px;
padding: 5px 6px 5px 6px;
padding: 1px;
border-radius: 3px;
border: 1px solid transparent;
cursor: pointer;
@ -123,5 +111,6 @@ const cssConditionInputAce = styled('div', `
`);
const cssAcePlaceholder = styled('div', `
padding: 4px 5px;
opacity: 0.5;
`);

@ -726,6 +726,18 @@ abstract class ObsRuleSet extends Disposable {
),
cssCell4(cssRuleBody.cls(''),
dom.forEach(this._body, part => part.buildRulePartDom()),
dom.maybe(use => !this.hasDefaultCondition(use), () =>
cssColumnGroup(
{style: 'min-height: 28px'},
cssCellIcon(
cssIconButton(icon('Plus'),
dom.on('click', () => this.addRulePart(null)),
testId('rule-add'),
)
),
testId('rule-extra-add'),
)
),
),
testId('rule-set'),
);
@ -738,8 +750,9 @@ abstract class ObsRuleSet extends Disposable {
}
}
public addRulePart(beforeRule: ObsRulePart) {
const i = this._body.get().indexOf(beforeRule);
public addRulePart(beforeRule: ObsRulePart|null) {
const body = this._body.get();
const i = beforeRule ? body.indexOf(beforeRule) : body.length;
this._body.splice(i, 0, ObsRulePart.create(this._body, this, undefined));
}
@ -768,6 +781,11 @@ abstract class ObsRuleSet extends Disposable {
return body[body.length - 1] === part;
}
public hasDefaultCondition(use: UseCB): boolean {
const body = use(this._body);
return body.length > 0 && body[body.length - 1].hasEmptyCondition(use);
}
/**
* Which permission bits to allow the user to set.
*/
@ -1127,6 +1145,10 @@ class ObsRulePart extends Disposable {
};
}
public hasEmptyCondition(use: UseCB): boolean {
return use(this._aclFormula) === '';
}
public matches(use: UseCB, aclFormula: string, permissionsText: string): boolean {
return (use(this._aclFormula) === aclFormula &&
permissionSetToText(use(this._permissions)) === permissionsText);

Loading…
Cancel
Save