mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-24 05:07:06 +08:00
feat(editor): add collapse/expand toggle for groups with caching (#12671)
https://github.com/user-attachments/assets/4ef71704-57bb-45b8-9e73-8a51c67fb158 Adds a collapsible toggle for group-by groups. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Collapsible groups for desktop and mobile table views with persistent per-view collapsed state and a keyboard-accessible toggle button. - **Bug Fixes** - Group title icons now render consistently across variants. - **Tests** - Added unit tests verifying collapse/expand behavior for group components. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: 3720 <zuozijian1994@gmail.com> Co-authored-by: L-Sun <zover.v@gmail.com>
This commit is contained in:
@@ -0,0 +1,36 @@
|
|||||||
|
import { describe, expect, test } from 'vitest';
|
||||||
|
|
||||||
|
import { mobileEffects } from '../view-presets/table/mobile/effect.js';
|
||||||
|
import type { MobileTableGroup } from '../view-presets/table/mobile/group.js';
|
||||||
|
import { pcEffects } from '../view-presets/table/pc/effect.js';
|
||||||
|
import type { TableGroup } from '../view-presets/table/pc/group.js';
|
||||||
|
|
||||||
|
/** @vitest-environment happy-dom */
|
||||||
|
|
||||||
|
describe('TableGroup', () => {
|
||||||
|
test('toggle collapse on pc', () => {
|
||||||
|
pcEffects();
|
||||||
|
const group = document.createElement(
|
||||||
|
'affine-data-view-table-group'
|
||||||
|
) as TableGroup;
|
||||||
|
|
||||||
|
expect(group.collapsed$.value).toBe(false);
|
||||||
|
(group as any)._toggleCollapse();
|
||||||
|
expect(group.collapsed$.value).toBe(true);
|
||||||
|
(group as any)._toggleCollapse();
|
||||||
|
expect(group.collapsed$.value).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('toggle collapse on mobile', () => {
|
||||||
|
mobileEffects();
|
||||||
|
const group = document.createElement(
|
||||||
|
'mobile-table-group'
|
||||||
|
) as MobileTableGroup;
|
||||||
|
|
||||||
|
expect(group.collapsed$.value).toBe(false);
|
||||||
|
(group as any)._toggleCollapse();
|
||||||
|
expect(group.collapsed$.value).toBe(true);
|
||||||
|
(group as any)._toggleCollapse();
|
||||||
|
expect(group.collapsed$.value).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -26,13 +26,10 @@ const GroupTitleMobile = (
|
|||||||
const type = groupData.tType;
|
const type = groupData.tType;
|
||||||
if (!type) return nothing;
|
if (!type) return nothing;
|
||||||
|
|
||||||
const icon =
|
const icon = html` <uni-lit
|
||||||
groupData.value == null
|
class="group-header-icon"
|
||||||
? ''
|
.uni="${groupData.property.icon}"
|
||||||
: html` <uni-lit
|
></uni-lit>`;
|
||||||
class="group-header-icon"
|
|
||||||
.uni="${groupData.property.icon}"
|
|
||||||
></uni-lit>`;
|
|
||||||
const props: GroupRenderProps = {
|
const props: GroupRenderProps = {
|
||||||
group: groupData,
|
group: groupData,
|
||||||
readonly: ops.readonly,
|
readonly: ops.readonly,
|
||||||
@@ -126,13 +123,10 @@ export const GroupTitle = (
|
|||||||
const type = groupData.tType;
|
const type = groupData.tType;
|
||||||
if (!type) return nothing;
|
if (!type) return nothing;
|
||||||
|
|
||||||
const icon =
|
const icon = html` <uni-lit
|
||||||
groupData.value == null
|
class="group-header-icon"
|
||||||
? ''
|
.uni="${groupData.property.icon}"
|
||||||
: html` <uni-lit
|
></uni-lit>`;
|
||||||
class="group-header-icon"
|
|
||||||
.uni="${groupData.property.icon}"
|
|
||||||
></uni-lit>`;
|
|
||||||
const props: GroupRenderProps = {
|
const props: GroupRenderProps = {
|
||||||
group: groupData,
|
group: groupData,
|
||||||
readonly: ops.readonly,
|
readonly: ops.readonly,
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Shared utility for managing table group collapsed state in sessionStorage.
|
||||||
|
* Used by both PC and mobile table group implementations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the collapsed state for a specific table group from sessionStorage.
|
||||||
|
* @param viewId - The ID of the table view
|
||||||
|
* @param groupKey - The key of the group
|
||||||
|
* @returns The collapsed state as a boolean, or false if not found or invalid
|
||||||
|
*/
|
||||||
|
export function getCollapsedState(viewId: string, groupKey: string): boolean {
|
||||||
|
try {
|
||||||
|
const value = sessionStorage.getItem(
|
||||||
|
`affine:table-group:${viewId}:${groupKey}:collapsed`
|
||||||
|
);
|
||||||
|
if (!value) return false;
|
||||||
|
const parsed = JSON.parse(value);
|
||||||
|
return typeof parsed === 'boolean' ? parsed : false;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the collapsed state for a specific table group in sessionStorage.
|
||||||
|
* @param viewId - The ID of the table view
|
||||||
|
* @param groupKey - The key of the group
|
||||||
|
* @param collapsed - The collapsed state to store
|
||||||
|
*/
|
||||||
|
export function setCollapsedState(
|
||||||
|
viewId: string,
|
||||||
|
groupKey: string,
|
||||||
|
collapsed: boolean
|
||||||
|
): void {
|
||||||
|
try {
|
||||||
|
sessionStorage.setItem(
|
||||||
|
`affine:table-group:${viewId}:${groupKey}:collapsed`,
|
||||||
|
JSON.stringify(collapsed)
|
||||||
|
);
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,16 +4,22 @@ import {
|
|||||||
popupTargetFromElement,
|
popupTargetFromElement,
|
||||||
} from '@blocksuite/affine-components/context-menu';
|
} from '@blocksuite/affine-components/context-menu';
|
||||||
import { SignalWatcher, WithDisposable } from '@blocksuite/global/lit';
|
import { SignalWatcher, WithDisposable } from '@blocksuite/global/lit';
|
||||||
import { PlusIcon } from '@blocksuite/icons/lit';
|
import {
|
||||||
|
PlusIcon,
|
||||||
|
ToggleDownIcon,
|
||||||
|
ToggleRightIcon,
|
||||||
|
} from '@blocksuite/icons/lit';
|
||||||
import { ShadowlessElement } from '@blocksuite/std';
|
import { ShadowlessElement } from '@blocksuite/std';
|
||||||
|
import { signal } from '@preact/signals-core';
|
||||||
import { cssVarV2 } from '@toeverything/theme/v2';
|
import { cssVarV2 } from '@toeverything/theme/v2';
|
||||||
import { css, html, unsafeCSS } from 'lit';
|
import { css, html, nothing, unsafeCSS } from 'lit';
|
||||||
import { property } from 'lit/decorators.js';
|
import { property } from 'lit/decorators.js';
|
||||||
import { repeat } from 'lit/directives/repeat.js';
|
import { repeat } from 'lit/directives/repeat.js';
|
||||||
|
|
||||||
import { GroupTitle } from '../../../core/group-by/group-title.js';
|
import { GroupTitle } from '../../../core/group-by/group-title.js';
|
||||||
import type { Group } from '../../../core/group-by/trait.js';
|
import type { Group } from '../../../core/group-by/trait.js';
|
||||||
import type { Row } from '../../../core/index.js';
|
import type { Row } from '../../../core/index.js';
|
||||||
|
import { getCollapsedState, setCollapsedState } from '../collapsed-state.js';
|
||||||
import { LEFT_TOOL_BAR_WIDTH } from '../consts.js';
|
import { LEFT_TOOL_BAR_WIDTH } from '../consts.js';
|
||||||
import type { MobileTableViewUILogic } from './table-view-ui-logic.js';
|
import type { MobileTableViewUILogic } from './table-view-ui-logic.js';
|
||||||
|
|
||||||
@@ -42,6 +48,28 @@ const styles = css`
|
|||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
color: var(--affine-text-secondary-color);
|
color: var(--affine-text-secondary-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.group-toggle-btn {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 150ms cubic-bezier(0.42, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-toggle-btn:hover {
|
||||||
|
background: var(--affine-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-toggle-btn svg {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export class MobileTableGroup extends SignalWatcher(
|
export class MobileTableGroup extends SignalWatcher(
|
||||||
@@ -49,6 +77,29 @@ export class MobileTableGroup extends SignalWatcher(
|
|||||||
) {
|
) {
|
||||||
static override styles = styles;
|
static override styles = styles;
|
||||||
|
|
||||||
|
collapsed$ = signal(false);
|
||||||
|
|
||||||
|
private storageLoaded = false;
|
||||||
|
|
||||||
|
private _loadCollapsedState() {
|
||||||
|
if (this.storageLoaded) return;
|
||||||
|
this.storageLoaded = true;
|
||||||
|
const view = this.tableViewLogic?.view;
|
||||||
|
if (!view) return;
|
||||||
|
const value = getCollapsedState(view.id, this.group?.key ?? 'all');
|
||||||
|
this.collapsed$.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly _toggleCollapse = (e?: MouseEvent) => {
|
||||||
|
e?.stopPropagation();
|
||||||
|
const next = !this.collapsed$.value;
|
||||||
|
this.collapsed$.value = next;
|
||||||
|
const view = this.tableViewLogic?.view;
|
||||||
|
if (view) {
|
||||||
|
setCollapsedState(view.id, this.group?.key ?? 'all', next);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private readonly clickAddRow = () => {
|
private readonly clickAddRow = () => {
|
||||||
this.view.rowAdd('end', this.group?.key);
|
this.view.rowAdd('end', this.group?.key);
|
||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
@@ -93,6 +144,27 @@ export class MobileTableGroup extends SignalWatcher(
|
|||||||
<div
|
<div
|
||||||
style="position: sticky;left: 0;width: max-content;padding: 6px 0;margin-bottom: 4px;display:flex;align-items:center;gap: 12px;max-width: 400px"
|
style="position: sticky;left: 0;width: max-content;padding: 6px 0;margin-bottom: 4px;display:flex;align-items:center;gap: 12px;max-width: 400px"
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
class=${`group-toggle-btn ${this.collapsed$.value ? '' : 'expanded'}`}
|
||||||
|
role="button"
|
||||||
|
aria-expanded=${this.collapsed$.value ? 'false' : 'true'}
|
||||||
|
aria-label=${this.collapsed$.value
|
||||||
|
? 'Expand group'
|
||||||
|
: 'Collapse group'}
|
||||||
|
tabindex="0"
|
||||||
|
@click=${this._toggleCollapse}
|
||||||
|
@keydown=${(e: KeyboardEvent) => {
|
||||||
|
if (e.key === 'Enter' || e.key === ' ') {
|
||||||
|
e.preventDefault();
|
||||||
|
this._toggleCollapse();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
${this.collapsed$.value
|
||||||
|
? ToggleRightIcon({ width: '16px', height: '16px' })
|
||||||
|
: ToggleDownIcon({ width: '16px', height: '16px' })}
|
||||||
|
</div>
|
||||||
|
|
||||||
${GroupTitle(this.group, {
|
${GroupTitle(this.group, {
|
||||||
readonly: this.view.readonly$.value,
|
readonly: this.view.readonly$.value,
|
||||||
clickAdd: this.clickAddRowInStart,
|
clickAdd: this.clickAddRowInStart,
|
||||||
@@ -109,7 +181,6 @@ export class MobileTableGroup extends SignalWatcher(
|
|||||||
private renderRows(rows: Row[]) {
|
private renderRows(rows: Row[]) {
|
||||||
return html`
|
return html`
|
||||||
<mobile-table-header
|
<mobile-table-header
|
||||||
.renderGroupHeader="${this.renderGroupHeader}"
|
|
||||||
.tableViewManager="${this.view}"
|
.tableViewManager="${this.view}"
|
||||||
></mobile-table-header>
|
></mobile-table-header>
|
||||||
<div class="mobile-affine-table-body">
|
<div class="mobile-affine-table-body">
|
||||||
@@ -144,8 +215,26 @@ export class MobileTableGroup extends SignalWatcher(
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override willUpdate(changed: Map<PropertyKey, unknown>): void {
|
||||||
|
super.willUpdate(changed);
|
||||||
|
if (
|
||||||
|
!this.storageLoaded &&
|
||||||
|
(changed.has('group') || changed.has('tableViewLogic'))
|
||||||
|
) {
|
||||||
|
this._loadCollapsedState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override connectedCallback(): void {
|
||||||
|
super.connectedCallback();
|
||||||
|
this._loadCollapsedState();
|
||||||
|
}
|
||||||
|
|
||||||
override render() {
|
override render() {
|
||||||
return this.renderRows(this.rows);
|
return html`
|
||||||
|
${this.collapsed$.value ? this.renderGroupHeader() : nothing}
|
||||||
|
${this.collapsed$.value ? nothing : this.renderRows(this.rows)}
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
|
|||||||
@@ -4,11 +4,15 @@ import {
|
|||||||
popupTargetFromElement,
|
popupTargetFromElement,
|
||||||
} from '@blocksuite/affine-components/context-menu';
|
} from '@blocksuite/affine-components/context-menu';
|
||||||
import { SignalWatcher, WithDisposable } from '@blocksuite/global/lit';
|
import { SignalWatcher, WithDisposable } from '@blocksuite/global/lit';
|
||||||
import { PlusIcon } from '@blocksuite/icons/lit';
|
import {
|
||||||
|
PlusIcon,
|
||||||
|
ToggleDownIcon,
|
||||||
|
ToggleRightIcon,
|
||||||
|
} from '@blocksuite/icons/lit';
|
||||||
import { ShadowlessElement } from '@blocksuite/std';
|
import { ShadowlessElement } from '@blocksuite/std';
|
||||||
import { effect } from '@preact/signals-core';
|
import { effect, signal } from '@preact/signals-core';
|
||||||
import { cssVarV2 } from '@toeverything/theme/v2';
|
import { cssVarV2 } from '@toeverything/theme/v2';
|
||||||
import { css, html, unsafeCSS } from 'lit';
|
import { css, html, nothing, unsafeCSS } from 'lit';
|
||||||
import { property, query } from 'lit/decorators.js';
|
import { property, query } from 'lit/decorators.js';
|
||||||
import { repeat } from 'lit/directives/repeat.js';
|
import { repeat } from 'lit/directives/repeat.js';
|
||||||
|
|
||||||
@@ -18,6 +22,7 @@ import type { Row } from '../../../core/index.js';
|
|||||||
import { createDndContext } from '../../../core/utils/wc-dnd/dnd-context.js';
|
import { createDndContext } from '../../../core/utils/wc-dnd/dnd-context.js';
|
||||||
import { defaultActivators } from '../../../core/utils/wc-dnd/sensors/index.js';
|
import { defaultActivators } from '../../../core/utils/wc-dnd/sensors/index.js';
|
||||||
import { linearMove } from '../../../core/utils/wc-dnd/utils/linear-move.js';
|
import { linearMove } from '../../../core/utils/wc-dnd/utils/linear-move.js';
|
||||||
|
import { getCollapsedState, setCollapsedState } from '../collapsed-state.js';
|
||||||
import { LEFT_TOOL_BAR_WIDTH } from '../consts.js';
|
import { LEFT_TOOL_BAR_WIDTH } from '../consts.js';
|
||||||
import { TableViewAreaSelection } from '../selection';
|
import { TableViewAreaSelection } from '../selection';
|
||||||
import { DataViewColumnPreview } from './header/column-renderer.js';
|
import { DataViewColumnPreview } from './header/column-renderer.js';
|
||||||
@@ -30,6 +35,12 @@ const styles = css`
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
affine-data-view-table-group {
|
||||||
|
margin-top: 4px;
|
||||||
|
padding-top: 4px;
|
||||||
|
border-top: 1px solid var(--affine-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
.data-view-table-group-add-row {
|
.data-view-table-group-add-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -42,6 +53,10 @@ const styles = css`
|
|||||||
border-bottom: 1px solid ${unsafeCSS(cssVarV2.layer.insideBorder.border)};
|
border-bottom: 1px solid ${unsafeCSS(cssVarV2.layer.insideBorder.border)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.affine-data-view-table-group:hover svg {
|
||||||
|
fill: var(--affine-icon-color);
|
||||||
|
}
|
||||||
|
|
||||||
@media print {
|
@media print {
|
||||||
.data-view-table-group-add-row {
|
.data-view-table-group-add-row {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -60,6 +75,28 @@ const styles = css`
|
|||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
color: var(--affine-text-secondary-color);
|
color: var(--affine-text-secondary-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.group-toggle-btn {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 150ms cubic-bezier(0.42, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-toggle-btn:hover {
|
||||||
|
background: var(--affine-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-toggle-btn svg {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export class TableGroup extends SignalWatcher(
|
export class TableGroup extends SignalWatcher(
|
||||||
@@ -67,6 +104,29 @@ export class TableGroup extends SignalWatcher(
|
|||||||
) {
|
) {
|
||||||
static override styles = styles;
|
static override styles = styles;
|
||||||
|
|
||||||
|
collapsed$ = signal(false);
|
||||||
|
|
||||||
|
private storageLoaded = false;
|
||||||
|
|
||||||
|
private _loadCollapsedState() {
|
||||||
|
if (this.storageLoaded) return;
|
||||||
|
this.storageLoaded = true;
|
||||||
|
const view = this.tableViewLogic?.view;
|
||||||
|
if (!view) return;
|
||||||
|
const value = getCollapsedState(view.id, this.group?.key ?? 'all');
|
||||||
|
this.collapsed$.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly _toggleCollapse = (e?: MouseEvent) => {
|
||||||
|
e?.stopPropagation();
|
||||||
|
const next = !this.collapsed$.value;
|
||||||
|
this.collapsed$.value = next;
|
||||||
|
const view = this.tableViewLogic?.view;
|
||||||
|
if (view) {
|
||||||
|
setCollapsedState(view.id, this.group?.key ?? 'all', next);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private readonly clickAddRow = () => {
|
private readonly clickAddRow = () => {
|
||||||
this.view.rowAdd('end', this.group?.key);
|
this.view.rowAdd('end', this.group?.key);
|
||||||
const selectionController = this.tableViewLogic.selectionController;
|
const selectionController = this.tableViewLogic.selectionController;
|
||||||
@@ -137,10 +197,32 @@ export class TableGroup extends SignalWatcher(
|
|||||||
if (!this.group) {
|
if (!this.group) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div
|
<div
|
||||||
style="position: sticky;left: 0;width: max-content;padding: 6px 0;margin-bottom: 4px;display:flex;align-items:center;gap: 12px;max-width: 400px"
|
style="position: sticky;left: 0;width: max-content;padding: 6px 0;margin-bottom: 4px;display:flex;align-items:center;gap: 8px;max-width: 400px"
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
class=${`group-toggle-btn ${this.collapsed$.value ? '' : 'expanded'}`}
|
||||||
|
role="button"
|
||||||
|
aria-expanded=${this.collapsed$.value ? 'false' : 'true'}
|
||||||
|
aria-label=${this.collapsed$.value
|
||||||
|
? 'Expand group'
|
||||||
|
: 'Collapse group'}
|
||||||
|
tabindex="0"
|
||||||
|
@click=${this._toggleCollapse}
|
||||||
|
@keydown=${(e: KeyboardEvent) => {
|
||||||
|
if (e.key === 'Enter' || e.key === ' ') {
|
||||||
|
e.preventDefault();
|
||||||
|
this._toggleCollapse();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
${this.collapsed$.value
|
||||||
|
? ToggleRightIcon({ width: '16px', height: '16px' })
|
||||||
|
: ToggleDownIcon({ width: '16px', height: '16px' })}
|
||||||
|
</div>
|
||||||
|
|
||||||
${GroupTitle(this.group, {
|
${GroupTitle(this.group, {
|
||||||
readonly: this.view.readonly$.value,
|
readonly: this.view.readonly$.value,
|
||||||
clickAdd: this.clickAddRowInStart,
|
clickAdd: this.clickAddRowInStart,
|
||||||
@@ -244,8 +326,8 @@ export class TableGroup extends SignalWatcher(
|
|||||||
private renderRows(rows: Row[]) {
|
private renderRows(rows: Row[]) {
|
||||||
return html`
|
return html`
|
||||||
<affine-database-column-header
|
<affine-database-column-header
|
||||||
.renderGroupHeader="${this.renderGroupHeader}"
|
.renderGroupHeader=${this.renderGroupHeader}
|
||||||
.tableViewLogic="${this.tableViewLogic}"
|
.tableViewLogic=${this.tableViewLogic}
|
||||||
></affine-database-column-header>
|
></affine-database-column-header>
|
||||||
<div class="affine-database-block-rows">
|
<div class="affine-database-block-rows">
|
||||||
${repeat(
|
${repeat(
|
||||||
@@ -284,13 +366,27 @@ export class TableGroup extends SignalWatcher(
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override willUpdate(changed: Map<PropertyKey, unknown>): void {
|
||||||
|
super.willUpdate(changed);
|
||||||
|
if (
|
||||||
|
!this.storageLoaded &&
|
||||||
|
(changed.has('group') || changed.has('tableViewLogic'))
|
||||||
|
) {
|
||||||
|
this._loadCollapsedState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override connectedCallback(): void {
|
override connectedCallback(): void {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
|
this._loadCollapsedState();
|
||||||
this.showIndicator();
|
this.showIndicator();
|
||||||
}
|
}
|
||||||
|
|
||||||
override render() {
|
override render() {
|
||||||
return this.renderRows(this.rows);
|
return html`
|
||||||
|
${this.collapsed$.value ? this.renderGroupHeader() : nothing}
|
||||||
|
${this.collapsed$.value ? nothing : this.renderRows(this.rows)}
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@query('.affine-database-block-rows')
|
@query('.affine-database-block-rows')
|
||||||
|
|||||||
Reference in New Issue
Block a user