diff options
author | usodhi <61431818+usodhi@users.noreply.github.com> | 2021-02-20 20:26:36 -0500 |
---|---|---|
committer | usodhi <61431818+usodhi@users.noreply.github.com> | 2021-02-20 20:26:36 -0500 |
commit | eff29ee31afdaf683fbd33d84833872c027c8a6c (patch) | |
tree | 23eade31af8ad70b8466cbce83769fde76900471 /src | |
parent | c2bcb4ac83ecafb0bf23f72ed1bc2d05b877da6d (diff) | |
parent | a2abfb07b783769094414c39e300b88c31cfc450 (diff) |
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into filters
Diffstat (limited to 'src')
-rw-r--r-- | src/client/documents/Documents.ts | 11 | ||||
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 23 | ||||
-rw-r--r-- | src/client/util/LinkManager.ts | 16 | ||||
-rw-r--r-- | src/client/views/LightboxView.tsx | 23 | ||||
-rw-r--r-- | src/client/views/collections/CollectionSubView.tsx | 44 | ||||
-rw-r--r-- | src/client/views/collections/CollectionTreeView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/TreeView.tsx | 8 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/search/SearchBox.tsx | 4 |
9 files changed, 90 insertions, 45 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d1a77f2ec..1a51f7a4b 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -937,6 +937,9 @@ export namespace DocUtils { } export function FilterDocs(docs: Doc[], docFilters: string[], docRangeFilters: string[], viewSpecScript?: ScriptField) { const childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs; + if (!docFilters?.length && !docRangeFilters?.length) { + return childDocs.filter(d => !d.cookies); // remove documents that need a cookie if there are no filters to provide one + } const filterFacets: { [key: string]: { [value: string]: string } } = {}; // maps each filter key to an object with value=>modifier fields docFilters.forEach(filter => { @@ -952,9 +955,13 @@ export namespace DocUtils { const filteredDocs = docFilters.length ? childDocs.filter(d => { if (d.z) return true; - for (const facetKey of Object.keys(filterFacets)) { + // if the document needs a cookie but no filter provides the cookie, then the document does not pass the filter + if (d["cookies"] && (!filterFacets["cookies"] || !Object.keys(filterFacets["cookies"]).some(key => d["cookies"] === key))) { + return false; + } + for (const facetKey of Object.keys(filterFacets).filter(fkey => fkey !== "cookies")) { const facet = filterFacets[facetKey]; - const matches = Object.keys(facet).filter(value => facet[value] === "match"); + const matches = Object.keys(facet).filter(value => value !== "cookies" && facet[value] === "match"); const checks = Object.keys(facet).filter(value => facet[value] === "check"); const xs = Object.keys(facet).filter(value => facet[value] === "x"); const failsNotEqualFacets = !xs.length ? false : xs.some(value => Doc.matchFieldValue(d, facetKey, value)); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 2cba99355..ae22320f3 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -524,7 +524,7 @@ export class CurrentUserUtils { { title: "Tools", target: Cast(doc.myTools, Doc, null), icon: "wrench", click: 'selectMainMenu(self)' }, // { title: "Filter", target: Cast(doc.currentFilter, Doc, null), icon: "filter", click: 'selectMainMenu(self)' }, { title: "Pres. Trails", target: Cast(doc.myPresentations, Doc, null), icon: "pres-trail", click: 'selectMainMenu(self)' }, - { title: "Catalog", target: undefined as any, icon: "file", click: 'selectMainMenu(self)' }, + { title: "My Files", target: Cast(doc.myFilesystem, Doc, null), icon: "file", click: 'selectMainMenu(self)' }, { title: "Help", target: undefined as any, icon: "question-circle", click: 'selectMainMenu(self)' }, { title: "Settings", target: undefined as any, icon: "cog", click: 'selectMainMenu(self)' }, { title: "User Doc", target: Cast(doc.myUserDoc, Doc, null), icon: "address-card", click: 'selectMainMenu(self)' }, @@ -580,6 +580,10 @@ export class CurrentUserUtils { btn.color = "white"; btn._backgroundColor = ""; btn.dontUndo = true; + if (btn.title === "Catalog" || btn.title === "My Files") { // migration from Catalog to My Files + btn.target = Doc.UserDoc().myFilesystem; + btn.title = "My Files"; + } })); }); }); @@ -772,6 +776,22 @@ export class CurrentUserUtils { return doc.myPresentations as any as Doc; } + static async setupFilesystem(doc: Doc) { + await doc.myFilesystem; + if (doc.myFilesystem === undefined) { + doc.myFileOrphans = Docs.Create.TreeDocument([], { title: "file orphans", _stayInCollection: true, system: true, isFolder: true }); + doc.myFileRoot = Docs.Create.TreeDocument([], { title: "file root", _stayInCollection: true, system: true, isFolder: true }); + doc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([doc.myFileRoot as Doc, doc.myFileOrphans as Doc], { + title: "My Documents", _height: 100, + treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", + treeViewTruncateTitleWidth: 150, treeViewPreventOpen: false, ignoreClick: true, + isFolder: true, treeViewType: "fileSystem", + lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true + })); + } + return doc.myFilesystem as any as Doc; + } + static setupRecentlyClosedDocs(doc: Doc) { // setup Recently Closed library item doc.myRecentlyClosedDocs === undefined; @@ -831,6 +851,7 @@ export class CurrentUserUtils { await CurrentUserUtils.setupToolsBtnPanel(doc); CurrentUserUtils.setupDashboards(doc); CurrentUserUtils.setupPresentations(doc); + CurrentUserUtils.setupFilesystem(doc); CurrentUserUtils.setupRecentlyClosedDocs(doc); // CurrentUserUtils.setupFilterDocs(doc); CurrentUserUtils.setupUserDoc(doc); diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 402cbdd68..0512864df 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -149,10 +149,18 @@ export class LinkManager { const target = (sourceDoc === linkDoc.anchor1 ? linkDoc.anchor2 : sourceDoc === linkDoc.anchor2 ? linkDoc.anchor1 : (Doc.AreProtosEqual(sourceDoc, linkDoc.anchor1 as Doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, sourceDoc) ? linkDoc.anchor2 : linkDoc.anchor1)) as Doc; if (target) { - const containerDoc = Cast(target.annotationOn, Doc, null) || target; - const targetContext = Cast(containerDoc?.context, Doc, null); - const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined; - DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "add:right"), finished), targetNavContext, linkDoc, undefined, sourceDoc, finished); + if (target.TourMap) { + const fieldKey = Doc.LayoutFieldKey(target); + const tour = DocListCast(target[fieldKey]).reverse(); + LightboxView.SetLightboxDoc(currentContext, undefined, tour); + setTimeout(LightboxView.Next); + finished?.(); + } else { + const containerDoc = Cast(target.annotationOn, Doc, null) || target; + const targetContext = Cast(containerDoc?.context, Doc, null); + const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined; + DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "add:right"), finished), targetNavContext, linkDoc, undefined, sourceDoc, finished); + } } else { finished?.(); } diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index af07ead97..5e810d335 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -24,6 +24,7 @@ interface LightboxViewProps { @observer export class LightboxView extends React.Component<LightboxViewProps> { + @computed public static get LightboxDoc() { return this._doc; } @observable private static _doc: Opt<Doc>; @observable private static _docTarget: Opt<Doc>; @@ -45,6 +46,7 @@ export class LightboxView extends React.Component<LightboxViewProps> { } this._future = this._history = []; } else { + TabDocView.PinDoc(doc, { hidePresBox: true }); this._history ? this._history.push({ doc, target }) : this._history = [{ doc, target }]; this._savedState = { panX: Cast(doc._panX, "number", null), @@ -88,9 +90,11 @@ export class LightboxView extends React.Component<LightboxViewProps> { public static GetSavedState(doc: Doc) { return this.LightboxDoc === doc && this._savedState ? this._savedState : undefined; } - public static SetDocFilter(filter: string) { - if (this.LightboxDoc && filter) { - this._docFilters = [`cookies:${filter}:match`]; + + // adds a cookie to the lightbox view - the cookie becomes part of a filter which will display any documents whose cookie metadata field matches this cookie + public static SetCookie(cookie: string) { + if (this.LightboxDoc && cookie) { + this._docFilters = (f => this._docFilters ? [this._docFilters.push(f) as any, this._docFilters][1] : [f])(`cookies:${cookie}:provide`); } } public static AddDocTab = (doc: Doc, location: string) => { @@ -104,8 +108,7 @@ export class LightboxView extends React.Component<LightboxViewProps> { } docFilters = () => LightboxView._docFilters || []; addDocTab = LightboxView.AddDocTab; - @action - stepForward = () => { + @action public static Next() { const doc = LightboxView._doc!; const target = LightboxView._docTarget = LightboxView._future?.pop(); const docView = target && DocumentManager.Instance.getLightboxDocumentView(target); @@ -138,8 +141,8 @@ export class LightboxView extends React.Component<LightboxViewProps> { return opp?.TourMap ? opp : undefined; }).filter(m => m).map(m => m!); } - @action - stepBackward = () => { + + @action public static Previous() { const previous = LightboxView._history?.pop(); if (!previous || !LightboxView._history?.length) { LightboxView.SetLightboxDoc(undefined); @@ -182,7 +185,7 @@ export class LightboxView extends React.Component<LightboxViewProps> { TabDocView.PinDoc(coll, { hidePresBox: true }); } } - setTimeout(() => this.stepForward()); + setTimeout(LightboxView.Next); } fitToBox = () => LightboxView._docTarget === LightboxView.LightboxDoc; @@ -242,12 +245,12 @@ export class LightboxView extends React.Component<LightboxViewProps> { {this.navBtn(0, undefined, this.props.PanelHeight / 2 - 12.50, "chevron-left", () => LightboxView.LightboxDoc && LightboxView._history?.length ? "" : "none", e => { e.stopPropagation(); - this.stepBackward(); + LightboxView.Previous(); })} {this.navBtn(this.props.PanelWidth - Math.min(this.props.PanelWidth / 4, this.props.maxBorder[0]), undefined, this.props.PanelHeight / 2 - 12.50, "chevron-right", () => LightboxView.LightboxDoc && LightboxView._future?.length ? "" : "none", e => { e.stopPropagation(); - this.stepForward(); + LightboxView.Next(); })} {this.navBtn("50%", 0, 0, "chevron-down", () => LightboxView.LightboxDoc && LightboxView._future?.length ? "" : "none", e => { diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 3cbda37e2..2ba45df2c 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -113,13 +113,13 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: const docRangeFilters = this.docRangeFilters(); const searchDocs = this.searchFilterDocs(); if (this.props.Document.dontRegisterView || (!docFilters.length && !docRangeFilters.length && !searchDocs.length)) { - return childDocs; + return childDocs.filter(cd => !cd.cookies); // remove any documents that require a cookie if there are no filters to provide one } const docsforFilter: Doc[] = []; childDocs.forEach((d) => { if (DocUtils.Excluded(d, docFilters)) return; - let notFiltered = d.z || ((!searchDocs.length || searchDocs.includes(d)) && ((!docFilters.length && !docRangeFilters.length) || DocUtils.FilterDocs([d], docFilters, docRangeFilters, viewSpecScript).length > 0)); + let notFiltered = d.z || ((!searchDocs.length || searchDocs.includes(d)) && (DocUtils.FilterDocs([d], docFilters, docRangeFilters, viewSpecScript).length > 0)); const fieldKey = Doc.LayoutFieldKey(d); const annos = !Field.toString(Doc.LayoutField(d) as Field).includes("CollectionView"); const data = d[annos ? fieldKey + "-annotations" : fieldKey]; @@ -127,7 +127,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: let subDocs = DocListCast(data); if (subDocs.length > 0) { let newarray: Doc[] = []; - notFiltered = notFiltered || (!searchDocs.length && (!docFilters.length && !docRangeFilters.length) && DocUtils.FilterDocs(subDocs, docFilters, docRangeFilters, viewSpecScript).length); + notFiltered = notFiltered || (!searchDocs.length && DocUtils.FilterDocs(subDocs, docFilters, docRangeFilters, viewSpecScript).length); while (subDocs.length > 0 && !notFiltered) { newarray = []; subDocs.forEach((t) => { @@ -252,9 +252,11 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: e.stopPropagation(); e.preventDefault(); - if (!this.addDocument) { - alert("this.props.addDocument does not exist. Aborting drop operation."); - return; + + const addDocument = (doc: Doc | Doc[]) => { + const docs = doc instanceof Doc ? [doc] : doc; + docs.forEach(doc => Doc.AddDocToList(Cast(Doc.UserDoc().myFileOrphans, Doc, null), "data", doc)); + this.addDocument(doc); } if (html) { @@ -266,14 +268,14 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: DocServer.GetRefField(docid).then(f => { if (f instanceof Doc) { if (options.x || options.y) { f.x = options.x; f.y = options.y; } // should be in CollectionFreeFormView - (f instanceof Doc) && this.addDocument(f); + (f instanceof Doc) && addDocument(f); } }); } else { - this.addDocument(Docs.Create.WebDocument(href, { ...options, title: href })); + addDocument(Docs.Create.WebDocument(href, { ...options, title: href })); } } else if (text) { - this.addDocument(Docs.Create.TextDocument(text, { ...options, _showTitle: StrCast(Doc.UserDoc().showTitle), _width: 100, _height: 25 })); + addDocument(Docs.Create.TextDocument(text, { ...options, _showTitle: StrCast(Doc.UserDoc().showTitle), _width: 100, _height: 25 })); } return; } @@ -293,7 +295,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: if (source.startsWith("http")) { const doc = Docs.Create.ImageDocument(source, { ...options, _width: 300 }); ImageUtils.ExtractExif(doc); - this.addDocument(doc); + addDocument(doc); } return; } else { @@ -303,7 +305,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: DocServer.GetRefField(docid).then(f => { if (f instanceof Doc) { if (options.x || options.y) { f.x = options.x; f.y = options.y; } // should be in CollectionFreeFormView - (f instanceof Doc) && this.addDocument(f); + (f instanceof Doc) && addDocument(f); } }); } else { @@ -317,7 +319,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: const modHtml = srcUrl ? html.replace(reg, srcUrl) : html; const htmlDoc = Docs.Create.HtmlDocument(modHtml, { ...options, title: "-web page-", _width: 300, _height: 300 }); Doc.GetProto(htmlDoc)["data-text"] = Doc.GetProto(htmlDoc).text = text; - this.addDocument(htmlDoc); + addDocument(htmlDoc); if (srcWeb) { const iframe = SelectionManager.Views()[0].ContentDiv?.getElementsByTagName("iframe")?.[0]; const focusNode = (iframe?.contentDocument?.getSelection()?.focusNode as any); @@ -345,7 +347,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: if ((uriList || text).includes("www.youtube.com/watch") || text.includes("www.youtube.com/embed")) { const url = (uriList || text).replace("youtube.com/watch?v=", "youtube.com/embed/").split("&")[0]; console.log("Video URI = ", uriList); - console.log("Add:" + this.addDocument(Docs.Create.VideoDocument(url, { + console.log("Add:" + addDocument(Docs.Create.VideoDocument(url, { ...options, title: url, _width: 400, @@ -382,7 +384,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: alias._nativeWidth = 850; alias._height = 512; alias._width = 400; - this.addDocument(alias); + addDocument(alias); } else { console.log("Adding ..."); const newDoc = Docs.Create.WebDocument(uriList.split("#annotations:")[0], {// clean hypothes.is URLs that reference a specific annotation (eg. https://en.wikipedia.org/wiki/Cartoon#annotations:t7qAeNbCEeqfG5972KR2Ig) @@ -394,7 +396,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: useCors: true }); console.log(" ... " + newDoc.title); - console.log(" ... " + this.addDocument(newDoc) + " " + newDoc.title); + console.log(" ... " + addDocument(newDoc) + " " + newDoc.title); } return; } @@ -425,7 +427,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: file?.type === "application/json" && Utils.readUploadedFileAsText(file).then(result => { const json = JSON.parse(result as string); - this.addDocument(Docs.Create.TreeDocument( + addDocument(Docs.Create.TreeDocument( json["rectangular-puzzle"].crossword.clues[0].clue.map((c: any) => { const label = Docs.Create.LabelDocument({ title: c["#text"], _width: 120, _height: 20 }); const proto = Doc.GetProto(label); @@ -437,10 +439,10 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: }); } } - this.slowLoadDocuments(files, options, generatedDocuments, text, completed, e.clientX, e.clientY); + this.slowLoadDocuments(files, options, generatedDocuments, text, completed, e.clientX, e.clientY, addDocument); batch.end(); } - slowLoadDocuments = async (files: File[], options: DocumentOptions, generatedDocuments: Doc[], text: string, completed: (() => void) | undefined, clientX: number, clientY: number) => { + slowLoadDocuments = async (files: File[], options: DocumentOptions, generatedDocuments: Doc[], text: string, completed: (() => void) | undefined, clientX: number, clientY: number, addDocument: (doc: Doc | Doc[]) => boolean) => { runInAction(() => CollectionSubViewLoader.Waiting = "block"); const disposer = OverlayView.Instance.addElement( <ReactLoading type={"spinningBubbles"} color={"green"} height={250} width={250} />, { x: clientX - 125, y: clientY - 125 }); @@ -448,14 +450,14 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: if (generatedDocuments.length) { const set = generatedDocuments.length > 1 && generatedDocuments.map(d => DocUtils.iconify(d)); if (set) { - UndoManager.RunInBatch(() => this.addDocument(DocUtils.pileup(generatedDocuments, options.x!, options.y!)!), "drop"); + UndoManager.RunInBatch(() => addDocument(DocUtils.pileup(generatedDocuments, options.x!, options.y!)!), "drop"); } else { - UndoManager.RunInBatch(() => generatedDocuments.forEach(this.addDocument), "drop"); + UndoManager.RunInBatch(() => generatedDocuments.forEach(addDocument), "drop"); } completed?.(); } else { if (text && !text.includes("https://")) { - UndoManager.RunInBatch(() => this.addDocument(Docs.Create.TextDocument(text, { ...options, title: text.substring(0, 20), _width: 400, _height: 315 })), "drop"); + UndoManager.RunInBatch(() => addDocument(Docs.Create.TextDocument(text, { ...options, title: text.substring(0, 20), _width: 400, _height: 315 })), "drop"); } else { alert("Document upload failed - possibly an unsupported file type."); } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 564b41a89..d67fa75e9 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -73,9 +73,9 @@ export class SelectionManager.DeselectAll(); if (result.length !== value.length) { const ind = targetDataDoc[this.props.fieldKey].indexOf(doc); + const prev = ind && targetDataDoc[this.props.fieldKey][ind - 1]; targetDataDoc[this.props.fieldKey] = new List<Doc>(result); if (ind > 0) { - const prev = targetDataDoc[this.props.fieldKey][ind - 1]; FormattedTextBox.SelectOnLoad = prev[Id]; const prevView = DocumentManager.Instance.getDocumentView(prev, this.props.CollectionView); prevView?.select(false); diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index f3def9a23..d091e477a 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -32,6 +32,7 @@ import { CollectionTreeView } from './CollectionTreeView'; import { CollectionView, CollectionViewType } from './CollectionView'; import "./TreeView.scss"; import React = require("react"); +import { ContextMenu } from '../ContextMenu'; export interface TreeViewProps { document: Doc; @@ -93,7 +94,7 @@ export class TreeView extends React.Component<TreeViewProps> { get noviceMode() { return BoolCast(Doc.UserDoc().noviceMode, false); } get displayName() { return "TreeView(" + this.props.document.title + ")"; } // this makes mobx trace() statements more descriptive get treeViewLockExpandedView() { return this.doc.treeViewLockExpandedView; } - get defaultExpandedView() { return StrCast(this.doc.treeViewDefaultExpandedView, this.noviceMode || this.outlineMode || this.fileSysMode ? "layout" : "fields"); } + get defaultExpandedView() { return StrCast(this.doc.treeViewDefaultExpandedView, this.fileSysMode ? "data" : this.noviceMode || this.outlineMode ? "layout" : "fields"); } get treeViewDefaultExpandedView() { return this.treeViewLockExpandedView ? this.defaultExpandedView : (this.childDocs && !this.fileSysMode ? this.fieldKey : this.defaultExpandedView); } @observable _overrideTreeViewOpen = false; // override of the treeViewOpen field allowing the display state to be independent of the document's state set treeViewOpen(c: boolean) { @@ -212,9 +213,10 @@ export class TreeView extends React.Component<TreeViewProps> { bullet.context = this.props.treeView.Document; return added; } + makeFolder = () => { Doc.SetInPlace(this.doc, "editTitle", undefined, false); - const folder = Docs.Create.FreeformDocument([], { title: "-folder-", _stayInCollection: true, isFolder: true, system: true }); + const folder = Docs.Create.TreeDocument([], { title: "-folder-", _stayInCollection: true, isFolder: true, system: true }); const added = this.props.addDocument(folder); folder.context = this.props.treeView.Document; return added; @@ -511,7 +513,7 @@ export class TreeView extends React.Component<TreeViewProps> { } showContextMenu = (e: React.MouseEvent) => simulateMouseClick(this._docRef.current?.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30); - contextMenuItems = () => Doc.IsSystem(this.doc) ? [] : [{ script: ScriptField.MakeFunction(`openOnRight(self)`)!, label: "Open" }, { script: ScriptField.MakeFunction(`DocFocus(self)`)!, label: "Focus" }]; + contextMenuItems = () => this.doc.isFolder ? [{ script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, label: "New Folder" }] : Doc.IsSystem(this.doc) ? [] : [{ script: ScriptField.MakeFunction(`openOnRight(self)`)!, label: "Open" }, { script: ScriptField.MakeFunction(`DocFocus(self)`)!, label: "Focus" }]; truncateTitleWidth = () => NumCast(this.props.treeView.props.Document.treeViewTruncateTitleWidth, this.props.panelWidth()); onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick)); onChildDoubleClick = () => (!this.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 5afbec7e6..161469e24 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -46,6 +46,7 @@ import { PresBox } from './PresBox'; import { RadialMenu } from './RadialMenu'; import React = require("react"); import { ObjectField } from "../../../fields/ObjectField"; +import { LightboxView } from "../LightboxView"; const { Howl } = require('howler'); interface Window { @@ -411,6 +412,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps } focus = (anchor: Doc, options?: DocFocusOptions) => { + LightboxView.SetCookie(StrCast(anchor["cookies-set"])); // copying over _VIEW fields immediately allows the view type to switch to create the right _componentView Array.from(Object.keys(Doc.GetProto(anchor))).filter(key => key.startsWith(ViewSpecPrefix)).forEach(spec => this.layoutDoc[spec.replace(ViewSpecPrefix, "")] = ((field) => field instanceof ObjectField ? ObjectField.MakeCopy(field) : field)(anchor[spec])); // after a timeout, the right _componentView should have been created, so call it to update its view spec values @@ -665,10 +667,10 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps const appearanceItems: ContextMenuProps[] = appearance && "subitems" in appearance ? appearance.subitems : []; !Doc.UserDoc().noviceMode && templateDoc && appearanceItems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, "add:right"), icon: "eye" }); DocListCast(this.Document.links).length && appearanceItems.splice(0, 0, { description: `${this.layoutDoc.hideLinkButton ? "Show" : "Hide"} Link Button`, event: action(() => this.layoutDoc.hideLinkButton = !this.layoutDoc.hideLinkButton), icon: "eye" }); - !Doc.UserDoc().noviceMode && appearanceItems.splice(0, 0, { description: `${!this.layoutDoc._showAudio ? "Show" : "Hide"} Audio Button`, event: action(() => this.layoutDoc._showAudio = !this.layoutDoc._showAudio), icon: "microphone" }); !appearance && cm.addItem({ description: "UI Controls...", subitems: appearanceItems, icon: "compass" }); if (!Doc.IsSystem(this.rootDoc) && this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Tree) { + !Doc.UserDoc().noviceMode && appearanceItems.splice(0, 0, { description: `${!this.layoutDoc._showAudio ? "Show" : "Hide"} Audio Button`, event: action(() => this.layoutDoc._showAudio = !this.layoutDoc._showAudio), icon: "microphone" }); const existingOnClick = cm.findByDescription("OnClick..."); const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index d10afdcf9..553443931 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -63,7 +63,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc @observable _deletedDocsStatus: boolean = false; @observable _onlyAliases: boolean = true; @observable _searchbarOpen = false; - @observable _searchFullDB = "DB"; + @observable _searchFullDB = "DB"; // "DB" means searh the entire database. "My Stuff" adds a flag that selects only documents that the current user has authored @observable _noResults = ""; @observable _pageStart = 0; @observable open = false; @@ -466,7 +466,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc } @computed get scopeButtons() { - return <div style={{ height: 25, paddingLeft: "4px", paddingRight: "4px"}}> + return <div style={{ height: 25, paddingLeft: "4px", paddingRight: "4px" }}> <form className="beta" style={{ justifyContent: "space-evenly", display: "flex" }}> <div style={{ display: "contents" }}> <div className="radio" style={{ margin: 0 }}> |