diff options
Diffstat (limited to 'src')
4 files changed, 60 insertions, 16 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index e8a1d08e4..772b4917e 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -442,7 +442,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let ruleProvider = cv && (Cast(cv.props.Document.ruleProvider, Doc) as Doc); let heading = NumCast(dv.props.Document.heading); cv && ((ruleProvider ? ruleProvider : cv.props.Document)["ruleRounding_" + heading] = StrCast(dv.props.Document.borderRounding)); - }) + }); e.stopPropagation(); e.preventDefault(); } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 9caa4ea37..94b49fb98 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -4,9 +4,9 @@ import { faColumns, faEllipsisV, faFingerprint, faImage, faProjectDiagram, faSig import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from "mobx-react"; import * as React from 'react'; -import { Doc } from '../../../new_fields/Doc'; +import { Doc, DocListCastAsync } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; -import { StrCast } from '../../../new_fields/Types'; +import { StrCast, Cast } from '../../../new_fields/Types'; import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from '../ContextMenuItem'; @@ -18,6 +18,7 @@ import { CollectionSchemaView } from "./CollectionSchemaView"; import { CollectionStackingView } from './CollectionStackingView'; import { CollectionTreeView } from "./CollectionTreeView"; import { CollectionViewBaseChrome } from './CollectionViewChromes'; +import { ImageField } from '../../../new_fields/URLField'; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh, faTree, faSquare, faProjectDiagram, faSignature, faThList, faFingerprint, faColumns, faEllipsisV, faImage, faEye as any, faCopy); @@ -89,7 +90,15 @@ export class CollectionView extends React.Component<FieldViewProps> { 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 existingVm = ContextMenu.Instance.findByDescription("View Modes..."); let subItems: ContextMenuProps[] = existingVm && "subitems" in existingVm ? existingVm.subitems : []; - subItems.push({ description: "Freeform", event: () => { this.props.Document.viewType = CollectionViewType.Freeform; delete this.props.Document.usePivotLayout; }, icon: "signature" }); + subItems.push({ + description: "Freeform", event: async () => { + this.props.Document.viewType = CollectionViewType.Freeform; + if (this.props.Document.usePivotLayout) { + (await DocListCastAsync(this.props.Document.data))!.filter(doc => Cast(doc.data, ImageField)).forEach(doc => doc.ignoreAspect = false); + delete this.props.Document.usePivotLayout; + } + }, icon: "signature" + }); if (CollectionBaseView.InSafeMode()) { ContextMenu.Instance.addItem({ description: "Test Freeform", event: () => this.props.Document.viewType = CollectionViewType.Invalid, icon: "project-diagram" }); } @@ -100,10 +109,17 @@ export class CollectionView extends React.Component<FieldViewProps> { switch (this.props.Document.viewType) { case CollectionViewType.Freeform: { subItems.push({ description: "Custom", icon: "fingerprint", event: CollectionFreeFormView.AddCustomLayout(this.props.Document, this.props.fieldKey) }); - subItems.push({ description: "Pivot", icon: "copy", event: () => this.props.Document.usePivotLayout = true }); break; } } + subItems.push({ + description: "Pivot", icon: "copy", event: async () => { + const doc = this.props.Document; + doc.viewType = CollectionViewType.Freeform; + (await DocListCastAsync(doc.data))!.filter(doc => Cast(doc.data, ImageField)).forEach(doc => doc.ignoreAspect = true); + doc.usePivotLayout = true; + } + }); !existingVm && ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems, icon: "eye" }); let existing = ContextMenu.Instance.findByDescription("Layout..."); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 9c7e8d22f..f7bda0a26 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,6 +1,6 @@ import { library } from "@fortawesome/fontawesome-svg-core"; import { faEye } from "@fortawesome/free-regular-svg-icons"; -import { faBraille, faChalkboard, faCompass, faCompressArrowsAlt, faExpandArrowsAlt, faPaintBrush, faTable, faUpload } from "@fortawesome/free-solid-svg-icons"; +import { faBraille, faChalkboard, faCompass, faCompressArrowsAlt, faExpandArrowsAlt, faPaintBrush, faTable, faUpload, faFileUpload } from "@fortawesome/free-solid-svg-icons"; import { action, computed, IReactionDisposer, observable, reaction, trace } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCastAsync, Field, FieldResult, HeightSym, Opt, WidthSym, DocListCast } from "../../../../new_fields/Doc"; @@ -40,8 +40,10 @@ import React = require("react"); import { DocServer } from "../../../DocServer"; import { FormattedTextBox } from "../../nodes/FormattedTextBox"; import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils"; +import { GooglePhotos } from "../../../apis/google_docs/GooglePhotosClientUtils"; +import { ImageField } from "../../../../new_fields/URLField"; -library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard); +library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload); export const panZoomSchema = createSchema({ panX: "number", @@ -74,13 +76,17 @@ export namespace PivotView { width: number; height: number; fontSize: number; + val: Doc[]; } + export const groups = new Map<FieldResult<Field>, Doc[]>(); + export const elements = (target: CollectionFreeFormView) => { let collection = target.Document; const field = StrCast(collection.pivotField) || "title"; const width = NumCast(collection.pivotWidth) || 200; - const groups = new Map<FieldResult<Field>, Doc[]>(); + + groups.clear(); for (const doc of target.childDocs) { const val = doc[field]; @@ -115,7 +121,8 @@ export namespace PivotView { y: width + 50, width: width * 1.25 * numCols, height: 100, - fontSize + fontSize, + val }); for (const doc of val) { docMap.set(doc, { @@ -259,8 +266,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { private addLiveTextBox = (newBox: Doc) => { FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed newBox.heading = 1; - for (let i = 0; i < this.childDocs.length; i++) { - if (this.childDocs[i].heading == 1) { + for (let child of this.childDocs) { + if (child.heading === 1) { newBox.heading = 2; } } @@ -353,7 +360,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { this.bringToFront(d); }); - de.data.droppedDocuments.length == 1 && this.updateCluster(de.data.droppedDocuments[0]); + de.data.droppedDocuments.length === 1 && this.updateCluster(de.data.droppedDocuments[0]); } } else if (de.data instanceof DragManager.AnnotationDragData) { @@ -786,16 +793,37 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { if ([text, x, y, width, height].some(val => val === undefined)) { return undefined; } - + const exported = this.props.Document[text!] !== undefined; return { ele: <div className="collectionFreeform-customText" style={{ transform: `translate(${x}px, ${y}px)`, - width, height, fontSize - }}>{text}</div>, bounds: { x: x!, y: y!, width: width!, height: height! } + width, height, fontSize, cursor: exported ? "pointer" : "alias", pointerEvents: "all", + }} onClick={() => !this.props.Document[text!] && this.exportPivotedGroupToAlbum(viewDef.val, text!)} >{text}{ + <img + width={70} + height={70} + src={"/assets/google_photos.png"} + style={{ + transition: "1s opacity ease", + opacity: exported ? 1 : 0, + marginLeft: 20, + marginTop: -7, + borderRadius: "50%", + border: "1px solid black", + padding: 10 + }} + />}</div>, bounds: { x: x!, y: y!, width: width!, height: height! } }; } } + exportPivotedGroupToAlbum = async (docs: Doc[], label: string) => { + const title = `Contents Match "${label}" from ${StrCast(this.props.Document.title)}`; + const collection = Docs.Create.MasonryDocument(docs.filter(doc => Cast(doc.data, ImageField)), { title }); + const result = await GooglePhotos.Export.CollectionToAlbum({ collection, title }); + this.props.Document[label] = result!.albumId; + } + @computed.struct get elements() { if (this.Document.usePivotLayout) return PivotView.elements(this); diff --git a/src/server/credentials/google_docs_token.json b/src/server/credentials/google_docs_token.json index a536d6c3d..9765dd4e3 100644 --- a/src/server/credentials/google_docs_token.json +++ b/src/server/credentials/google_docs_token.json @@ -1 +1 @@ -{"access_token":"ya29.GlyGB1dc7fKtWD1FtSvh_6aL3eaDJMFAfiV2EGTDK20fCjinY2FNpzJKhDn8p_IN2NupjQ_fXwqM6orx-E6MUCyGN3YZdTmPOaSd-pQlqIl6TFN49pxuzoxguBL4Sw","refresh_token":"1/HTv_xFHszu2Nf3iiFrUTaeKzC_Vp2-6bpIB06xW_WHI","scope":"https://www.googleapis.com/auth/presentations.readonly https://www.googleapis.com/auth/documents.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/documents https://www.googleapis.com/auth/photoslibrary https://www.googleapis.com/auth/photoslibrary.appendonly https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/presentations https://www.googleapis.com/auth/photoslibrary.sharing","token_type":"Bearer","expiry_date":1568679048543}
\ No newline at end of file +{"access_token":"ya29.ImCGB4LCtQF4V2mY1S4ANuTSrclZ6R4QYDq5RGezUwTnk381Fg9b-oZYtJTdkW2zwryoFDjCRXaMGJqPvzIBYZvsFm1Zdwi_AH1by2bDAEOl0GqFlZukxa2W036ujGDv8tY","refresh_token":"1/HTv_xFHszu2Nf3iiFrUTaeKzC_Vp2-6bpIB06xW_WHI","scope":"https://www.googleapis.com/auth/presentations.readonly https://www.googleapis.com/auth/documents.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/documents https://www.googleapis.com/auth/photoslibrary https://www.googleapis.com/auth/photoslibrary.appendonly https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/presentations https://www.googleapis.com/auth/photoslibrary.sharing","token_type":"Bearer","expiry_date":1568708539924}
\ No newline at end of file |