mirror of
https://github.com/anyproto/anytype-ts.git
synced 2025-06-11 02:13:48 +09:00
Merge pull request #850 from anyproto/feature/JS-4800-sorts-and-filters-logic-update
Feature/JS-4800: Sorts and filters empty logic
This commit is contained in:
commit
6476427f02
13 changed files with 326 additions and 62 deletions
|
@ -31,12 +31,18 @@
|
|||
.iconObject { margin-right: 2px; }
|
||||
}
|
||||
|
||||
.txt { width: calc(100% - 70px); line-height: 20px; height: 40px; display: flex; flex-direction: column; }
|
||||
.txt { width: calc(100% - 70px); line-height: 20px; height: 40px; display: flex; flex-direction: column; align-items: flex-start; }
|
||||
.txt {
|
||||
.name { @include text-overflow-nw; width: 100%; }
|
||||
.name { @include text-overflow-nw; }
|
||||
.flex { line-height: 20px; }
|
||||
|
||||
.condition { color: var(--color-text-secondary); margin-right: 4px; }
|
||||
.name,
|
||||
.flex { display: flex; align-items: center; }
|
||||
.name::after,
|
||||
.flex::after { content: ''; width: 20px; height: 20px; background-image: url('~img/arrow/select/dark.svg'); }
|
||||
.flex::after { background-image: url('~img/arrow/select/light.svg'); }
|
||||
|
||||
.condition { color: var(--color-text-secondary); }
|
||||
.value { color: var(--color-text-secondary); white-space: nowrap; overflow: hidden; }
|
||||
}
|
||||
}
|
||||
|
@ -106,4 +112,4 @@
|
|||
|
||||
.input { border: 0px; padding: 0px; height: 20px; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,12 +11,11 @@
|
|||
.item {
|
||||
.iconObject { margin-right: 10px; }
|
||||
|
||||
.select { border: 0px; padding: 0px; display: block; }
|
||||
.select { border: 0px; padding: 0px; display: block; padding-right: 20px; }
|
||||
.select:hover, .select.isFocused { background: none; }
|
||||
.select.grey { color: var(--color-control-active); }
|
||||
.select {
|
||||
.icon.relation { display: none; }
|
||||
.icon.arrow { display: none; }
|
||||
}
|
||||
|
||||
.buttons { line-height: 44px; opacity: 0; transition: $transitionAllCommon; }
|
||||
|
@ -24,7 +23,11 @@
|
|||
.icon { vertical-align: middle; opacity: 1; }
|
||||
}
|
||||
|
||||
.txt { width: calc(100% - 74px); line-height: 20px; height: 40px; display: flex; flex-direction: column; }
|
||||
.txt { width: calc(100% - 74px); line-height: 20px; height: 40px; display: flex; flex-direction: column; align-items: flex-start; }
|
||||
.txt {
|
||||
.label { @include text-common; display: flex; align-items: center; font-weight: 400; line-height: 20px; padding: 0px; margin: 0px; color: var(--color-text-primary); }
|
||||
.label::after { content: ''; width: 20px; height: 20px; background-image: url('~img/arrow/select/dark.svg'); }
|
||||
}
|
||||
}
|
||||
.item.empty { margin: 8px 0px; padding: 14px 16px; }
|
||||
.item.isReadonly {
|
||||
|
@ -43,4 +46,4 @@
|
|||
.line { margin-top: 0px; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,11 @@
|
|||
|
||||
.menu.menuSelect.withFilter {
|
||||
.content { padding: 8px 0px 0px 0px; }
|
||||
.items { height: calc(100% - 38px); }
|
||||
.items { height: calc(100% - 30px); }
|
||||
}
|
||||
|
||||
.menu.menuSelect.withAdd {
|
||||
.content { max-height: 378px; }
|
||||
}
|
||||
|
||||
.menu.menuSelect.skip { width: var(--menu-width-value); }
|
||||
|
|
|
@ -241,6 +241,26 @@
|
|||
}
|
||||
}
|
||||
|
||||
/* DataviewFilterList */
|
||||
|
||||
.menu.menuDataviewFilterList {
|
||||
.item {
|
||||
.txt {
|
||||
.name::after { background-image: url('#{$themePath}/arrow/select/dark.svg'); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* DataviewSort */
|
||||
|
||||
.menu.menuDataviewSort {
|
||||
.item {
|
||||
.txt {
|
||||
.label::after { background-image: url('#{$themePath}/arrow/select/dark.svg'); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* QuickCapture */
|
||||
|
||||
.menuQuickCapture { background: none; box-shadow: none; }
|
||||
|
|
|
@ -78,6 +78,8 @@ const BlockDataview = observer(class BlockDataview extends React.Component<Props
|
|||
this.onSelectEnd = this.onSelectEnd.bind(this);
|
||||
this.onSelectToggle = this.onSelectToggle.bind(this);
|
||||
this.onFilterChange = this.onFilterChange.bind(this);
|
||||
this.onSortAdd = this.onSortAdd.bind(this);
|
||||
this.onFilterAdd = this.onFilterAdd.bind(this);
|
||||
|
||||
this.getSearchIds = this.getSearchIds.bind(this);
|
||||
this.objectOrderUpdate = this.objectOrderUpdate.bind(this);
|
||||
|
@ -167,6 +169,8 @@ const BlockDataview = observer(class BlockDataview extends React.Component<Props
|
|||
onRecordAdd: this.onRecordAdd,
|
||||
onTemplateMenu: this.onTemplateMenu,
|
||||
onTemplateAdd: this.onTemplateAdd,
|
||||
onSortAdd: this.onSortAdd,
|
||||
onFilterAdd: this.onFilterAdd,
|
||||
isAllowedObject: this.isAllowedObject,
|
||||
isAllowedDefaultType: this.isAllowedDefaultType,
|
||||
onSourceSelect: this.onSourceSelect,
|
||||
|
@ -1105,6 +1109,41 @@ const BlockDataview = observer(class BlockDataview extends React.Component<Props
|
|||
this.objectOrderUpdate([ { viewId: view.id, groupId: '', objectIds: records } ], records);
|
||||
};
|
||||
|
||||
onSortAdd (item: any, callBack?: () => void) {
|
||||
const { rootId, block, isInline } = this.props;
|
||||
const view = this.getView();
|
||||
const object = this.getTarget();
|
||||
|
||||
C.BlockDataviewSortAdd(rootId, block.id, view.id, item, () => {
|
||||
if (callBack) {
|
||||
callBack();
|
||||
};
|
||||
|
||||
analytics.event('AddSort', {
|
||||
objectType: object.type,
|
||||
embedType: analytics.embedType(isInline)
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
onFilterAdd (item: any, callBack?: () => void) {
|
||||
const { rootId, block, isInline } = this.props;
|
||||
const view = this.getView();
|
||||
const object = this.getTarget();
|
||||
|
||||
C.BlockDataviewFilterAdd(rootId, block.id, view.id, item, () => {
|
||||
if (callBack) {
|
||||
callBack();
|
||||
};
|
||||
|
||||
analytics.event('AddFilter', {
|
||||
condition: item.condition,
|
||||
objectType: object.type,
|
||||
embedType: analytics.embedType(isInline)
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
getIdPrefix () {
|
||||
return [ 'dataviewCell', this.props.block.id ].join('-');
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@ import { observer } from 'mobx-react';
|
|||
import { observable } from 'mobx';
|
||||
import { SortableContainer, SortableElement } from 'react-sortable-hoc';
|
||||
import { Icon, Button, Filter } from 'Component';
|
||||
import { C, I, S, U, analytics, Relation, keyboard, translate, Dataview, sidebar } from 'Lib';
|
||||
import { C, I, S, U, analytics, Relation, keyboard, translate, Dataview, sidebar, J } from 'Lib';
|
||||
import Head from './head';
|
||||
|
||||
interface Props extends I.ViewComponent {
|
||||
|
@ -23,6 +23,8 @@ const Controls = observer(class Controls extends React.Component<Props> {
|
|||
super(props);
|
||||
|
||||
this.onButton = this.onButton.bind(this);
|
||||
this.sortOrFilterRelationSelect = this.sortOrFilterRelationSelect.bind(this);
|
||||
this.onSortOrFilterAdd = this.onSortOrFilterAdd.bind(this);
|
||||
this.onSortStart = this.onSortStart.bind(this);
|
||||
this.onSortEnd = this.onSortEnd.bind(this);
|
||||
this.onViewAdd = this.onViewAdd.bind(this);
|
||||
|
@ -259,11 +261,18 @@ const Controls = observer(class Controls extends React.Component<Props> {
|
|||
|
||||
const {
|
||||
rootId, block, readonly, loadData, getView, getSources, getVisibleRelations, getTarget, isInline, isCollection,
|
||||
getTypeId, getTemplateId, isAllowedDefaultType, onTemplateAdd,
|
||||
getTypeId, getTemplateId, isAllowedDefaultType, onTemplateAdd, onSortAdd, onFilterAdd,
|
||||
} = this.props;
|
||||
const view = getView();
|
||||
const obj = $(element);
|
||||
|
||||
if (((component == 'dataviewSort') && !view.sorts.length) || ((component == 'dataviewFilterList') && !view.filters.length)) {
|
||||
this.sortOrFilterRelationSelect(component,{ element }, () => {
|
||||
this.onButton(element, component);
|
||||
});
|
||||
return;
|
||||
};
|
||||
|
||||
const param: any = {
|
||||
element,
|
||||
horizontal: I.MenuDirection.Center,
|
||||
|
@ -296,10 +305,19 @@ const Controls = observer(class Controls extends React.Component<Props> {
|
|||
isCollection,
|
||||
isAllowedDefaultType,
|
||||
onTemplateAdd,
|
||||
onSortAdd,
|
||||
onFilterAdd,
|
||||
onViewSwitch: this.onViewSwitch,
|
||||
onViewCopy: this.onViewCopy,
|
||||
onViewRemove: this.onViewRemove,
|
||||
view: observable.box(view)
|
||||
view: observable.box(view),
|
||||
onAdd: (menuId, menuWidth) => {
|
||||
this.sortOrFilterRelationSelect(component,{
|
||||
element: `#${menuId} #item-add`,
|
||||
offsetX: menuWidth,
|
||||
horizontal: I.MenuDirection.Right
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -307,9 +325,58 @@ const Controls = observer(class Controls extends React.Component<Props> {
|
|||
param.title = translate('menuDataviewViewSettings');
|
||||
};
|
||||
|
||||
if (S.Menu.isOpen('select')) {
|
||||
S.Menu.close('select');
|
||||
};
|
||||
S.Menu.open(component, param);
|
||||
};
|
||||
|
||||
sortOrFilterRelationSelect (component: string, param: any, callBack?: () => void) {
|
||||
const { rootId, block, getView } = this.props;
|
||||
|
||||
U.Menu.sortOrFilterRelationSelect({
|
||||
menuParam: param,
|
||||
rootId,
|
||||
blockId: block.id,
|
||||
getView,
|
||||
onSelect: (item) => {
|
||||
this.onSortOrFilterAdd(item, component, () => {
|
||||
if (callBack) {
|
||||
callBack();
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onSortOrFilterAdd (item: any, component: string, callBack: () => void) {
|
||||
const { onSortAdd, onFilterAdd } = this.props;
|
||||
|
||||
let newItem = {
|
||||
relationKey: item.relationKey ? item.relationKey : item.id
|
||||
};
|
||||
|
||||
if (component == 'dataviewSort') {
|
||||
newItem = Object.assign(newItem, {
|
||||
type: I.SortType.Asc,
|
||||
});
|
||||
|
||||
onSortAdd(newItem, callBack);
|
||||
} else
|
||||
if (component == 'dataviewFilterList') {
|
||||
const conditions = Relation.filterConditionsByType(item.format);
|
||||
const condition = conditions.length ? conditions[0].id : I.FilterCondition.None;
|
||||
|
||||
newItem = Object.assign(newItem, {
|
||||
operator: I.FilterOperator.And,
|
||||
condition: condition as I.FilterCondition,
|
||||
value: Relation.formatValue(item, null, false),
|
||||
});
|
||||
|
||||
onFilterAdd(newItem, callBack);
|
||||
};
|
||||
};
|
||||
|
||||
onViewAdd (e: any) {
|
||||
e.persist();
|
||||
|
||||
|
|
|
@ -192,17 +192,20 @@ const MenuFilterList = observer(class MenuFilterList extends React.Component<I.M
|
|||
};
|
||||
|
||||
onAdd (e: any) {
|
||||
const { param, getId } = this.props;
|
||||
const { param, getId, getSize } = this.props;
|
||||
const { data } = param;
|
||||
const { rootId, blockId, getView, isInline, getTarget } = data;
|
||||
const view = getView();
|
||||
const { onFilterAdd, onAdd } = data;
|
||||
const relationOptions = this.getRelationOptions();
|
||||
const object = getTarget();
|
||||
|
||||
if (!relationOptions.length) {
|
||||
return;
|
||||
};
|
||||
|
||||
if (onAdd) {
|
||||
onAdd(getId(), getSize().width);
|
||||
return;
|
||||
};
|
||||
|
||||
const obj = $(`#${getId()} .content`);
|
||||
const first = relationOptions[0];
|
||||
const conditions = Relation.filterConditionsByType(first.format);
|
||||
|
@ -214,14 +217,8 @@ const MenuFilterList = observer(class MenuFilterList extends React.Component<I.M
|
|||
value: Relation.formatValue(first, null, false),
|
||||
};
|
||||
|
||||
C.BlockDataviewFilterAdd(rootId, blockId, view.id, newItem);
|
||||
|
||||
obj.animate({ scrollTop: obj.get(0).scrollHeight }, 50);
|
||||
|
||||
analytics.event('AddFilter', {
|
||||
condition: newItem.condition,
|
||||
objectType: object.type,
|
||||
embedType: analytics.embedType(isInline)
|
||||
onFilterAdd(newItem, () => {
|
||||
obj.animate({ scrollTop: obj.get(0).scrollHeight }, 50);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -348,4 +345,4 @@ const MenuFilterList = observer(class MenuFilterList extends React.Component<I.M
|
|||
|
||||
});
|
||||
|
||||
export default MenuFilterList;
|
||||
export default MenuFilterList;
|
||||
|
|
|
@ -414,7 +414,7 @@ const MenuDataviewFilterValues = observer(class MenuDataviewFilterValues extends
|
|||
onOver (e: any, item: any) {
|
||||
const { getId, getSize, setActive, param } = this.props;
|
||||
const { data } = param;
|
||||
const { getView, itemId } = data;
|
||||
const { rootId, blockId, getView, itemId } = data;
|
||||
const view = getView();
|
||||
const filter = view.getFilter(itemId);
|
||||
const isReadonly = this.isReadonly();
|
||||
|
@ -430,13 +430,29 @@ const MenuDataviewFilterValues = observer(class MenuDataviewFilterValues extends
|
|||
let options = [];
|
||||
let key = item.id;
|
||||
|
||||
switch (item.id) {
|
||||
case 'relation': {
|
||||
options = this.getRelationOptions();
|
||||
key = 'relationKey';
|
||||
break;
|
||||
if (item.id == 'relation') {
|
||||
const menuParam = {
|
||||
element: `#${getId()} #item-${item.id}`,
|
||||
offsetX: getSize().width,
|
||||
horizontal: I.MenuDirection.Right,
|
||||
vertical: I.MenuDirection.Center,
|
||||
passThrough: true,
|
||||
};
|
||||
|
||||
U.Menu.sortOrFilterRelationSelect({
|
||||
menuParam,
|
||||
rootId,
|
||||
blockId,
|
||||
getView,
|
||||
onSelect: (item) => {
|
||||
this.onChange('relationKey', item.relationKey ? item.relationKey : item.id);
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
switch (item.id) {
|
||||
case 'condition': {
|
||||
if (Relation.isDictionary(filter.relationKey)) {
|
||||
options = Relation.filterConditionsDictionary();
|
||||
|
@ -758,4 +774,4 @@ const MenuDataviewFilterValues = observer(class MenuDataviewFilterValues extends
|
|||
|
||||
});
|
||||
|
||||
export default MenuDataviewFilterValues;
|
||||
export default MenuDataviewFilterValues;
|
||||
|
|
|
@ -4,7 +4,7 @@ import $ from 'jquery';
|
|||
import { observer } from 'mobx-react';
|
||||
import { AutoSizer, CellMeasurer, InfiniteLoader, List as VList, CellMeasurerCache } from 'react-virtualized';
|
||||
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
|
||||
import { Icon, IconObject, Select } from 'Component';
|
||||
import { Icon, IconObject, Label, Select } from 'Component';
|
||||
import { I, C, S, U, J, Relation, keyboard, analytics, translate } from 'Lib';
|
||||
|
||||
const HEIGHT = 48;
|
||||
|
@ -26,6 +26,7 @@ const MenuSort = observer(class MenuSort extends React.Component<I.Menu> {
|
|||
this.onSortStart = this.onSortStart.bind(this);
|
||||
this.onSortEnd = this.onSortEnd.bind(this);
|
||||
this.onScroll = this.onScroll.bind(this);
|
||||
this.onSortNameClick = this.onSortNameClick.bind(this);
|
||||
};
|
||||
|
||||
render () {
|
||||
|
@ -47,8 +48,6 @@ const MenuSort = observer(class MenuSort extends React.Component<I.Menu> {
|
|||
{ id: String(I.SortType.Asc), name: translate('commonAscending') },
|
||||
{ id: String(I.SortType.Desc), name: translate('commonDescending') },
|
||||
];
|
||||
|
||||
const relationOptions = this.getRelationOptions();
|
||||
|
||||
const Handle = SortableHandle(() => (
|
||||
<Icon className="dnd" />
|
||||
|
@ -56,6 +55,7 @@ const MenuSort = observer(class MenuSort extends React.Component<I.Menu> {
|
|||
|
||||
const Item = SortableElement((item: any) => {
|
||||
const relation: any = S.Record.getRelationByKey(item.relationKey) || {};
|
||||
|
||||
return (
|
||||
<div
|
||||
id={'item-' + item.id}
|
||||
|
@ -66,18 +66,13 @@ const MenuSort = observer(class MenuSort extends React.Component<I.Menu> {
|
|||
{!isReadonly ? <Handle /> : ''}
|
||||
<IconObject size={40} object={{ relationFormat: relation.format, layout: I.ObjectLayout.Relation }} />
|
||||
<div className="txt">
|
||||
<Select
|
||||
id={[ 'filter', 'relation', item.id ].join('-')}
|
||||
options={relationOptions}
|
||||
value={item.relationKey}
|
||||
onChange={v => this.onChange(item.id, 'relationKey', v)}
|
||||
readonly={isReadonly}
|
||||
/>
|
||||
<Label id={[ 'filter', 'relation', item.id ].join('-')} text={relation.name} onClick={e => this.onSortNameClick(e, item)} />
|
||||
|
||||
<Select
|
||||
id={[ 'filter', 'type', item.id ].join('-')}
|
||||
className="grey"
|
||||
options={typeOptions}
|
||||
options={typeOptions}
|
||||
arrowClassName={'light'}
|
||||
value={item.type}
|
||||
onChange={v => this.onChange(item.id, 'type', v)}
|
||||
readonly={isReadonly}
|
||||
|
@ -290,19 +285,48 @@ const MenuSort = observer(class MenuSort extends React.Component<I.Menu> {
|
|||
});
|
||||
};
|
||||
|
||||
onSortNameClick (e: React.MouseEvent, item: any) {
|
||||
if (this.isReadonly()) {
|
||||
return;
|
||||
};
|
||||
|
||||
const { param, getId, getSize } = this.props;
|
||||
const { data } = param;
|
||||
const { rootId, blockId, getView } = data;
|
||||
|
||||
const menuParam = {
|
||||
element: `#${getId()} #item-${item.id}`,
|
||||
offsetX: getSize().width,
|
||||
horizontal: I.MenuDirection.Right,
|
||||
vertical: I.MenuDirection.Center
|
||||
};
|
||||
|
||||
U.Menu.sortOrFilterRelationSelect({
|
||||
menuParam,
|
||||
rootId,
|
||||
blockId,
|
||||
getView,
|
||||
onSelect: (v) => {
|
||||
this.onChange(item.id, 'relationKey', v.relationKey ? v.relationKey : v.id);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onAdd () {
|
||||
const { param, getId } = this.props;
|
||||
const { param, getId, getSize } = this.props;
|
||||
const { data } = param;
|
||||
const { rootId, getView, getTarget, blockId, isInline } = data;
|
||||
const view = getView();
|
||||
const object = getTarget();
|
||||
const { onSortAdd, onAdd } = data;
|
||||
const relationOptions = this.getRelationOptions();
|
||||
|
||||
if (!relationOptions.length) {
|
||||
return;
|
||||
};
|
||||
|
||||
if (onAdd) {
|
||||
onAdd(getId(), getSize().width);
|
||||
return;
|
||||
};
|
||||
|
||||
const obj = $(`#${getId()}`);
|
||||
const content = obj.find('.content');
|
||||
const newItem = {
|
||||
|
@ -310,13 +334,8 @@ const MenuSort = observer(class MenuSort extends React.Component<I.Menu> {
|
|||
type: I.SortType.Asc,
|
||||
};
|
||||
|
||||
C.BlockDataviewSortAdd(rootId, blockId, view.id, newItem, () => {
|
||||
onSortAdd(newItem, () => {
|
||||
content.animate({ scrollTop: content.get(0).scrollHeight }, 50);
|
||||
|
||||
analytics.event('AddSort', {
|
||||
objectType: object.type,
|
||||
embedType: analytics.embedType(isInline)
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -408,4 +427,4 @@ const MenuSort = observer(class MenuSort extends React.Component<I.Menu> {
|
|||
|
||||
});
|
||||
|
||||
export default MenuSort;
|
||||
export default MenuSort;
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as React from 'react';
|
|||
import $ from 'jquery';
|
||||
import { observer } from 'mobx-react';
|
||||
import { AutoSizer, CellMeasurer, InfiniteLoader, List, CellMeasurerCache } from 'react-virtualized';
|
||||
import { Filter, MenuItemVertical, Label } from 'Component';
|
||||
import { Filter, MenuItemVertical, Label, Icon } from 'Component';
|
||||
import { I, U, Relation, keyboard, translate } from 'Lib';
|
||||
|
||||
const HEIGHT_ITEM = 28;
|
||||
|
@ -61,6 +61,20 @@ const MenuSelect = observer(class MenuSelect extends React.Component<I.Menu> {
|
|||
<div className="inner" />
|
||||
</div>
|
||||
);
|
||||
} else
|
||||
if (item.id == 'add') {
|
||||
content = (
|
||||
<div
|
||||
id="item-add"
|
||||
className="item add"
|
||||
onMouseEnter={e => this.onMouseEnter(e, item)}
|
||||
onClick={e => this.onClick(e, item)}
|
||||
style={item.style}
|
||||
>
|
||||
<Icon className="plus" />
|
||||
<div className="name">{item.name}</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
if (item.isInitial) {
|
||||
cn.push('isInitial');
|
||||
|
@ -144,7 +158,8 @@ const MenuSelect = observer(class MenuSelect extends React.Component<I.Menu> {
|
|||
<React.Fragment>
|
||||
{withFilter ? (
|
||||
<Filter
|
||||
ref={ref => this.refFilter = ref}
|
||||
ref={ref => this.refFilter = ref}
|
||||
className="outlined"
|
||||
value={filter}
|
||||
placeholder={placeholder}
|
||||
onChange={this.onFilterChange}
|
||||
|
@ -268,7 +283,7 @@ const MenuSelect = observer(class MenuSelect extends React.Component<I.Menu> {
|
|||
getItems (withSections: boolean) {
|
||||
const { param } = this.props;
|
||||
const { data } = param;
|
||||
const { preventFilter } = data;
|
||||
const { preventFilter, onAdd } = data;
|
||||
const sections = this.getSections();
|
||||
|
||||
let items: any[] = [];
|
||||
|
@ -289,6 +304,14 @@ const MenuSelect = observer(class MenuSelect extends React.Component<I.Menu> {
|
|||
|
||||
items = items.filter(it => String(it.name || '').match(filter));
|
||||
};
|
||||
|
||||
if (onAdd) {
|
||||
items = items.concat([
|
||||
{ isDiv: true },
|
||||
{ id: 'add', name: translate('commonAddRelation') }
|
||||
]);
|
||||
};
|
||||
|
||||
return items || [];
|
||||
};
|
||||
|
||||
|
@ -314,14 +337,19 @@ const MenuSelect = observer(class MenuSelect extends React.Component<I.Menu> {
|
|||
};
|
||||
|
||||
onClick (e: any, item: any) {
|
||||
const { param, close } = this.props;
|
||||
const { param, close, getId, getSize } = this.props;
|
||||
const { data } = param;
|
||||
const { onSelect, canSelectInitial, noClose, disabled } = data;
|
||||
const { onSelect, canSelectInitial, noClose, disabled, onAdd } = data;
|
||||
|
||||
if (item.isInitial && !canSelectInitial) {
|
||||
return;
|
||||
};
|
||||
|
||||
if ((item.id == 'add') && onAdd) {
|
||||
onAdd(getId(), getSize().width);
|
||||
return;
|
||||
};
|
||||
|
||||
if (!noClose) {
|
||||
close();
|
||||
};
|
||||
|
@ -397,7 +425,7 @@ const MenuSelect = observer(class MenuSelect extends React.Component<I.Menu> {
|
|||
resize () {
|
||||
const { position, getId, param } = this.props;
|
||||
const { data } = param;
|
||||
const { noScroll, maxHeight, noVirtualisation } = data;
|
||||
const { noScroll, maxHeight, noVirtualisation, onAdd } = data;
|
||||
const items = this.getItems(true);
|
||||
const obj = $(`#${getId()}`);
|
||||
const content = obj.find('.content');
|
||||
|
@ -425,6 +453,7 @@ const MenuSelect = observer(class MenuSelect extends React.Component<I.Menu> {
|
|||
};
|
||||
|
||||
withFilter ? obj.addClass('withFilter') : obj.removeClass('withFilter');
|
||||
onAdd ? obj.addClass('withAdd') : obj.removeClass('withAdd');
|
||||
noScroll ? obj.addClass('noScroll') : obj.removeClass('noScroll');
|
||||
noVirtualisation ? obj.addClass('noVirtualisation') : obj.removeClass('noVirtualisation');
|
||||
|
||||
|
|
|
@ -412,4 +412,4 @@ const MenuSyncStatus = observer(class MenuSyncStatus extends React.Component<I.M
|
|||
|
||||
});
|
||||
|
||||
export default MenuSyncStatus;
|
||||
export default MenuSyncStatus;
|
||||
|
|
|
@ -136,6 +136,8 @@ export interface ViewComponent {
|
|||
getEmpty?(type: string): any;
|
||||
onRecordAdd?: (e: any, dir: number, groupId?: string) => void;
|
||||
onTemplateAdd?: () => void;
|
||||
onSortAdd?: (item: any, callBack?: () => void) => void;
|
||||
onFilterAdd?: (item: any, callBack?: () => void) => void;
|
||||
onTemplateMenu?: (e: any, dur: number) => void;
|
||||
onCellClick?(e: any, key: string, id?: string, record?: any): void;
|
||||
onContext?(e: any, id: string): void;
|
||||
|
|
|
@ -832,6 +832,68 @@ class UtilMenu {
|
|||
];
|
||||
};
|
||||
|
||||
sortOrFilterRelationSelect (param: any) {
|
||||
const { rootId, blockId, getView, onSelect, menuParam } = param;
|
||||
const options = Relation.getFilterOptions(rootId, blockId, getView());
|
||||
|
||||
const callBack = (item: any) => {
|
||||
onSelect(item);
|
||||
S.Menu.close('select');
|
||||
};
|
||||
|
||||
const menu = Object.assign({
|
||||
horizontal: I.MenuDirection.Center,
|
||||
offsetY: 10,
|
||||
noFlipY: true,
|
||||
}, menuParam);
|
||||
|
||||
if (S.Menu.isOpen('select')) {
|
||||
S.Menu.close('select');
|
||||
};
|
||||
|
||||
S.Menu.open('select', {
|
||||
...menu,
|
||||
data: {
|
||||
options,
|
||||
withFilter: true,
|
||||
maxHeight: 378,
|
||||
onAdd: (menuId, menuWidth) => {
|
||||
this.sortOrFilterRelationAdd({ menuId, menuWidth }, param, (relation) => callBack(relation));
|
||||
},
|
||||
onSelect: (e: any, item: any) => callBack(item)
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
sortOrFilterRelationAdd (menuParam: any, param: any, callBack: (relation: any) => void) {
|
||||
const { rootId, blockId, getView } = param;
|
||||
const { menuId, menuWidth } = menuParam;
|
||||
const relations = Relation.getFilterOptions(rootId, blockId, getView());
|
||||
const element = `#${menuId} #item-add`;
|
||||
|
||||
S.Menu.open('relationSuggest', {
|
||||
element,
|
||||
offsetX: menuWidth,
|
||||
horizontal: I.MenuDirection.Right,
|
||||
vertical: I.MenuDirection.Center,
|
||||
onOpen: () => $(element).addClass('active'),
|
||||
onClose: () => $(element).removeClass('active'),
|
||||
data: {
|
||||
rootId,
|
||||
blockId,
|
||||
skipKeys: relations.map(it => it.id),
|
||||
ref: 'dataview',
|
||||
menuIdEdit: 'blockRelationEdit',
|
||||
addCommand: (rootId: string, blockId: string, relation: any, onChange: (message: any) => void) => {
|
||||
Dataview.relationAdd(rootId, blockId, relation.relationKey, relations.length, getView(), (message: any) => {
|
||||
callBack(relation);
|
||||
S.Menu.close('relationSuggest');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
export default new UtilMenu();
|
||||
export default new UtilMenu();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue