mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Aggregate and reverse lookups
Summary: Reverse and Aggregation lookup. Aggregation lookup works when table have a reference list column. It allow to list value of any fields of a referenced values, or to make some basic operation on them (sum, average, count) Reverse lookup works as reverse one, but it allow do to the same operations on all rows that have reference to given row Test Plan: Manual so far. Reviewers: jarek Reviewed By: jarek Differential Revision: https://phab.getgrist.com/D4083
This commit is contained in:
@@ -56,8 +56,10 @@ export interface SearchableMenuOptions {
|
||||
|
||||
export interface SearchableMenuItem {
|
||||
cleanText: string;
|
||||
label: string;
|
||||
action: (item: HTMLElement) => void;
|
||||
builder?: () => Element;
|
||||
|
||||
label?: string;
|
||||
action?: (item: HTMLElement) => void;
|
||||
args?: DomElementArg[];
|
||||
}
|
||||
|
||||
@@ -86,19 +88,29 @@ export function searchableMenu(
|
||||
const cleanSearchValue = value.trim().toLowerCase();
|
||||
return dom.forEach(menuItems, (item) => {
|
||||
if (!item.cleanText.includes(cleanSearchValue)) { return null; }
|
||||
|
||||
return menuItem(item.action, item.label, ...(item.args ?? []));
|
||||
if (item.label && item.action) {
|
||||
return menuItem(item.action, item.label, ...(item.args || []));
|
||||
} else if (item.builder) {
|
||||
return item.builder();
|
||||
} else {
|
||||
throw new Error('Invalid menu item');
|
||||
}
|
||||
});
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO Weasel doesn't allow other options for submenus, but probably should.
|
||||
export type ISubMenuOptions =
|
||||
weasel.ISubMenuOptions &
|
||||
weasel.IPopupOptions &
|
||||
{allowNothingSelected?: boolean};
|
||||
|
||||
/**
|
||||
* Menu item with submenu
|
||||
*/
|
||||
export function menuItemSubmenu(
|
||||
submenu: weasel.MenuCreateFunc,
|
||||
options: ISubMenuOptions,
|
||||
@@ -108,7 +120,8 @@ export function menuItemSubmenu(
|
||||
submenu,
|
||||
{
|
||||
...defaults,
|
||||
expandIcon: () => icon('Expand'),
|
||||
expandIcon: () => cssExpandIcon('Expand'),
|
||||
menuCssClass: `${cssSubMenuElem.className} ${defaults.menuCssClass}`,
|
||||
...options,
|
||||
},
|
||||
dom.cls(cssMenuItemSubmenu.className),
|
||||
@@ -116,6 +129,41 @@ export function menuItemSubmenu(
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subheader as a menu item.
|
||||
*/
|
||||
export function menuSubHeaderMenu(
|
||||
submenu: weasel.MenuCreateFunc,
|
||||
options: ISubMenuOptions,
|
||||
...args: DomElementArg[]
|
||||
): Element {
|
||||
return menuItemSubmenu(
|
||||
submenu,
|
||||
{
|
||||
...options,
|
||||
},
|
||||
menuSubHeader.cls(''),
|
||||
cssPointer.cls(''),
|
||||
...args,
|
||||
);
|
||||
}
|
||||
|
||||
export const cssEllipsisLabel = styled('div', `
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
`);
|
||||
|
||||
export const cssExpandIcon = styled(icon, `
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
`);
|
||||
|
||||
const cssSubMenuElem = styled('div', `
|
||||
white-space: nowrap;
|
||||
min-width: 200px;
|
||||
`);
|
||||
|
||||
export const cssMenuElem = styled('div', `
|
||||
font-family: ${vars.fontFamily};
|
||||
font-size: ${vars.mediumFontSize};
|
||||
@@ -483,11 +531,15 @@ export const menuSubHeader = styled('div', `
|
||||
color: ${theme.menuSubheaderFg};
|
||||
font-size: ${vars.xsmallFontSize};
|
||||
text-transform: uppercase;
|
||||
font-weight: ${vars.bigControlTextWeight};
|
||||
font-weight: ${vars.headerControlTextWeight};
|
||||
padding: 8px 24px 8px 24px;
|
||||
cursor: default;
|
||||
`);
|
||||
|
||||
export const cssPointer = styled('div', `
|
||||
cursor: pointer;
|
||||
`);
|
||||
|
||||
export const menuText = styled('div', `
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -503,6 +555,12 @@ export const menuItem = styled(weasel.menuItem, menuItemStyle);
|
||||
|
||||
export const menuItemLink = styled(weasel.menuItemLink, menuItemStyle);
|
||||
|
||||
// when element name is, to long, it will be trimmed with ellipsis ("...")
|
||||
export function menuItemTrimmed(
|
||||
action: (item: HTMLElement, ev: Event) => void, label: string, ...args: DomElementArg[]) {
|
||||
return menuItem(action, cssEllipsisLabel(label), ...args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A version of menuItem which runs the action on next tick, allowing the menu to close even when
|
||||
@@ -706,6 +764,7 @@ const cssUpgradeTextButton = styled(textButton, `
|
||||
`);
|
||||
|
||||
const cssMenuItemSubmenu = styled('div', `
|
||||
position: relative;
|
||||
color: ${theme.menuItemFg};
|
||||
--icon-color: ${theme.menuItemFg};
|
||||
.${weasel.cssMenuItem.className}-sel {
|
||||
|
||||
Reference in New Issue
Block a user