mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Two way reference polish
Summary: - Fixing BulkRemoveRecord bug - Rewriting copy on the `delete reverse column` dialog - Rewriting text on the `reassign reference dialog` - Adding tooltip that explains why 2-way references are not enabled for formula columns Test Plan: Added tests Reviewers: georgegevoian Reviewed By: georgegevoian Subscribers: paulfitz Differential Revision: https://phab.getgrist.com/D4355
This commit is contained in:
@@ -503,3 +503,14 @@ const cssSkipIcon = styled(icon, `
|
||||
height: 20px;
|
||||
margin: 0px -3px;
|
||||
`);
|
||||
|
||||
// This is aligned with css in ./DocTutorial.css
|
||||
export const cssCode = styled('code', `
|
||||
padding: 2px 5px;
|
||||
color: ${theme.tutorialsPopupCodeFg};
|
||||
background: ${theme.tutorialsPopupCodeBg};
|
||||
border: 1px solid ${theme.tutorialsPopupCodeBorder};
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
font-size: max(12.6px, 90%); /* 90% of 13px */
|
||||
`);
|
||||
|
||||
@@ -45,6 +45,7 @@ export type Tooltip =
|
||||
| 'setRefDropdownCondition'
|
||||
| 'communityWidgets'
|
||||
| 'twoWayReferences'
|
||||
| 'twoWayReferencesDisabled'
|
||||
| 'reasignTwoWayReference';
|
||||
|
||||
export type TooltipContentFunc = (...domArgs: DomElementArg[]) => DomContents;
|
||||
@@ -166,16 +167,23 @@ see or edit which parts of your document.')
|
||||
),
|
||||
twoWayReferences: (...args: DomElementArg[]) => cssTooltipContent(
|
||||
dom('div',
|
||||
t('Creates a reverse column in target table that can be edited from either end.')
|
||||
t('Creates a new Reference List column in the target table, with both this ' +
|
||||
'and the target columns editable and synchronized.')
|
||||
),
|
||||
...args,
|
||||
),
|
||||
twoWayReferencesDisabled: (...args: DomElementArg[]) => cssTooltipContent(
|
||||
dom('div',
|
||||
t('Two-way references are not currently supported for Formula or Trigger Formula columns')
|
||||
),
|
||||
...args,
|
||||
),
|
||||
reasignTwoWayReference: (...args: DomElementArg[]) => cssTooltipContent(
|
||||
dom('div',
|
||||
t('This limitation occurs when one end of a two-way reference is configured as a single Reference.')
|
||||
t('This limitation occurs when one column in a two-way reference has the Reference type.')
|
||||
),
|
||||
dom('div',
|
||||
t('To allow multiple assignments, change the type of the Reference column to Reference List.')
|
||||
t(`To allow multiple assignments, change the referenced column's type to Reference List.`)
|
||||
),
|
||||
...args,
|
||||
),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as commands from 'app/client/components/commands';
|
||||
import {makeT} from 'app/client/lib/localization';
|
||||
import {ColumnRec, DocModel} from 'app/client/models/DocModel';
|
||||
import {cssCode} from 'app/client/ui/DocTutorial';
|
||||
import {withInfoTooltip} from 'app/client/ui/tooltips';
|
||||
import {bigBasicButton, bigPrimaryButton, textButton} from 'app/client/ui2018/buttons';
|
||||
import {labeledSquareCheckbox} from 'app/client/ui2018/checkbox';
|
||||
@@ -101,10 +102,10 @@ export async function buildReassignModal(options: {
|
||||
`{{targetTable}} record {{targetName}} is already assigned to {{sourceTable}} record \
|
||||
{{oldSourceName}}.`,
|
||||
{
|
||||
targetTable: dom('i', Pets),
|
||||
sourceTable: dom('i', Owners),
|
||||
targetName: dom('b', Azor),
|
||||
oldSourceName: dom('b', Bob),
|
||||
targetTable: cssCode(Pets),
|
||||
sourceTable: cssCode(Owners),
|
||||
targetName: cssName(Azor),
|
||||
oldSourceName: cssName(Bob),
|
||||
});
|
||||
|
||||
return cssBulletLine(text);
|
||||
@@ -117,11 +118,11 @@ export async function buildReassignModal(options: {
|
||||
// Task is the name of the revRec table
|
||||
const Pets = revRec.table().tableNameDef();
|
||||
const Owners = colRec.table().tableNameDef();
|
||||
return dom('div', [
|
||||
return cssHigherLine([
|
||||
t(`Each {{targetTable}} record may only be assigned to a single {{sourceTable}} record.`,
|
||||
{
|
||||
targetTable: dom('i', Pets),
|
||||
sourceTable: dom('i', Owners),
|
||||
targetTable: cssCode(Pets),
|
||||
sourceTable: cssCode(Owners),
|
||||
})
|
||||
]);
|
||||
}
|
||||
@@ -151,14 +152,14 @@ export async function buildReassignModal(options: {
|
||||
const Ann = rowDisplay(colRec.table().tableId(), newRowId, colRec.colId()) as string;
|
||||
const singleText = () => t(`Reassign to {{sourceTable}} record {{sourceName}}.`,
|
||||
{
|
||||
sourceTable: dom('i', colRec.table().tableNameDef()),
|
||||
sourceName: dom('b', Ann),
|
||||
sourceTable: cssCode(colRec.table().tableNameDef()),
|
||||
sourceName: cssName(Ann),
|
||||
});
|
||||
const multiText = () => t(`Reassign to new {{sourceTable}} records.`,
|
||||
{
|
||||
sourceTable: dom('i', colRec.table().tableNameDef()),
|
||||
sourceTable: cssCode(colRec.table().tableNameDef()),
|
||||
});
|
||||
return labeledSquareCheckbox(checked, multiple ? multiText() : singleText());
|
||||
return cssCheckbox(checked, multiple ? multiText() : singleText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,9 +369,23 @@ function* bulkToSingle(actions: DocAction[]): Iterable<DocAction> {
|
||||
|
||||
const cssBulletLine = styled('div', `
|
||||
margin-bottom: 8px;
|
||||
line-height: 22px;
|
||||
&::before {
|
||||
content: '•';
|
||||
margin-right: 4px;
|
||||
color: ${theme.lightText};
|
||||
}
|
||||
`);
|
||||
|
||||
const cssHigherLine = styled('div', `
|
||||
line-height: 22px;
|
||||
`);
|
||||
|
||||
const cssName = (text: string) => dom('span', `"${text}"`);
|
||||
|
||||
const cssCheckbox = styled(labeledSquareCheckbox, `
|
||||
line-height: 22px;
|
||||
& > span {
|
||||
overflow: unset; /* make some room for cssCode */
|
||||
}
|
||||
`);
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
*/
|
||||
|
||||
import {logTelemetryEvent} from 'app/client/lib/telemetry';
|
||||
import {GristTooltips, Tooltip, TooltipContentFunc} from 'app/client/ui/GristTooltips';
|
||||
import {GristTooltips, Tooltip} from 'app/client/ui/GristTooltips';
|
||||
import {prepareForTransition} from 'app/client/ui/transitions';
|
||||
import {testId, theme, vars} from 'app/client/ui2018/cssVars';
|
||||
import {icon} from 'app/client/ui2018/icons';
|
||||
import {makeLinks} from 'app/client/ui2018/links';
|
||||
import {menuCssClass} from 'app/client/ui2018/menus';
|
||||
import {dom, DomContents, DomElementArg, DomElementMethod, styled} from 'grainjs';
|
||||
import {BindableValue, dom, DomContents, DomElementArg, DomElementMethod, styled} from 'grainjs';
|
||||
import Popper from 'popper.js';
|
||||
import {cssMenu, cssMenuItem, defaultMenuOptions, IPopupOptions, setPopupToCreateDom} from 'popweasel';
|
||||
import merge = require('lodash/merge');
|
||||
@@ -324,12 +324,12 @@ export type InfoTooltipVariant = 'click' | 'hover';
|
||||
* Renders an info icon that shows a tooltip with the specified `content`.
|
||||
*/
|
||||
export function infoTooltip(
|
||||
tooltip: Tooltip|TooltipContentFunc,
|
||||
tooltip: BindableValue<Tooltip>,
|
||||
options: InfoTooltipOptions = {},
|
||||
...domArgs: DomElementArg[]
|
||||
) {
|
||||
const {variant = 'click'} = options;
|
||||
const content = typeof tooltip === 'function' ? tooltip() : GristTooltips[tooltip]();
|
||||
const content = dom.domComputed(tooltip, (t) => GristTooltips[t]());
|
||||
const onOpen = () => logTelemetryEvent('viewedTip', {full: {tipName: tooltip}});
|
||||
switch (variant) {
|
||||
case 'click': {
|
||||
@@ -433,7 +433,7 @@ export interface WithInfoTooltipOptions {
|
||||
*/
|
||||
export function withInfoTooltip(
|
||||
domContents: DomContents,
|
||||
tooltip: Tooltip,
|
||||
tooltip: BindableValue<Tooltip>,
|
||||
options: WithInfoTooltipOptions = {},
|
||||
) {
|
||||
const {variant = 'click', domArgs, iconDomArgs, popupOptions} = options;
|
||||
|
||||
Reference in New Issue
Block a user