Skip to content

Commit

Permalink
refactor(database): context-menu ui and ux
Browse files Browse the repository at this point in the history
  • Loading branch information
zzj3720 committed Oct 14, 2024
1 parent 7b77c4d commit 00d50f4
Show file tree
Hide file tree
Showing 11 changed files with 363 additions and 340 deletions.
12 changes: 8 additions & 4 deletions packages/affine/components/src/context-menu/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,17 +186,21 @@ export const menuButtonItems = {
<div class="affine-menu-action-text">
${config.label?.() ?? config.name}
</div>
<toggle-switch
.on="${config.on}"
.onChange="${onChange}"
></toggle-switch>
${config.postfix}
`,
select: () => config.onChange(config.on),
select: () => {
config.onChange(config.on);
return false;
},
class: config.class ?? '',
};
return html`
<affine-menu-button.data='${data}'.menu='${menu}'></affine-menu-button>`;
return html` <affine-menu-button
.data="${data}"
.menu="${menu}"
></affine-menu-button>`;
},
} satisfies Record<string, MenuItemRender<never>>;
75 changes: 42 additions & 33 deletions packages/affine/data-view/src/core/common/ref/ref.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import type { ReadonlySignal } from '@preact/signals-core';

import {
popFilterableSimpleMenu,
popMenu,
type PopupTarget,
popupTargetFromElement,
} from '@blocksuite/affine-components/context-menu';
Expand Down Expand Up @@ -110,42 +113,48 @@ declare global {
export const popCreateFilter = (
target: PopupTarget,
props: {
vars: Variable[];
vars: ReadonlySignal<Variable[]>;
onSelect: (filter: Filter) => void;
onClose?: () => void;
onBack?: () => void;
}
) => {
popFilterableSimpleMenu(
target,
[
...props.vars.map(v => ({
type: 'action' as const,
name: v.name,
prefix: renderUniLit(v.icon, {}),
select: () => {
props.onSelect(
firstFilterByRef(props.vars, {
type: 'ref',
name: v.id,
})
);
},
})),
{
type: 'group',
name: '',
items: [
{
type: 'action',
name: 'Add filter group',
prefix: AddCursorIcon(),
select: () => {
props.onSelect(firstFilterInGroup(props.vars));
},
},
],
popMenu(target, {
options: {
onClose: props.onClose,
title: {
onBack: props.onBack,
text: 'New filter',
},
],
props.onClose
);
items: [
...props.vars.value.map(v => ({
type: 'action' as const,
name: v.name,
prefix: renderUniLit(v.icon, {}),
select: () => {
props.onSelect(
firstFilterByRef(props.vars.value, {
type: 'ref',
name: v.id,
})
);
},
})),
{
type: 'group',
name: '',
items: [
{
type: 'action',
name: 'Add filter group',
prefix: AddCursorIcon(),
select: () => {
props.onSelect(firstFilterInGroup(props.vars.value));
},
},
],
},
],
},
});
};
2 changes: 0 additions & 2 deletions packages/affine/data-view/src/effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ import { DatabaseColumnStatsCell } from './view-presets/table/stats/column-stats
import { FilterConditionView } from './widget-presets/filter/condition.js';
import { FilterBar } from './widget-presets/filter/filter-bar.js';
import { FilterGroupView } from './widget-presets/filter/filter-group.js';
import { AdvancedFilterModal } from './widget-presets/filter/filter-modal.js';
import { FilterRootView } from './widget-presets/filter/filter-root.js';
import { DataViewHeaderToolsFilter } from './widget-presets/tools/presets/filter/filter.js';
import { DataViewHeaderToolsSearch } from './widget-presets/tools/presets/search/search.js';
Expand Down Expand Up @@ -143,7 +142,6 @@ export function effects() {
customElements.define('data-view-literal-number-view', NumberLiteral);
customElements.define('data-view-literal-string-view', StringLiteral);
customElements.define('data-view-group-setting', GroupSetting);
customElements.define('advanced-filter-modal', AdvancedFilterModal);
customElements.define('data-view-literal-tag-view', TagLiteral);
customElements.define('data-view-literal-multi-tag-view', MultiTagLiteral);
customElements.define('data-view-literal-union-string-view', UnionTagLiteral);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
popupTargetFromElement,
} from '@blocksuite/affine-components/context-menu';
import { ShadowlessElement } from '@blocksuite/block-std';
import { WithDisposable } from '@blocksuite/global/utils';
import { SignalWatcher } from '@blocksuite/global/utils';
import { CloseIcon } from '@blocksuite/icons/lit';
import { css, html, nothing } from 'lit';
import { property } from 'lit/decorators.js';
Expand All @@ -28,7 +28,7 @@ import { tBoolean } from '../../core/logical/data-type.js';
import { typesystem } from '../../core/logical/typesystem.js';
import { filterMatcher } from './matcher/matcher.js';

export class FilterConditionView extends WithDisposable(ShadowlessElement) {
export class FilterConditionView extends SignalWatcher(ShadowlessElement) {
static override styles = css`
filter-condition-view {
display: flex;
Expand Down
78 changes: 44 additions & 34 deletions packages/affine/data-view/src/widget-presets/filter/filter-bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import {
popupTargetFromElement,
} from '@blocksuite/affine-components/context-menu';
import { ShadowlessElement } from '@blocksuite/block-std';
import { WithDisposable } from '@blocksuite/global/utils';
import { SignalWatcher } from '@blocksuite/global/utils';
import { CloseIcon, FilterIcon, PlusIcon } from '@blocksuite/icons/lit';
import { computed, type ReadonlySignal } from '@preact/signals-core';
import { css, html, type TemplateResult } from 'lit';
import { property } from 'lit/decorators.js';
import { repeat } from 'lit/directives/repeat.js';
Expand All @@ -14,9 +15,9 @@ import type { Filter, FilterGroup, Variable } from '../../core/common/ast.js';

import { popCreateFilter } from '../../core/common/ref/ref.js';
import { renderTemplate } from '../../core/utils/uni-component/render-template.js';
import { popFilterRoot } from './filter-modal.js';
import { popFilterGroup } from './filter-modal.js';

export class FilterBar extends WithDisposable(ShadowlessElement) {
export class FilterBar extends SignalWatcher(ShadowlessElement) {
static override styles = css`
filter-bar {
margin-top: 8px;
Expand Down Expand Up @@ -49,9 +50,9 @@ export class FilterBar extends WithDisposable(ShadowlessElement) {
`;

private _setFilter = (index: number, filter: Filter) => {
this.setData({
...this.data,
conditions: this.data.conditions.map((v, i) =>
this.onChange({
...this.filterGroup.value,
conditions: this.filterGroup.value.conditions.map((v, i) =>
index === i ? filter : v
),
});
Expand All @@ -62,10 +63,10 @@ export class FilterBar extends WithDisposable(ShadowlessElement) {
popCreateFilter(element, {
vars: this.vars,
onSelect: filter => {
const index = this.data.conditions.length;
this.setData({
...this.data,
conditions: [...this.data.conditions, filter],
const index = this.filterGroup.value.conditions.length;
this.onChange({
...this.filterGroup.value,
conditions: [...this.filterGroup.value.conditions, filter],
});
requestAnimationFrame(() => {
this.expandGroup(element, index);
Expand All @@ -75,20 +76,20 @@ export class FilterBar extends WithDisposable(ShadowlessElement) {
};

private expandGroup = (position: PopupTarget, i: number) => {
const value = this.data.conditions[i];
if (value.type !== 'group') {
if (this.filterGroup.value.conditions[i]?.type !== 'group') {
return;
}
popFilterRoot(position, {
isRoot: false,
popFilterGroup(position, {
vars: this.vars,
value: value,
onBack: () => {
// do nothing
},
onChange: filter => this._setFilter(i, filter),
onDelete: () => {
this.deleteFilter(i);
value$: computed(() => {
return this.filterGroup.value.conditions[i] as FilterGroup;
}),
onChange: filter => {
if (filter) {
this._setFilter(i, filter);
} else {
this.deleteFilter(i);
}
},
});
};
Expand All @@ -104,7 +105,7 @@ export class FilterBar extends WithDisposable(ShadowlessElement) {
};

renderMore = (count: number) => {
const max = this.data.conditions.length;
const max = this.filterGroup.value.conditions.length;
if (count === max) {
return this.renderAddFilter();
}
Expand All @@ -126,7 +127,7 @@ export class FilterBar extends WithDisposable(ShadowlessElement) {
style="padding: 8px;background-color: var(--affine-background-overlay-panel-color);display:flex;flex-direction: column;gap: 8px;"
>
${repeat(
this.data.conditions.slice(count),
this.filterGroup.value.conditions.slice(count),
(_, i) =>
html` <div style="width: max-content;">
${this.renderCondition(i + count)}
Expand All @@ -141,7 +142,7 @@ export class FilterBar extends WithDisposable(ShadowlessElement) {
const ins = renderTemplate(() => this.renderMoreFilter(count));
ins.style.position = 'absolute';
this.updateMoreFilterPanel = () => {
const max = this.data.conditions.length;
const max = this.filterGroup.value.conditions.length;
if (count === max) {
close();
this.updateMoreFilterPanel = undefined;
Expand All @@ -163,9 +164,11 @@ export class FilterBar extends WithDisposable(ShadowlessElement) {
updateMoreFilterPanel?: () => void;

private deleteFilter(i: number) {
this.setData({
...this.data,
conditions: this.data.conditions.filter((_, index) => index !== i),
this.onChange({
...this.filterGroup.value,
conditions: this.filterGroup.value.conditions.filter(
(_, index) => index !== i
),
});
}

Expand All @@ -179,21 +182,26 @@ export class FilterBar extends WithDisposable(ShadowlessElement) {
}

renderCondition(i: number) {
const condition = this.data.conditions[i];
const condition = this.filterGroup.value.conditions[i];
const deleteFilter = () => {
this.deleteFilter(i);
};
if (!condition) {
return;
}
if (condition.type === 'filter') {
return html` <filter-condition-view
style="margin-right: 8px;"
.vars="${this.vars}"
.vars="${this.vars.value}"
.data="${condition}"
.setData="${(v: Filter) => this._setFilter(i, v)}"
.onDelete="${deleteFilter}"
></filter-condition-view>`;
}
const expandGroup = (e: MouseEvent) => {
this.expandGroup(popupTargetFromElement(e.target as HTMLElement), i);
const element = (e.currentTarget as HTMLElement)
.parentElement as HTMLElement;
this.expandGroup(popupTargetFromElement(element), i);
};
const length = condition.conditions.length;
const text = length > 1 ? `${length} rules` : `${length} rule`;
Expand All @@ -219,21 +227,23 @@ export class FilterBar extends WithDisposable(ShadowlessElement) {
}

renderFilters() {
return this.data.conditions.map((_, i) => () => this.renderCondition(i));
return this.filterGroup.value.conditions.map(
(_, i) => () => this.renderCondition(i)
);
}

override updated() {
this.updateMoreFilterPanel?.();
}

@property({ attribute: false })
accessor data!: FilterGroup;
accessor filterGroup!: ReadonlySignal<FilterGroup>;

@property({ attribute: false })
accessor setData!: (filter: FilterGroup) => void;
accessor onChange!: (filter: FilterGroup) => void;

@property({ attribute: false })
accessor vars!: Variable[];
accessor vars!: ReadonlySignal<Variable[]>;
}

declare global {
Expand Down
Loading

0 comments on commit 00d50f4

Please sign in to comment.