diff options
Diffstat (limited to 'src/client/views')
33 files changed, 563 insertions, 656 deletions
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index ae55c8ebf..21808d6e0 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -43,7 +43,7 @@ export class DashboardView extends React.Component { @observable private selectedDashboardGroup = DashboardGroup.MyDashboards; @observable private newDashboardName: string | undefined = undefined; - @observable private newDashboardColor: string | undefined = "#AFAFAF"; + @observable private newDashboardColor: string | undefined = '#AFAFAF'; @action abortCreateNewDashboard = () => { this.newDashboardName = undefined; }; @@ -100,30 +100,15 @@ export class DashboardView extends React.Component { const dashboardCount = DocListCast(Doc.MyDashboards.data).length + 1; const placeholder = `Dashboard ${dashboardCount}`; return ( - <div className="new-dashboard" - style={{ + <div + className="new-dashboard" + style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), - color: StrCast(Doc.UserDoc().userColor) - }} - > + color: StrCast(Doc.UserDoc().userColor), + }}> <div className="header">Create New Dashboard</div> - <EditableText - formLabel='Title' - placeholder={placeholder} - type={Type.SEC} - color={StrCast(Doc.UserDoc().userColor)} - setVal={val => this.setNewDashboardName(val as string)} - fillWidth - /> - <ColorPicker - formLabel='Background' - colorPickerType='github' - type={Type.TERT} - selectedColor={this.newDashboardColor} - setSelectedColor={color => { - this.setNewDashboardColor(color); - }} - /> + <EditableText formLabel="Title" placeholder={placeholder} type={Type.SEC} color={StrCast(Doc.UserDoc().userColor)} setVal={val => this.setNewDashboardName(val as string)} fillWidth /> + <ColorPicker formLabel="Background" colorPickerType="github" type={Type.TERT} selectedColor={this.newDashboardColor} setSelectedColor={this.setNewDashboardColor} /> <div className="button-bar"> <Button text="Cancel" color={StrCast(Doc.UserDoc().userColor)} onClick={this.abortCreateNewDashboard} /> <Button type={Type.TERT} text="Create" color={StrCast(Doc.UserDoc().userVariantColor)} onClick={() => this.createNewDashboard(this.newDashboardName!, this.newDashboardColor)} /> @@ -165,21 +150,14 @@ export class DashboardView extends React.Component { }; render() { - const color = StrCast(Doc.UserDoc().userColor) - const variant = StrCast(Doc.UserDoc().userVariantColor) + const color = StrCast(Doc.UserDoc().userColor); + const variant = StrCast(Doc.UserDoc().userVariantColor); return ( <> <div className="dashboard-view"> <div className="left-menu"> - <Button - text={'My Dashboards'} - active={this.selectedDashboardGroup === DashboardGroup.MyDashboards} - color={color} - align={'flex-start'} - onClick={() => this.selectDashboardGroup(DashboardGroup.MyDashboards)} - fillWidth - /> - <Button + <Button text={'My Dashboards'} active={this.selectedDashboardGroup === DashboardGroup.MyDashboards} color={color} align={'flex-start'} onClick={() => this.selectDashboardGroup(DashboardGroup.MyDashboards)} fillWidth /> + <Button text={'Shared Dashboards' + ' (' + this.getDashboards(DashboardGroup.SharedDashboards).length + ')'} active={this.selectedDashboardGroup === DashboardGroup.SharedDashboards} color={this.getDashboards(DashboardGroup.SharedDashboards).some(dash => !DocListCast(Doc.MySharedDocs.viewed).includes(dash)) ? 'green' : color} @@ -196,11 +174,11 @@ export class DashboardView extends React.Component { .filter(key => key !== `acl-${Doc.CurrentUserEmailNormalized}` && !['acl-Me', 'acl-Guest'].includes(key)) .some(key => dashboard[DocAcl][key] !== AclPrivate); return ( - <div - className="dashboard-container" - key={dashboard[Id]} + <div + className="dashboard-container" + key={dashboard[Id]} style={{ background: this.isUnviewedSharedDashboard(dashboard) && this.selectedDashboardGroup === DashboardGroup.SharedDashboards ? '#6CB982' : shared ? variant : '' }} - onContextMenu={e => this.onContextMenu(dashboard, e)} + onContextMenu={e => this.onContextMenu(dashboard, e)} onClick={e => this.clickDashboard(e, dashboard)}> <img src={ @@ -208,12 +186,7 @@ export class DashboardView extends React.Component { } /> <div className="info"> - <EditableText - type={Type.PRIM} - color={color} - val={StrCast(dashboard.title)} - setVal={val => (Doc.GetProto(dashboard).title = val)} - /> + <EditableText type={Type.PRIM} color={color} val={StrCast(dashboard.title)} setVal={val => (Doc.GetProto(dashboard).title = val)} /> {this.selectedDashboardGroup === DashboardGroup.SharedDashboards && this.isUnviewedSharedDashboard(dashboard) ? <div>unviewed</div> : <div></div>} <div className="more" @@ -229,10 +202,13 @@ export class DashboardView extends React.Component { <Button size={Size.SMALL} color={color} icon={<FontAwesomeIcon color={color} icon="bars" />} /> </div> </div> - <div className={`background`} style={{ - background: StrCast(Doc.UserDoc().userColor), - filter: 'opacity(0.2)' - }}/> + <div + className={`background`} + style={{ + background: StrCast(Doc.UserDoc().userColor), + filter: 'opacity(0.2)', + }} + /> <div className={'dashboard-status' + (shared ? '-shared' : '')}>{shared ? 'shared' : ''}</div> </div> ); @@ -243,10 +219,13 @@ export class DashboardView extends React.Component { this.setNewDashboardName(''); }}> + - <div className={`background`} style={{ - background: StrCast(Doc.UserDoc().userColor), - filter: 'opacity(0.2)' - }}/> + <div + className={`background`} + style={{ + background: StrCast(Doc.UserDoc().userColor), + filter: 'opacity(0.2)', + }} + /> </div> </div> </div> diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 8fe5c2e01..e076e69ca 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -3,7 +3,7 @@ import { DateField } from '../../fields/DateField'; import { Doc, DocListCast, HierarchyMapping, Opt, ReverseHierarchyMap } from '../../fields/Doc'; import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, DocAcl, DocData } from '../../fields/DocSymbols'; import { List } from '../../fields/List'; -import { Cast, StrCast } from '../../fields/Types'; +import { Cast, DocCast, StrCast } from '../../fields/Types'; import { distributeAcls, GetEffectiveAcl, inheritParentAcls, SharingPermissions } from '../../fields/util'; import { returnFalse } from '../../Utils'; import { DocUtils } from '../documents/Documents'; @@ -149,9 +149,9 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>() toRemove.forEach(doc => { leavePushpin && DocUtils.LeavePushpin(doc, annotationKey ?? this.annotationKey); Doc.RemoveDocFromList(targetDataDoc, annotationKey ?? this.annotationKey, doc); + Doc.RemoveDocFromList(Doc.GetProto(doc), 'proto_embeddings', doc); doc.embedContainer = undefined; if (recent) { - Doc.RemoveDocFromList(recent, 'data', doc); doc.type !== DocumentType.LOADING && Doc.AddDocToList(recent, 'data', doc, undefined, true, true); } }); diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 68d29942b..63bd01b19 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -169,8 +169,6 @@ export class FilterPanel extends React.Component<filterProps> { render() { const options = this._allFacets.filter(facet => this.currentFacets.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); - console.log("this is option " + options) - console.log("this is alll facets " + this._allFacets) return ( <div className="filterBox-treeView"> <div className="filterBox-select"> @@ -192,17 +190,15 @@ export class FilterPanel extends React.Component<filterProps> { <div className="filterBox-tree" key="tree"> {Array.from(this.activeFacets.keys()).map(facetHeader => ( <div> - <div className = "filterBox-facetHeader"> - <div className = "filterBox-facetHeader-Header"> </div> + <div className="filterBox-facetHeader"> + <div className="filterBox-facetHeader-Header"> </div> {facetHeader.charAt(0).toUpperCase() + facetHeader.slice(1)} - - <div className = "filterBox-facetHeader-collapse"> - <AiOutlineMinusSquare/> - {/* <CiCircleRemove/> */} - </div> - + + <div className="filterBox-facetHeader-collapse"> + <AiOutlineMinusSquare /> + {/* <CiCircleRemove/> */} + </div> </div> - {this.displayFacetValueFilterUIs(this.activeFacets.get(facetHeader), facetHeader)} </div> diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index 286d39943..f79a30ad3 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -313,8 +313,10 @@ export class LightboxView extends React.Component<LightboxViewProps> { className="lightboxView-tabBtn" title="open in tab" onClick={e => { + const lightdoc = LightboxView._docTarget || LightboxView._doc!; e.stopPropagation(); - CollectionDockingView.AddSplit(LightboxView._docTarget || LightboxView._doc!, OpenWhereMod.none); + Doc.RemoveDocFromList(Doc.MyRecentlyClosed, 'data', lightdoc); + CollectionDockingView.AddSplit(lightdoc, OpenWhereMod.none); SelectionManager.DeselectAll(); LightboxView.SetLightboxDoc(undefined); }}> diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 2fa42d091..2a73d77ed 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -6,10 +6,7 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import { AssignAllExtensions } from '../../extensions/General/Extensions'; import { FieldLoader } from '../../fields/FieldLoader'; -import { DocServer } from '../DocServer'; -import { Docs } from '../documents/Documents'; import { CurrentUserUtils } from '../util/CurrentUserUtils'; -import { LinkManager } from '../util/LinkManager'; // this must come before importing Docs and CurrentUserUtils import { ReplayMovements } from '../util/ReplayMovements'; import { TrackMovements } from '../util/TrackMovements'; import { CollectionView } from './collections/CollectionView'; @@ -20,7 +17,7 @@ import './global/globalScripts'; dotenv.config(); AssignAllExtensions(); -FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0 }; // bcz: not sure why this is needed to get the code loaded properly... +FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0, message: 'cache' }; // bcz: not sure why this is needed to get the code loaded properly... (async () => { MainView.Live = window.location.search.includes('live'); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index cbaa763f5..dc236b603 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -4,7 +4,7 @@ import * as far from '@fortawesome/free-regular-svg-icons'; import * as fa from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import 'browndash-components/dist/styles/global.min.css'; -import { action, computed, configure, observable, reaction, runInAction } from 'mobx'; +import { action, computed, configure, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import 'normalize.css'; import * as React from 'react'; @@ -182,14 +182,6 @@ export class MainView extends React.Component { 'currentFrame', ]); // can play with these fields on someone else's } - DocServer.GetRefField('rtfProto').then( - proto => - proto instanceof Doc && - reaction( - () => StrCast(proto.BROADCAST_MESSAGE), - msg => msg && alert(msg) - ) - ); const tag = document.createElement('script'); tag.src = 'https://www.youtube.com/iframe_api'; @@ -527,7 +519,7 @@ export class MainView extends React.Component { }); initEventListeners = () => { - window.addEventListener('beforeunload', () => DocServer.UPDATE_SERVER_CACHE()); + window.addEventListener('beforeunload', DocServer.UPDATE_SERVER_CACHE); window.addEventListener('drop', e => e.preventDefault(), false); // prevent default behavior of navigating to a new web page window.addEventListener('dragover', e => e.preventDefault(), false); // document.addEventListener("pointermove", action(e => SearchBox.Instance._undoBackground = UndoManager.batchCounter ? "#000000a8" : undefined)); diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index b74eabcc3..8cae34d7d 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -375,7 +375,6 @@ export class PropertiesButtons extends React.Component<{}, {}> { val: value[1], }; }); - console.log('click val: ', this.onClickVal); return !this.selectedDoc ? null : ( <Dropdown tooltip={'Choose onClick behavior'} diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx index 395aa2b61..d157e7b1c 100644 --- a/src/client/views/PropertiesDocContextSelector.tsx +++ b/src/client/views/PropertiesDocContextSelector.tsx @@ -38,7 +38,6 @@ export class PropertiesDocContextSelector extends React.Component<PropertiesDocC }, new Set<Doc>()) .keys() ); - console.log('embeddings ' + embeddings.length); return doclayouts .filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance?.props.Document)) diff --git a/src/client/views/PropertiesSection.tsx b/src/client/views/PropertiesSection.tsx index ec8043ffe..6fab0168b 100644 --- a/src/client/views/PropertiesSection.tsx +++ b/src/client/views/PropertiesSection.tsx @@ -1,19 +1,19 @@ import React = require('react'); -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" -import { action, computed, observable } from "mobx" -import { observer } from "mobx-react" -import './PropertiesSection.scss' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { action, computed, observable } from 'mobx'; +import { observer } from 'mobx-react'; +import './PropertiesSection.scss'; import { Doc } from '../../fields/Doc'; import { StrCast } from '../../fields/Types'; export interface PropertiesSectionProps { - title: string, - content?: JSX.Element | string | null, - isOpen: boolean, - setIsOpen: (bool: boolean) => any - inSection?: boolean, - setInSection?: (bool: boolean) => any - onDoubleClick?: () => void + title: string; + content?: JSX.Element | string | null; + isOpen: boolean; + setIsOpen: (bool: boolean) => any; + inSection?: boolean; + setInSection?: (bool: boolean) => any; + onDoubleClick?: () => void; } @observer @@ -33,34 +33,32 @@ export class PropertiesSection extends React.Component<PropertiesSectionProps> { @observable isDouble: boolean = false; render() { - console.log(this.props.title, this.props.content) - if (this.props.content === undefined || this.props.content === null) return null - else return <div className="propertiesView-section" onPointerEnter={action(() => (this.props.setInSection && this.props.setInSection(true)))} onPointerLeave={action(() => (this.props.setInSection && this.props.setInSection(false)))}> - <div className="propertiesView-sectionTitle" - onDoubleClick={action((e) => { - this.isDouble = true; - this.props.onDoubleClick && this.props.onDoubleClick() - console.log("open options") - this.props.setIsOpen(true) - setTimeout(() => this.isDouble = false, 300) - })} - onClick={action((e) => { - this.props.setIsOpen(!this.props.isOpen) - })} - style={{ - background: this.props.isOpen ? this.variantColor : this.backgroundColor, - color: this.color - }}> - {this.props.title} - <div className="propertiesView-sectionTitle-icon"> - <FontAwesomeIcon icon={this.props.isOpen ? 'caret-down' : 'caret-right'} size="lg" /> - </div> - </div> - {!this.props.isOpen ? null : - <div className="propertiesView-content"> - {this.props.content} - </div> - } - </div> + if (this.props.content === undefined || this.props.content === null) return null; + else + return ( + <div className="propertiesView-section" onPointerEnter={action(() => this.props.setInSection && this.props.setInSection(true))} onPointerLeave={action(() => this.props.setInSection && this.props.setInSection(false))}> + <div + className="propertiesView-sectionTitle" + onDoubleClick={action(e => { + this.isDouble = true; + this.props.onDoubleClick && this.props.onDoubleClick(); + this.props.setIsOpen(true); + setTimeout(() => (this.isDouble = false), 300); + })} + onClick={action(e => { + this.props.setIsOpen(!this.props.isOpen); + })} + style={{ + background: this.props.isOpen ? this.variantColor : this.backgroundColor, + color: this.color, + }}> + {this.props.title} + <div className="propertiesView-sectionTitle-icon"> + <FontAwesomeIcon icon={this.props.isOpen ? 'caret-down' : 'caret-right'} size="lg" /> + </div> + </div> + {!this.props.isOpen ? null : <div className="propertiesView-content">{this.props.content}</div>} + </div> + ); } -}
\ No newline at end of file +} diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 27b9c3c7a..872f1c6ab 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -8,7 +8,7 @@ import { concat } from 'lodash'; import { Lambda, action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import { ColorState, SketchPicker } from 'react-color'; -import * as Icons from "react-icons/bs"; //{BsCollectionFill, BsFillFileEarmarkImageFill} from "react-icons/bs" +import * as Icons from 'react-icons/bs'; //{BsCollectionFill, BsFillFileEarmarkImageFill} from "react-icons/bs" import { GrCircleInformation } from 'react-icons/gr'; import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../Utils'; import { Doc, DocListCast, Field, FieldResult, HierarchyMapping, NumListCast, Opt, ReverseHierarchyMap, StrListCast } from '../../fields/Doc'; @@ -51,7 +51,6 @@ interface PropertiesViewProps { addDocTab: (doc: Doc, where: OpenWhere) => boolean; } - @observer export class PropertiesView extends React.Component<PropertiesViewProps> { private _widthUndo?: UndoManager.Batch; @@ -191,7 +190,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { }); rows.push( - <div className="propertiesView-field" key="newKeyValue" style={{ marginTop: '3px', backgroundColor: "white", textAlign: "center" }}> + <div className="propertiesView-field" key="newKeyValue" style={{ marginTop: '3px', backgroundColor: 'white', textAlign: 'center' }}> <EditableView key="editableView" oneLine contents={'add key:value or #tags'} height={13} fontSize={10} GetValue={() => ''} SetValue={this.setKeyValue} /> </div> ); @@ -249,14 +248,12 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return !this.selectedDoc ? null : <PropertiesDocContextSelector DocView={this.selectedDocumentView} hideTitle={true} addDocTab={this.props.addDocTab} />; } - @computed get contextCount(){ - console.log("in context count"); - if (this.selectedDocumentView){ - const target = (this.selectedDocumentView.props.Document) - const embeddings = DocListCast(target.proto_embeddings) - console.log(embeddings.length -1 ); - return (embeddings.length - 1) - } else{ + @computed get contextCount() { + if (this.selectedDocumentView) { + const target = this.selectedDocumentView.props.Document; + const embeddings = DocListCast(target.proto_embeddings); + return embeddings.length - 1; + } else { return 0; } } @@ -266,13 +263,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return !selAnchor ? null : <PropertiesDocBacklinksSelector Document={selAnchor} hideTitle={true} addDocTab={this.props.addDocTab} />; } - @computed get linkCount(){ - const selAnchor = this.selectedDocumentView?.anchorViewDoc ?? LinkManager.currentLinkAnchor ?? this.selectedDoc; + @computed get linkCount() { + const selAnchor = this.selectedDocumentView?.anchorViewDoc ?? LinkManager.currentLinkAnchor ?? this.selectedDoc; var counter = 0; - LinkManager.Links(selAnchor).forEach((l, i) => - counter ++ - ); + LinkManager.Links(selAnchor).forEach((l, i) => counter++); return counter; } @@ -356,7 +351,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return ( <Tooltip title={<div className="dash-tooltip">Notify with message</div>}> <div className="notify-button"> - <FontAwesomeIcon className="notify-button-icon" icon="bell" size="sm" /> + <FontAwesomeIcon className="notify-button-icon" icon="bell" size="sm" /> </div> </Tooltip> ); @@ -367,16 +362,16 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { */ @computed get expansionIcon() { return ( - <div className="expansion-button" > - <IconButton - icon={<FontAwesomeIcon icon={'ellipsis-h'} />} - size={Size.XSMALL} - color={StrCast(Doc.UserDoc().userColor)} + <div className="expansion-button"> + <IconButton + icon={<FontAwesomeIcon icon={'ellipsis-h'} />} + size={Size.XSMALL} + color={StrCast(Doc.UserDoc().userColor)} onClick={action(() => { if (this.selectedDocumentView || this.selectedDoc) { SharingManager.Instance.open(this.selectedDocumentView?.props.Document === this.selectedDoc ? this.selectedDocumentView : undefined, this.selectedDoc); } - })} + })} /> </div> ); @@ -418,7 +413,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div> <div className={'propertiesView-shareDropDown'}> <div className={`propertiesView-shareDropDown${permission}`}> - <div >{admin && permission !== 'Owner' ? this.getPermissionsSelect(name, permission, showGuestOptions) : concat(shareImage, ' ', permission)}</div> + <div>{admin && permission !== 'Owner' ? this.getPermissionsSelect(name, permission, showGuestOptions) : concat(shareImage, ' ', permission)}</div> </div> </div> </div> @@ -450,7 +445,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const target = docs[0]; const showAdmin = GetEffectiveAcl(target) == AclAdmin; - console.log(GetEffectiveAcl(target), Doc.GetProto(target)[`acl-${normalizeEmail(Doc.CurrentUserEmail)}`]) const individualTableEntries = []; const usersAdded: string[] = []; // all shared users being added - organized by denormalized email @@ -522,7 +516,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div> <br></br> Individuals with Access to this Document </div> - <div className="propertiesView-sharingTable" style={{background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor)}}> + <div className="propertiesView-sharingTable" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor) }}> {<div> {individualTableEntries}</div>} </div> {groupTableEntries.length > 0 ? ( @@ -530,7 +524,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div> <br></br> Groups with Access to this Document </div> - <div className="propertiesView-sharingTable" style={{background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor)}}> + <div className="propertiesView-sharingTable" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor) }}> {<div> {groupTableEntries}</div>} </div> </div> @@ -562,68 +556,43 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } @computed get editableTitle() { - const titles = new Set<string>(); const title = Array.from(titles.keys()).length > 1 ? '--multiple selected--' : StrCast(this.selectedDoc?.title); SelectionManager.Views().forEach(dv => titles.add(StrCast(dv.rootDoc.title))); - return ( - <EditableText - val={title} - setVal={this.setTitle} - color={this.color} - type={Type.SEC} - formLabel={"Title"} - fillWidth - /> - ); + return <EditableText val={title} setVal={this.setTitle} color={this.color} type={Type.SEC} formLabel={'Title'} fillWidth />; } @computed get currentType() { - // console.log("current type " + this.selectedDoc?.type) - - const documentType = StrCast(this.selectedDoc?.type) - var currentType: string = documentType; - var capitalizedDocType = Utils.cleanDocumentType(currentType as DocumentType); - - return ( - <div> - <div className = "propertiesView-wordType">Type</div> - <div className= "currentType"> - <div className='currentType-icon'> - {this.currentComponent} - </div> - - {capitalizedDocType} - - </div> - - </div> - - ) - } + const documentType = StrCast(this.selectedDoc?.type); + var currentType: string = documentType; + var capitalizedDocType = Utils.cleanDocumentType(currentType as DocumentType); - @computed get currentComponent() { + return ( + <div> + <div className="propertiesView-wordType">Type</div> + <div className="currentType"> + <div className="currentType-icon">{this.currentComponent}</div> - var iconName = StrCast(this.selectedDoc?.systemIcon) + {capitalizedDocType} + </div> + </div> + ); + } - // if (this.selectedDoc?.type === DocumentType.COL){ - // console.log("i did it!") - // } - + @computed get currentComponent() { + var iconName = StrCast(this.selectedDoc?.systemIcon); - if (iconName){ + if (iconName) { const Icon = Icons[iconName as keyof typeof Icons]; return <Icon />; - } else{ - return <Icons.BsFillCollectionFill/> - + } else { + return <Icons.BsFillCollectionFill />; } } @undoBatch @action setTitle = (value: string | number) => { - console.log(value) if (SelectionManager.Views().length > 1) { SelectionManager.Views().map(dv => Doc.SetInPlace(dv.rootDoc, 'title', value, true)); } else if (this.dataDoc) { @@ -687,7 +656,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { className="inking-button-points" style={{ backgroundColor: InkStrokeProperties.Instance._controlButton ? 'black' : '' }} onPointerDown={action(() => (InkStrokeProperties.Instance._controlButton = !InkStrokeProperties.Instance._controlButton))}> - <FontAwesomeIcon icon="bezier-curve" size="lg" /> + <FontAwesomeIcon icon="bezier-curve" size="lg" /> </div> </Tooltip> </div> @@ -706,10 +675,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <input className="inputBox-input" type="text" value={value} onChange={e => setter(e.target.value)} onKeyPress={e => e.stopPropagation()} /> <div className="inputBox-button"> <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}> - <FontAwesomeIcon icon="caret-up" size="sm" /> + <FontAwesomeIcon icon="caret-up" size="sm" /> </div> <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}> - <FontAwesomeIcon icon="caret-down" size="sm" /> + <FontAwesomeIcon icon="caret-down" size="sm" /> </div> </div> </div> @@ -963,10 +932,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <input className="inputBox-input" type="text" value={value} onChange={e => setter(e.target.value)} /> <div className="inputBox-button"> <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}> - <FontAwesomeIcon icon="caret-up" size="sm" /> + <FontAwesomeIcon icon="caret-up" size="sm" /> </div> <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}> - <FontAwesomeIcon icon="caret-down" size="sm" /> + <FontAwesomeIcon icon="caret-down" size="sm" /> </div> </div> </div> @@ -983,7 +952,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { this.openSharing = false; this.openLayout = false; this.openFilters = false; - } + }; @computed get widthAndDash() { return ( @@ -1065,64 +1034,45 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } getNumber = (label: string, unit: string, min: number, max: number, number: number, setNumber: any) => { - return <div> - <NumberInput - formLabel={label} - formLabelPlacement={'left'} - type={Type.SEC} - unit={unit} - fillWidth - color={this.color} - number={number} - setNumber={setNumber} - min={min} - max={max} - /> - <Slider - multithumb={false} - color={this.color} - size={Size.XSMALL} - min={min} - max={max} - unit={unit} - number={number} - setNumber={setNumber} - fillWidth - /> - </div> - } + return ( + <div> + <NumberInput formLabel={label} formLabelPlacement={'left'} type={Type.SEC} unit={unit} fillWidth color={this.color} number={number} setNumber={setNumber} min={min} max={max} /> + <Slider multithumb={false} color={this.color} size={Size.XSMALL} min={min} max={max} unit={unit} number={number} setNumber={setNumber} fillWidth /> + </div> + ); + }; @computed get transformEditor() { return ( <div className="transform-editor"> {this.isInk ? this.controlPointsButton : null} {this.getNumber( - "Height", - " px", + 'Height', + ' px', 0, 1000, Number(this.shapeHgt), undoable((val: string) => !isNaN(Number(val)) && (this.shapeHgt = val), 'set height') )} {this.getNumber( - "Width", - " px", + 'Width', + ' px', 0, 1000, Number(this.shapeWid), undoable((val: string) => !isNaN(Number(val)) && (this.shapeWid = val), 'set width') )} {this.getNumber( - "X Coordinate", - " px", + 'X Coordinate', + ' px', -2000, 2000, Number(this.shapeXps), undoable((val: string) => !isNaN(Number(val)) && (this.shapeXps = val), 'set x coord') )} {this.getNumber( - "Y Coordinate", - " px", + 'Y Coordinate', + ' px', -2000, 2000, Number(this.shapeYps), @@ -1133,38 +1083,44 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } @computed get optionsSubMenu() { - return <PropertiesSection - title="Options" - content={<PropertiesButtons />} - inSection={this.inOptions} - isOpen={this.openOptions} - setInSection={(bool) => this.inOptions = bool} - setIsOpen={(bool) => this.openOptions = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return ( + <PropertiesSection + title="Options" + content={<PropertiesButtons />} + inSection={this.inOptions} + isOpen={this.openOptions} + setInSection={bool => (this.inOptions = bool)} + setIsOpen={bool => (this.openOptions = bool)} + onDoubleClick={() => this.onDoubleClick()} + /> + ); } @computed get sharingSubMenu() { - return <PropertiesSection - title="Sharing & Permissions" - content={<> - {/* <div className="propertiesView-buttonContainer"> */} - <div className="propertiesView-acls-checkbox"> - Layout Permissions - <Checkbox color="primary" onChange={action(() => (this.layoutDocAcls = !this.layoutDocAcls))} checked={this.layoutDocAcls} /> - </div> - {/* <Tooltip title={<><div className="dash-tooltip">{"Re-distribute sharing settings"}</div></>}> + return ( + <PropertiesSection + title="Sharing & Permissions" + content={ + <> + {/* <div className="propertiesView-buttonContainer"> */} + <div className="propertiesView-acls-checkbox"> + Layout Permissions + <Checkbox color="primary" onChange={action(() => (this.layoutDocAcls = !this.layoutDocAcls))} checked={this.layoutDocAcls} /> + </div> + {/* <Tooltip title={<><div className="dash-tooltip">{"Re-distribute sharing settings"}</div></>}> <button onPointerDown={() => SharingManager.Instance.distributeOverCollection(this.selectedDoc!)}> <FontAwesomeIcon icon="redo-alt" size="1x" /> </button> </Tooltip> */} - {/* </div> */} - {this.sharingTable} - </>} - isOpen={this.openSharing} - setIsOpen={(bool) => this.openSharing = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + {/* </div> */} + {this.sharingTable} + </> + } + isOpen={this.openSharing} + setIsOpen={bool => (this.openSharing = bool)} + onDoubleClick={() => this.onDoubleClick()} + /> + ); } /** @@ -1192,15 +1148,19 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { }; @computed get filtersSubMenu() { - return <PropertiesSection - title="Filters" - content={<div className="propertiesView-content filters" style={{ position: 'relative', height: 'auto' }}> - <FilterPanel rootDoc={this.selectedDoc ?? Doc.ActiveDashboard!} /> - </div>} - isOpen={this.openFilters} - setIsOpen={(bool) => this.openFilters = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return ( + <PropertiesSection + title="Filters" + content={ + <div className="propertiesView-content filters" style={{ position: 'relative', height: 'auto' }}> + <FilterPanel rootDoc={this.selectedDoc ?? Doc.ActiveDashboard!} /> + </div> + } + isOpen={this.openFilters} + setIsOpen={bool => (this.openFilters = bool)} + onDoubleClick={() => this.onDoubleClick()} + /> + ); } @computed get inkSubMenu() { @@ -1208,68 +1168,42 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return ( <> - <PropertiesSection - title="Appearance" - content={this.isInk ? this.appearanceEditor : null} - isOpen={this.openAppearance} - setIsOpen={(bool) => this.openAppearance = bool} - onDoubleClick={() => this.onDoubleClick()} - /> - <PropertiesSection - title="Transform" - content={this.transformEditor} - isOpen={this.openTransform} - setIsOpen={(bool) => this.openTransform = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + <PropertiesSection title="Appearance" content={this.isInk ? this.appearanceEditor : null} isOpen={this.openAppearance} setIsOpen={bool => (this.openAppearance = bool)} onDoubleClick={() => this.onDoubleClick()} /> + <PropertiesSection title="Transform" content={this.transformEditor} isOpen={this.openTransform} setIsOpen={bool => (this.openTransform = bool)} onDoubleClick={() => this.onDoubleClick()} /> </> ); } @computed get fieldsSubMenu() { - return <PropertiesSection - title="Fields & Tags" - content={<div className="propertiesView-content fields">{ - Doc.noviceMode ? this.noviceFields : this.expandedField} - </div>} - isOpen={this.openFields} - setIsOpen={(bool) => this.openFields = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return ( + <PropertiesSection + title="Fields & Tags" + content={<div className="propertiesView-content fields">{Doc.noviceMode ? this.noviceFields : this.expandedField}</div>} + isOpen={this.openFields} + setIsOpen={bool => (this.openFields = bool)} + onDoubleClick={() => this.onDoubleClick()} + /> + ); } @computed get contextsSubMenu() { - return <PropertiesSection - title="Other Contexts" - content={this.contextCount > 0 ? this.contexts : "There are no other contexts."} - isOpen={this.openContexts} - setIsOpen={(bool) => this.openContexts = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return ( + <PropertiesSection + title="Other Contexts" + content={this.contextCount > 0 ? this.contexts : 'There are no other contexts.'} + isOpen={this.openContexts} + setIsOpen={bool => (this.openContexts = bool)} + onDoubleClick={() => this.onDoubleClick()} + /> + ); } - - - - @computed get linksSubMenu() { - return <PropertiesSection - title="Linked To" - content={this.linkCount > 0 ? this.links : "There are no current links." } - isOpen={this.openLinks} - setIsOpen={(bool) => this.openLinks = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return <PropertiesSection title="Linked To" content={this.linkCount > 0 ? this.links : 'There are no current links.'} isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={() => this.onDoubleClick()} />; } @computed get layoutSubMenu() { - return <PropertiesSection - title="Layout" - content={this.layoutPreview} - isOpen={this.openLayout} - setIsOpen={(bool) => this.openLayout = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return <PropertiesSection title="Layout" content={this.layoutPreview} isOpen={this.openLayout} setIsOpen={bool => (this.openLayout = bool)} onDoubleClick={() => this.onDoubleClick()} />; } @computed get description() { @@ -1470,224 +1404,226 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { if (scale > 1) scale = 1; this.sourceAnchor && (this.sourceAnchor.followLinkZoomScale = scale); }; - + @computed get linkProperties() { const zoom = Number((NumCast(this.sourceAnchor?.followLinkZoomScale, 1) * 100).toPrecision(3)); const targZoom = this.sourceAnchor?.followLinkZoom; const indent = 30; const hasSelectedAnchor = LinkManager.Links(this.sourceAnchor).includes(LinkManager.currentLink!); - return <> - <div className="propertiesView-section" style={{ background: 'darkgray' }}> - <div className="propertiesView-input first" style={{ display: 'grid', gridTemplateColumns: '84px auto' }}> - <p>Relationship</p> - {this.editRelationship} - </div> - <div className="propertiesView-input" style={{ display: 'grid', gridTemplateColumns: '84px auto' }}> - <p>Description</p> - {this.editDescription} - </div> - <div className="propertiesView-input inline"> - <p>Show link</p> - <button - style={{ background: !LinkManager.currentLink?.link_displayLine ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleLinkProp(e, 'link_displayLine')} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline" style={{ marginLeft: 10 }}> - <p>Auto-move anchors</p> - <button - style={{ background: !LinkManager.currentLink?.link_autoMoveAnchors ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleLinkProp(e, 'link_autoMoveAnchors')} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline" style={{ marginLeft: 10 }}> - <p>Display arrow</p> - <button - style={{ background: !LinkManager.currentLink?.link_displayArrow ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleLinkProp(e, 'link_displayArrow')} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> - </button> - </div> - </div> - {!hasSelectedAnchor ? null : ( - <div className="propertiesView-section"> - <div className="propertiesView-input inline first" style={{ display: 'grid', gridTemplateColumns: '84px calc(100% - 84px)' }}> - <p>Follow by</p> - <select onChange={e => this.changeFollowBehavior(e.currentTarget.value === 'Default' ? undefined : e.currentTarget.value)} value={Cast(this.sourceAnchor?.followLinkLocation, 'string', null)}> - <option value={undefined}>Default</option> - <option value={OpenWhere.addLeft}>Opening in new left pane</option> - <option value={OpenWhere.addRight}>Opening in new right pane</option> - <option value={OpenWhere.replaceLeft}>Replacing left tab</option> - <option value={OpenWhere.replaceRight}>Replacing right tab</option> - <option value={OpenWhere.lightbox}>Opening in lightbox</option> - <option value={OpenWhere.add}>Opening in new tab</option> - <option value={OpenWhere.replace}>Replacing current tab</option> - <option value={OpenWhere.inParent}>Opening in same collection</option> - {LinkManager.currentLink?.linksToAnnotation ? <option value="openExternal">Open in external page</option> : null} - </select> - </div> - <div className="propertiesView-input inline first" style={{ display: 'grid', gridTemplateColumns: '84px calc(100% - 134px) 50px' }}> - <p>Animation</p> - <select style={{ width: '100%', gridColumn: 2 }} onChange={e => this.changeAnimationBehavior(e.currentTarget.value)} value={StrCast(this.sourceAnchor?.followLinkAnimEffect, 'default')}> - <option value="default">Default</option> - {[PresEffect.None, PresEffect.Zoom, PresEffect.Lightspeed, PresEffect.Fade, PresEffect.Flip, PresEffect.Rotate, PresEffect.Bounce, PresEffect.Roll].map(effect => ( - <option key={effect.toString()} value={effect.toString()}> - {effect.toString()} - </option> - ))} - </select> - <div className="effectDirection" style={{ marginLeft: '10px', display: 'grid', width: 40, height: 36, gridColumn: 3, gridTemplateRows: '12px 12px 12px' }}> - {this.animationDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})} - {this.animationDirection(PresEffectDirection.Right, 'angle-left', 3, 2, {})} - {this.animationDirection(PresEffectDirection.Top, 'angle-down', 2, 1, {})} - {this.animationDirection(PresEffectDirection.Bottom, 'angle-up', 2, 3, {})} - {this.animationDirection(PresEffectDirection.Center, '', 2, 2, { width: 10, height: 10, alignSelf: 'center' })} + return ( + <> + <div className="propertiesView-section" style={{ background: 'darkgray' }}> + <div className="propertiesView-input first" style={{ display: 'grid', gridTemplateColumns: '84px auto' }}> + <p>Relationship</p> + {this.editRelationship} + </div> + <div className="propertiesView-input" style={{ display: 'grid', gridTemplateColumns: '84px auto' }}> + <p>Description</p> + {this.editDescription} + </div> + <div className="propertiesView-input inline"> + <p>Show link</p> + <button + style={{ background: !LinkManager.currentLink?.link_displayLine ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleLinkProp(e, 'link_displayLine')} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline" style={{ marginLeft: 10 }}> + <p>Auto-move anchors</p> + <button + style={{ background: !LinkManager.currentLink?.link_autoMoveAnchors ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleLinkProp(e, 'link_autoMoveAnchors')} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline" style={{ marginLeft: 10 }}> + <p>Display arrow</p> + <button + style={{ background: !LinkManager.currentLink?.link_displayArrow ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleLinkProp(e, 'link_displayArrow')} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> + </button> </div> </div> - {PresBox.inputter( - '0.1', - '0.1', - '10', - NumCast(this.sourceAnchor?.followLinkTransitionTime) / 1000, - true, - (val: string) => PresBox.SetTransitionTime(val, (timeInMS: number) => this.sourceAnchor && (this.sourceAnchor.followLinkTransitionTime = timeInMS)), - indent - )}{' '} - <div - className={'slider-headers'} - style={{ - display: 'grid', - justifyContent: 'space-between', - width: `calc(100% - ${indent * 2}px)`, - marginLeft: indent, - marginRight: indent, - gridTemplateColumns: 'auto auto', - borderTop: 'solid', - }}> - <div className="slider-text">Fast</div> - <div className="slider-text">Slow</div> - </div>{' '} - <div className="propertiesView-input inline"> - <p>Play Target Audio</p> - <button - style={{ background: !this.sourceAnchor?.followLinkAudio ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkAudio', this.sourceAnchor)} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline"> - <p>Zoom Text Selections</p> - <button - style={{ background: !this.sourceAnchor?.followLinkZoomText ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoomText', this.sourceAnchor)} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline"> - <p>Toggle Follow to Outer Context</p> - <button - style={{ background: !this.sourceAnchor?.followLinkToOuterContext ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToOuterContext', this.sourceAnchor)} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faWindowMaximize as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline"> - <p>Toggle Target (Show/Hide)</p> - <button - style={{ background: !this.sourceAnchor?.followLinkToggle ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToggle', this.sourceAnchor)} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline"> - <p>Ease Transitions</p> - <button - style={{ background: this.sourceAnchor?.followLinkEase === 'linear' ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkEase', this.sourceAnchor, 'ease', 'linear')} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline"> - <p>Capture Offset to Target</p> - <button - style={{ background: this.sourceAnchor?.followLinkXoffset === undefined ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => { - this.toggleAnchorProp(e, 'followLinkXoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.x) - NumCast(this.sourceAnchor?.x), undefined); - this.toggleAnchorProp(e, 'followLinkYoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.y) - NumCast(this.sourceAnchor?.y), undefined); - }} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline"> - <p>Center Target (no zoom)</p> - <button - style={{ background: this.sourceAnchor?.followLinkZoom ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline" style={{ display: 'grid', gridTemplateColumns: '78px calc(100% - 108px) 50px' }}> - <p>Zoom %</p> - <div className="ribbon-property" style={{ display: !targZoom ? 'none' : 'inline-flex' }}> - <input className="presBox-input" style={{ width: '100%' }} readOnly={true} type="number" value={zoom} /> - <div className="ribbon-propertyUpDown" style={{ display: 'flex', flexDirection: 'column' }}> - <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), 0.1))}> - <FontAwesomeIcon icon={'caret-up'} /> + {!hasSelectedAnchor ? null : ( + <div className="propertiesView-section"> + <div className="propertiesView-input inline first" style={{ display: 'grid', gridTemplateColumns: '84px calc(100% - 84px)' }}> + <p>Follow by</p> + <select onChange={e => this.changeFollowBehavior(e.currentTarget.value === 'Default' ? undefined : e.currentTarget.value)} value={Cast(this.sourceAnchor?.followLinkLocation, 'string', null)}> + <option value={undefined}>Default</option> + <option value={OpenWhere.addLeft}>Opening in new left pane</option> + <option value={OpenWhere.addRight}>Opening in new right pane</option> + <option value={OpenWhere.replaceLeft}>Replacing left tab</option> + <option value={OpenWhere.replaceRight}>Replacing right tab</option> + <option value={OpenWhere.lightbox}>Opening in lightbox</option> + <option value={OpenWhere.add}>Opening in new tab</option> + <option value={OpenWhere.replace}>Replacing current tab</option> + <option value={OpenWhere.inParent}>Opening in same collection</option> + {LinkManager.currentLink?.linksToAnnotation ? <option value="openExternal">Open in external page</option> : null} + </select> + </div> + <div className="propertiesView-input inline first" style={{ display: 'grid', gridTemplateColumns: '84px calc(100% - 134px) 50px' }}> + <p>Animation</p> + <select style={{ width: '100%', gridColumn: 2 }} onChange={e => this.changeAnimationBehavior(e.currentTarget.value)} value={StrCast(this.sourceAnchor?.followLinkAnimEffect, 'default')}> + <option value="default">Default</option> + {[PresEffect.None, PresEffect.Zoom, PresEffect.Lightspeed, PresEffect.Fade, PresEffect.Flip, PresEffect.Rotate, PresEffect.Bounce, PresEffect.Roll].map(effect => ( + <option key={effect.toString()} value={effect.toString()}> + {effect.toString()} + </option> + ))} + </select> + <div className="effectDirection" style={{ marginLeft: '10px', display: 'grid', width: 40, height: 36, gridColumn: 3, gridTemplateRows: '12px 12px 12px' }}> + {this.animationDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})} + {this.animationDirection(PresEffectDirection.Right, 'angle-left', 3, 2, {})} + {this.animationDirection(PresEffectDirection.Top, 'angle-down', 2, 1, {})} + {this.animationDirection(PresEffectDirection.Bottom, 'angle-up', 2, 3, {})} + {this.animationDirection(PresEffectDirection.Center, '', 2, 2, { width: 10, height: 10, alignSelf: 'center' })} </div> - <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), -0.1))}> - <FontAwesomeIcon icon={'caret-down'} /> + </div> + {PresBox.inputter( + '0.1', + '0.1', + '10', + NumCast(this.sourceAnchor?.followLinkTransitionTime) / 1000, + true, + (val: string) => PresBox.SetTransitionTime(val, (timeInMS: number) => this.sourceAnchor && (this.sourceAnchor.followLinkTransitionTime = timeInMS)), + indent + )}{' '} + <div + className={'slider-headers'} + style={{ + display: 'grid', + justifyContent: 'space-between', + width: `calc(100% - ${indent * 2}px)`, + marginLeft: indent, + marginRight: indent, + gridTemplateColumns: 'auto auto', + borderTop: 'solid', + }}> + <div className="slider-text">Fast</div> + <div className="slider-text">Slow</div> + </div>{' '} + <div className="propertiesView-input inline"> + <p>Play Target Audio</p> + <button + style={{ background: !this.sourceAnchor?.followLinkAudio ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkAudio', this.sourceAnchor)} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline"> + <p>Zoom Text Selections</p> + <button + style={{ background: !this.sourceAnchor?.followLinkZoomText ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoomText', this.sourceAnchor)} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline"> + <p>Toggle Follow to Outer Context</p> + <button + style={{ background: !this.sourceAnchor?.followLinkToOuterContext ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToOuterContext', this.sourceAnchor)} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faWindowMaximize as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline"> + <p>Toggle Target (Show/Hide)</p> + <button + style={{ background: !this.sourceAnchor?.followLinkToggle ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToggle', this.sourceAnchor)} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline"> + <p>Ease Transitions</p> + <button + style={{ background: this.sourceAnchor?.followLinkEase === 'linear' ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkEase', this.sourceAnchor, 'ease', 'linear')} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline"> + <p>Capture Offset to Target</p> + <button + style={{ background: this.sourceAnchor?.followLinkXoffset === undefined ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => { + this.toggleAnchorProp(e, 'followLinkXoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.x) - NumCast(this.sourceAnchor?.x), undefined); + this.toggleAnchorProp(e, 'followLinkYoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.y) - NumCast(this.sourceAnchor?.y), undefined); + }} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline"> + <p>Center Target (no zoom)</p> + <button + style={{ background: this.sourceAnchor?.followLinkZoom ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline" style={{ display: 'grid', gridTemplateColumns: '78px calc(100% - 108px) 50px' }}> + <p>Zoom %</p> + <div className="ribbon-property" style={{ display: !targZoom ? 'none' : 'inline-flex' }}> + <input className="presBox-input" style={{ width: '100%' }} readOnly={true} type="number" value={zoom} /> + <div className="ribbon-propertyUpDown" style={{ display: 'flex', flexDirection: 'column' }}> + <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), 0.1))}> + <FontAwesomeIcon icon={'caret-up'} /> + </div> + <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), -0.1))}> + <FontAwesomeIcon icon={'caret-down'} /> + </div> + </div> </div> + <button + style={{ background: !targZoom || this.sourceAnchor?.followLinkZoomScale === 0 ? '' : '#4476f7', borderRadius: 3, gridColumn: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> + </button> </div> + {!targZoom ? null : PresBox.inputter('0', '1', '100', zoom, true, this.setZoom, 30)} + <div + className={'slider-headers'} + style={{ + display: !targZoom ? 'none' : 'grid', + justifyContent: 'space-between', + width: `calc(100% - ${indent * 2}px)`, + marginLeft: indent, + marginRight: indent, + gridTemplateColumns: 'auto auto', + borderTop: 'solid', + }}> + <div className="slider-text">0%</div> + <div className="slider-text">100%</div> + </div>{' '} </div> - <button - style={{ background: !targZoom || this.sourceAnchor?.followLinkZoomScale === 0 ? '' : '#4476f7', borderRadius: 3, gridColumn: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> - </button> - </div> - {!targZoom ? null : PresBox.inputter('0', '1', '100', zoom, true, this.setZoom, 30)} - <div - className={'slider-headers'} - style={{ - display: !targZoom ? 'none' : 'grid', - justifyContent: 'space-between', - width: `calc(100% - ${indent * 2}px)`, - marginLeft: indent, - marginRight: indent, - gridTemplateColumns: 'auto auto', - borderTop: 'solid', - }}> - <div className="slider-text">0%</div> - <div className="slider-text">100%</div> - </div>{' '} - </div> - )} - </> + )} + </> + ); } /** @@ -1723,23 +1659,20 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { width: this.props.width, minWidth: this.props.width, }}> - <div className = "propertiesView-propAndInfoGrouping"> + <div className="propertiesView-propAndInfoGrouping"> <div className="propertiesView-title" style={{ width: this.props.width }}> Properties </div> - <div className = "propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/')}> - <GrCircleInformation/> </div> - + <div className="propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/')}> + <GrCircleInformation />{' '} + </div> </div> - <div className="propertiesView-name">{this.editableTitle}</div> - <div className = "propertiesView-type"> {this.currentType} </div> + <div className="propertiesView-type"> {this.currentType} </div> {this.contextsSubMenu} {this.linksSubMenu} - {!this.selectedDoc || !LinkManager.currentLink || (!hasSelectedAnchor && this.selectedDoc !== LinkManager.currentLink) ? null : ( - this.linkProperties - )} + {!this.selectedDoc || !LinkManager.currentLink || (!hasSelectedAnchor && this.selectedDoc !== LinkManager.currentLink) ? null : this.linkProperties} {this.inkSubMenu} {this.optionsSubMenu} {this.fieldsSubMenu} @@ -1760,7 +1693,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { Presentation </div> <div className="propertiesView-name" style={{ borderBottom: 0 }}> - {this.editableTitle} <div className="propertiesView-presSelected"> <div className="propertiesView-selectedCount">{PresBox.Instance.selectedArray.size} selected</div> @@ -1772,7 +1704,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div className="propertiesView-presTrails-title" onPointerDown={action(() => (this.openPresTransitions = !this.openPresTransitions))} style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> Transitions <div className="propertiesView-presTrails-title-icon"> - <FontAwesomeIcon icon={this.openPresTransitions ? 'caret-down' : 'caret-right'} size="lg" /> + <FontAwesomeIcon icon={this.openPresTransitions ? 'caret-down' : 'caret-right'} size="lg" /> </div> </div> {this.openPresTransitions ? <div className="propertiesView-presTrails-content">{PresBox.Instance.transitionDropdown}</div> : null} @@ -1786,7 +1718,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> Visibilty <div className="propertiesView-presTrails-title-icon"> - <FontAwesomeIcon icon={this.openPresVisibilityAndDuration ? 'caret-down' : 'caret-right'} size="lg" /> + <FontAwesomeIcon icon={this.openPresVisibilityAndDuration ? 'caret-down' : 'caret-right'} size="lg" /> </div> </div> {this.openPresVisibilityAndDuration ? <div className="propertiesView-presTrails-content">{PresBox.Instance.visibiltyDurationDropdown}</div> : null} @@ -1797,7 +1729,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div className="propertiesView-presTrails-title" onPointerDown={action(() => (this.openPresProgressivize = !this.openPresProgressivize))} style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> Progressivize <div className="propertiesView-presTrails-title-icon"> - <FontAwesomeIcon icon={this.openPresProgressivize ? 'caret-down' : 'caret-right'} size="lg" /> + <FontAwesomeIcon icon={this.openPresProgressivize ? 'caret-down' : 'caret-right'} size="lg" /> </div> </div> {this.openPresProgressivize ? <div className="propertiesView-presTrails-content">{PresBox.Instance.progressivizeDropdown}</div> : null} @@ -1808,7 +1740,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div className="propertiesView-presTrails-title" onPointerDown={action(() => (this.openSlideOptions = !this.openSlideOptions))} style={{ backgroundColor: this.openSlideOptions ? 'black' : '' }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={type === DocumentType.AUDIO ? 'file-audio' : 'file-video'} /> {type === DocumentType.AUDIO ? 'Audio Options' : 'Video Options'} <div className="propertiesView-presTrails-title-icon"> - <FontAwesomeIcon icon={this.openSlideOptions ? 'caret-down' : 'caret-right'} size="lg" /> + <FontAwesomeIcon icon={this.openSlideOptions ? 'caret-down' : 'caret-right'} size="lg" /> </div> </div> {this.openSlideOptions ? <div className="propertiesView-presTrails-content">{PresBox.Instance.mediaOptionsDropdown}</div> : null} diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index bbbad3690..94748e884 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -22,7 +22,7 @@ import { DocumentViewProps } from './nodes/DocumentView'; import { FieldViewProps } from './nodes/FieldView'; import { KeyValueBox } from './nodes/KeyValueBox'; import { SliderBox } from './nodes/SliderBox'; -import { BsArrowDown, BsArrowUp, BsArrowDownUp } from 'react-icons/bs' +import { BsArrowDown, BsArrowUp, BsArrowDownUp } from 'react-icons/bs'; import './StyleProvider.scss'; import React = require('react'); @@ -161,7 +161,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps '' ); case StyleProp.Color: - if (MainView.Instance.LastButton === doc) return Doc.UserDoc().userBackgroundColor; + if (MainView.Instance.LastButton === doc) return SettingsManager.Instance.userBackgroundColor; if (Doc.IsSystem(doc!)) return StrCast(Doc.UserDoc().userColor) if (doc?.type === DocumentType.FONTICON) return Doc.UserDoc().userColor; const docColor: Opt<string> = StrCast(doc?.[fieldKey + 'color'], StrCast(doc?._color)); @@ -208,12 +208,10 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps case DocumentType.PRES: docColor = docColor || (darkScheme() ? 'transparent' : 'transparent'); break; case DocumentType.FONTICON: docColor = boxBackground ? undefined : docColor || Colors.DARK_GRAY; break; case DocumentType.RTF: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break; - case DocumentType.FILTER: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : 'rgba(105, 105, 105, 0.432)'); break; case DocumentType.INK: docColor = doc?.stroke_isInkMask ? 'rgba(0,0,0,0.7)' : undefined; break; case DocumentType.EQUATION: docColor = docColor || 'transparent'; break; case DocumentType.LABEL: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break; case DocumentType.BUTTON: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break; - case DocumentType.LINKANCHOR: docColor = isAnchor ? Colors.LIGHT_BLUE : 'transparent'; break; case DocumentType.LINK: docColor = (isAnchor ? docColor : '') || 'transparent'; break; case DocumentType.IMG: case DocumentType.WEB: @@ -224,7 +222,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps case DocumentType.COL: if (StrCast(Doc.LayoutField(doc)).includes(SliderBox.name)) break; docColor = docColor || (Doc.IsSystem(doc) - ? StrCast(Doc.UserDoc().userBackgroundColor) + ? SettingsManager.Instance.userBackgroundColor : doc.annotationOn ? '#00000010' // faint interior for collections on PDFs, images, etc : doc?._isGroup diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx index caf04cc1b..a551e5332 100644 --- a/src/client/views/UndoStack.tsx +++ b/src/client/views/UndoStack.tsx @@ -7,6 +7,7 @@ import { StrCast } from '../../fields/Types'; import { Doc } from '../../fields/Doc'; import { Popup, Type, isDark } from 'browndash-components'; import { Colors } from './global/globalEnums'; +import { SettingsManager } from '../util/SettingsManager'; interface UndoStackProps { width?: number; @@ -18,35 +19,37 @@ export class UndoStack extends React.Component<UndoStackProps> { @observable static HideInline: boolean; @observable static Expand: boolean; render() { - const background = UndoManager.batchCounter.get() ? 'yellow' : StrCast(Doc.UserDoc().userBackgroundColor) + const background = UndoManager.batchCounter.get() ? 'yellow' : SettingsManager.Instance.userBackgroundColor; return this.props.inline && UndoStack.HideInline ? null : ( <div className="undoStack-outerContainer"> - <Popup + <Popup text={'Undo/Redo Stack'} color={UndoManager.batchCounter.get() ? 'yellow' : StrCast(Doc.UserDoc().userVariantColor)} placement={`top-start`} type={Type.TERT} popup={ - <div className="undoStack-commandsContainer" ref={r => r?.scroll({ behavior: 'auto', top: r?.scrollHeight + 20 })} - style={{ - background: background, - color: isDark(background) ? Colors.LIGHT_GRAY : Colors.DARK_GRAY - }}> - {UndoManager.undoStackNames.map((name, i) => ( - <div className="undoStack-resultContainer" key={i}> - <div className="undoStack-commandString">{name.replace(/[^\.]*\./, '')}</div> - </div> - ))} - {Array.from(UndoManager.redoStackNames) - .reverse() - .map((name, i) => ( + <div + className="undoStack-commandsContainer" + ref={r => r?.scroll({ behavior: 'auto', top: r?.scrollHeight + 20 })} + style={{ + background: background, + color: isDark(background) ? Colors.LIGHT_GRAY : Colors.DARK_GRAY, + }}> + {UndoManager.undoStackNames.map((name, i) => ( <div className="undoStack-resultContainer" key={i}> - <div className="undoStack-commandString" style={{ fontWeight: 'bold', color: 'red' }}> - {name.replace(/[^\.]*\./, '')} - </div> + <div className="undoStack-commandString">{name.replace(/[^\.]*\./, '')}</div> </div> - ))} - </div> + ))} + {Array.from(UndoManager.redoStackNames) + .reverse() + .map((name, i) => ( + <div className="undoStack-resultContainer" key={i}> + <div className="undoStack-commandString" style={{ fontWeight: 'bold', color: 'red' }}> + {name.replace(/[^\.]*\./, '')} + </div> + </div> + ))} + </div> } /> </div> diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 16982595d..0052c4196 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -164,7 +164,7 @@ export class CollectionDockingView extends CollectionSubView() { public static AddSplit(document: Doc, pullSide: OpenWhereMod, stack?: any, panelName?: string, keyValue?: boolean) { if (document?._type_collection === CollectionViewType.Docking && !keyValue) return DashboardView.openDashboard(document); if (!CollectionDockingView.Instance) return false; - const tab = Array.from(CollectionDockingView.Instance.tabMap).find(tab => tab.DashDoc === document && !keyValue); + const tab = Array.from(CollectionDockingView.Instance.tabMap).find(tab => tab.DashDoc === document && !tab.contentItem.config.props.keyValue && !keyValue); if (tab) { tab.header.parent.setActiveContentItem(tab.contentItem); return true; @@ -466,7 +466,10 @@ export class CollectionDockingView extends CollectionSubView() { this._flush = this._flush ?? UndoManager.StartBatch('tab movement'); if (tab.DashDoc && ![DocumentType.PRES].includes(tab.DashDoc?.type) && !tab.contentItem.config.props.keyValue) { Doc.AddDocToList(Doc.MyHeaderBar, 'data', tab.DashDoc); - Doc.AddDocToList(Doc.MyRecentlyClosed, 'data', tab.DashDoc, undefined, true, true); + // if you close a tab that is not embedded somewhere else (an embedded Doc can be opened simultaneously in a tab), then add the tab to recently closed + if (tab.DashDoc.embedContainer === this.rootDoc) tab.DashDoc.embedContainer = undefined; + if (!tab.DashDoc.embedContainer) Doc.AddDocToList(Doc.MyRecentlyClosed, 'data', tab.DashDoc, undefined, true, true); + Doc.RemoveDocFromList(Doc.GetProto(tab.DashDoc), 'proto_embeddings', tab.DashDoc); } if (CollectionDockingView.Instance) { const dview = CollectionDockingView.Instance.props.Document; diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 5135cfb57..f65e8698f 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -181,7 +181,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> { <div className="collectionMenu-container" style={{ - background: StrCast(Doc.UserDoc().userBackgroundColor), + background: SettingsManager.Instance.userBackgroundColor, // borderColor: StrCast(Doc.UserDoc().userColor) }}> {this.contMenuButtons} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index a5c276125..056204ad3 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -669,7 +669,6 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection if (menuDoc) { const width: number = NumCast(menuDoc._width, 30); const height: number = NumCast(menuDoc._height, 30); - console.log(menuDoc.title, width, height); return ( <div className="buttonMenu-docBtn" style={{ width: width, height: height }}> <DocumentView diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 00137736d..ea3b5065f 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -150,6 +150,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree console.log('WHAAAT'); } dragData.dropAction = dropAction && !isAlreadyInTree() ? dropAction : sameTree ? 'same' : dragData.dropAction; + e.stopPropagation(); } }; diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 67b7b39dd..d787f5262 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -396,7 +396,7 @@ export class TabDocView extends React.Component<TabDocViewProps> { return NumCast(Cast(PresBox.Instance.activeItem.presentationTargetDoc, Doc, null)._currentFrame); }; static Activate = (tabDoc: Doc) => { - const tab = Array.from(CollectionDockingView.Instance?.tabMap!).find(tab => tab.DashDoc === tabDoc); + const tab = Array.from(CollectionDockingView.Instance?.tabMap!).find(tab => tab.DashDoc === tabDoc && !tab.contentItem.config.props.keyValue); tab?.header.parent.setActiveContentItem(tab.contentItem); // glr: Panning does not work when this is set - (this line is for trying to make a tab that is not topmost become topmost) return tab !== undefined; }; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index fb23fc7f1..6e0ccd4be 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -127,7 +127,7 @@ export class TreeView extends React.Component<TreeViewProps> { : this.props.treeView.fileSysMode ? this.doc.isFolder ? this.fieldKey - : 'embeddings' // for displaying + : 'data' // file system folders display their contents (data). used to be they displayed their embeddings but now its a tree structure and not a flat list : this.props.treeView.outlineMode || this.childDocs ? this.fieldKey : Doc.noviceMode diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 090cf356c..7c53bfdbe 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -377,7 +377,6 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque : ((doc: Doc) => { Doc.GetProto(doc).data = new List<Doc>(selected); Doc.GetProto(doc).title = makeGroup ? 'grouping' : 'nested freeform'; - !this.props.isAnnotationOverlay && Doc.AddFileOrphan(Doc.GetProto(doc)); doc._freeform_panX = doc._freeform_panY = 0; return doc; })(Doc.MakeCopy(Doc.UserDoc().emptyCollection as Doc, true)); diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 79842047b..256377758 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -197,7 +197,6 @@ ScriptingGlobals.add(function toggleCharStyle(charStyle: attrname, checkResult?: }); export function checkInksToGroup() { - // console.log("getting here to inks group"); if (Doc.ActiveTool === InkTool.Write) { CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those diff --git a/src/client/views/newlightbox/ExploreView/ExploreView.tsx b/src/client/views/newlightbox/ExploreView/ExploreView.tsx index 44a0bcd5f..a1d6375c4 100644 --- a/src/client/views/newlightbox/ExploreView/ExploreView.tsx +++ b/src/client/views/newlightbox/ExploreView/ExploreView.tsx @@ -12,14 +12,11 @@ export const ExploreView = (props: IExploreView) => { <div className={`exploreView-container`}> {recs && recs.map(rec => { - console.log(rec.embedding, bounds); const x_bound: number = Math.max(Math.abs(bounds.max_x), Math.abs(bounds.min_x)); const y_bound: number = Math.max(Math.abs(bounds.max_y), Math.abs(bounds.min_y)); - console.log(x_bound, y_bound); if (rec.embedding) { const x = (rec.embedding.x / x_bound) * 50; const y = (rec.embedding.y / y_bound) * 50; - console.log(x, y); return ( <div className={`exploreView-doc`} onClick={() => {}} style={{ top: `calc(50% + ${y}%)`, left: `calc(50% + ${x}%)` }}> {rec.title} diff --git a/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx b/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx index b9d05c531..2c2f04b9f 100644 --- a/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx +++ b/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx @@ -22,7 +22,6 @@ export const Recommendation = (props: IRecommendation) => { doc = docView.rootDoc; } } else if (data) { - console.log(data, type); switch (type) { case 'YouTube': console.log('create ', type, 'document'); diff --git a/src/client/views/nodes/DataVizBox/utils/D3Utils.ts b/src/client/views/nodes/DataVizBox/utils/D3Utils.ts index e1ff6f8eb..10bfb0c64 100644 --- a/src/client/views/nodes/DataVizBox/utils/D3Utils.ts +++ b/src/client/views/nodes/DataVizBox/utils/D3Utils.ts @@ -34,7 +34,6 @@ export const createLineGenerator = (xScale: d3.ScaleLinear<number, number, never }; export const xAxisCreator = (g: d3.Selection<SVGGElement, unknown, null, undefined>, height: number, xScale: d3.ScaleLinear<number, number, never>) => { - console.log('x axis creator being called'); g.attr('class', 'x-axis').attr('transform', `translate(0,${height})`).call(d3.axisBottom(xScale).tickSize(15)); }; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 70d2f95ea..d379b2b52 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,5 +1,5 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; -import { action, computed, IReactionDisposer, observable, reaction, runInAction, trace } from 'mobx'; +import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal'; @@ -47,7 +47,6 @@ import { DocumentLinksButton } from './DocumentLinksButton'; import './DocumentView.scss'; import { FieldViewProps } from './FieldView'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; -import { KeyValueBox } from './KeyValueBox'; import { LinkAnchorBox } from './LinkAnchorBox'; import { PresEffect, PresEffectDirection } from './trails'; import { PinProps, PresBox } from './trails/PresBox'; diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 86191de63..d69009415 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -4,7 +4,7 @@ import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import wiki from 'wikijs'; import { Doc, DocCastAsync, Opt } from '../../../fields/Doc'; -import { Height, Width } from '../../../fields/DocSymbols'; +import { DirectLinks, Height, Width } from '../../../fields/DocSymbols'; import { Cast, DocCast, NumCast, PromiseValue, StrCast } from '../../../fields/Types'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnNone, setupMoveUpEvents } from '../../../Utils'; import { DocServer } from '../../DocServer'; diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index de0b57fd7..4919ee94c 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -61,7 +61,6 @@ const script = document.createElement('script'); script.defer = true; script.async = true; script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places,drawing`; -console.log(script.src); document.head.appendChild(script); /** diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 312b3c619..bbf56bdf9 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -224,7 +224,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl const aud_chunks: any = []; this._audioRec.ondataavailable = (e: any) => aud_chunks.push(e.data); this._audioRec.onstop = async (e: any) => { - const [{ result }] = await Networking.UploadFilesToServer(aud_chunks.map((file: any) => ({file}))); + const [{ result }] = await Networking.UploadFilesToServer(aud_chunks.map((file: any) => ({ file }))); if (!(result instanceof Error)) { this.dataDoc[this.props.fieldKey + '-audio'] = new AudioField(result.accessPaths.agnostic.client); } @@ -235,9 +235,8 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl this._videoRec.onstart = () => (this.dataDoc[this.props.fieldKey + '-recordingStart'] = new DateField(new Date())); this._videoRec.ondataavailable = (e: any) => vid_chunks.push(e.data); this._videoRec.onstop = async (e: any) => { - console.log('screenshotbox: upload'); const file = new File(vid_chunks, `${this.rootDoc[Id]}.mkv`, { type: vid_chunks[0].type, lastModified: Date.now() }); - const [{ result }] = await Networking.UploadFilesToServer({file}); + const [{ result }] = await Networking.UploadFilesToServer({ file }); this.dataDoc[this.fieldKey + '_duration'] = (new Date().getTime() - this.recordingStart!) / 1000; if (!(result instanceof Error)) { // convert this screenshotBox into normal videoBox diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx index 3ad3c911d..7c8a1849e 100644 --- a/src/client/views/nodes/ScriptingBox.tsx +++ b/src/client/views/nodes/ScriptingBox.tsx @@ -610,7 +610,6 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable ' ': { dataProvider: (token: any) => this.handleToken(token), component: (blob: any) => { - console.log('Blob', blob); return this.renderFuncListElement(blob.entity); }, output: (item: any, trigger: any) => { @@ -621,7 +620,6 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable '.': { dataProvider: (token: any) => this.handleToken(token), component: (blob: any) => { - console.log('Blob', blob); return this.renderFuncListElement(blob.entity); }, output: (item: any, trigger: any) => { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 895bb80f0..1dcc445e8 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -96,6 +96,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps private _scrollRef: React.RefObject<HTMLDivElement> = React.createRef(); private _editorView: Opt<EditorView>; public _applyingChange: string = ''; + private _finishingLink = false; private _searchIndex = 0; private _lastTimedMark: Mark | undefined = undefined; private _cachedLinks: Doc[] = []; @@ -245,7 +246,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps if (!pinProps && this._editorView?.state.selection.empty) return this.rootDoc; const anchor = Docs.Create.ConfigDocument({ title: StrCast(this.rootDoc.title), annotationOn: this.rootDoc }); this.addDocument(anchor); + this._finishingLink = true; this.makeLinkAnchor(anchor, OpenWhere.addRight, undefined, 'Anchored Selection', false, addAsAnnotation); + this._finishingLink = false; PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: true } }, this.rootDoc); return anchor; }; @@ -326,7 +329,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps textChange && (dataDoc[this.fieldKey + '_modificationDate'] = new DateField(new Date(Date.now()))); if ((!prevData && !protoData) || newText || (!newText && !templateData)) { // if no template, or there's text that didn't come from the layout template, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended) - if (this.props.isContentActive() && removeSelection(newJson) !== removeSelection(prevData?.Data)) { + if ((this._finishingLink || this.props.isContentActive()) && removeSelection(newJson) !== removeSelection(prevData?.Data)) { const numstring = NumCast(dataDoc[this.fieldKey], null); dataDoc[this.fieldKey] = numstring !== undefined ? Number(newText) : new RichTextField(newJson, newText); dataDoc[this.fieldKey + '_noTemplate'] = true; // mark the data field as being split from the template if it has been edited @@ -457,8 +460,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps if (node.firstChild === null && !node.marks.find((m: Mark) => m.type.name === schema.marks.noAutoLinkAnchor.name) && node.marks.find((m: Mark) => m.type.name === schema.marks.splitter.name)) { alink = alink ?? - (LinkManager.Links(this.Document).find(link => Doc.AreProtosEqual(Cast(link.link_anchor_1, Doc, null), this.rootDoc) && Doc.AreProtosEqual(Cast(link.link_anchor_2, Doc, null), target)) || - DocUtils.MakeLink(this.props.Document, target, { link_relationship: LinkManager.AutoKeywords })!); + (LinkManager.Links(this.rootDoc).find( + link => + Doc.AreProtosEqual(Cast(link.link_anchor_1, Doc, null), this.rootDoc) && // + Doc.AreProtosEqual(Cast(link.link_anchor_2, Doc, null), target) + ) || + DocUtils.MakeLink(this.rootDoc, target, { link_relationship: LinkManager.AutoKeywords })!); newAutoLinks.add(alink); const allAnchors = [{ href: Doc.localServerPath(target), title: 'a link', anchorId: this.props.Document[Id] }]; allAnchors.push(...(node.marks.find((m: Mark) => m.type.name === schema.marks.autoLinkAnchor.name)?.attrs.allAnchors ?? [])); @@ -840,7 +847,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps const appearance = cm.findByDescription('Appearance...'); const appearanceItems = appearance && 'subitems' in appearance ? appearance.subitems : []; - appearanceItems.push({ description: 'Change Perspective...', noexpand: true, subitems: changeItems, icon: 'external-link-alt' }); + appearanceItems.push({ description: 'Change Style...', noexpand: true, subitems: changeItems, icon: 'external-link-alt' }); // this.rootDoc.isTemplateDoc && appearanceItems.push({ description: "Make Default Layout", event: async () => Doc.UserDoc().defaultTextLayout = new PrefetchProxy(this.rootDoc), icon: "eye" }); !Doc.noviceMode && @@ -1996,12 +2003,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } cycleAlternateText = () => { if (this.layoutDoc._layout_enableAltContentUI) { - const usePath = this.rootDoc[`${this.props.fieldKey}_usePath`]; + const usePath = this.rootDoc[`_${this.props.fieldKey}_usePath`]; this.rootDoc[`_${this.props.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined; } }; @computed get overlayAlternateIcon() { - const usePath = this.rootDoc[`${this.props.fieldKey}_usePath`]; + const usePath = this.rootDoc[`_${this.props.fieldKey}_usePath`]; return ( <Tooltip title={ @@ -2080,7 +2087,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps ? {} : { transform: `scale(${scale})`, - transformOrigin: 'top left', width: `${100 / scale}%`, height: `${100 / scale}%`, }), diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index ac1e7ce5d..8bafc2cef 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -243,13 +243,13 @@ export class RichTextRules { // create a text display of a metadata field on this or another document, or create a hyperlink portal to another document // [[<fieldKey> : <Doc>]] - // [[:Doc]] => hyperlink + // [[:docTitle]] => hyperlink // [[fieldKey]] => show field // [[fieldKey=value]] => show field and also set its value - // [[fieldKey:Doc]] => show field of doc + // [[fieldKey:docTitle]] => show field of doc new InputRule(new RegExp(/\[\[([a-zA-Z_\? \-0-9]*)(=[a-zA-Z_@\? /\-0-9]*)?(:[a-zA-Z_@:\.\? \-0-9]+)?\]\]$/), (state, match, start, end) => { const fieldKey = match[1]; - const docId = match[3]?.replace(':', ''); + const docTitle = match[3]?.replace(':', ''); const value = match[2]?.substring(1); const linkToDoc = (target: Doc) => { const rstate = this.TextBox.EditorView?.state; @@ -266,12 +266,12 @@ export class RichTextRules { } }; if (!fieldKey) { - if (docId) { - const target = DocServer.QUERY_SERVER_CACHE(docId); - if (target) setTimeout(() => linkToDoc(target)); - else DocServer.GetRefField(docId).then(docx => linkToDoc((docx instanceof Doc && docx) || Docs.Create.FreeformDocument([], { title: docId + '(auto)', _width: 500, _height: 500 }, docId))); - - return state.tr.deleteRange(end - 1, end).deleteRange(start, start + 3); + if (docTitle) { + const target = DocServer.FindDocByTitle(docTitle); + if (target) { + setTimeout(() => linkToDoc(target)); + return state.tr.deleteRange(end - 1, end).deleteRange(start, start + 3); + } } return state.tr; } @@ -279,8 +279,12 @@ export class RichTextRules { const num = value.match(/^[0-9.]$/); this.Document[DocData][fieldKey] = value === 'true' ? true : value === 'false' ? false : num ? Number(value) : value; } - const fieldView = state.schema.nodes.dashField.create({ fieldKey, docId, hideKey: false }); - return state.tr.setSelection(new TextSelection(state.doc.resolve(start), state.doc.resolve(end))).replaceSelectionWith(fieldView, true); + const target = DocServer.FindDocByTitle(docTitle); + if (target) { + const fieldView = state.schema.nodes.dashField.create({ fieldKey, docId: target[Id], hideKey: false }); + return state.tr.setSelection(new TextSelection(state.doc.resolve(start), state.doc.resolve(end))).replaceSelectionWith(fieldView, true); + } + return state.tr; }), // create a text display of a metadata field on this or another document, or create a hyperlink portal to another document diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index b877cc36a..e35e011e2 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -17,6 +17,7 @@ import { EditorView } from 'prosemirror-view'; import './AnchorMenu.scss'; import { ColorPicker, Group, IconButton, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components'; import { StrCast } from '../../../fields/Types'; +import { DocumentType } from '../../documents/DocumentTypes'; @observer export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { @@ -262,7 +263,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { colorPicker={this.highlightColor} color={StrCast(Doc.UserDoc().userColor)} /> - <ColorPicker colorPickerType={'github'} selectedColor={this.highlightColor} setSelectedColor={color => this.changeHighlightColor(color)} size={Size.XSMALL} /> + <ColorPicker selectedColor={this.highlightColor} setSelectedColor={this.changeHighlightColor} size={Size.XSMALL} /> </Group> ); } @@ -287,7 +288,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { canSummarize = (): boolean => { const docs = SelectionManager.Docs(); if (docs.length > 0) { - return docs.some(doc => doc.type === 'pdf' || doc.type === 'web'); + return docs.some(doc => doc.type === DocumentType.PDF || doc.type === DocumentType.WEB); } return false; }; diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index e911bd283..a28561107 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -18,6 +18,7 @@ import './SearchBox.scss'; import { fetchRecommendations } from '../newlightbox/utils'; import { IRecommendation, Recommendation } from '../newlightbox/components'; import { Colors } from '../global/globalEnums'; +import { SettingsManager } from '../../util/SettingsManager'; const DAMPENING_FACTOR = 0.9; const MAX_ITERATIONS = 25; @@ -218,7 +219,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() { } @action static staticSearchCollection(rootDoc: Opt<Doc>, query: string) { - const blockedTypes = [DocumentType.PRESELEMENT, DocumentType.CONFIG, DocumentType.KVP, DocumentType.FILTER, DocumentType.SEARCH, DocumentType.SEARCHITEM, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING]; + const blockedTypes = [DocumentType.PRESELEMENT, DocumentType.CONFIG, DocumentType.KVP, DocumentType.SEARCH, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING]; const blockedKeys = [ 'x', 'y', @@ -398,22 +399,21 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() { if (query) { this.searchCollection(query); - const response = await fetchRecommendations('', query, [], true) - const recs = response.recommendations - const recommendations:IRecommendation[] = [] + const response = await fetchRecommendations('', query, [], true); + const recs = response.recommendations; + const recommendations: IRecommendation[] = []; for (const key in recs) { const title = recs[key].title; - console.log(title); - const url = recs[key].url - const type = recs[key].type - const text = recs[key].text - const transcript = recs[key].transcript - const previewUrl = recs[key].previewUrl - const embedding = recs[key].embedding - const distance = recs[key].distance - const source = recs[key].source - const related_concepts = recs[key].related_concepts - const docId = recs[key].doc_id + const url = recs[key].url; + const type = recs[key].type; + const text = recs[key].text; + const transcript = recs[key].transcript; + const previewUrl = recs[key].previewUrl; + const embedding = recs[key].embedding; + const distance = recs[key].distance; + const source = recs[key].source; + const related_concepts = recs[key].related_concepts; + const docId = recs[key].doc_id; recommendations.push({ title: title, data: url, @@ -425,11 +425,11 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() { distance: Math.round(distance * 100) / 100, source: source, related_concepts: related_concepts, - docId: docId - }) + docId: docId, + }); } - const setRecommendations = action(() => this._recommendations = recommendations) - setRecommendations() + const setRecommendations = action(() => (this._recommendations = recommendations)); + setRecommendations(); } }; @@ -461,7 +461,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() { */ @computed public get selectOptions() { - const selectValues = ['all', 'rtf', 'image', 'pdf', 'web', 'video', 'audio', 'collection']; + const selectValues = ['all', DocumentType.RTF, DocumentType.IMG, DocumentType.PDF, DocumentType.WEB, DocumentType.VID, DocumentType.AUDIO, DocumentType.COL]; return selectValues.map(value => ( <option key={value} value={value}> @@ -517,19 +517,19 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() { className={className}> <div className="searchBox-result-title">{title as string}</div> <div className="searchBox-result-type">{formattedType}</div> - <div className="searchBox-result-keys">{result[1].join(', ')}</div> + <div className="searchBox-result-keys" style={{ color: SettingsManager.Instance.userVariantColor }}> + {result[1].join(', ')} + </div> </div> </Tooltip> ); } }); - const recommendationsJSX: JSX.Element[] = this._recommendations.map((props) => ( - <Recommendation {...props}/> - )) + const recommendationsJSX: JSX.Element[] = this._recommendations.map(props => <Recommendation {...props} />); return ( - <div className="searchBox-container" style={{pointerEvents: 'all', background: StrCast(Doc.UserDoc().userBackgroundColor)}}> + <div className="searchBox-container" style={{ pointerEvents: 'all', color: SettingsManager.Instance.userColor, background: SettingsManager.Instance.userBackgroundColor }}> <div className="searchBox-bar"> {isLinkSearch ? null : ( <select name="type" id="searchBox-type" className="searchBox-type" onChange={this.onSelectChange}> @@ -552,20 +552,24 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() { ref={this._inputRef} /> </div> - {resultsJSX.length > 0 && <div className="searchBox-results-container"> - <div className="section-header" style={{background: StrCast(Doc.UserDoc().userVariantColor, Colors.MEDIUM_BLUE)}}> - <div className="section-title">Results</div> - <div className="section-subtitle">{`${validResults}` + ' result' + (validResults === 1 ? '' : 's')}</div> + {resultsJSX.length > 0 && ( + <div className="searchBox-results-container"> + <div className="section-header" style={{ background: StrCast(Doc.UserDoc().userVariantColor, Colors.MEDIUM_BLUE) }}> + <div className="section-title">Results</div> + <div className="section-subtitle">{`${validResults}` + ' result' + (validResults === 1 ? '' : 's')}</div> + </div> + <div className="searchBox-results-view">{resultsJSX}</div> </div> - <div className="searchBox-results-view">{resultsJSX}</div> - </div>} - {recommendationsJSX.length > 0 && <div className="searchBox-recommendations-container"> - <div className="section-header" style={{background: StrCast(Doc.UserDoc().userVariantColor, Colors.MEDIUM_BLUE)}}> - <div className="section-title">Recommendations</div> - <div className="section-subtitle">{`${validResults}` + ' result' + (validResults === 1 ? '' : 's')}</div> + )} + {recommendationsJSX.length > 0 && ( + <div className="searchBox-recommendations-container"> + <div className="section-header" style={{ background: StrCast(Doc.UserDoc().userVariantColor, Colors.MEDIUM_BLUE) }}> + <div className="section-title">Recommendations</div> + <div className="section-subtitle">{`${validResults}` + ' result' + (validResults === 1 ? '' : 's')}</div> + </div> + <div className="searchBox-recommendations-view">{recommendationsJSX}</div> </div> - <div className="searchBox-recommendations-view">{recommendationsJSX}</div> - </div>} + )} </div> ); } diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index cb8eda9de..8caba930d 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -35,10 +35,14 @@ export class TopBar extends React.Component { }); }; - @computed get color() { return StrCast(Doc.UserDoc().userColor, Colors.LIGHT_GRAY); } - @computed get variantColor() { return StrCast(Doc.UserDoc().userVariantColor, Colors.MEDIUM_BLUE); } + @computed get color() { + return StrCast(Doc.UserDoc().userColor, Colors.LIGHT_GRAY); + } + @computed get variantColor() { + return StrCast(Doc.UserDoc().userVariantColor, Colors.MEDIUM_BLUE); + } @computed get backgroundColor() { - return PingManager.Instance.IsBeating ? StrCast(Doc.UserDoc().userBackgroundColor, Colors.DARK_GRAY) : Colors.MEDIUM_GRAY; + return PingManager.Instance.IsBeating ? SettingsManager.Instance.userBackgroundColor : Colors.MEDIUM_GRAY; } @observable happyHeart: boolean = PingManager.Instance.IsBeating; @@ -102,7 +106,7 @@ export class TopBar extends React.Component { tooltip="Open Dashboards" size={Size.SMALL} color={this.color} - style={{fontWeight: 700, fontSize: '1rem'}} + style={{ fontWeight: 700, fontSize: '1rem' }} onClick={(e: React.MouseEvent) => { const dashView = Doc.ActiveDashboard && DocumentManager.Instance.getDocumentView(Doc.ActiveDashboard); ContextMenu.Instance.addItem({ description: 'Open Dashboard View', event: this.navigateToHome, icon: 'edit' }); @@ -134,7 +138,7 @@ export class TopBar extends React.Component { @computed get topbarRight() { return ( <div className="topbar-right"> - {Doc.ActiveDashboard ? + {Doc.ActiveDashboard ? ( <Button text={GetEffectiveAcl(Doc.ActiveDashboard) === AclAdmin ? 'Share' : 'View Original'} type={Type.TERT} @@ -143,15 +147,15 @@ export class TopBar extends React.Component { SharingManager.Instance.open(undefined, Doc.ActiveDashboard); }} /> - : null } - <IconButton tooltip={"Issue Reporter ⌘I"} size={Size.SMALL} color={this.color} onClick={ReportManager.Instance.open} icon={<FaBug />} /> - <IconButton tooltip={"Documentation ⌘D"} size={Size.SMALL} color={this.color} onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/', '_blank')} icon={<FontAwesomeIcon icon="question-circle" />} /> - <IconButton tooltip={"Settings ⌘⇧S"} size={Size.SMALL} color={this.color} onClick={SettingsManager.Instance.open} icon={<FontAwesomeIcon icon="cog" />} /> + ) : null} + <IconButton tooltip={'Issue Reporter ⌘I'} size={Size.SMALL} color={this.color} onClick={ReportManager.Instance.open} icon={<FaBug />} /> + <IconButton tooltip={'Documentation ⌘D'} size={Size.SMALL} color={this.color} onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/', '_blank')} icon={<FontAwesomeIcon icon="question-circle" />} /> + <IconButton tooltip={'Settings ⌘⇧S'} size={Size.SMALL} color={this.color} onClick={SettingsManager.Instance.open} icon={<FontAwesomeIcon icon="cog" />} /> <IconButton size={Size.SMALL} onClick={ServerStats.Instance.open} type={Type.TERT} - tooltip={'Server is ' + (PingManager.Instance.IsBeating ? '' : 'NOT ') + 'running'} + tooltip={'Server is ' + (PingManager.Instance.IsBeating ? '' : 'NOT ') + 'running ' + SettingsManager.Version} color={this.happyHeart ? Colors.LIGHT_BLUE : Colors.ERROR_RED} icon={<FontAwesomeIcon icon={this.happyHeart ? 'heart' : 'heart-broken'} />} /> @@ -163,12 +167,14 @@ export class TopBar extends React.Component { render() { return ( //TODO:glr Add support for light / dark mode - <div style={{ - pointerEvents: 'all', - color: this.color, - background: this.backgroundColor, - // borderColor: this.color - }} className="topbar-container"> + <div + style={{ + pointerEvents: 'all', + color: this.color, + background: this.backgroundColor, + // borderColor: this.color + }} + className="topbar-container"> <div className="topbar-inner-container"> {this.topbarLeft} {this.topbarCenter} |
