(core) Minimazing widgets

Summary:
A feature that allows minimizing widgets on the ViewLayout.
- Code in ViewLayout and Layout hasn't been changed. Only some methods or variables were made public, and some events are now triggered when a section is dragged.
- Widgets can be collapsed or expanded (added back to the main area)
- Collapsed widgets can be expanded and shown as a popup
- Collapsed widgets support drugging, reordering, and transferring between the main and collapsed areas.

Test Plan: New test

Reviewers: georgegevoian

Reviewed By: georgegevoian

Differential Revision: https://phab.getgrist.com/D3779
This commit is contained in:
Jarosław Sadziński
2023-02-24 12:12:55 +01:00
parent e9efac05f7
commit 59cf654190
19 changed files with 1949 additions and 259 deletions

View File

@@ -1,3 +1,4 @@
import {BoxSpec} from 'app/client/components/Layout';
import {KoArray} from 'app/client/lib/koArray';
import * as koUtil from 'app/client/lib/koUtil';
import {DocModel, IRowModel, recordSet, refRecord} from 'app/client/models/DocModel';
@@ -10,11 +11,21 @@ export interface ViewRec extends IRowModel<"_grist_Views"> {
viewSections: ko.Computed<KoArray<ViewSectionRec>>;
tabBarItem: ko.Computed<KoArray<TabBarRec>>;
layoutSpecObj: modelUtil.ObjObservable<any>;
layoutSpecObj: modelUtil.SaveableObjObservable<BoxSpec>;
// An observable for the ref of the section last selected by the user.
activeSectionId: ko.Computed<number>;
// This is active collapsed section id. Set when the widget is clicked.
activeCollapsedSectionId: ko.Observable<number>;
// Saved collapsed sections.
collapsedSections: ko.Computed<number[]>;
// Active collapsed sections, changed by the user, can be different from the
// saved collapsed sections, for a brief moment (editor is buffering changes).
activeCollapsedSections: ko.Observable<number[]>;
activeSection: ko.Computed<ViewSectionRec>;
// If the active section is removed, set the next active section to be the default.
@@ -39,6 +50,15 @@ export function createViewRec(this: ViewRec, docModel: DocModel): void {
this.activeSection = refRecord(docModel.viewSections, this.activeSectionId);
this.activeCollapsedSectionId = ko.observable(0);
this.collapsedSections = this.autoDispose(ko.pureComputed(() => {
const allSections = new Set(this.viewSections().all().map(x => x.id()));
const collapsed: number[] = (this.layoutSpecObj().collapsed || []).map(x => x.leaf as number);
return collapsed.filter(x => allSections.has(x));
}));
this.activeCollapsedSections = ko.observable(this.collapsedSections.peek());
// If the active section is removed, set the next active section to be the default.
this._isActiveSectionGone = this.autoDispose(ko.computed(() => this.activeSection()._isDeleted()));
this.autoDispose(this._isActiveSectionGone.subscribe(gone => {

View File

@@ -56,6 +56,7 @@ export interface ViewSectionRec extends IRowModel<"_grist_Views_section">, RuleO
// true if this record is its table's rawViewSection, i.e. a 'raw data view'
// in which case the UI prevents various things like hiding columns or changing the widget type.
isRaw: ko.Computed<boolean>;
isCollapsed: ko.Computed<boolean>;
borderWidthPx: ko.Computed<string>;
@@ -722,4 +723,9 @@ export function createViewSectionRec(this: ViewSectionRec, docModel: DocModel):
};
this.removeRule = (index: number) => removeRule(docModel, this, index);
this.isCollapsed = this.autoDispose(ko.pureComputed(() => {
const list = this.view().activeCollapsedSections();
return list.includes(this.id());
}));
}