mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Revealing hidden pages with visible children.
Summary: When a page is hidden, all its nested pages are shown as children of a different page that happens to be before (as in pagePos) that page. This diff shows those pages as CENSORED. Test Plan: Updated Reviewers: alexmojaki Reviewed By: alexmojaki Subscribers: alexmojaki Differential Revision: https://phab.getgrist.com/D3670
This commit is contained in:
@@ -13,6 +13,7 @@ import {KoArray} from 'app/client/lib/koArray';
|
||||
import {KoSaveableObservable} from 'app/client/models/modelUtil';
|
||||
|
||||
import * as ko from 'knockout';
|
||||
import memoize from 'lodash/memoize';
|
||||
|
||||
import * as koArray from 'app/client/lib/koArray';
|
||||
import * as koUtil from 'app/client/lib/koUtil';
|
||||
@@ -142,6 +143,8 @@ export class DocModel {
|
||||
|
||||
public allTabs: KoArray<TabBarRec> = this.tabBar.createAllRowsModel('tabPos');
|
||||
|
||||
/** Pages that are shown in the menu. These can include censored pages if they have children. */
|
||||
public menuPages: ko.Computed<PageRec[]>;
|
||||
// Excludes pages hidden by ACL rules or other reasons (e.g. doc-tour)
|
||||
public visibleDocPages: ko.Computed<PageRec[]>;
|
||||
|
||||
@@ -189,6 +192,19 @@ export class DocModel {
|
||||
|
||||
// Get a list of only the visible pages.
|
||||
const allPages = this.pages.createAllRowsModel('pagePos');
|
||||
this.menuPages = ko.computed(() => {
|
||||
const pagesToShow = allPages.all().filter(p => !p.isSpecial()).sort((a, b) => a.pagePos() - b.pagePos());
|
||||
// Helper to find all children of a page.
|
||||
const children = memoize((page: PageRec) => {
|
||||
const following = pagesToShow.slice(pagesToShow.indexOf(page) + 1);
|
||||
const firstOutside = following.findIndex(p => p.indentation() <= page.indentation());
|
||||
return firstOutside >= 0 ? following.slice(0, firstOutside) : following;
|
||||
});
|
||||
// Helper to test if the page is hidden and all its children are hidden.
|
||||
// In that case, we won't show it at all.
|
||||
const hide = memoize((page: PageRec): boolean => page.isCensored() && children(page).every(p => hide(p)));
|
||||
return pagesToShow.filter(p => !hide(p));
|
||||
});
|
||||
this.visibleDocPages = ko.computed(() => allPages.all().filter(p => !p.isHidden()));
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import reverse = require("lodash/reverse");
|
||||
* `TreeModel` and any item in it implements `TreeItem`.
|
||||
*/
|
||||
export interface TreeNode {
|
||||
hidden?: boolean;
|
||||
// Returns an observable array of children. Or null if the node does not accept children.
|
||||
children(): ObsArray<TreeItem>|null;
|
||||
|
||||
@@ -61,7 +62,7 @@ export interface TreeTableData {
|
||||
}
|
||||
|
||||
// describes a function that builds dom for a particular record
|
||||
type DomBuilder = (id: number) => HTMLElement;
|
||||
type DomBuilder = (id: number, hidden: boolean) => HTMLElement;
|
||||
|
||||
|
||||
// Returns a list of the records from table that is suitable to build the tree model, ie: records
|
||||
@@ -108,8 +109,9 @@ export function fromTableData(table: TreeTableData, buildDom: DomBuilder, oldMod
|
||||
const children = indentations[rec.indentation + 1] || [];
|
||||
delete indentations[rec.indentation + 1];
|
||||
const item = oldItems[rec.id] || new TreeItemRecord();
|
||||
item.hidden = rec.hidden;
|
||||
item.init(storage, index, reverse(children));
|
||||
item.buildDom = () => buildDom(rec.id);
|
||||
item.buildDom = () => buildDom(rec.id, rec.hidden);
|
||||
siblings.push(item);
|
||||
});
|
||||
return new TreeModelRecord(storage, reverse(indentations[0] || []));
|
||||
@@ -123,7 +125,7 @@ interface Storage {
|
||||
|
||||
// TreeNode implementation that uses a grist table.
|
||||
export class TreeNodeRecord implements TreeNode {
|
||||
|
||||
public hidden: boolean = false;
|
||||
public storage: Storage;
|
||||
public index: number|"root";
|
||||
public children: () => ObsArray<TreeItemRecord>;
|
||||
@@ -187,6 +189,7 @@ export class TreeNodeRecord implements TreeNode {
|
||||
forEach(update[0], (val, key) => values[key] = update.map(rec => rec[key]));
|
||||
const rowIds = values.id;
|
||||
delete values.id;
|
||||
delete values.hidden;
|
||||
userActions.push(["BulkUpdateRecord", rowIds, values]);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,20 @@ import * as ko from 'knockout';
|
||||
export interface PageRec extends IRowModel<"_grist_Pages"> {
|
||||
view: ko.Computed<ViewRec>;
|
||||
isHidden: ko.Computed<boolean>;
|
||||
isCensored: ko.Computed<boolean>;
|
||||
isSpecial: ko.Computed<boolean>;
|
||||
}
|
||||
|
||||
export function createPageRec(this: PageRec, docModel: DocModel): void {
|
||||
this.view = refRecord(docModel.views, this.viewRef);
|
||||
this.isHidden = ko.pureComputed(() => {
|
||||
// Page is hidden when any of this is true:
|
||||
// - It has an empty name (or no name at all)
|
||||
// - It is GristDocTour (unless user wants to see it)
|
||||
// - It is a page generated for a hidden table TODO: Follow up - don't create
|
||||
// pages for hidden tables.
|
||||
// This is used currently only the left panel, to hide pages from the user.
|
||||
this.isCensored = ko.pureComputed(() => !this.view().name());
|
||||
this.isSpecial = ko.pureComputed(() => {
|
||||
const name = this.view().name();
|
||||
const isTableHidden = () => {
|
||||
const viewId = this.view().id();
|
||||
@@ -17,12 +26,9 @@ export function createPageRec(this: PageRec, docModel: DocModel): void {
|
||||
const primaryTable = tables.find(t => t.primaryViewId() === viewId);
|
||||
return !!primaryTable && primaryTable.tableId()?.startsWith("GristHidden_");
|
||||
};
|
||||
// Page is hidden when any of this is true:
|
||||
// - It has an empty name (or no name at all)
|
||||
// - It is GristDocTour (unless user wants to see it)
|
||||
// - It is a page generated for a hidden table TODO: Follow up - don't create
|
||||
// pages for hidden tables.
|
||||
// This is used currently only the left panel, to hide pages from the user.
|
||||
return !name || (name === 'GristDocTour' && !docModel.showDocTourTable) || isTableHidden();
|
||||
return (name === 'GristDocTour' && !docModel.showDocTourTable) || isTableHidden();
|
||||
});
|
||||
this.isHidden = ko.pureComputed(() => {
|
||||
return this.isCensored() || this.isSpecial();
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user