From b285803c4e8c37302f6e02624a6127667d628305 Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Tue, 25 Jun 2019 19:49:54 -0400 Subject: Youtube Api Exploration --- src/client/documents/Documents.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ab61b915c..fd4532807 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -23,7 +23,7 @@ import { MINIMIZED_ICON_SIZE } from "../views/globalCssVariables.scss"; import { IconBox } from "../views/nodes/IconBox"; import { Field, Doc, Opt } from "../../new_fields/Doc"; import { OmitKeys } from "../../Utils"; -import { ImageField, VideoField, AudioField, PdfField, WebField } from "../../new_fields/URLField"; +import { ImageField, VideoField, AudioField, PdfField, WebField, YoutubeField } from "../../new_fields/URLField"; import { HtmlField } from "../../new_fields/HtmlField"; import { List } from "../../new_fields/List"; import { Cast, NumCast } from "../../new_fields/Types"; @@ -35,6 +35,8 @@ import { dropActionType } from "../util/DragManager"; import { DateField } from "../../new_fields/DateField"; import { UndoManager } from "../util/UndoManager"; import { RouteStore } from "../../server/RouteStore"; +import { createInstance } from "@react-pdf/renderer"; +import { YoutubeBox } from "../apis/youtube/YoutubeBox"; var requestImageSize = require('request-image-size'); var path = require('path'); @@ -113,6 +115,7 @@ export namespace Docs { let audioProto: Doc; let pdfProto: Doc; let iconProto: Doc; + let youtubeProto: Doc; const textProtoId = "textProto"; const histoProtoId = "histoProto"; const pdfProtoId = "pdfProto"; @@ -123,9 +126,10 @@ export namespace Docs { const videoProtoId = "videoProto"; const audioProtoId = "audioProto"; const iconProtoId = "iconProto"; + const youtubeProtoId = "youtubeProto"; export function initProtos(): Promise { - return DocServer.GetRefFields([textProtoId, histoProtoId, collProtoId, imageProtoId, webProtoId, kvpProtoId, videoProtoId, audioProtoId, pdfProtoId, iconProtoId]).then(fields => { + return DocServer.GetRefFields([textProtoId, histoProtoId, collProtoId, imageProtoId, webProtoId, kvpProtoId, videoProtoId, audioProtoId, pdfProtoId, iconProtoId, youtubeProtoId]).then(fields => { textProto = fields[textProtoId] as Doc || CreateTextPrototype(); histoProto = fields[histoProtoId] as Doc || CreateHistogramPrototype(); collProto = fields[collProtoId] as Doc || CreateCollectionPrototype(); @@ -136,6 +140,7 @@ export namespace Docs { audioProto = fields[audioProtoId] as Doc || CreateAudioPrototype(); pdfProto = fields[pdfProtoId] as Doc || CreatePdfPrototype(); iconProto = fields[iconProtoId] as Doc || CreateIconPrototype(); + youtubeProto = fields[youtubeProtoId] as Doc || CreateYoutubePrototype(); }); } @@ -183,6 +188,13 @@ export namespace Docs { { x: 0, y: 0, width: 300, height: 300 }); return webProto; } + function CreateYoutubePrototype(): Doc { + let webProto = setupPrototypeOptions(youtubeProtoId, "YOUTUBE_PROTO", YoutubeBox.LayoutString(), + { x: 0, y: 0, width: 300, height: 300 }); + return webProto; + } + + function CreateCollectionPrototype(): Doc { let collProto = setupPrototypeOptions(collProtoId, "COLLECTION_PROTO", CollectionView.LayoutString("data"), { panX: 0, panY: 0, scale: 1, width: 500, height: 500 }); @@ -238,6 +250,10 @@ export namespace Docs { // doc.SetText(KeyStore.OverlayLayout, FixedCaption()); // return doc; } + export function YoutubeDocument(url: string, options: DocumentOptions = {}) { + return CreateInstance(youtubeProto, new YoutubeField(new URL(url)), options); + } + export function VideoDocument(url: string, options: DocumentOptions = {}) { return CreateInstance(videoProto, new VideoField(new URL(url)), options); } -- cgit v1.2.3-70-g09d2 From 0591b8f1e60d1285fd9aac3e61160824948a166b Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Tue, 23 Jul 2019 17:33:31 -0400 Subject: Everything related to search stored --- src/client/apis/youtube/YoutubeBox.tsx | 123 +++++++++++++++++++----------- src/client/documents/Documents.ts | 2 +- src/server/youtubeApi/youtubeApiSample.js | 4 - 3 files changed, 81 insertions(+), 48 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/client/apis/youtube/YoutubeBox.tsx b/src/client/apis/youtube/YoutubeBox.tsx index 373eee5c4..e630c11ae 100644 --- a/src/client/apis/youtube/YoutubeBox.tsx +++ b/src/client/apis/youtube/YoutubeBox.tsx @@ -16,6 +16,16 @@ import { Doc, DocListCastAsync } from "../../../new_fields/Doc"; import { listSpec } from "../../../new_fields/Schema"; import { List } from "../../../new_fields/List"; +interface VideoTemplate { + thumbnailUrl: string; + videoTitle: string; + videoId: string; + duration: string; + channelTitle: string; + viewCount: string; + publishDate: string; + videoDescription: string; +} @observer export class YoutubeBox extends React.Component { @@ -28,58 +38,71 @@ export class YoutubeBox extends React.Component { @observable lisOfBackUp: JSX.Element[] = []; @observable videoIds: string | undefined; @observable videoDetails: any[] = []; + @observable curVideoTemplates: VideoTemplate[] = []; public static LayoutString() { return FieldView.LayoutString(YoutubeBox); } async componentWillMount() { //DocServer.getYoutubeChannels(); - //DocServer.getYoutubeVideoDetails("Ks-_Mh1QhMc, 1NmvhSmN2uM", (results: any[]) => console.log("Details results: ", results)); - let castedBackUpDocs = Cast(this.props.Document.cachedSearch, listSpec(Doc)); let castedSearchBackUp = Cast(this.props.Document.cachedSearchResults, Doc); let awaitedBackUp = await castedSearchBackUp; + let castedDetailBackUp = Cast(this.props.Document.cachedDetails, Doc); + let awaitedDetails = await castedDetailBackUp; - console.log("Backup results: ", awaitedBackUp); - console.log("Original Backup results: ", castedBackUpDocs); - - let json = Cast(awaitedBackUp!.json, Doc); - let jsonList = await DocListCastAsync(json); - console.log("Fucked up list: ", jsonList); - for (let video of jsonList!) { - let videoId = await Cast(video.id, Doc); - let id = StrCast(videoId!.videoId); - console.log("ID: ", id); - } + let jsonList = await DocListCastAsync(awaitedBackUp!.json); + let jsonDetailList = await DocListCastAsync(awaitedDetails!.json); - if (!castedBackUpDocs) { - this.props.Document.cachedSearch = castedBackUpDocs = new List(); - } - if (castedBackUpDocs.length !== 0) { - + if (jsonList!.length !== 0) { runInAction(() => this.searchResultsFound = true); + let index = 0; + for (let video of jsonList!) { + + let videoId = await Cast(video.id, Doc); + let id = StrCast(videoId!.videoId); + let snippet = await Cast(video.snippet, Doc); + let videoTitle = this.filterYoutubeTitleResult(StrCast(snippet!.title)); + let thumbnail = await Cast(snippet!.thumbnails, Doc); + let thumbnailMedium = await Cast(thumbnail!.medium, Doc); + let thumbnailUrl = StrCast(thumbnailMedium!.url); + let videoDescription = StrCast(snippet!.description); + let pusblishDate = (this.roundPublishTime2(StrCast(snippet!.publishedAt)))!; + let channelTitle = StrCast(snippet!.channelTitle); + let duration: string; + let viewCount: string; + if (jsonDetailList!.length !== 0) { + let contentDetails = await Cast(jsonDetailList![index].contentDetails, Doc); + let statistics = await Cast(jsonDetailList![index].statistics, Doc); + duration = this.convertIsoTimeToDuration(StrCast(contentDetails!.duration)); + viewCount = this.abbreviateViewCount(NumCast(statistics!.viewCount))!; + } + index = index + 1; + let newTemplate: VideoTemplate = { videoId: id, videoTitle: videoTitle, thumbnailUrl: thumbnailUrl, publishDate: pusblishDate, channelTitle: channelTitle, videoDescription: videoDescription, duration: duration!, viewCount: viewCount! }; + runInAction(() => this.curVideoTemplates.push(newTemplate)); + + // runInAction(() => this.lisOfBackUp.push(( + //
  • this.embedVideoOnClick(id, videoTitle)} key={Utils.GenerateGuid() + id}> + //
    + //
    + // + // {duration} + //
    + //
    + // {videoTitle} + // {channelTitle} + // {viewCount} + // {pusblishDate} + //

    {videoDescription}

    + + //
    + //
    + //
  • ) + // )); - for (let videoBackUp of castedBackUpDocs) { - let curBackUp = await videoBackUp; - let videoId = StrCast(curBackUp.videoId); - let videoTitle = StrCast(curBackUp.videoTitle); - let thumbnailUrl = StrCast(curBackUp.thumbnailUrl); - runInAction(() => this.lisOfBackUp.push(( -
  • this.embedVideoOnClick(videoId, videoTitle)} - key={Utils.GenerateGuid()} - > - - {videoTitle} -
  • ) - )); } - - } - - } _ignore = 0; @@ -134,11 +157,10 @@ export class YoutubeBox extends React.Component { @action processVideoDetails = (videoDetails: any[]) => { this.videoDetails = videoDetails; - console.log("Detail Res: ", this.videoDetails); + this.props.Document.cachedDetails = Docs.Get.DocumentHierarchyFromJson(videoDetails, "detailBackUp"); } backUpSearchResults = (videos: any[]) => { - console.log("Res: ", videos); this.props.Document.cachedSearchResults = Docs.Get.DocumentHierarchyFromJson(videos, "videosBackUp"); let newCachedList = new List(); this.props.Document.cachedSearch = newCachedList; @@ -164,7 +186,6 @@ export class YoutubeBox extends React.Component { let videoYearDif = curDate.getFullYear() - date.getFullYear(); let videoMonthDif = curDate.getMonth() - date.getMonth(); let videoDayDif = curDate.getDay() - date.getDay(); - console.log("video day dif: ", videoDayDif, " first day: ", curDate.getDay(), " second day: ", date.getDay()); let videoHoursDif = curDate.getHours() - date.getHours(); let videoMinutesDif = curDate.getMinutes() - date.getMinutes(); let videoSecondsDif = curDate.getSeconds() - date.getSeconds(); @@ -182,7 +203,6 @@ export class YoutubeBox extends React.Component { return videoSecondsDif + " seconds ago"; } - console.log("Date : ", date); } roundPublishTime2 = (publishTime: string) => { @@ -290,8 +310,26 @@ export class YoutubeBox extends React.Component { ; })} ; - } else if (this.lisOfBackUp.length !== 0) { - return
      {this.lisOfBackUp}
    ; + } else if (this.curVideoTemplates.length !== 0) { + return
      + {this.curVideoTemplates.map((video: VideoTemplate) => { + return
    • this.embedVideoOnClick(video.videoId, video.videoTitle)} key={Utils.GenerateGuid()}> +
      +
      + + {video.duration} +
      +
      + {video.videoTitle} + {video.channelTitle} + {video.viewCount} + {video.publishDate} +

      {video.videoDescription}

      +
      +
      +
    • ; + })} +
    ; } } else { return (null); @@ -301,7 +339,6 @@ export class YoutubeBox extends React.Component { @action embedVideoOnClick = (videoId: string, filteredTitle: string) => { let embeddedUrl = "https://www.youtube.com/embed/" + videoId; - console.log("EmbeddedUrl: ", embeddedUrl); this.selectedVideoUrl = embeddedUrl; let addFunction = this.props.addDocument!; let newVideoX = NumCast(this.props.Document.x); diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 191be9b7d..333e9859b 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -498,7 +498,7 @@ export namespace Docs { const convertObject = (object: any, title?: string): Doc => { let target = new Doc(), result: Opt; Object.keys(object).map(key => (result = toField(object[key], key)) && (target[key] = result)); - title && (target.title = title); + title && !target.title && (target.title = title); return target; }; diff --git a/src/server/youtubeApi/youtubeApiSample.js b/src/server/youtubeApi/youtubeApiSample.js index cf41a33e7..4fede08aa 100644 --- a/src/server/youtubeApi/youtubeApiSample.js +++ b/src/server/youtubeApi/youtubeApiSample.js @@ -23,8 +23,6 @@ module.exports.readApiKey = (callback) => { module.exports.authorizedGetChannel = (apiKey) => { //this didnt get called - console.log("I get called ", apiKey); - console.log(TOKEN_PATH); // Authorize a client with the loaded credentials, then call the YouTube API. authorize(JSON.parse(apiKey), getChannel); } @@ -157,7 +155,6 @@ function getSampleVideos(auth, args) { return; } let videos = response.data.items; - console.log('Videos found: ' + videos[0].id.videoId, " ", unescape(videos[0].snippet.title)); args.callBack(videos); }); } @@ -174,7 +171,6 @@ function getVideoDetails(auth, args) { return; } let videoDetails = response.data.items; - console.log('Video Details founds: ', videoDetails); args.callBack(videoDetails); }); } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 27cafb6eebd1c6229c3377187a5c0043db25ba0a Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sun, 28 Jul 2019 22:58:32 -0400 Subject: templating fixes, context menu undo streamlining --- src/.DS_Store | Bin 6148 -> 6148 bytes src/client/documents/Documents.ts | 5 ++--- src/client/views/ContextMenuItem.tsx | 4 ++-- src/client/views/collections/CollectionTreeView.tsx | 10 +++++----- src/client/views/collections/CollectionView.tsx | 14 +++++++------- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/KeyValueBox.tsx | 17 ++++++++++++----- src/scraping/buxton/scraper.py | 4 ++-- 8 files changed, 31 insertions(+), 25 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/.DS_Store b/src/.DS_Store index 071dafa1e..c544bc837 100644 Binary files a/src/.DS_Store and b/src/.DS_Store differ diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 3859f2255..30a114e33 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -163,7 +163,6 @@ export namespace Docs { [DocumentType.LINKDOC, { data: new List(), layout: { view: EmptyBox }, - options: {} }], [DocumentType.BUTTON, { layout: { view: ButtonBox }, @@ -414,8 +413,8 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Tree }); } - export function StackingDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Stacking }); + export function StackingDocument(documents: Array, options: DocumentOptions, viewType: CollectionViewType = CollectionViewType.Stacking) { + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: viewType }); } export function ButtonDocument(options?: DocumentOptions) { diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 4ff0fe388..a1787e78f 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -37,13 +37,13 @@ export class ContextMenuItem extends React.Component) => { + handleEvent = async (e: React.MouseEvent) => { if ("event" in this.props) { let batch: UndoManager.Batch | undefined; if (this.props.undoable !== false) { batch = UndoManager.StartBatch(`Context menu event: ${this.props.description}`); } - this.props.event(); + await this.props.event(); batch && batch.end(); this.props.closeMenu && this.props.closeMenu(); } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 1c7fe4bee..3eab109bc 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -237,10 +237,10 @@ class TreeView extends React.Component { if (DocumentManager.Instance.getDocumentViews(this.dataDoc).length) { ContextMenu.Instance.addItem({ description: "Focus", event: () => DocumentManager.Instance.getDocumentViews(this.dataDoc).map(view => view.props.focus(this.props.document, true)), icon: "camera" }); } - ContextMenu.Instance.addItem({ description: "Delete Item", event: undoBatch(() => this.props.deleteDoc(this.props.document)), icon: "trash-alt" }); + ContextMenu.Instance.addItem({ description: "Delete Item", event: () => this.props.deleteDoc(this.props.document), icon: "trash-alt" }); } else { - ContextMenu.Instance.addItem({ description: "Open as Workspace", event: undoBatch(() => MainView.Instance.openWorkspace(this.dataDoc)), icon: "caret-square-right" }); - ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.props.deleteDoc(this.props.document)), icon: "trash-alt" }); + ContextMenu.Instance.addItem({ description: "Open as Workspace", event: () => MainView.Instance.openWorkspace(this.dataDoc), icon: "caret-square-right" }); + ContextMenu.Instance.addItem({ description: "Delete Workspace", event: () => this.props.deleteDoc(this.props.document), icon: "trash-alt" }); } ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { let kvp = Docs.Create.KVPDocument(this.props.document, { width: 300, height: 300 }); this.props.addDocTab(kvp, this.props.dataDoc ? this.props.dataDoc : kvp, "onRight"); }, icon: "layer-group" }); ContextMenu.Instance.displayMenu(e.pageX > 156 ? e.pageX - 156 : 0, e.pageY - 15); @@ -520,8 +520,8 @@ export class CollectionTreeView extends CollectionSubView(Document) { onContextMenu = (e: React.MouseEvent): void => { // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout if (!e.isPropagationStopped() && this.props.Document.workspaceLibrary) { // excludeFromLibrary means this is the user document - ContextMenu.Instance.addItem({ description: "Create Workspace", event: undoBatch(() => MainView.Instance.createNewWorkspace()), icon: "plus" }); - ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.remove(this.props.Document)), icon: "minus" }); + ContextMenu.Instance.addItem({ description: "Create Workspace", event: () => MainView.Instance.createNewWorkspace(), icon: "plus" }); + ContextMenu.Instance.addItem({ description: "Delete Workspace", event: () => this.remove(this.props.Document), icon: "minus" }); e.stopPropagation(); e.preventDefault(); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index b4f29755c..e3f5d1eb8 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -53,14 +53,14 @@ export class CollectionView extends React.Component { onContextMenu = (e: React.MouseEvent): void => { if (!this.isAnnotationOverlay && !e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 let subItems: ContextMenuProps[] = []; - subItems.push({ description: "Freeform", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Freeform), icon: "signature" }); + subItems.push({ description: "Freeform", event: () => this.props.Document.viewType = CollectionViewType.Freeform, icon: "signature" }); if (CollectionBaseView.InSafeMode()) { - ContextMenu.Instance.addItem({ description: "Test Freeform", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Invalid), icon: "project-diagram" }); + ContextMenu.Instance.addItem({ description: "Test Freeform", event: () => this.props.Document.viewType = CollectionViewType.Invalid, icon: "project-diagram" }); } - subItems.push({ description: "Schema", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Schema), icon: "th-list" }); - subItems.push({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree), icon: "tree" }); - subItems.push({ description: "Stacking", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Stacking), icon: "ellipsis-v" }); - subItems.push({ description: "Masonry", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Masonry), icon: "columns" }); + subItems.push({ description: "Schema", event: () => this.props.Document.viewType = CollectionViewType.Schema, icon: "th-list" }); + subItems.push({ description: "Treeview", event: () => this.props.Document.viewType = CollectionViewType.Tree, icon: "tree" }); + subItems.push({ description: "Stacking", event: () => this.props.Document.viewType = CollectionViewType.Stacking, icon: "ellipsis-v" }); + subItems.push({ description: "Masonry", event: () => this.props.Document.viewType = CollectionViewType.Masonry, icon: "columns" }); switch (this.props.Document.viewType) { case CollectionViewType.Freeform: { subItems.push({ description: "Custom", icon: "fingerprint", event: CollectionFreeFormView.AddCustomLayout(this.props.Document, this.props.fieldKey) }); @@ -68,7 +68,7 @@ export class CollectionView extends React.Component { } } ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems, icon: "eye" }); - ContextMenu.Instance.addItem({ description: "Apply Template", event: undoBatch(() => this.props.addDocTab && this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight")), icon: "project-diagram" }); + ContextMenu.Instance.addItem({ description: "Apply Template", event: () => this.props.addDocTab && this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" }); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d07fc7f80..a6152e1b7 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -496,7 +496,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { let layoutItems: ContextMenuProps[] = []; layoutItems.push({ description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`, - event: undoBatch(async () => this.props.Document.fitToBox = !this.fitToBox), + event: async () => this.props.Document.fitToBox = !this.fitToBox, icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt" }); layoutItems.push({ diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 77824b4ff..b0fcc4202 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -20,6 +20,7 @@ import { RichTextField } from "../../../new_fields/RichTextField"; import { ImageField } from "../../../new_fields/URLField"; import { SelectionManager } from "../../util/SelectionManager"; import { listSpec } from "../../../new_fields/Schema"; +import { CollectionViewType } from "../collections/CollectionBaseView"; export type KVPScript = { script: CompiledScript; @@ -195,6 +196,9 @@ export class KeyValueBox extends React.Component { } let fieldTemplate = await this.inferType(sourceDoc[metaKey], metaKey); + if (!fieldTemplate) { + return; + } let previousViewType = fieldTemplate.viewType; Doc.MakeTemplate(fieldTemplate, metaKey, Doc.GetProto(parentStackingDoc)); previousViewType && (fieldTemplate.viewType = previousViewType); @@ -211,14 +215,17 @@ export class KeyValueBox extends React.Component { return Docs.Create.StackingDocument([], options); } let first = await Cast(data[0], Doc); - if (!first) { + if (!first || !first.data) { return Docs.Create.StackingDocument([], options); } - switch (first.type) { - case "image": - return Docs.Create.StackingDocument([], options); - case "text": + switch (first.data.constructor) { + case RichTextField: return Docs.Create.TreeDocument([], options); + case ImageField: + return Docs.Create.StackingDocument([], options, CollectionViewType.Masonry); + default: + console.log(`Template for ${first.data.constructor} not supported!`); + return undefined; } } else if (data instanceof ImageField) { return Docs.Create.ImageDocument("https://image.flaticon.com/icons/png/512/23/23765.png", options); diff --git a/src/scraping/buxton/scraper.py b/src/scraping/buxton/scraper.py index 182b22a1a..1ff0e3b31 100644 --- a/src/scraping/buxton/scraper.py +++ b/src/scraping/buxton/scraper.py @@ -139,7 +139,7 @@ def write_text_doc(content): data_doc = { "_id": data_doc_guid, "fields": { - "proto": protofy("commonImportProto"), + "proto": protofy("textProto"), "data": { "Data": '{"doc":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + content + '"}]}]},"selection":{"type":"text","anchor":1,"head":1}' + '}', "__type": "RichTextField" @@ -235,7 +235,7 @@ def parse_document(file_name: str): count += 1 view_guids.append(write_image(pure_name, image)) copyfile(dir_path + "/" + image, dir_path + - "/" + image.replace(".", "_o.", 1)) + "/" + image.replace(".", "_o.", 1)) os.rename(dir_path + "/" + image, dir_path + "/" + image.replace(".", "_m.", 1)) print(f"extracted {count} images...") -- cgit v1.2.3-70-g09d2 From f1cb6a2212b11ba6d18dfa2e800b2c8e4ad94a88 Mon Sep 17 00:00:00 2001 From: fawn Date: Mon, 29 Jul 2019 14:28:25 -0400 Subject: made hit box on col resizer smaller and hit box on coll expander bigger --- src/client/documents/Documents.ts | 8 ++--- src/client/views/MainView.tsx | 2 +- .../views/collections/CollectionSchemaCells.tsx | 2 +- .../views/collections/CollectionSchemaView.scss | 39 +++++++++++++++------- .../views/collections/CollectionSchemaView.tsx | 6 ++-- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- src/client/views/nodes/LinkEditor.tsx | 2 +- src/client/views/nodes/LinkMenuGroup.tsx | 2 +- src/new_fields/SchemaHeaderField.ts | 4 +-- 9 files changed, 41 insertions(+), 26 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ee1b9fd0d..01e3ced5d 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -404,7 +404,7 @@ export namespace Docs { } export function FreeformDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Freeform }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Freeform }); } export function SchemaDocument(schemaColumns: SchemaHeaderField[], documents: Array, options: DocumentOptions) { @@ -412,15 +412,15 @@ export namespace Docs { } export function TreeDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Tree }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Tree }); } export function StackingDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Stacking }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Stacking }); } export function MasonryDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Masonry }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Masonry }); } export function ButtonDocument(options?: DocumentOptions) { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f5a6715e5..d4c0711a2 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -375,7 +375,7 @@ export class MainView extends React.Component { let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"; // let addDockingNode = action(() => Docs.Create.StandardCollectionDockingDocument([{ doc: addColNode(), initialWidth: 200 }], { width: 200, height: 200, title: "a nested docking freeform collection" })); - let addSchemaNode = action(() => Docs.Create.SchemaDocument([new SchemaHeaderField("title")], [], { width: 200, height: 200, title: "a schema collection" })); + let addSchemaNode = action(() => Docs.Create.SchemaDocument([new SchemaHeaderField("title", "#f1efeb")], [], { width: 200, height: 200, title: "a schema collection" })); //let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" })); // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy" })); let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" })); diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 194765880..e06a5c66b 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -108,7 +108,7 @@ export class CollectionSchemaCell extends React.Component { this._document[fieldKey] = de.data.draggedDocuments[0]; } else { - let coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title")], de.data.draggedDocuments, {}); + let coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title", "f1efeb")], de.data.draggedDocuments, {}); this._document[fieldKey] = coll; } e.stopPropagation(); diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 053d6452c..749b9a364 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -97,15 +97,6 @@ // margin-right: -30px; } - .rt-resizable-header { - padding: 0; - height: 30px; - - &:last-child { - overflow: visible; - } - } - .rt-resizable-header-content { height: 100%; overflow: visible; @@ -198,8 +189,22 @@ } .rt-resizer { - width: 20px; - right: -10px; + width: 8px; + right: -4px; + } + + .rt-resizable-header { + padding: 0; + height: 30px; + } + + .rt-resizable-header:last-child { + overflow: visible; + border: 3px solid red !important; + + .rt-resizer { + width: 5px !important; + } } } @@ -318,7 +323,7 @@ button.add-column { input[type="radio"] { display: none; } - + .columnMenu-colorPicker { width: 20px; height: 20px; @@ -497,4 +502,14 @@ button.add-column { .collectionSchemaView-expander { height: 100%; + min-height: 30px; + position: relative; + color: gray; + + svg { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 53dd9523b..ece638ec7 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -635,15 +635,15 @@ export class SchemaTable extends React.Component { let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField)); if (list === undefined) { console.log("change columns new"); - this.props.Document.schemaColumns = list = new List([new SchemaHeaderField(newKey, "f1efeb")]); + this.props.Document.schemaColumns = list = new List([new SchemaHeaderField(newKey, "#f1efeb")]); } else { console.log("change column"); if (addNew) { - this.columns.push(new SchemaHeaderField(newKey, "f1efeb")); + this.columns.push(new SchemaHeaderField(newKey, "#f1efeb")); } else { const index = list.map(c => c.heading).indexOf(oldKey); if (index > -1) { - list[index] = new SchemaHeaderField(newKey, "f1efeb"); + list[index] = new SchemaHeaderField(newKey, "#f1efeb"); } } } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 1c767e012..7decadbe9 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -135,7 +135,7 @@ export class MarqueeView extends React.Component doc.width = 200; docList.push(doc); } - let newCol = Docs.Create.SchemaDocument([...(groupAttr ? [new SchemaHeaderField("_group")] : []), ...columns.filter(c => c).map(c => new SchemaHeaderField(c))], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 }); + let newCol = Docs.Create.SchemaDocument([...(groupAttr ? [new SchemaHeaderField("_group", "#f1efeb")] : []), ...columns.filter(c => c).map(c => new SchemaHeaderField(c))], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 }); this.props.addDocument(newCol, false); } diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 0ea948c81..ecb3e9db4 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -290,7 +290,7 @@ export class LinkGroupEditor extends React.Component { let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); let index = keys.indexOf(""); if (index > -1) keys.splice(index, 1); - let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c)); + let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb")); let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType); let createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" })); let ref = React.createRef(); diff --git a/src/client/views/nodes/LinkMenuGroup.tsx b/src/client/views/nodes/LinkMenuGroup.tsx index 0cb216aa6..e04044266 100644 --- a/src/client/views/nodes/LinkMenuGroup.tsx +++ b/src/client/views/nodes/LinkMenuGroup.tsx @@ -72,7 +72,7 @@ export class LinkMenuGroup extends React.Component { let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); let index = keys.indexOf(""); if (index > -1) keys.splice(index, 1); - let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c)); + let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb")); let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType); let createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" })); let ref = React.createRef(); diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts index d124a3907..475296d5c 100644 --- a/src/new_fields/SchemaHeaderField.ts +++ b/src/new_fields/SchemaHeaderField.ts @@ -48,12 +48,12 @@ export class SchemaHeaderField extends ObjectField { color: string; type: number; - constructor(heading: string = "", color?: string, type?: ColumnType) { + constructor(heading: string = "", color: string, type?: ColumnType) { console.log("CREATING SCHEMA HEADER FIELD"); super(); this.heading = heading; - this.color = color === "" || color === undefined ? RandomPastel() : color; + this.color = color === undefined ? "#000" : color; if (type) { this.type = type; } -- cgit v1.2.3-70-g09d2 From d87020047c1953b212257236a25036df3903dd47 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Mon, 29 Jul 2019 16:20:20 -0400 Subject: chrome default to collapsed --- src/client/documents/Documents.ts | 11 ++++++----- src/client/views/collections/CollectionView.tsx | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 18709499a..d1b3071ed 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -82,6 +82,7 @@ export interface DocumentOptions { backgroundColor?: string; dropAction?: dropActionType; backgroundLayout?: string; + chromeStatus?: string; curPage?: number; documentText?: string; borderRounding?: string; @@ -403,23 +404,23 @@ export namespace Docs { } export function FreeformDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Freeform }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Freeform }); } export function SchemaDocument(schemaColumns: SchemaHeaderField[], documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema }); } export function TreeDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Tree }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Tree }); } export function StackingDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Stacking }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Stacking }); } export function MasonryDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Masonry }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Masonry }); } export function ButtonDocument(options?: DocumentOptions) { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 55e014c66..b7ac8768f 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -35,7 +35,7 @@ library.add(faImage, faEye); @observer export class CollectionView extends React.Component { - @observable private _collapsed = false; + @observable private _collapsed = true; private _reactionDisposer: IReactionDisposer | undefined; -- cgit v1.2.3-70-g09d2 From ec224416fc454c7fdbb62943408226c973d8c751 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Thu, 1 Aug 2019 02:30:47 -0400 Subject: fixed import ordering issue, allow for multiple targets and valid document types --- src/client/documents/Documents.ts | 45 ++++++++------- src/client/util/DictationManager.ts | 66 ++++++++-------------- .../collectionFreeForm/CollectionFreeFormView.tsx | 8 --- src/client/views/nodes/DocumentView.tsx | 1 - src/client/views/search/FilterBox.tsx | 2 +- src/client/views/search/SearchItem.tsx | 2 +- src/client/views/search/ToggleBar.tsx | 2 +- 7 files changed, 49 insertions(+), 77 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2a1f63d59..3c7de17c8 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1,3 +1,24 @@ +export enum DocumentType { + NONE = "none", + TEXT = "text", + HIST = "histogram", + IMG = "image", + WEB = "web", + COL = "collection", + KVP = "kvp", + VID = "video", + AUDIO = "audio", + PDF = "pdf", + ICON = "icon", + IMPORT = "import", + LINK = "link", + LINKDOC = "linkdoc", + BUTTON = "button", + TEMPLATE = "template", + EXTENSION = "extension", + YOUTUBE = "youtube", +} + import { HistogramField } from "../northstar/dash-fields/HistogramField"; import { HistogramBox } from "../northstar/dash-nodes/HistogramBox"; import { HistogramOperation } from "../northstar/operations/HistogramOperation"; @@ -25,14 +46,13 @@ import { OmitKeys, JSONUtils } from "../../Utils"; import { ImageField, VideoField, AudioField, PdfField, WebField, YoutubeField } from "../../new_fields/URLField"; import { HtmlField } from "../../new_fields/HtmlField"; import { List } from "../../new_fields/List"; -import { Cast, NumCast, StrCast, ToConstructor, InterfaceValue, FieldValue } from "../../new_fields/Types"; +import { Cast, NumCast } from "../../new_fields/Types"; import { IconField } from "../../new_fields/IconField"; import { listSpec } from "../../new_fields/Schema"; import { DocServer } from "../DocServer"; import { dropActionType } from "../util/DragManager"; import { DateField } from "../../new_fields/DateField"; import { UndoManager } from "../util/UndoManager"; -import { RouteStore } from "../../server/RouteStore"; import { YoutubeBox } from "../apis/youtube/YoutubeBox"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import { LinkManager } from "../util/LinkManager"; @@ -44,27 +64,6 @@ import { SchemaHeaderField, RandomPastel } from "../../new_fields/SchemaHeaderFi var requestImageSize = require('../util/request-image-size'); var path = require('path'); -export enum DocumentType { - NONE = "none", - TEXT = "text", - HIST = "histogram", - IMG = "image", - WEB = "web", - COL = "collection", - KVP = "kvp", - VID = "video", - AUDIO = "audio", - PDF = "pdf", - ICON = "icon", - IMPORT = "import", - LINK = "link", - LINKDOC = "linkdoc", - BUTTON = "button", - TEMPLATE = "template", - EXTENSION = "extension", - YOUTUBE = "youtube", -} - export interface DocumentOptions { x?: number; y?: number; diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index 49afe5371..b0866a826 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -6,9 +6,9 @@ import { Doc } from "../../new_fields/Doc"; import { List } from "../../new_fields/List"; import { Docs, DocumentType } from "../documents/Documents"; import { CollectionViewType } from "../views/collections/CollectionBaseView"; -import { listSpec } from "../../new_fields/Schema"; import { Cast, CastCtor } from "../../new_fields/Types"; -import { ImageField, AudioField } from "../../new_fields/URLField"; +import { listSpec } from "../../new_fields/Schema"; +import { AudioField, ImageField } from "../../new_fields/URLField"; import { HistogramField } from "../northstar/dash-fields/HistogramField"; namespace CORE { @@ -17,7 +17,7 @@ namespace CORE { } } -const Mapping = new Map([ +const ConstructorMap = new Map([ [DocumentType.COL, listSpec(Doc)], [DocumentType.AUDIO, AudioField], [DocumentType.IMG, ImageField], @@ -26,7 +26,7 @@ const Mapping = new Map([ ]); const tryCast = (view: DocumentView, type: DocumentType) => { - let ctor = Mapping.get(type); + let ctor = ConstructorMap.get(type); if (!ctor) { return false; } @@ -82,28 +82,6 @@ export default class DictationManager { }); } - private sanitize = (title: string) => { - return title.replace("...", "").toLowerCase().trim(); - } - - public registerStatic = (keys: Array, action: IndependentAction, filter?: ActionPredicate) => { - let success = true; - keys.forEach(key => { - key = this.sanitize(key); - let existing = RegisteredCommands.Independent.get(key); - if (!existing) { - let unit = { - action: action, - filter: filter - }; - RegisteredCommands.Independent.set(key, unit); - } else { - success = false; - } - }); - return success; - } - public interpretNumber = (number: string) => { let initial = parseInt(number); if (!isNaN(initial)) { @@ -116,34 +94,38 @@ export default class DictationManager { return typeof converted === "string" ? parseInt(converted) : converted; } - public registerDynamic = (dynamicKey: RegExp, action: DependentAction) => { - RegisteredCommands.Dependent.push({ - expression: dynamicKey, - action: action - }); - } - @undoBatch public execute = async (phrase: string) => { - let target = SelectionManager.SelectedDocuments()[0]; - if (!target) { + let targets = SelectionManager.SelectedDocuments(); + if (!targets || !targets.length) { return; } - phrase = this.sanitize(phrase); let entry = RegisteredCommands.Independent.get(phrase); - if (entry && (!entry.restrictTo || validate(target, entry.restrictTo))) { - await entry.action(target); - return true; + if (entry) { + let success = false; + for (let target of targets) { + if (!entry.restrictTo || validate(target, entry.restrictTo)) { + await entry.action(target); + success = true; + } + } + return success; } for (let entry of RegisteredCommands.Dependent) { let regex = entry.expression; let matches = regex.exec(phrase); regex.lastIndex = 0; - if (matches !== null && (!entry.restrictTo || validate(target, entry.restrictTo))) { - await entry.action(target, matches); - return true; + if (matches !== null) { + let success = false; + for (let target of targets) { + if (!entry.restrictTo || validate(target, entry.restrictTo)) { + await entry.action(target, matches); + success = true; + } + } + return success; } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 59c77f1c9..fa49e7175 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -123,14 +123,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { }); } - constructor(props: SubCollectionViewProps) { - super(props); - let fixed = DictationManager.Instance.registerStatic; - fixed(["Unset Fit To Container", "Set Fit To Container"], this.fitToContainer); - fixed(["Arrange contents in grid"], this.arrangeContents); - fixed(["Analyze Strokes"], this.analyzeStrokes); - } - @computed get fieldExtensionDoc() { return Doc.resolvedFieldDataDoc(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, "true"); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 39574db0f..51661d1ae 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -41,7 +41,6 @@ import { ClientUtils } from '../../util/ClientUtils'; import { EditableView } from '../EditableView'; import { faHandPointer, faHandPointRight } from '@fortawesome/free-regular-svg-icons'; import { DocumentDecorations } from '../DocumentDecorations'; -import { CognitiveServices } from '../../cognitive_services/CognitiveServices'; import DictationManager from '../../util/DictationManager'; import { CollectionViewType } from '../collections/CollectionBaseView'; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index 995ddd5c3..3e8582d61 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -384,7 +384,7 @@ export class FilterBox extends React.Component {
    Collection Filters Active
    : undefined} - ) + ); } // Useful queries: diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index 0390359b3..6fbc92007 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -134,7 +134,7 @@ export class LinkContextMenu extends React.Component { - ) + ); } } diff --git a/src/client/views/search/ToggleBar.tsx b/src/client/views/search/ToggleBar.tsx index a30104089..ed5ecd3ba 100644 --- a/src/client/views/search/ToggleBar.tsx +++ b/src/client/views/search/ToggleBar.tsx @@ -59,7 +59,7 @@ export class ToggleBar extends React.Component{ this._forwardTimeline.play(); this._forwardTimeline.reverse(); this.props.handleChange(); - console.log(this.props.getStatus()) + console.log(this.props.getStatus()); } @action.bound -- cgit v1.2.3-70-g09d2 From 46843c105c5fb3dfed3bab9283ae4b2917eade4e Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 1 Aug 2019 15:20:40 -0400 Subject: Fixed Doc.MakeCopy promise stuff --- src/client/documents/Documents.ts | 4 ++++ src/new_fields/Doc.ts | 12 +++++++----- src/new_fields/Proxy.ts | 29 +++++++++++++++++++++++++++++ src/new_fields/ScriptField.ts | 12 +++++++----- src/new_fields/util.ts | 5 +---- 5 files changed, 48 insertions(+), 14 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2a1f63d59..63b4d4e32 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -41,6 +41,8 @@ import DirectoryImportBox from "../util/Import & Export/DirectoryImportBox"; import { Scripting } from "../util/Scripting"; import { ButtonBox } from "../views/nodes/ButtonBox"; import { SchemaHeaderField, RandomPastel } from "../../new_fields/SchemaHeaderField"; +import { ComputedField } from "../../new_fields/ScriptField"; +import { ProxyField } from "../../new_fields/Proxy"; var requestImageSize = require('../util/request-image-size'); var path = require('path'); @@ -193,6 +195,8 @@ export namespace Docs { * haven't been initialized, the newly initialized prototype document. */ export async function initialize(): Promise { + ProxyField.initPlugin(); + ComputedField.initPlugin(); // non-guid string ids for each document prototype let prototypeIds = Object.values(DocumentType).filter(type => type !== DocumentType.NONE).map(type => type + suffix); // fetch the actual prototype documents from the server diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 84b8589dd..6e2c5e697 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -12,7 +12,7 @@ import { scriptingGlobal } from "../client/util/Scripting"; import { List } from "./List"; import { DocumentType } from "../client/documents/Documents"; import { ComputedField } from "./ScriptField"; -import { PrefetchProxy } from "./Proxy"; +import { PrefetchProxy, ProxyField } from "./Proxy"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -420,7 +420,7 @@ export namespace Doc { export function MakeCopy(doc: Doc, copyProto: boolean = false): Doc { const copy = new Doc; Object.keys(doc).forEach(key => { - const field = doc[key]; + const field = ProxyField.WithoutProxy(() => doc[key]); if (key === "proto" && copyProto) { if (field instanceof Doc) { copy[key] = Doc.MakeCopy(field); @@ -431,7 +431,7 @@ export namespace Doc { } else if (field instanceof ObjectField) { copy[key] = ObjectField.MakeCopy(field); } else if (field instanceof Promise) { - field.then(f => (copy[key] === undefined) && (copy[key] = f)); //TODO what should we do here? + debugger; //This shouldn't happend... } else { copy[key] = field; } @@ -525,8 +525,10 @@ export namespace Doc { } export function UseDetailLayout(d: Doc) { runInAction(async () => { - let detailLayout1 = await PromiseValue(d.detailedLayout); - let detailLayout = await PromiseValue(d.detailedLayout); + const dl1 = d.detailedLayout; + let detailLayout1 = await PromiseValue(dl1); + const dl2 = d.detailedLayout; + let detailLayout = await PromiseValue(dl2); if (detailLayout) { d.layout = detailLayout; d.nativeWidth = d.nativeHeight = undefined; diff --git a/src/new_fields/Proxy.ts b/src/new_fields/Proxy.ts index b3e8d6467..c6292e37c 100644 --- a/src/new_fields/Proxy.ts +++ b/src/new_fields/Proxy.ts @@ -7,6 +7,7 @@ import { RefField } from "./RefField"; import { ObjectField } from "./ObjectField"; import { Id, Copy, ToScriptString } from "./FieldSymbols"; import { scriptingGlobal } from "../client/util/Scripting"; +import { Plugins } from "./util"; @Deserializable("proxy") export class ProxyField extends ObjectField { @@ -68,6 +69,34 @@ export class ProxyField extends ObjectField { } } +export namespace ProxyField { + let useProxy = true; + export function DisableProxyFields() { + useProxy = false; + } + + export function EnableProxyFields() { + useProxy = true; + } + + export function WithoutProxy(fn: () => T) { + DisableProxyFields(); + try { + return fn(); + } finally { + EnableProxyFields(); + } + } + + export function initPlugin() { + Plugins.addGetterPlugin((doc, _, value) => { + if (useProxy && value instanceof ProxyField) { + return { value: value.value() }; + } + }); + } +} + function prefetchValue(proxy: PrefetchProxy) { return proxy.value() as any; } diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts index 6d52525b8..83fb52d07 100644 --- a/src/new_fields/ScriptField.ts +++ b/src/new_fields/ScriptField.ts @@ -137,9 +137,11 @@ export namespace ComputedField { } } - Plugins.addGetterPlugin((doc, _, value) => { - if (useComputed && value instanceof ComputedField) { - return { value: value.value(doc), shouldReturn: true }; - } - }); + export function initPlugin() { + Plugins.addGetterPlugin((doc, _, value) => { + if (useComputed && value instanceof ComputedField) { + return { value: value.value(doc), shouldReturn: true }; + } + }); + } } \ No newline at end of file diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index 2ebfb9e71..c6f693f7f 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -14,7 +14,7 @@ function _readOnlySetter(): never { export interface GetterResult { value: FieldResult; - shouldReturn: boolean; + shouldReturn?: boolean; } export type GetterPlugin = (receiver: any, prop: string | number, currentValue: any) => GetterResult | undefined; const getterPlugins: GetterPlugin[] = []; @@ -103,9 +103,6 @@ export function getter(target: any, prop: string | symbol | number, receiver: an function getFieldImpl(target: any, prop: string | number, receiver: any, ignoreProto: boolean = false): any { receiver = receiver || target[SelfProxy]; let field = target.__fields[prop]; - if (field instanceof ProxyField) { - return field.value(); - } for (const plugin of getterPlugins) { const res = plugin(receiver, prop, field); if (res === undefined) continue; -- cgit v1.2.3-70-g09d2 From e0fb04a7748666a41a7cd500dcdd23027ef12b6f Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 2 Aug 2019 12:56:37 -0400 Subject: links --- src/client/documents/Documents.ts | 7 +++++- src/client/util/LinkManager.ts | 13 ++++++++-- .../views/collections/CollectionTreeView.tsx | 28 +++++++++++++++------- src/client/views/nodes/KeyValuePair.tsx | 17 ++++++------- 4 files changed, 43 insertions(+), 22 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 63b4d4e32..818383765 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -38,7 +38,7 @@ import { CollectionDockingView } from "../views/collections/CollectionDockingVie import { LinkManager } from "../util/LinkManager"; import { DocumentManager } from "../util/DocumentManager"; import DirectoryImportBox from "../util/Import & Export/DirectoryImportBox"; -import { Scripting } from "../util/Scripting"; +import { Scripting, CompileScript } from "../util/Scripting"; import { ButtonBox } from "../views/nodes/ButtonBox"; import { SchemaHeaderField, RandomPastel } from "../../new_fields/SchemaHeaderField"; import { ComputedField } from "../../new_fields/ScriptField"; @@ -623,6 +623,11 @@ export namespace DocUtils { LinkManager.Instance.addLink(linkDoc); + let script = `return links(self)};`; + let computed = CompileScript(script, { params: { this: "Doc" }, capturedVariables: { self: source }, typecheck: false }); + computed.compiled && (Doc.GetProto(source).links = new ComputedField(computed)); + computed.compiled && (Doc.GetProto(target).links = new ComputedField(computed)); + }, "make link"); return linkDoc; } diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index a647f22c1..448a8e9cf 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -6,6 +6,7 @@ import { List } from "../../new_fields/List"; import { Id } from "../../new_fields/FieldSymbols"; import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils"; import { Docs } from "../documents/Documents"; +import { Scripting } from "./Scripting"; /* @@ -42,7 +43,12 @@ export class LinkManager { } public getAllLinks(): Doc[] { - return LinkManager.Instance.LinkManagerDoc ? LinkManager.Instance.LinkManagerDoc.allLinks ? DocListCast(LinkManager.Instance.LinkManagerDoc.allLinks) : [] : []; + let ldoc = LinkManager.Instance.LinkManagerDoc; + if (ldoc) { + let docs = DocListCast(ldoc.allLinks); + return docs; + } + return []; } public addLink(linkDoc: Doc): boolean { @@ -242,4 +248,7 @@ export class LinkManager { return Cast(linkDoc.anchor1, Doc, null); } } -} \ No newline at end of file +} +Scripting.addGlobal(function links(doc: any) { + return new List(LinkManager.Instance.getAllRelatedLinks(doc)); +}); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 7f5d78313..02b2583cd 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -27,6 +27,7 @@ import "./CollectionTreeView.scss"; import React = require("react"); import { ComputedField } from '../../../new_fields/ScriptField'; import { KeyValueBox } from '../nodes/KeyValueBox'; +import { exportNamedDeclaration } from 'babel-types'; export interface TreeViewProps { @@ -79,11 +80,17 @@ class TreeView extends React.Component { return splits.length > 1 ? splits[1].split("\"")[0] : "data"; } @computed get childDocs() { - let layout = this.props.document.layout as Doc; + let layout = this.props.document.layout instanceof Doc ? this.props.document.layout : undefined; return (this.props.dataDoc ? Cast(this.props.dataDoc[this.fieldKey], listSpec(Doc)) : undefined) || (layout ? Cast(layout[this.fieldKey], listSpec(Doc)) : undefined) || Cast(this.props.document[this.fieldKey], listSpec(Doc)); } + @computed get childLinks() { + let layout = this.props.document.layout instanceof Doc ? this.props.document.layout : undefined; + return (this.props.dataDoc ? Cast(this.props.dataDoc.links, listSpec(Doc)) : undefined) || + (layout instanceof Doc ? Cast(layout.links, listSpec(Doc)) : undefined) || + Cast(this.props.document.links, listSpec(Doc)); + } @computed get resolvedDataDoc() { if (this.props.dataDoc === undefined && this.props.document.layout instanceof Doc) { // if there is no dataDoc (ie, we're not rendering a template layout), but this document @@ -276,13 +283,15 @@ class TreeView extends React.Component { noOverlays = (doc: Doc) => ({ title: "", caption: "" }); @computed get renderContent() { - if (this.treeViewExpandedView === this.fieldKey) { - let remDoc = (doc: Doc) => this.remove(doc, this.fieldKey); - let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, this.fieldKey, doc, addBefore, before); - return
      - {!this.childDocs ? (null) : - TreeView.GetChildElements(this.childDocs as Doc[], this.props.treeViewId, this.props.document.layout as Doc, - this.resolvedDataDoc, this.fieldKey, addDoc, remDoc, this.move, + const expandKey = this.treeViewExpandedView === this.fieldKey ? this.fieldKey : this.treeViewExpandedView === "links" ? "links" : undefined; + if (expandKey !== undefined) { + let remDoc = (doc: Doc) => this.remove(doc, expandKey); + let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, expandKey, doc, addBefore, before); + let docs = expandKey === "links" ? this.childLinks : this.childDocs; + return
        + {!docs ? (null) : + TreeView.GetChildElements(docs as Doc[], this.props.treeViewId, this.props.document.layout as Doc, + this.resolvedDataDoc, expandKey, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.renderDepth)}
      ; @@ -334,7 +343,8 @@ class TreeView extends React.Component { onPointerDown={action(() => { this.props.document.treeViewExpandedView = this.treeViewExpandedView === this.fieldKey ? "fields" : this.treeViewExpandedView === "fields" && this.props.document.layout ? "layout" : - this.childDocs ? this.fieldKey : "fields"; + this.treeViewExpandedView === "layout" && this.props.document.links ? "links" : + this.childDocs ? this.fieldKey : "fields"; this._collapsed = false; })}> {this.treeViewExpandedView} diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 3775f0f47..534a42efc 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -1,22 +1,19 @@ import { action, observable } from 'mobx'; import { observer } from "mobx-react"; import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app -import { emptyFunction, returnFalse, returnZero, returnTrue, returnOne } from '../../../Utils'; -import { CompileScript, CompiledScript, ScriptOptions } from "../../util/Scripting"; +import { Doc, Field } from '../../../new_fields/Doc'; +import { emptyFunction, returnFalse, returnOne, returnZero } from '../../../Utils'; +import { Docs } from '../../documents/Documents'; import { Transform } from '../../util/Transform'; +import { undoBatch } from '../../util/UndoManager'; +import { CollectionDockingView } from '../collections/CollectionDockingView'; +import { ContextMenu } from '../ContextMenu'; import { EditableView } from "../EditableView"; import { FieldView, FieldViewProps } from './FieldView'; +import { KeyValueBox } from './KeyValueBox'; import "./KeyValueBox.scss"; import "./KeyValuePair.scss"; import React = require("react"); -import { Doc, Opt, Field } from '../../../new_fields/Doc'; -import { FieldValue } from '../../../new_fields/Types'; -import { KeyValueBox } from './KeyValueBox'; -import { DragManager, SetupDrag } from '../../util/DragManager'; -import { ContextMenu } from '../ContextMenu'; -import { Docs } from '../../documents/Documents'; -import { CollectionDockingView } from '../collections/CollectionDockingView'; -import { undoBatch } from '../../util/UndoManager'; // Represents one row in a key value plane -- cgit v1.2.3-70-g09d2 From e7e0c506121c3074447df2fd6556fff7b2990d2a Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 2 Aug 2019 14:44:29 -0400 Subject: fixed loading of link compute field --- src/client/documents/Documents.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 818383765..17e474e0e 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -623,11 +623,10 @@ export namespace DocUtils { LinkManager.Instance.addLink(linkDoc); - let script = `return links(self)};`; - let computed = CompileScript(script, { params: { this: "Doc" }, capturedVariables: { self: source }, typecheck: false }); + let script = `return links(this)};`; + let computed = CompileScript(script, { params: { this: "Doc" }, typecheck: false }); computed.compiled && (Doc.GetProto(source).links = new ComputedField(computed)); computed.compiled && (Doc.GetProto(target).links = new ComputedField(computed)); - }, "make link"); return linkDoc; } -- cgit v1.2.3-70-g09d2 From df93a00ed3047abeee90f3ba4858cf7339ce046b Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 2 Aug 2019 17:14:42 -0400 Subject: removed proto from links --- src/client/documents/Documents.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2a1f63d59..5d1b6b382 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -599,9 +599,8 @@ export namespace DocUtils { let linkDoc: Doc | undefined; UndoManager.RunInBatch(() => { - linkDoc = Docs.Create.TextDocument({ width: 100, height: 30, borderRounding: "100%" }); - linkDoc.type = DocumentType.LINK; - let linkDocProto = Doc.GetProto(linkDoc); + let linkDocProto = new Doc(); + linkDocProto.type = DocumentType.LINK; linkDocProto.targetContext = targetContext; linkDocProto.sourceContext = sourceContext; @@ -617,7 +616,7 @@ export namespace DocUtils { linkDocProto.anchor2Page = target.curPage; linkDocProto.anchor2Groups = new List([]); - LinkManager.Instance.addLink(linkDoc); + LinkManager.Instance.addLink(linkDocProto); }, "make link"); return linkDoc; -- cgit v1.2.3-70-g09d2 From 753615c80d4cf08605ebaaeeaf0a44a0fd88d898 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 3 Aug 2019 15:21:10 -0400 Subject: working version of clustering --- src/Utils.ts | 2 + src/client/documents/Documents.ts | 3 +- src/client/util/DragManager.ts | 8 +- src/client/views/MainView.tsx | 4 +- src/client/views/TemplateMenu.tsx | 5 +- .../views/collections/CollectionDockingView.tsx | 3 +- .../views/collections/CollectionSchemaView.tsx | 3 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 142 +++++++++++++-------- .../collections/collectionFreeForm/MarqueeView.tsx | 1 + .../views/nodes/CollectionFreeFormDocumentView.tsx | 12 +- src/client/views/nodes/DocumentView.tsx | 17 +-- .../views/presentationview/PresentationElement.tsx | 3 +- src/client/views/search/SearchItem.tsx | 3 +- 13 files changed, 125 insertions(+), 81 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/Utils.ts b/src/Utils.ts index 8df67df5d..502540eb0 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -140,6 +140,8 @@ export function returnOne() { return 1; } export function returnZero() { return 0; } +export function returnEmptyString() { return ""; } + export function emptyFunction() { } export type Without = Pick>; diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 09bafcf43..07e38a4c0 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -84,6 +84,7 @@ export interface DocumentOptions { templates?: List; viewType?: number; backgroundColor?: string; + defaultBackgroundColor?: string; dropAction?: dropActionType; backgroundLayout?: string; chromeStatus?: string; @@ -124,7 +125,7 @@ export namespace Docs { const TemplateMap: TemplateMap = new Map([ [DocumentType.TEXT, { layout: { view: FormattedTextBox }, - options: { height: 150, backgroundColor: "#f1efeb" } + options: { height: 150, backgroundColor: "#f1efeb", defaultBackgroundColor: "#f1efeb" } }], [DocumentType.HIST, { layout: { view: HistogramBox, collectionView: [CollectionView, data] as CollectionViewType }, diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 0b5c785a4..a7aaaed7c 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -404,7 +404,8 @@ export namespace DragManager { hideSource = options.hideSource(); } } - eles.map(ele => (ele.hidden = hideSource)); + eles.map(ele => (ele.hidden = hideSource) && + (ele.parentElement && ele.parentElement.className.indexOf("collectionFreeFormDocumentView") !== -1 && (ele.parentElement.hidden = hideSource))); let lastX = downX; let lastY = downY; @@ -434,7 +435,10 @@ export namespace DragManager { let hideDragElements = () => { dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement)); - eles.map(ele => (ele.hidden = false)); + eles.map(ele => { + ele.hidden = false; + (ele.parentElement && ele.parentElement.className.indexOf("collectionFreeFormDocumentView") !== -1 && (ele.parentElement.hidden = false)); + }); }; let endDrag = () => { document.removeEventListener("pointermove", moveHandler, true); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 2ecf5fd85..53f589684 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -15,7 +15,7 @@ import { listSpec } from '../../new_fields/Schema'; import { Cast, FieldValue, NumCast, BoolCast, StrCast } from '../../new_fields/Types'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { RouteStore } from '../../server/RouteStore'; -import { emptyFunction, returnOne, returnTrue, Utils } from '../../Utils'; +import { emptyFunction, returnOne, returnTrue, Utils, returnEmptyString } from '../../Utils'; import { DocServer } from '../DocServer'; import { Docs } from '../documents/Documents'; import { SetupDrag } from '../util/DragManager'; @@ -270,6 +270,7 @@ export class MainView extends React.Component { PanelWidth={this.getPWidth} PanelHeight={this.getPHeight} renderDepth={0} + backgroundColor={returnEmptyString} selectOnLoad={false} focus={emptyFunction} parentActive={returnTrue} @@ -334,6 +335,7 @@ export class MainView extends React.Component { renderDepth={0} selectOnLoad={false} focus={emptyFunction} + backgroundColor={returnEmptyString} parentActive={returnTrue} whenActiveChanged={emptyFunction} bringToFront={emptyFunction} diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index e654a0644..6dd908445 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -60,12 +60,9 @@ export class TemplateMenu extends React.Component { let de = new DragManager.DocumentDragData([topDoc], [undefined]); de.moveDocument = topDocView.props.moveDocument; let xf = newDocView.ContentDiv!.getBoundingClientRect(); - console.log("ex = " + ex + " " + xf.left + " " + (ex - xf.left)); DragManager.StartDocumentDrag([newDocView.ContentDiv!], de, ex, ey, { offsetX: (ex - xf.left), offsetY: (ey - xf.top), - handlers: { - dragComplete: () => { }, - }, + handlers: { dragComplete: () => { }, }, hideSource: false }); } diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 588102f01..f559480ed 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -10,7 +10,7 @@ import { Id } from '../../../new_fields/FieldSymbols'; import { FieldId } from "../../../new_fields/RefField"; import { listSpec } from "../../../new_fields/Schema"; import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types"; -import { emptyFunction, returnTrue, Utils, returnOne } from "../../../Utils"; +import { emptyFunction, returnTrue, Utils, returnOne, returnEmptyString } from "../../../Utils"; import { DocServer } from "../../DocServer"; import { DocumentManager } from '../../util/DocumentManager'; import { DragLinksAsDocuments, DragManager } from "../../util/DragManager"; @@ -607,6 +607,7 @@ export class DockedFrameRenderer extends React.Component { parentActive={returnTrue} whenActiveChanged={emptyFunction} focus={emptyFunction} + backgroundColor={returnEmptyString} addDocTab={this.addDocTab} ContainingCollectionView={undefined} zoomToScale={emptyFunction} diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 9efd0d3ec..8218877ba 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -6,7 +6,7 @@ import { action, computed, observable, trace, untracked } from "mobx"; import { observer } from "mobx-react"; import ReactTable, { CellInfo, ComponentPropsGetterR, Column, RowInfo, ResizedChangeFunction, Resize } from "react-table"; import "react-table/react-table.css"; -import { emptyFunction, returnOne } from "../../../Utils"; +import { emptyFunction, returnOne, returnEmptyString } from "../../../Utils"; import { Doc, DocListCast, Field, Opt } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; @@ -999,6 +999,7 @@ export class CollectionSchemaPreview extends React.Component r1.left + r1.width || r2.left + r2.width < r1.left || r2.top > r1.top + r1.height || r2.top + r2.height < r1.top); } - _groupingBorder = 100; + _clusterDistance = 75; bounsdSelect(doc: Doc, doc2: Doc) { - var x2 = NumCast(doc2.x) - this._groupingBorder; - var y2 = NumCast(doc2.y) - this._groupingBorder; - var w2 = NumCast(doc2.width) + this._groupingBorder; - var h2 = NumCast(doc2.height) + this._groupingBorder; - var x = NumCast(doc.x) - this._groupingBorder; - var y = NumCast(doc.y) - this._groupingBorder; - var w = NumCast(doc.width) + this._groupingBorder; - var h = NumCast(doc.height) + this._groupingBorder; - if (this.intersectRect({ left: x, top: y, width: w, height: h }, { left: x2, top: y2, width: w2, height: h2 })) { + var x2 = NumCast(doc2.x) - this._clusterDistance; + var y2 = NumCast(doc2.y) - this._clusterDistance; + var w2 = NumCast(doc2.width) + this._clusterDistance; + var h2 = NumCast(doc2.height) + this._clusterDistance; + var x = NumCast(doc.x) - this._clusterDistance; + var y = NumCast(doc.y) - this._clusterDistance; + var w = NumCast(doc.width) + this._clusterDistance; + var h = NumCast(doc.height) + this._clusterDistance; + if (doc.z === doc2.z && this.intersectRect({ left: x, top: y, width: w, height: h }, { left: x2, top: y2, width: w2, height: h2 })) { return true; } return false; @@ -197,36 +199,83 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return false; } + tryDragCluster(e: PointerEvent) { + let probe = this.getTransform().transformPoint(e.clientX, e.clientY); + let cluster = this.childDocs.reduce((cluster, cd) => { + let cx = NumCast(cd.x) - this._clusterDistance; + let cy = NumCast(cd.y) - this._clusterDistance; + let cw = NumCast(cd.width) + 2 * this._clusterDistance; + let ch = NumCast(cd.height) + 2 * this._clusterDistance; + if (!cd.z && this.intersectRect({ left: cx, top: cy, width: cw, height: ch }, { left: probe[0], top: probe[1], width: 1, height: 1 })) + return NumCast(cd.cluster); + return cluster; + }, -1); + if (cluster !== -1) { + let eles = this.childDocs.filter(cd => NumCast(cd.cluster) === cluster); + this.selectDocuments(eles); + let clusterDocs = SelectionManager.SelectedDocuments(); + SelectionManager.DeselectAll(); + let de = new DragManager.DocumentDragData(eles, eles.map(d => undefined)); + de.moveDocument = this.props.moveDocument; + const [left, top] = clusterDocs[0].props.ScreenToLocalTransform().scale(clusterDocs[0].props.ContentScaling()).inverse().transformPoint(0, 0); + const [xoff, yoff] = this.getTransform().transformDirection(e.x - left, e.y - top); + de.dropAction = e.ctrlKey || e.altKey ? "alias" : undefined; + de.xOffset = xoff; + de.yOffset = yoff; + DragManager.StartDocumentDrag(clusterDocs.map(v => v.ContentDiv!), de, e.clientX, e.clientY, { + handlers: { dragComplete: action(emptyFunction) }, + hideSource: !de.dropAction + }); + return true; + } + + return false; + } + @observable sets: (Doc[])[] = []; @action updateClusters() { - let sets: (Doc[])[] = [] + this.sets.length = 0; this.childDocs.map(c => { let included = [] - for (let i = 0; i < sets.length; i++) { - for (let j = 0; j < sets[i].length; j++) { - if (this.bounsdSelect(c, sets[i][j])) { + for (let i = 0; i < this.sets.length; i++) { + for (let j = 0; j < this.sets[i].length; j++) { + if (this.bounsdSelect(c, this.sets[i][j])) { included.push(i); break; } } } if (included.length === 0) - sets.push([c]); + this.sets.push([c]); else if (included.length === 1) - sets[included[0]].push(c); + this.sets[included[0]].push(c); else { - sets[included[0]].push(c); + this.sets[included[0]].push(c); for (let s = 1; s < included.length; s++) { - sets[included[0]].push(...sets[included[s]]); - sets[included[s]].length = 0; + this.sets[included[0]].push(...this.sets[included[s]]); + this.sets[included[s]].length = 0; } } }); - for (let s = 0; s < sets.length; s++) { - for (let i = 0; i < sets[s].length; i++) { - Doc.GetProto(sets[s][i]).cluster = s; + for (let s = 0; s < this.sets.length; s++) { + for (let i = 0; i < this.sets[s].length; i++) { + this.sets[s][i].cluster = s; + } + } + } + + getClusterColor = (doc: Doc) => { + if (this.props.Document.useClusters) { + let cluster = NumCast(doc.cluster); + let set = this.sets.length > cluster ? this.sets[NumCast(doc.cluster)] : undefined; + let colors = ["#da42429e", "#31ea318c", "#8c4000", "#4a7ae2c4", "#d809ff", "#ff7601", "#1dffff", "yellow", "#1b8231f2", "#000000ad"]; + let clusterColor = colors[cluster % colors.length]; + for (let i = 0; set && i < set.length; i++) { + if (set[i].backgroundColor && set[i].backgroundColor !== set[i].defaultBackgroundColor) clusterColor = StrCast(set[i].backgroundColor); } + return clusterColor; } + return ""; } @action @@ -249,34 +298,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @action onPointerMove = (e: PointerEvent): void => { if (!e.cancelBubble) { - let probe = this.getTransform().transformPoint(e.clientX, e.clientY); - let cluster = this.childDocs.reduce((cluster, cd) => { - let cx = NumCast(cd.x) - this._groupingBorder; - let cy = NumCast(cd.y) - this._groupingBorder; - let cw = NumCast(cd.width) + 2 * this._groupingBorder; - let ch = NumCast(cd.height) + 2 * this._groupingBorder; - if (this.intersectRect({ left: cx, top: cy, width: cw, height: ch }, { left: probe[0], top: probe[1], width: 1, height: 1 })) - return NumCast(cd.cluster); - return cluster; - }, -1); - if (cluster !== -1) { - let eles = this.childDocs.filter(cd => NumCast(cd.cluster) === cluster); - this.selectDocuments(eles); - let clusterDocs = SelectionManager.SelectedDocuments(); - SelectionManager.DeselectAll(); - let de = new DragManager.DocumentDragData(eles, eles.map(d => undefined)); - de.moveDocument = this.props.moveDocument; - const [left, top] = clusterDocs[0].props.ScreenToLocalTransform().scale(clusterDocs[0].props.ContentScaling()).inverse().transformPoint(0, 0); - const [xoff, yoff] = this.getTransform().transformDirection(e.x - left, e.y - top); - de.dropAction = e.ctrlKey || e.altKey ? "alias" : undefined; - de.xOffset = xoff; - de.yOffset = yoff; - DragManager.StartDocumentDrag(clusterDocs.map(v => v.ContentDiv!), de, e.clientX, e.clientY, { - handlers: { - dragComplete: action(emptyFunction) - }, - hideSource: !de.dropAction - }); + if (this.props.Document.useClusters && this.tryDragCluster(e)) { e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document' however it does mark the event as cancelBubble=true which we test for in the move event handlers e.preventDefault(); document.removeEventListener("pointermove", this.onPointerMove); @@ -493,6 +515,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { ContentScaling: returnOne, ContainingCollectionView: this.props.CollectionView, focus: this.focusDocument, + backgroundColor: this.getClusterColor, parentActive: this.props.active, whenActiveChanged: this.props.whenActiveChanged, bringToFront: this.bringToFront, @@ -516,6 +539,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { ContentScaling: returnOne, ContainingCollectionView: this.props.CollectionView, focus: this.focusDocument, + backgroundColor: returnEmptyString, parentActive: this.props.active, whenActiveChanged: this.props.whenActiveChanged, bringToFront: this.bringToFront, @@ -625,6 +649,15 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { event: async () => this.props.Document.fitToBox = !this.fitToBox, icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt" }); + layoutItems.push({ + description: `${this.props.Document.useClusters ? "Uncluster" : "Use Clusters"}`, + event: async () => { + Docs.Prototypes.get(DocumentType.TEXT).defaultBackgroundColor = "#f1efeb"; + Docs.Prototypes.get(DocumentType.COL).defaultBackgroundColor = "white"; + this.props.Document.useClusters = !this.props.Document.useClusters; + }, + icon: !this.props.Document.useClusters ? "expand-arrows-alt" : "compress-arrows-alt" + }); layoutItems.push({ description: "Arrange contents in grid", icon: "table", @@ -700,10 +733,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { ...this.views ] private overlayChildViews = () => { - console.log(this.overlayViews.length); - return [ - ...this.overlayViews - ]; + return [...this.overlayViews]; } public static AddCustomLayout(doc: Doc, dataKey: string): () => void { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index b9ee588dd..ff96bd993 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -278,6 +278,7 @@ export class MarqueeView extends React.Component panX: 0, panY: 0, backgroundColor: this.props.container.isAnnotationOverlay ? undefined : "white", + defaultBackgroundColor: this.props.container.isAnnotationOverlay ? undefined : "white", width: bounds.width, height: bounds.height, title: e.key === "s" || e.key === "S" ? "-summary-" : "a nested collection", diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 3b6c443c2..ee596c841 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -8,6 +8,7 @@ import { DocumentView, DocumentViewProps, positionSchema } from "./DocumentView" import "./DocumentView.scss"; import React = require("react"); import { Doc } from "../../../new_fields/Doc"; +import { returnEmptyString } from "../../../Utils"; export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { x?: number; @@ -69,6 +70,11 @@ export class CollectionFreeFormDocumentView extends DocComponent this.clusterColor; + render() { const hasPosition = this.props.x !== undefined || this.props.y !== undefined; return ( @@ -77,7 +83,10 @@ export class CollectionFreeFormDocumentView extends DocComponent void; collapseToPoint?: (scrpt: number[], expandedDocs: Doc[] | undefined) => void; zoomToScale: (scale: number) => void; + backgroundColor: (doc: Doc) => string; getScale: () => number; animateBetweenIcon?: (iconPos: number[], startTime: number, maximizing: boolean) => void; ChromeHeight?: () => number; @@ -675,12 +676,9 @@ export class DocumentView extends DocComponent(Docu // to determine the render JSX string, otherwise the layout field should directly contain a JSX layout string. return this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document; } + render() { - if (this.Document.hidden) { - return null; - } - let self = this; - let backgroundColor = StrCast(this.layoutDoc.backgroundColor); + let backgroundColor = this.props.backgroundColor(this.props.Document) || StrCast(this.layoutDoc.backgroundColor); let foregroundColor = StrCast(this.layoutDoc.color); var nativeWidth = this.nativeWidth > 0 && !BoolCast(this.props.Document.ignoreAspect) ? `${this.nativeWidth}px` : "100%"; var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; @@ -695,8 +693,6 @@ export class DocumentView extends DocComponent(Docu }); } let showTextTitle = showTitle && StrCast(this.layoutDoc.layout).startsWith("(Docu color: foregroundColor, outlineColor: "maroon", outlineStyle: "dashed", - boxShadow: this.layoutDoc.isBackground ? - `0px 0px 50px 50px ${groupCol}` : - `${groupCol} ${StrCast(this.props.Document.boxShadow, `0vw 0vw ${50 / this.props.ContentScaling()}px`)}`, outlineWidth: BoolCast(this.layoutDoc.libraryBrush) && !StrCast(Doc.GetProto(this.props.Document).borderRounding) ? `${this.props.ScreenToLocalTransform().Scale}px` : "0px", marginLeft: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ? @@ -717,7 +710,7 @@ export class DocumentView extends DocComponent(Docu border: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ? `dashed maroon ${this.props.ScreenToLocalTransform().Scale}px` : undefined, borderRadius: "inherit", - background: this.layoutDoc.isBackground ? groupCol : backgroundColor, + background: backgroundColor, width: nativeWidth, height: nativeHeight, transform: `scale(${this.props.ContentScaling()})`, diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 11f3eb846..e2d8daea9 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -9,7 +9,7 @@ import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types"; -import { Utils, returnFalse, emptyFunction, returnOne } from "../../../Utils"; +import { Utils, returnFalse, emptyFunction, returnOne, returnEmptyString } from "../../../Utils"; import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager"; import { SelectionManager } from "../../util/SelectionManager"; import { ContextMenu } from "../ContextMenu"; @@ -843,6 +843,7 @@ export default class PresentationElement extends React.Component 350} PanelHeight={() => 90} focus={emptyFunction} + backgroundColor={returnEmptyString} selectOnLoad={false} parentActive={returnFalse} whenActiveChanged={returnFalse} diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index 0390359b3..1b9bba5c6 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -7,7 +7,7 @@ import { observer } from "mobx-react"; import { Doc, DocListCast, HeightSym, WidthSym } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; -import { emptyFunction, returnFalse, returnOne, Utils } from "../../../Utils"; +import { emptyFunction, returnFalse, returnOne, Utils, returnEmptyString } from "../../../Utils"; import { DocumentType } from "../../documents/Documents"; import { DocumentManager } from "../../util/DocumentManager"; import { SetupDrag, DragManager } from "../../util/DragManager"; @@ -223,6 +223,7 @@ export class SearchItem extends React.Component { PanelWidth={returnXDimension} PanelHeight={returnYDimension} focus={emptyFunction} + backgroundColor={returnEmptyString} selectOnLoad={false} parentActive={returnFalse} whenActiveChanged={returnFalse} -- cgit v1.2.3-70-g09d2 From fd047fa87334b948a4a0b00ccf9bd02ded03ea36 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 4 Aug 2019 10:16:46 -0400 Subject: fixed MakeLink (& text linking) --- src/client/documents/Documents.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 07e38a4c0..e804d5440 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -602,9 +602,8 @@ export namespace DocUtils { if (sv && sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === target) return; if (target === CurrentUserUtils.UserDocument) return undefined; - let linkDoc: Doc | undefined; + let linkDocProto = new Doc(); UndoManager.RunInBatch(() => { - let linkDocProto = new Doc(); linkDocProto.type = DocumentType.LINK; linkDocProto.targetContext = targetContext; @@ -628,7 +627,7 @@ export namespace DocUtils { computed.compiled && (Doc.GetProto(source).links = new ComputedField(computed)); computed.compiled && (Doc.GetProto(target).links = new ComputedField(computed)); }, "make link"); - return linkDoc; + return linkDocProto; } } -- cgit v1.2.3-70-g09d2 From 941c50617a0cbaef054f2be856de013bd69ea81f Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 7 Aug 2019 18:15:38 -0400 Subject: pdf annotaitons --- src/client/documents/Documents.ts | 1 + src/client/views/nodes/PDFBox.tsx | 3 +- src/client/views/pdf/Annotation.scss | 2 +- src/client/views/pdf/Annotation.tsx | 8 +-- src/client/views/pdf/PDFViewer.tsx | 95 ++++++++++++++---------------------- src/client/views/pdf/Page.tsx | 6 +-- 6 files changed, 47 insertions(+), 68 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e804d5440..9c1278150 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -84,6 +84,7 @@ export interface DocumentOptions { templates?: List; viewType?: number; backgroundColor?: string; + opacity?: number; defaultBackgroundColor?: string; dropAction?: dropActionType; backgroundLayout?: string; diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index e9207404e..6450cb826 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -194,10 +194,11 @@ export class PDFBox extends DocComponent(PdfDocumen onScroll={this.onScroll} style={{ marginTop: `${this.containingCollectionDocument ? NumCast(this.containingCollectionDocument.panY) : 0}px` }} ref={this._mainCont}> -
      +
      {this.settingsPanel()}
      ); diff --git a/src/client/views/pdf/Annotation.scss b/src/client/views/pdf/Annotation.scss index 817115690..0c6df74f0 100644 --- a/src/client/views/pdf/Annotation.scss +++ b/src/client/views/pdf/Annotation.scss @@ -2,6 +2,6 @@ pointer-events: all; user-select: none; position: absolute; - background-color: pink; + background-color: red; opacity: 0.1; } \ No newline at end of file diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index 2610f6c6e..7ba7b6d14 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -120,10 +120,10 @@ class RegionAnnotation extends React.Component { render() { return (
      ); } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index f3281047a..95df10c58 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -36,6 +36,7 @@ interface IViewerProps { active: () => boolean; setPanY?: (n: number) => void; addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; + addDocument?: (doc: Doc, allowDuplicates?: boolean) => boolean; } /** @@ -124,7 +125,7 @@ export class PDFViewer extends React.Component { if (this.props.active() && e.clipboardData) { e.clipboardData.setData("text/plain", this._selectionText); e.clipboardData.setData("dash/pdfOrigin", this.props.Document[Id]); - e.clipboardData.setData("dash/pdfRegion", this.makeAnnotationDocument(undefined, 0, "#0390fc")[Id]); + e.clipboardData.setData("dash/pdfRegion", this.makeAnnotationDocument(undefined, "#0390fc")[Id]); e.preventDefault(); } } @@ -133,7 +134,7 @@ export class PDFViewer extends React.Component { if (e.clipboardData && e.clipboardData.getData("dash/pdfOrigin") === this.props.Document[Id]) { let linkDocId = e.clipboardData.getData("dash/linkDoc"); linkDocId && DocServer.GetRefField(linkDocId).then(async (link) => - (link instanceof Doc) && (Doc.GetProto(link).anchor2 = this.makeAnnotationDocument(await Cast(Doc.GetProto(link), Doc), 0, "#0390fc", false))); + (link instanceof Doc) && (Doc.GetProto(link).anchor2 = this.makeAnnotationDocument(await Cast(Doc.GetProto(link), Doc), "#0390fc", false))); } } @@ -166,32 +167,50 @@ export class PDFViewer extends React.Component { } @action - makeAnnotationDocument = (sourceDoc: Doc | undefined, s: number, color: string, createLink: boolean = true): Doc => { + makeAnnotationDocument = (sourceDoc: Doc | undefined, color: string, createLink: boolean = true): Doc => { let mainAnnoDoc = Docs.Create.InstanceFromProto(new Doc(), "", {}); + let mainAnnoDocProto = Doc.GetProto(mainAnnoDoc); let annoDocs: Doc[] = []; let minY = Number.MAX_VALUE; - this._savedAnnotations.forEach((key: number, value: HTMLDivElement[]) => value.map(anno => { - let annoDoc = new Doc(); - if (anno.style.left) annoDoc.x = parseInt(anno.style.left) / scale; - if (anno.style.top) annoDoc.y = parseInt(anno.style.top) / scale; - if (anno.style.height) annoDoc.height = parseInt(anno.style.height) / scale; - if (anno.style.width) annoDoc.width = parseInt(anno.style.width) / scale; - annoDoc.page = key; + if (this._savedAnnotations.size() === 1 && this._savedAnnotations.values()[0].length === 1 && !createLink) { + let anno = this._savedAnnotations.values()[0][0]; + let annoDoc = Docs.Create.FreeformDocument([], { backgroundColor: "rgba(255, 0, 0, 0.1)", title: "Annotation on " + StrCast(this.props.Document.title) }); + if (anno.style.left) annoDoc.x = parseInt(anno.style.left); + if (anno.style.top) annoDoc.y = parseInt(anno.style.top); + if (anno.style.height) annoDoc.height = parseInt(anno.style.height); + if (anno.style.width) annoDoc.width = parseInt(anno.style.width); annoDoc.target = sourceDoc; annoDoc.group = mainAnnoDoc; annoDoc.color = color; annoDoc.type = AnnotationTypes.Region; annoDocs.push(annoDoc); + annoDoc.isBackground = true; anno.remove(); - (annoDoc.y !== undefined) && (minY = Math.min(NumCast(annoDoc.y), minY)); - })); - - let mainAnnoDocProto = Doc.GetProto(mainAnnoDoc); - mainAnnoDocProto.title = "Annotation on " + StrCast(this.props.Document.title); + this.props.addDocument && this.props.addDocument(annoDoc, false); + mainAnnoDoc = annoDoc; + mainAnnoDocProto = Doc.GetProto(annoDoc); + } else { + this._savedAnnotations.forEach((key: number, value: HTMLDivElement[]) => value.map(anno => { + let annoDoc = new Doc(); + if (anno.style.left) annoDoc.x = parseInt(anno.style.left); + if (anno.style.top) annoDoc.y = parseInt(anno.style.top); + if (anno.style.height) annoDoc.height = parseInt(anno.style.height); + if (anno.style.width) annoDoc.width = parseInt(anno.style.width); + annoDoc.target = sourceDoc; + annoDoc.group = mainAnnoDoc; + annoDoc.color = color; + annoDoc.type = AnnotationTypes.Region; + annoDocs.push(annoDoc); + anno.remove(); + (annoDoc.y !== undefined) && (minY = Math.min(NumCast(annoDoc.y), minY)); + })); + + mainAnnoDocProto.y = Math.max(minY, 0); + mainAnnoDocProto.annotations = new List(annoDocs); + } mainAnnoDocProto.pdfDoc = this.props.Document; + mainAnnoDocProto.title = "Annotation on " + StrCast(this.props.Document.title); mainAnnoDocProto.annotationOn = this.props.Document; - mainAnnoDocProto.y = Math.max(minY, 0); - mainAnnoDocProto.annotations = new List(annoDocs); if (sourceDoc && createLink) { DocUtils.MakeLink(sourceDoc, mainAnnoDocProto, undefined, `Annotation from ${StrCast(this.props.Document.title)}`, "", StrCast(this.props.Document.title)); } @@ -346,48 +365,6 @@ export class PDFViewer extends React.Component { this._mainCont.current.addEventListener("pagesloaded", executeFind); this._mainCont.current.addEventListener("pagerendered", executeFind); } - - // let viewer = this._viewer.current; - - // if (!this._pdfFindController) { - // if (container && viewer) { - // let simpleLinkService = new SimpleLinkService(); - // let pdfViewer = new PDFJSViewer.PDFViewer({ - // container: container, - // viewer: viewer, - // linkService: simpleLinkService - // }); - // simpleLinkService.setPdf(this.props.pdf); - // container.addEventListener("pagesinit", () => { - // pdfViewer.currentScaleValue = 1; - // }); - // container.addEventListener("pagerendered", () => { - // console.log("rendered"); - // this._pdfFindController.executeCommand('find', - // { - // caseSensitive: false, - // findPrevious: undefined, - // highlightAll: true, - // phraseSearch: true, - // query: searchString - // }); - // }); - // pdfViewer.setDocument(this.props.pdf); - // this._pdfFindController = new PDFJSViewer.PDFFindController(pdfViewer); - // // this._pdfFindController._linkService = pdfLinkService; - // pdfViewer.findController = this._pdfFindController; - // } - // } - // else { - // this._pdfFindController.executeCommand('find', - // { - // caseSensitive: false, - // findPrevious: undefined, - // highlightAll: true, - // phraseSearch: true, - // query: searchString - // }); - // } } diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx index 6de2db427..4986f44d5 100644 --- a/src/client/views/pdf/Page.tsx +++ b/src/client/views/pdf/Page.tsx @@ -24,7 +24,7 @@ interface IPageProps { renderAnnotations: (annotations: Doc[], removeOld: boolean) => void; sendAnnotations: (annotations: HTMLDivElement[], page: number) => void; createAnnotation: (div: HTMLDivElement, page: number) => void; - makeAnnotationDocuments: (doc: Doc | undefined, scale: number, color: string, linkTo: boolean) => Doc; + makeAnnotationDocuments: (doc: Doc | undefined, color: string, linkTo: boolean) => Doc; getScrollFromPage: (page: number) => number; setSelectionText: (text: string) => void; } @@ -87,7 +87,7 @@ export default class Page extends React.Component { @action highlight = (targetDoc: Doc | undefined, color: string) => { // creates annotation documents for current highlights - let annotationDoc = this.props.makeAnnotationDocuments(targetDoc, scale, color, false); + let annotationDoc = this.props.makeAnnotationDocuments(targetDoc, color, false); Doc.AddDocToList(this.props.fieldExtensionDoc, "annotations", annotationDoc); return annotationDoc; } @@ -143,7 +143,7 @@ export default class Page extends React.Component { @action onPointerDown = (e: React.PointerEvent): void => { // if alt+left click, drag and annotate - if (this.props.Document.scale !== 1) return; + if (NumCast(this.props.Document.scale, 1) !== 1) return; if (e.altKey && e.button === 0) { e.stopPropagation(); } -- cgit v1.2.3-70-g09d2 From ff087aca29a01a8aa254148c9ab6082c3921fb3b Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 8 Aug 2019 10:18:23 -0400 Subject: added retitling of aliases. --- src/client/documents/Documents.ts | 2 +- src/client/util/LinkManager.ts | 4 ++++ src/new_fields/Doc.ts | 14 +++++++++----- 3 files changed, 14 insertions(+), 6 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 9c1278150..318493822 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -623,7 +623,7 @@ export namespace DocUtils { LinkManager.Instance.addLink(linkDocProto); - let script = `return links(this)};`; + let script = `return links(this);`; let computed = CompileScript(script, { params: { this: "Doc" }, typecheck: false }); computed.compiled && (Doc.GetProto(source).links = new ComputedField(computed)); computed.compiled && (Doc.GetProto(target).links = new ComputedField(computed)); diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 448a8e9cf..c87e4a022 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -252,3 +252,7 @@ export class LinkManager { Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); }); + +Scripting.addGlobal(function renameAlias(doc: any, n: any) { + return doc.title;// StrCast(doc.title).replace(/\\([0-9]*\\)/, "") + `(${n})`; +}); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 736e8e69d..c51b42e07 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -8,10 +8,10 @@ import { listSpec } from "./Schema"; import { ObjectField } from "./ObjectField"; import { RefField, FieldId } from "./RefField"; import { ToScriptString, SelfProxy, Parent, OnUpdate, Self, HandleUpdate, Update, Id } from "./FieldSymbols"; -import { scriptingGlobal } from "../client/util/Scripting"; +import { scriptingGlobal, CompileScript, Scripting } from "../client/util/Scripting"; import { List } from "./List"; import { DocumentType } from "../client/documents/Documents"; -import { ComputedField } from "./ScriptField"; +import { ComputedField, ScriptField } from "./ScriptField"; import { PrefetchProxy, ProxyField } from "./Proxy"; export namespace Field { @@ -390,10 +390,14 @@ export namespace Doc { } } export function MakeAlias(doc: Doc) { - if (!GetT(doc, "isPrototype", "boolean", true)) { - return Doc.MakeCopy(doc); + let alias = !GetT(doc, "isPrototype", "boolean", true) ? Doc.MakeCopy(doc) : Doc.MakeDelegate(doc); + let aliasNumber = Doc.GetProto(doc).aliasNumber = NumCast(Doc.GetProto(doc).aliasNumber) + 1; + let script = `return renameAlias(self, ${aliasNumber})`; + let compiled = CompileScript(script, { params: { this: "Doc" }, capturedVariables: { self: doc }, typecheck: false }); + if (compiled.compiled) { + alias.title = new ComputedField(compiled); } - return Doc.MakeDelegate(doc); // bcz? + return alias; } // -- cgit v1.2.3-70-g09d2 From 316c241d72fb83aad5f2bf9b143c317fdc906654 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 8 Aug 2019 12:23:47 -0400 Subject: fixed issues with jumptoDocument --- package.json | 2 +- src/client/documents/Documents.ts | 3 +-- src/client/util/DocumentManager.ts | 12 ++++++----- .../views/collections/CollectionBaseView.tsx | 5 ++--- src/client/views/nodes/DocumentView.tsx | 24 +++++++++------------- src/client/views/nodes/LinkMenuItem.tsx | 4 ++-- src/client/views/pdf/PDFViewer.tsx | 2 +- src/client/views/pdf/Page.tsx | 3 +-- 8 files changed, 25 insertions(+), 30 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/package.json b/package.json index 29a903d71..d699d1e6f 100644 --- a/package.json +++ b/package.json @@ -218,4 +218,4 @@ "xoauth2": "^1.2.0", "youtube": "^0.1.0" } -} \ No newline at end of file +} diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index a8545206a..7dd853156 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -596,7 +596,7 @@ export namespace Docs { export namespace DocUtils { - export function MakeLink(source: Doc, target: Doc, targetContext?: Doc, title: string = "", description: string = "", tags: string = "Default", sourceContext?: Doc) { + export function MakeLink(source: Doc, target: Doc, targetContext?: Doc, title: string = "", description: string = "", sourceContext?: Doc) { if (LinkManager.Instance.doesLinkExist(source, target)) return undefined; let sv = DocumentManager.Instance.getDocumentView(source); if (sv && sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === target) return; @@ -610,7 +610,6 @@ export namespace DocUtils { linkDocProto.sourceContext = sourceContext; linkDocProto.title = title === "" ? source.title + " to " + target.title : title; linkDocProto.linkDescription = description; - linkDocProto.linkTags = tags; linkDocProto.type = DocumentType.LINK; linkDocProto.anchor1 = source; diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 0d46df406..7f526b247 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,5 +1,5 @@ import { action, computed, observable } from 'mobx'; -import { Doc } from '../../new_fields/Doc'; +import { Doc, DocListCastAsync } from '../../new_fields/Doc'; import { Id } from '../../new_fields/FieldSymbols'; import { Cast, NumCast } from '../../new_fields/Types'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; @@ -140,13 +140,15 @@ export class DocumentManager { if (!forceDockFunc && (docView = DocumentManager.Instance.getDocumentView(doc))) { Doc.BrushDoc(docView.props.Document); if (linkPage !== undefined) docView.props.Document.curPage = linkPage; - UndoManager.RunInBatch(() => { - docView!.props.focus(docView!.props.Document, willZoom); - }, "focus"); + UndoManager.RunInBatch(() => docView!.props.focus(docView!.props.Document, willZoom), "focus"); } else { if (!contextDoc) { - if (docContext) { + let docs = docContext ? await DocListCastAsync(docContext.data) : undefined; + let found = false; + docs && docs.map(d => found = found || Doc.AreProtosEqual(d, docDelegate)); + if (docContext && found) { let targetContextView: DocumentView | null; + if (!forceDockFunc && docContext && (targetContextView = DocumentManager.Instance.getDocumentView(docContext))) { docContext.panTransformType = "Ease"; targetContextView.props.focus(docDelegate, willZoom); diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index b53e83eb1..cad87ebcc 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -99,7 +99,7 @@ export class CollectionBaseView extends React.Component { addDocument(doc: Doc, allowDuplicates: boolean = false): boolean { var curPage = NumCast(this.props.Document.curPage, -1); Doc.GetProto(doc).page = curPage; - if (curPage >= 0) { + if (this.props.fieldExt) { // bcz: fieldExt !== undefined means this is an overlay layer Doc.GetProto(doc).annotationOn = this.props.Document; } allowDuplicates = true; @@ -126,8 +126,7 @@ export class CollectionBaseView extends React.Component { let value = Cast(targetDataDoc[targetField], listSpec(Doc), []); let index = value.reduce((p, v, i) => (v instanceof Doc && v[Id] === doc[Id]) ? i : p, -1); PromiseValue(Cast(doc.annotationOn, Doc)).then(annotationOn => - annotationOn === this.dataDoc.Document && (doc.annotationOn = undefined) - ); + annotationOn === this.dataDoc.Document && (doc.annotationOn = undefined)); if (index !== -1) { value.splice(index, 1); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 861b53abf..c8eab85c2 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -8,7 +8,7 @@ import { Copy, Id } from '../../../new_fields/FieldSymbols'; import { List } from "../../../new_fields/List"; import { ObjectField } from "../../../new_fields/ObjectField"; import { createSchema, listSpec, makeInterface } from "../../../new_fields/Schema"; -import { BoolCast, Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types"; +import { BoolCast, Cast, FieldValue, NumCast, StrCast, PromiseValue } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { RouteStore } from '../../../server/RouteStore'; import { emptyFunction, returnTrue, Utils } from "../../../Utils"; @@ -359,12 +359,12 @@ export class DocumentView extends DocComponent(Docu if (!linkedFwdDocs.some(l => l instanceof Promise)) { let maxLocation = StrCast(linkedFwdDocs[0].maximizeLocation, "inTab"); let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined; - DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false, document => { - this.props.focus(this.props.Document, true, 1); - setTimeout(() => - this.props.addDocTab(document, undefined, maxLocation), 1000); - } - , linkedFwdPage[altKey ? 1 : 0], targetContext); + DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false, + document => { // open up target if it's not already in view ... + this.props.focus(this.props.Document, true, 1); // by zooming into the button document first + setTimeout(() => this.props.addDocTab(document, undefined, maxLocation), 1000); // then after the 1sec animation, open up the target in a new tab + }, + linkedFwdPage[altKey ? 1 : 0], targetContext); } } } @@ -445,13 +445,9 @@ export class DocumentView extends DocComponent(Docu let targetDoc = this.props.Document; targetDoc.targetContext = de.data.targetContext; let annotations = await DocListCastAsync(annotationDoc.annotations); - if (annotations) { - annotations.forEach(anno => anno.target = targetDoc); - } - let annotDoc = await Cast(annotationDoc.annotationOn, Doc); - if (annotDoc) { - DocUtils.MakeLink(annotationDoc, targetDoc, this.props.ContainingCollectionView!.props.Document, `Annotation from ${StrCast(annotDoc.title)}`, "", StrCast(annotDoc.title)); - } + annotations && annotations.forEach(anno => anno.target = targetDoc); + + DocUtils.MakeLink(annotationDoc, targetDoc, this.props.ContainingCollectionView!.props.Document, `Link from ${StrCast(annotationDoc.title)}`); } if (de.data instanceof DragManager.LinkDragData) { let sourceDoc = de.data.linkSourceDocument; diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx index 1d4fcad69..a119eb39b 100644 --- a/src/client/views/nodes/LinkMenuItem.tsx +++ b/src/client/views/nodes/LinkMenuItem.tsx @@ -6,7 +6,7 @@ import { DocumentManager } from "../../util/DocumentManager"; import { undoBatch } from "../../util/UndoManager"; import './LinkMenu.scss'; import React = require("react"); -import { Doc } from '../../../new_fields/Doc'; +import { Doc, DocListCastAsync } from '../../../new_fields/Doc'; import { StrCast, Cast, FieldValue, NumCast } from '../../../new_fields/Types'; import { observable, action } from 'mobx'; import { LinkManager } from '../../util/LinkManager'; @@ -52,7 +52,7 @@ export class LinkMenuItem extends React.Component { } if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) { - DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => dockingFunc(targetContext!)); + DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, async document => dockingFunc(document), undefined, targetContext!); } else if (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext) { DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => dockingFunc(sourceContext!)); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 7cd62f4e0..08674720d 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -211,7 +211,7 @@ export class PDFViewer extends React.Component { mainAnnoDocProto.title = "Annotation on " + StrCast(this.props.Document.title); mainAnnoDocProto.annotationOn = this.props.Document; if (sourceDoc && createLink) { - DocUtils.MakeLink(sourceDoc, mainAnnoDocProto, undefined, `Annotation from ${StrCast(this.props.Document.title)}`, "", StrCast(this.props.Document.title)); + DocUtils.MakeLink(sourceDoc, mainAnnoDocProto, undefined, `Annotation from ${StrCast(this.props.Document.title)}`); } this._savedAnnotations.clear(); this.Index = -1; diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx index 6bd98cbaa..7ca9d2d7d 100644 --- a/src/client/views/pdf/Page.tsx +++ b/src/client/views/pdf/Page.tsx @@ -112,8 +112,7 @@ export default class Page extends React.Component { if (!BoolCast(annotationDoc.linkedToDoc)) { let annotations = await DocListCastAsync(annotationDoc.annotations); annotations && annotations.forEach(anno => anno.target = targetDoc); - let parentDoc = await Cast(annotationDoc.annotationOn, Doc); - parentDoc && DocUtils.MakeLink(annotationDoc, targetDoc, dragData.targetContext, `Annotation from ${StrCast(parentDoc.title)}`, "", StrCast(parentDoc.title)) + DocUtils.MakeLink(annotationDoc, targetDoc, dragData.targetContext, `Annotation from ${StrCast(this.props.Document.title)}`) } } }, -- cgit v1.2.3-70-g09d2 From 18d02f8eb8cef6e0ae3bdb95a5d22958f0fda91e Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 8 Aug 2019 16:19:09 -0400 Subject: dragBoxes --- src/client/documents/Documents.ts | 11 +++ src/client/views/MainView.tsx | 5 +- .../views/collections/CollectionStackingView.tsx | 2 +- src/client/views/nodes/DocumentContentsView.tsx | 3 +- src/client/views/nodes/DragBox.scss | 13 ++++ src/client/views/nodes/DragBox.tsx | 80 ++++++++++++++++++++++ 6 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 src/client/views/nodes/DragBox.scss create mode 100644 src/client/views/nodes/DragBox.tsx (limited to 'src/client/documents/Documents.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 7dd853156..9c8b6c129 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -17,6 +17,7 @@ export enum DocumentType { TEMPLATE = "template", EXTENSION = "extension", YOUTUBE = "youtube", + DRAGBOX = "dragbox", } import { HistogramField } from "../northstar/dash-fields/HistogramField"; @@ -60,6 +61,7 @@ import { DocumentManager } from "../util/DocumentManager"; import DirectoryImportBox from "../util/Import & Export/DirectoryImportBox"; import { Scripting, CompileScript } from "../util/Scripting"; import { ButtonBox } from "../views/nodes/ButtonBox"; +import { DragBox } from "../views/nodes/DragBox"; import { SchemaHeaderField, RandomPastel } from "../../new_fields/SchemaHeaderField"; import { ComputedField } from "../../new_fields/ScriptField"; import { ProxyField } from "../../new_fields/Proxy"; @@ -177,6 +179,10 @@ export namespace Docs { }], [DocumentType.BUTTON, { layout: { view: ButtonBox }, + }], + [DocumentType.DRAGBOX, { + layout: { view: DragBox }, + options: { width: 40, height: 40 }, }] ]); @@ -442,6 +448,11 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.BUTTON), undefined, { ...(options || {}) }); } + + export function DragboxDocument(options?: DocumentOptions) { + return InstanceFromProto(Prototypes.get(DocumentType.DRAGBOX), undefined, { ...(options || {}) }); + } + export function DockDocument(documents: Array, config: string, options: DocumentOptions, id?: string) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }, id); } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index ddb023aca..a4db753ab 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -446,7 +446,7 @@ export class MainView extends React.Component { //let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" })); // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy" })); let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" })); - let addTreeNode = action(() => CurrentUserUtils.UserDocument); + let addDragboxNode = action(() => Docs.Create.DragboxDocument({ width: 40, height: 40, title: "drag collection" })); let addImageNode = action(() => Docs.Create.ImageDocument(imgurl, { width: 200, title: "an image of a cat" })); let addButtonDocument = action(() => Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })); let addImportCollectionNode = action(() => Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })); @@ -458,7 +458,8 @@ export class MainView extends React.Component { [React.createRef(), "bolt", "Add Button", addButtonDocument], // [React.createRef(), "clone", "Add Docking Frame", addDockingNode], [React.createRef(), "cloud-upload-alt", "Import Directory", addImportCollectionNode], - [React.createRef(), "play", "Add Youtube Searcher", addYoutubeSearcher] + [React.createRef(), "play", "Add Youtube Searcher", addYoutubeSearcher], + [React.createRef(), "bolt", "Add Document Dragger", addDragboxNode] ]; if (!ClientUtils.RELEASE) btns.unshift([React.createRef(), "cat", "Add Cat Image", addImageNode]); diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 4a751c84c..112d64e3d 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -120,7 +120,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { DataDocument={dataDoc} showOverlays={this.overlays} renderDepth={this.props.renderDepth} - fitToBox={true} + fitToBox={this.props.fitToBox} width={width} height={height} getTransform={finalDxf} diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 396233551..6b7b239f0 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -11,6 +11,7 @@ import { DocumentViewProps } from "./DocumentView"; import "./DocumentView.scss"; import { FormattedTextBox } from "./FormattedTextBox"; import { ImageBox } from "./ImageBox"; +import { DragBox } from "./DragBox"; import { ButtonBox } from "./ButtonBox"; import { IconBox } from "./IconBox"; import { KeyValueBox } from "./KeyValueBox"; @@ -99,7 +100,7 @@ export class DocumentContentsView extends React.Component 7) return (null); if (!this.layout && (this.props.layoutKey !== "overlayLayout" || !this.templates.length)) return (null); return ; +const DragDocument = makeInterface(DragSchema); + +@observer +export class DragBox extends DocComponent(DragDocument) { + public static LayoutString() { return FieldView.LayoutString(DragBox); } + _mainCont = React.createRef(); + onDragStart = (e: React.PointerEvent) => { + if (!e.ctrlKey && !e.altKey && !e.shiftKey && !this.props.isSelected()) { + const onDragStart = this.Document.onDragStart; + e.stopPropagation(); + e.preventDefault(); + let res = onDragStart ? onDragStart.script.run({ this: this.props.Document }) : undefined; + let doc = res !== undefined && res.success ? + res.result as Doc : + Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" }); + doc && DragManager.StartDocumentDrag([this._mainCont.current!], new DragManager.DocumentDragData([doc], [undefined]), e.clientX, e.clientY); + } + } + + onContextMenu = () => { + ContextMenu.Instance.addItem({ + description: "Edit OnClick script", icon: "edit", event: () => { + let overlayDisposer: () => void = emptyFunction; + const script = this.Document.onDragStart; + let originalText: string | undefined = undefined; + if (script) originalText = script.script.originalScript; + // tslint:disable-next-line: no-unnecessary-callback-wrapper + let scriptingBox = overlayDisposer()} onSave={(text, onError) => { + const script = CompileScript(text, { + params: { this: Doc.name }, + typecheck: false, + editable: true, + transformer: DocumentIconContainer.getTransformer() + }); + if (!script.compiled) { + onError(script.errors.map(error => error.messageText).join("\n")); + return; + } + this.Document.onClick = new ScriptField(script); + overlayDisposer(); + }} showDocumentIcons />; + overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, { x: 400, y: 200, width: 500, height: 400, title: `${this.Document.title || ""} OnDragStart` }); + } + }); + } + + render() { + return (
      + +
      ); + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2