aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/newlightbox
diff options
context:
space:
mode:
authorSophie Zhang <sophie_zhang@brown.edu>2023-09-18 17:40:01 -0400
committerSophie Zhang <sophie_zhang@brown.edu>2023-09-18 17:40:01 -0400
commit013f25f01e729feee5db94900c61f4be4dd46869 (patch)
tree765dd5f2e06d6217ca79438e1098cefc8da627bf /src/client/views/newlightbox
parentf5e765adff1e7b32250eb503c9724a4ac99117f3 (diff)
parent84aa8806a62e2e957e8281d7d492139e3d8225f2 (diff)
Merge branch 'master' into sophie-report-manager
Diffstat (limited to 'src/client/views/newlightbox')
-rw-r--r--src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx92
-rw-r--r--src/client/views/newlightbox/ExploreView/ExploreView.tsx50
-rw-r--r--src/client/views/newlightbox/NewLightboxView.tsx139
-rw-r--r--src/client/views/newlightbox/components/Recommendation/Recommendation.tsx170
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
+ );
+};