diff options
| author | Sophie Zhang <sophie_zhang@brown.edu> | 2023-09-18 17:40:01 -0400 |
|---|---|---|
| committer | Sophie Zhang <sophie_zhang@brown.edu> | 2023-09-18 17:40:01 -0400 |
| commit | 013f25f01e729feee5db94900c61f4be4dd46869 (patch) | |
| tree | 765dd5f2e06d6217ca79438e1098cefc8da627bf /src/client/views/newlightbox | |
| parent | f5e765adff1e7b32250eb503c9724a4ac99117f3 (diff) | |
| parent | 84aa8806a62e2e957e8281d7d492139e3d8225f2 (diff) | |
Merge branch 'master' into sophie-report-manager
Diffstat (limited to 'src/client/views/newlightbox')
4 files changed, 230 insertions, 221 deletions
diff --git a/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx b/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx index 0ede75407..3a95e5f74 100644 --- a/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx +++ b/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx @@ -1,53 +1,49 @@ -import './ButtonMenu.scss'; +import { action } from 'mobx'; import * as React from 'react'; -import { IButtonMenu } from "./utils"; -import { NewLightboxView } from '../NewLightboxView'; -import { SelectionManager } from '../../../util/SelectionManager'; -import { CollectionDockingView } from '../../collections/CollectionDockingView'; -import { OpenWhereMod } from '../../nodes/DocumentView'; import { Doc } from '../../../../fields/Doc'; import { InkTool } from '../../../../fields/InkField'; -import { MainView } from '../../MainView'; -import { action } from 'mobx'; +import { SelectionManager } from '../../../util/SelectionManager'; +import { CollectionDockingView } from '../../collections/CollectionDockingView'; +import { DocumentView, OpenWhereMod } from '../../nodes/DocumentView'; +import { NewLightboxView } from '../NewLightboxView'; +import './ButtonMenu.scss'; +import { IButtonMenu } from './utils'; export const ButtonMenu = (props: IButtonMenu) => { - - return <div className={`newLightboxButtonMenu-container`}> - <div - className="newLightboxView-navBtn" - title="toggle fit width" - onClick={e => { - e.stopPropagation(); - NewLightboxView.NewLightboxDoc!._fitWidth = !NewLightboxView.NewLightboxDoc!._fitWidth; - }}> - </div> - <div - className="newLightboxView-tabBtn" - title="open in tab" - onClick={e => { - e.stopPropagation(); - CollectionDockingView.AddSplit(NewLightboxView.NewLightboxDoc || NewLightboxView.NewLightboxDoc!, OpenWhereMod.none); - SelectionManager.DeselectAll(); - NewLightboxView.SetNewLightboxDoc(undefined); - }}> - </div> - <div - className="newLightboxView-penBtn" - title="toggle pen annotation" - style={{ background: Doc.ActiveTool === InkTool.Pen ? 'white' : undefined }} - onClick={e => { - e.stopPropagation(); - Doc.ActiveTool = Doc.ActiveTool === InkTool.Pen ? InkTool.None : InkTool.Pen; - }}> - </div> - <div - className="newLightboxView-exploreBtn" - title="toggle explore mode to navigate among documents only" - style={{ background: MainView.Instance._exploreMode ? 'white' : undefined }} - onClick={action(e => { - e.stopPropagation(); - MainView.Instance._exploreMode = !MainView.Instance._exploreMode; - })}> - </div> - </div> -}
\ No newline at end of file + return ( + <div className={`newLightboxButtonMenu-container`}> + <div + className="newLightboxView-navBtn" + title="toggle fit width" + onClick={e => { + e.stopPropagation(); + NewLightboxView.LightboxDoc!._fitWidth = !NewLightboxView.LightboxDoc!._fitWidth; + }}></div> + <div + className="newLightboxView-tabBtn" + title="open in tab" + onClick={e => { + e.stopPropagation(); + CollectionDockingView.AddSplit(NewLightboxView.LightboxDoc || NewLightboxView.LightboxDoc!, OpenWhereMod.none); + SelectionManager.DeselectAll(); + NewLightboxView.SetNewLightboxDoc(undefined); + }}></div> + <div + className="newLightboxView-penBtn" + title="toggle pen annotation" + style={{ background: Doc.ActiveTool === InkTool.Pen ? 'white' : undefined }} + onClick={e => { + e.stopPropagation(); + Doc.ActiveTool = Doc.ActiveTool === InkTool.Pen ? InkTool.None : InkTool.Pen; + }}></div> + <div + className="newLightboxView-exploreBtn" + title="toggle explore mode to navigate among documents only" + style={{ background: DocumentView.ExploreMode ? 'white' : undefined }} + onClick={action(e => { + e.stopPropagation(); + DocumentView.ExploreMode = !DocumentView.ExploreMode; + })}></div> + </div> + ); +}; diff --git a/src/client/views/newlightbox/ExploreView/ExploreView.tsx b/src/client/views/newlightbox/ExploreView/ExploreView.tsx index 855bfd9e2..a1d6375c4 100644 --- a/src/client/views/newlightbox/ExploreView/ExploreView.tsx +++ b/src/client/views/newlightbox/ExploreView/ExploreView.tsx @@ -1,30 +1,32 @@ import './ExploreView.scss'; -import { IBounds, IExploreView, emptyBounds } from "./utils"; -import { IRecommendation } from "../components"; +import { IBounds, IExploreView, emptyBounds } from './utils'; +import { IRecommendation } from '../components'; import * as React from 'react'; import { NewLightboxView } from '../NewLightboxView'; import { StrCast } from '../../../../fields/Types'; - - export const ExploreView = (props: IExploreView) => { - const { recs, bounds=emptyBounds } = props - - return <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} - </div> - } else return (null) - })} - <div className={`exploreView-doc`} style={{top: `calc(50% + ${0}%)`, left: `calc(50% + ${0}%)`, background: '#073763', color: 'white'}}>{StrCast(NewLightboxView.NewLightboxDoc?.title)}</div> - </div> -}
\ No newline at end of file + const { recs, bounds = emptyBounds } = props; + + return ( + <div className={`exploreView-container`}> + {recs && + recs.map(rec => { + 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)); + if (rec.embedding) { + const x = (rec.embedding.x / x_bound) * 50; + const y = (rec.embedding.y / y_bound) * 50; + return ( + <div className={`exploreView-doc`} onClick={() => {}} style={{ top: `calc(50% + ${y}%)`, left: `calc(50% + ${x}%)` }}> + {rec.title} + </div> + ); + } else return null; + })} + <div className={`exploreView-doc`} style={{ top: `calc(50% + ${0}%)`, left: `calc(50% + ${0}%)`, background: '#073763', color: 'white' }}> + {StrCast(NewLightboxView.LightboxDoc?.title)} + </div> + </div> + ); +}; diff --git a/src/client/views/newlightbox/NewLightboxView.tsx b/src/client/views/newlightbox/NewLightboxView.tsx index 3acbd1a32..ca90f6a0f 100644 --- a/src/client/views/newlightbox/NewLightboxView.tsx +++ b/src/client/views/newlightbox/NewLightboxView.tsx @@ -2,35 +2,32 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue } from '../../../Utils'; -import { Doc, DocListCast, Opt, StrListCast } from '../../../fields/Doc'; +import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { InkTool } from '../../../fields/InkField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue } from '../../../Utils'; import { DocUtils } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { LinkManager } from '../../util/LinkManager'; import { SelectionManager } from '../../util/SelectionManager'; import { Transform } from '../../util/Transform'; -import { GestureOverlay } from '../GestureOverlay'; -import { MainView } from '../MainView'; -import { DefaultStyleProvider } from '../StyleProvider'; import { CollectionStackedTimeline } from '../collections/CollectionStackedTimeline'; import { TabDocView } from '../collections/TabDocView'; +import { GestureOverlay } from '../GestureOverlay'; +import { LightboxView } from '../LightboxView'; import { DocumentView, OpenWhere } from '../nodes/DocumentView'; +import { DefaultStyleProvider } from '../StyleProvider'; +import { IRecommendation } from './components'; import { ExploreView } from './ExploreView'; -import { IBounds, emptyBounds } from './ExploreView/utils'; +import { emptyBounds, IBounds } from './ExploreView/utils'; import { NewLightboxHeader } from './Header'; import './NewLightboxView.scss'; import { RecommendationList } from './RecommendationList'; -import { IRecommendation } from './components'; -import { fetchKeywords, fetchRecommendations } from './utils'; -import { List } from '../../../fields/List'; -import { LightboxView } from '../LightboxView'; enum LightboxStatus { - RECOMMENDATIONS = "recommendations", - ANNOTATIONS = "annotations", - NONE = "none" + RECOMMENDATIONS = 'recommendations', + ANNOTATIONS = 'annotations', + NONE = 'none', } interface LightboxViewProps { @@ -63,30 +60,30 @@ export class NewLightboxView extends React.Component<LightboxViewProps> { @observable private static _docView: Opt<DocumentView>; // keywords - @observable private static _keywords: string[] = [] + @observable private static _keywords: string[] = []; @action public static SetKeywords(kw: string[]) { - this._keywords = kw + this._keywords = kw; } @computed public static get Keywords() { - return this._keywords + return this._keywords; } // query - @observable private static _query: string = '' + @observable private static _query: string = ''; @action public static SetQuery(query: string) { - this._query = query + this._query = query; } @computed public static get Query() { - return this._query + return this._query; } // keywords - @observable private static _recs: IRecommendation[] = [] + @observable private static _recs: IRecommendation[] = []; @action public static SetRecs(recs: IRecommendation[]) { - this._recs = recs + this._recs = recs; } @computed public static get Recs() { - return this._recs + return this._recs; } // bounds @@ -108,7 +105,7 @@ export class NewLightboxView extends React.Component<LightboxViewProps> { } // newLightbox sidebar status - @observable private static _sidebarStatus: Opt<string> = ""; + @observable private static _sidebarStatus: Opt<string> = ''; @action public static SetSidebarStatus(sidebarStatus: Opt<string>) { this._sidebarStatus = sidebarStatus; } @@ -129,7 +126,7 @@ export class NewLightboxView extends React.Component<LightboxViewProps> { this._docFilters && (this._docFilters.length = 0); this._future = this._history = []; Doc.ActiveTool = InkTool.None; - MainView.Instance._exploreMode = false; + DocumentView.ExploreMode = false; } else { const l = DocUtils.MakeLinkToActiveAudio(() => doc).lastElement(); l && (Cast(l.link_anchor_2, Doc, null).backgroundColor = 'lightgreen'); @@ -289,35 +286,38 @@ export class NewLightboxView extends React.Component<LightboxViewProps> { @computed get documentView() { - if (!LightboxView.LightboxDoc) return null - else return (<GestureOverlay isActive={true}> - <DocumentView - ref={action((r: DocumentView | null) => (NewLightboxView._docView = r !== null ? r : undefined))} - Document={LightboxView.LightboxDoc} - DataDoc={undefined} - PanelWidth={this.newLightboxWidth} - PanelHeight={this.newLightboxHeight} - LayoutTemplate={NewLightboxView.LightboxDocTemplate} - isDocumentActive={returnTrue} // without this being true, sidebar annotations need to be activated before text can be selected. - isContentActive={returnTrue} - styleProvider={DefaultStyleProvider} - ScreenToLocalTransform={this.newLightboxScreenToLocal} - renderDepth={0} - rootSelected={returnTrue} - docViewPath={returnEmptyDoclist} - childFilters={this.docFilters} - childFiltersByRanges={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - addDocument={undefined} - removeDocument={undefined} - whenChildContentsActiveChanged={emptyFunction} - addDocTab={this.addDocTab} - pinToPres={TabDocView.PinDoc} - bringToFront={emptyFunction} - onBrowseClick={MainView.Instance.exploreMode} - focus={emptyFunction} - /> - </GestureOverlay>) + if (!LightboxView.LightboxDoc) return null; + else + return ( + <GestureOverlay isActive={true}> + <DocumentView + ref={action((r: DocumentView | null) => (NewLightboxView._docView = r !== null ? r : undefined))} + Document={LightboxView.LightboxDoc} + DataDoc={undefined} + PanelWidth={this.newLightboxWidth} + PanelHeight={this.newLightboxHeight} + LayoutTemplate={NewLightboxView.LightboxDocTemplate} + isDocumentActive={returnTrue} // without this being true, sidebar annotations need to be activated before text can be selected. + isContentActive={returnTrue} + styleProvider={DefaultStyleProvider} + ScreenToLocalTransform={this.newLightboxScreenToLocal} + renderDepth={0} + rootSelected={returnTrue} + docViewPath={returnEmptyDoclist} + childFilters={this.docFilters} + childFiltersByRanges={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} + addDocument={undefined} + removeDocument={undefined} + whenChildContentsActiveChanged={emptyFunction} + addDocTab={this.addDocTab} + pinToPres={TabDocView.PinDoc} + bringToFront={emptyFunction} + onBrowseClick={DocumentView.exploreMode} + focus={emptyFunction} + /> + </GestureOverlay> + ); } future = () => NewLightboxView._future; @@ -337,29 +337,28 @@ export class NewLightboxView extends React.Component<LightboxViewProps> { NewLightboxView.SetNewLightboxDoc(undefined); } }}> - <div className={`app-document`} style={{gridTemplateColumns: `calc(100% - 400px) 400px`}}> - <div - className="newLightboxView-contents" - style={{ - top: 20, - left: 20, - width: this.newLightboxWidth(), - height: this.newLightboxHeight() - 40, - }}> + <div className={`app-document`} style={{ gridTemplateColumns: `calc(100% - 400px) 400px` }}> + <div + className="newLightboxView-contents" + style={{ + top: 20, + left: 20, + width: this.newLightboxWidth(), + height: this.newLightboxHeight() - 40, + }}> <NewLightboxHeader height={newLightboxHeaderHeight} width={this.newLightboxWidth()} /> - {!NewLightboxView._explore ? - <div className="newLightboxView-doc" style={{height: this.newLightboxHeight()}}> + {!NewLightboxView._explore ? ( + <div className="newLightboxView-doc" style={{ height: this.newLightboxHeight() }}> {this.documentView} </div> - : + ) : ( <div className={`explore`}> - <ExploreView recs={NewLightboxView.Recs} bounds={NewLightboxView.Bounds}/> + <ExploreView recs={NewLightboxView.Recs} bounds={NewLightboxView.Bounds} /> </div> - } - </div> - <RecommendationList keywords={NewLightboxView.Keywords}/> + )} + </div> + <RecommendationList keywords={NewLightboxView.Keywords} /> </div> - </div> ); } diff --git a/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx b/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx index c0d357ad5..96846673b 100644 --- a/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx +++ b/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { IRecommendation } from "./utils"; +import { IRecommendation } from './utils'; import './Recommendation.scss'; import { getType } from '../../utils'; import { FaEyeSlash } from 'react-icons/fa'; @@ -9,82 +9,94 @@ import { Doc } from '../../../../../fields/Doc'; import { Docs } from '../../../../documents/Documents'; export const Recommendation = (props: IRecommendation) => { - const {title, data, type, text, transcript, loading, source, previewUrl, related_concepts, distance, docId} = props - - return <div className={`recommendation-container ${loading && 'loading'} ${previewUrl && 'previewUrl'}`} onClick={() => { - let doc: Doc | null = null; - if (source == "Dash" && docId) { - const docView = DocumentManager.Instance.getDocumentViewById(docId) - if (docView) { - doc = docView.rootDoc; - } - } else if (data) { - console.log(data, type) - switch(type) { - case "YouTube": - console.log('create ', type, 'document') - doc = Docs.Create.VideoDocument(data, { title: title, _width: 400, _height: 315, transcript: transcript }) - break; - case "Video": - console.log('create ', type, 'document') - doc = Docs.Create.VideoDocument(data, { title: title, _width: 400, _height: 315, transcript: transcript }) - break; - case "Webpage": - console.log('create ', type, 'document') - doc = Docs.Create.WebDocument(data, { title: title, text: text }) - break; - case "HTML": - console.log('create ', type, 'document') - doc = Docs.Create.WebDocument(data, { title: title, text: text }) - break; - case "Text": - console.log('create ', type, 'document') - doc = Docs.Create.TextDocument(data, { title: title, text: text }) - break; - case "PDF": - console.log('create ', type, 'document') - doc = Docs.Create.PdfDocument(data, { title: title, text: text }) - break; - } - } - if (doc !== null) NewLightboxView.SetNewLightboxDoc(doc) - }}> - {loading ? - <div className={`image-container`}> - </div> - : - previewUrl ? <div className={`image-container`}> - {<img className={`image`} src={previewUrl}></img>} - </div> - : null - } - <div className={`title`}>{title}</div> - <div className={`info`}> - {!loading && <div className={`type-container`}> - <div className={`lb-label`}>Type</div><div className={`lb-type`}>{getType(type!)}</div> - </div>} - {!loading && <div className={`distance-container`}> - <div className={`lb-label`}>Distance</div><div className={`lb-distance`}>{distance}</div> - </div>} - </div> - <div className={`source`}> - {!loading && <div className={`source-container`}> - <div className={`lb-label`}>Source</div><div className={`lb-source`}>{source}</div> - </div>} - </div> - <div className={`explainer`}> - {!loading && - <div> - You are seeing this recommendation because this document also explores - <div className={`concepts-container`}> - {related_concepts?.map((val) => { - return <div className={'concept'}>{val}</div> - })} - </div> - </div>} - </div> - <div className={`hide-rec`}> - {!loading && <><div>Hide Recommendation</div><div style={{fontSize: 15, paddingRight: 5}}><FaEyeSlash/></div></>} + const { title, data, type, text, transcript, loading, source, previewUrl, related_concepts, distance, docId } = props; + + return ( + <div + className={`recommendation-container ${loading && 'loading'} ${previewUrl && 'previewUrl'}`} + onClick={() => { + let doc: Doc | null = null; + if (source == 'Dash' && docId) { + const docView = DocumentManager.Instance.getDocumentViewsById(docId).lastElement(); + if (docView) { + doc = docView.rootDoc; + } + } else if (data) { + switch (type) { + case 'YouTube': + console.log('create ', type, 'document'); + doc = Docs.Create.VideoDocument(data, { title: title, _width: 400, _height: 315, transcript }); + break; + case 'Video': + console.log('create ', type, 'document'); + doc = Docs.Create.VideoDocument(data, { title: title, _width: 400, _height: 315, transcript }); + break; + case 'Webpage': + console.log('create ', type, 'document'); + doc = Docs.Create.WebDocument(data, { title: title, text: text }); + break; + case 'HTML': + console.log('create ', type, 'document'); + doc = Docs.Create.WebDocument(data, { title: title, text: text }); + break; + case 'Text': + console.log('create ', type, 'document'); + doc = Docs.Create.TextDocument(data, { title: title, text: text }); + break; + case 'PDF': + console.log('create ', type, 'document'); + doc = Docs.Create.PdfDocument(data, { title: title, text: text }); + break; + } + } + if (doc !== null) NewLightboxView.SetNewLightboxDoc(doc); + }}> + {loading ? <div className={`image-container`}></div> : previewUrl ? <div className={`image-container`}>{<img className={`image`} src={previewUrl}></img>}</div> : null} + <div className={`title`}>{title}</div> + <div className={`info`}> + {!loading && ( + <div className={`type-container`}> + <div className={`lb-label`}>Type</div> + <div className={`lb-type`}>{getType(type!)}</div> + </div> + )} + {!loading && ( + <div className={`distance-container`}> + <div className={`lb-label`}>Distance</div> + <div className={`lb-distance`}>{distance}</div> + </div> + )} + </div> + <div className={`source`}> + {!loading && ( + <div className={`source-container`}> + <div className={`lb-label`}>Source</div> + <div className={`lb-source`}>{source}</div> + </div> + )} + </div> + <div className={`explainer`}> + {!loading && ( + <div> + You are seeing this recommendation because this document also explores + <div className={`concepts-container`}> + {related_concepts?.map(val => { + return <div className={'concept'}>{val}</div>; + })} + </div> + </div> + )} + </div> + <div className={`hide-rec`}> + {!loading && ( + <> + <div>Hide Recommendation</div> + <div style={{ fontSize: 15, paddingRight: 5 }}> + <FaEyeSlash /> + </div> + </> + )} + </div> </div> - </div> -}
\ No newline at end of file + ); +}; |
