2020-10-02 15:10:00 +00:00
|
|
|
import { createGroup } from "app/client/components/commands";
|
|
|
|
import { duplicatePage } from "app/client/components/duplicatePage";
|
|
|
|
import { GristDoc } from "app/client/components/GristDoc";
|
|
|
|
import { PageRec } from "app/client/models/DocModel";
|
|
|
|
import { urlState } from "app/client/models/gristUrlState";
|
|
|
|
import * as MetaTableModel from "app/client/models/MetaTableModel";
|
2021-08-27 17:25:20 +00:00
|
|
|
import { find as findInTree, fromTableData, TreeItemRecord, TreeRecord,
|
|
|
|
TreeTableData} from "app/client/models/TreeModel";
|
2020-10-02 15:10:00 +00:00
|
|
|
import { TreeViewComponent } from "app/client/ui/TreeViewComponent";
|
|
|
|
import { buildPageDom, PageActions } from "app/client/ui2018/pages";
|
|
|
|
import { mod } from 'app/common/gutil';
|
2021-08-27 17:25:20 +00:00
|
|
|
import { Computed, Disposable, dom, fromKo, observable, Observable } from "grainjs";
|
2020-10-02 15:10:00 +00:00
|
|
|
|
|
|
|
// build dom for the tree view of pages
|
|
|
|
export function buildPagesDom(owner: Disposable, activeDoc: GristDoc, isOpen: Observable<boolean>) {
|
|
|
|
const pagesTable = activeDoc.docModel.pages;
|
|
|
|
const buildDom = buildDomFromTable.bind(null, pagesTable, activeDoc);
|
|
|
|
|
2021-08-27 17:25:20 +00:00
|
|
|
const records = Computed.create<TreeRecord[]>(owner, (use) =>
|
|
|
|
use(activeDoc.docModel.visibleDocPages).map(page => ({
|
|
|
|
id: page.getRowId(),
|
|
|
|
indentation: use(page.indentation),
|
|
|
|
pagePos: use(page.pagePos),
|
|
|
|
viewRef: use(page.viewRef),
|
|
|
|
}))
|
|
|
|
);
|
|
|
|
const getTreeTableData = (): TreeTableData => ({
|
|
|
|
getRecords: () => records.get(),
|
|
|
|
sendTableActions: (...args) => pagesTable.tableData.sendTableActions(...args),
|
|
|
|
});
|
|
|
|
|
2020-10-02 15:10:00 +00:00
|
|
|
// create the model and keep in sync with the table
|
2021-08-27 17:25:20 +00:00
|
|
|
const model = observable(fromTableData(getTreeTableData(), buildDom));
|
|
|
|
owner.autoDispose(records.addListener(() => {
|
|
|
|
model.set(fromTableData(getTreeTableData(), buildDom, model.get()));
|
2020-10-02 15:10:00 +00:00
|
|
|
}));
|
|
|
|
|
|
|
|
// create a computed that reads the selected page from the url and return the corresponding item
|
|
|
|
const selected = Computed.create(owner, activeDoc.activeViewId, (use, viewId) =>
|
|
|
|
findInTree(model.get(), (i: TreeItemRecord) => i.record.viewRef === viewId) || null
|
|
|
|
);
|
|
|
|
|
|
|
|
owner.autoDispose(createGroup({
|
|
|
|
nextPage: () => selected.get() && otherPage(selected.get()!, +1),
|
|
|
|
prevPage: () => selected.get() && otherPage(selected.get()!, -1)
|
|
|
|
}, null, true));
|
|
|
|
|
|
|
|
// dom
|
|
|
|
return dom('div', dom.create(TreeViewComponent, model, {isOpen, selected, isReadonly: activeDoc.isReadonly}));
|
|
|
|
}
|
|
|
|
|
|
|
|
function buildDomFromTable(pagesTable: MetaTableModel<PageRec>, activeDoc: GristDoc, id: number) {
|
2022-04-27 17:46:24 +00:00
|
|
|
const {isReadonly} = activeDoc;
|
2020-10-02 15:10:00 +00:00
|
|
|
const pageName = pagesTable.rowModels[id].view.peek().name;
|
|
|
|
const viewId = pagesTable.rowModels[id].view.peek().id.peek();
|
|
|
|
const docData = pagesTable.tableData.docData;
|
|
|
|
const actions: PageActions = {
|
|
|
|
onRename: (newName: string) => newName.length && pageName.saveOnly(newName),
|
|
|
|
onRemove: () => docData.sendAction(['RemoveRecord', '_grist_Views', viewId]),
|
|
|
|
// TODO: duplicate should prompt user for confirmation
|
|
|
|
onDuplicate: () => duplicatePage(activeDoc, id),
|
2022-04-27 17:46:24 +00:00
|
|
|
// Can't remove last visible page
|
|
|
|
isRemoveDisabled: () => activeDoc.docModel.visibleDocPages.peek().length <= 1,
|
2020-10-02 15:10:00 +00:00
|
|
|
isReadonly
|
|
|
|
};
|
|
|
|
|
2021-08-27 17:25:20 +00:00
|
|
|
return buildPageDom(fromKo(pageName), actions, urlState().setLinkUrl({docPage: viewId}));
|
2020-10-02 15:10:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Select another page in cyclic ordering of pages. Order is downard if given a positive `delta`,
|
|
|
|
// upward otherwise.
|
|
|
|
function otherPage(currentPage: TreeItemRecord, delta: number) {
|
|
|
|
const records = currentPage.storage.records;
|
|
|
|
const index = mod(currentPage.index + delta, records.length);
|
|
|
|
const docPage = records[index].viewRef;
|
|
|
|
return urlState().pushUrl({docPage});
|
|
|
|
}
|