diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/documents/Documents.ts | 10 | ||||
-rw-r--r-- | src/client/views/collections/CollectionSubView.tsx | 109 | ||||
-rw-r--r-- | src/client/views/webcam/DashWebRTCVideo.scss | 49 | ||||
-rw-r--r-- | src/client/views/webcam/DashWebRTCVideo.tsx | 57 | ||||
-rw-r--r-- | src/client/views/webcam/WebCamLogic.js | 14 | ||||
-rw-r--r-- | src/scraping/buxton/final/BuxtonImporter.ts | 30 | ||||
-rw-r--r-- | src/server/DashUploadUtils.ts | 10 |
7 files changed, 175 insertions, 104 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 855c59ba2..8304c2a7f 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -369,11 +369,15 @@ export namespace Docs { const { __images } = device; delete device.__images; const { ImageDocument, StackingDocument } = Docs.Create; - const constructed = __images.map(relative => Utils.prepend(relative)); - const deviceImages = constructed.map((url, i) => ImageDocument(url, { title: `image${i}.${extname(url)}` })); + const constructed = __images.map(({ url, nativeWidth, nativeHeight }) => ({ url: Utils.prepend(url), nativeWidth, nativeHeight })); + const deviceImages = constructed.map(({ url, nativeWidth, nativeHeight }, i) => ImageDocument(url, { + title: `image${i}.${extname(url)}`, + _nativeWidth: nativeWidth, + _nativeHeight: nativeHeight + })); const doc = StackingDocument(deviceImages, { title: device.title, _LODdisable: true }); const deviceProto = Doc.GetProto(doc); - deviceProto.hero = new ImageField(constructed[0]); + deviceProto.hero = new ImageField(constructed[0].url); Docs.Get.DocumentHierarchyFromJson(device, undefined, deviceProto); Doc.AddDocToList(parentProto, "data", doc); } else if (errors) { diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index acab45078..343be1b58 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -283,63 +283,74 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { const albumId = matches[3]; const mediaItems = await GooglePhotos.Query.AlbumSearch(albumId); console.log(mediaItems); + return; } - const batch = UndoManager.StartBatch("collection view drop"); - const promises: Promise<void>[] = []; - // tslint:disable-next-line:prefer-for-of - for (let i = 0; i < e.dataTransfer.items.length; i++) { - const item = e.dataTransfer.items[i]; - if (item.kind === "string" && item.type.indexOf("uri") !== -1) { - let str: string; - const prom = new Promise<string>(resolve => e.dataTransfer.items[i].getAsString(resolve)) - .then(action((s: string) => rp.head(Utils.CorsProxy(str = s)))) - .then(result => { - const type = result["content-type"]; - if (type) { - Docs.Get.DocumentFromType(type, str, options) - .then(doc => doc && this.props.addDocument(doc)); - } - }); - promises.push(prom); - } - const type = item.type; - if (item.kind === "file") { - const file = item.getAsFile(); - const formData = new FormData(); - - if (!file || !file.type) { - continue; + const { items } = e.dataTransfer; + const { length } = items; + if (length) { + const batch = UndoManager.StartBatch("collection view drop"); + const promises: Promise<void>[] = []; + // tslint:disable-next-line:prefer-for-of + for (let i = 0; i < length; i++) { + const item = e.dataTransfer.items[i]; + if (item.kind === "string" && item.type.indexOf("uri") !== -1) { + let str: string; + const prom = new Promise<string>(resolve => item.getAsString(resolve)) + .then(action((s: string) => rp.head(Utils.CorsProxy(str = s)))) + .then(result => { + const type = result["content-type"]; + if (type) { + Docs.Get.DocumentFromType(type, str, options) + .then(doc => doc && this.props.addDocument(doc)); + } + }); + promises.push(prom); } + const type = item.type; + if (item.kind === "file") { + const file = item.getAsFile(); + const formData = new FormData(); + + if (!file || !file.type) { + continue; + } - formData.append('file', file); - const dropFileName = file ? file.name : "-empty-"; - promises.push(Networking.PostFormDataToServer("/uploadFormData", formData).then(results => { - results.map(action((result: any) => { - const { agnostic, accessPaths, nativeWidth, nativeHeight, contentSize } = result; - const full = { ...options, _width: 300, title: dropFileName }; - const pathname = Utils.prepend(accessPaths?.agnostic.client || agnostic.client); - Docs.Get.DocumentFromType(type, pathname, full).then(doc => { - if (doc) { - const proto = Doc.GetProto(doc); - proto.fileUpload = basename(pathname).replace("upload_", "").replace(/\.[a-z0-9]*$/, ""); - nativeWidth && (proto["data-nativeWidth"] = nativeWidth); - nativeHeight && (proto["data-nativeHeight"] = nativeHeight); - contentSize && (proto.contentSize = contentSize); - this.props?.addDocument(doc); + formData.append('file', file); + const dropFileName = file ? file.name : "-empty-"; + promises.push(Networking.PostFormDataToServer("/uploadFormData", formData).then(results => { + results.map(action((result: any) => { + const { accessPaths, nativeWidth, nativeHeight, contentSize } = result; + if (Object.keys(accessPaths).length) { + const full = { ...options, _width: 300, title: dropFileName }; + const pathname = Utils.prepend(accessPaths.agnostic.client); + Docs.Get.DocumentFromType(type, pathname, full).then(doc => { + if (doc) { + const proto = Doc.GetProto(doc); + proto.fileUpload = basename(pathname).replace("upload_", "").replace(/\.[a-z0-9]*$/, ""); + nativeWidth && (proto["data-nativeWidth"] = nativeWidth); + nativeHeight && (proto["data-nativeHeight"] = nativeHeight); + contentSize && (proto.contentSize = contentSize); + this.props?.addDocument(doc); + } + }); + } else { + alert("Upload failed..."); } - }); + })); })); - })); + } } - } - if (promises.length) { - Promise.all(promises).finally(() => { completed && completed(); batch.end(); }); - } else { - if (text && !text.includes("https://")) { - this.props.addDocument(Docs.Create.TextDocument(text, { ...options, _width: 400, _height: 315 })); + if (promises.length) { + Promise.all(promises).finally(() => { completed && completed(); batch.end(); }); + } else { + if (text && !text.includes("https://")) { + this.props.addDocument(Docs.Create.TextDocument(text, { ...options, _width: 400, _height: 315 })); + } + batch.end(); } - batch.end(); + } else { + alert("No uploadable content found."); } } } diff --git a/src/client/views/webcam/DashWebRTCVideo.scss b/src/client/views/webcam/DashWebRTCVideo.scss index 2f35eeca2..41307a808 100644 --- a/src/client/views/webcam/DashWebRTCVideo.scss +++ b/src/client/views/webcam/DashWebRTCVideo.scss @@ -4,7 +4,7 @@ background: whitesmoke; color: grey; border-radius: 15px; - box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw; + box-shadow: #9c9396 0.2vw 0.2vw 0.4vw; border: solid #BBBBBBBB 5px; pointer-events: all; display: flex; @@ -18,29 +18,66 @@ letter-spacing: 2px; font-size: 16px; width: 100%; + margin-top: 20px; + } + + .videoContainer { + position: relative; + width: calc(100% - 20px); + height: 100%; + /* border: 10px solid red; */ + margin-left: 10px; + } + + .buttonContainer { + display: flex; + width: calc(100% - 20px); + height: 50px; + justify-content: center; + text-align: center; + /* border: 1px solid black; */ + margin-left: 10px; + margin-top: 0; + margin-bottom: 15px; } #roomName { outline: none; border-radius: inherit; border: 1px solid #BBBBBBBB; + margin: 10px; + padding: 10px; } .side { width: 25%; height: 20%; position: absolute; - top: 65%; + /* top: 65%; */ z-index: 2; - right: 5%; + right: 0px; + bottom: 18px; } .main { position: absolute; - width: 95%; - height: 75%; - top: 20%; + width: 100%; + height: 100%; + /* top: 20%; */ + align-self: center; + } + + .videoButtons { + border-radius: 50%; + height: 30px; + width: 30px; + display: flex; + justify-content: center; + align-items: center; + justify-self: center; align-self: center; + margin: 5px; + border: 1px solid black; } }
\ No newline at end of file diff --git a/src/client/views/webcam/DashWebRTCVideo.tsx b/src/client/views/webcam/DashWebRTCVideo.tsx index cbf75f708..9c339e986 100644 --- a/src/client/views/webcam/DashWebRTCVideo.tsx +++ b/src/client/views/webcam/DashWebRTCVideo.tsx @@ -8,7 +8,14 @@ import { InkingControl } from "../InkingControl"; import "../../views/nodes/WebBox.scss"; import "./DashWebRTCVideo.scss"; import adapter from 'webrtc-adapter'; -import { initialize, hangup } from "./WebCamLogic"; +import { initialize, hangup, refreshVideos } from "./WebCamLogic"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; +import { faSync, faPhoneSlash } from "@fortawesome/free-solid-svg-icons"; + +library.add(faSync); +library.add(faPhoneSlash); + /** * This models the component that will be rendered, that can be used as a doc that will reflect the video cams. @@ -19,14 +26,6 @@ export class DashWebRTCVideo extends React.Component<CollectionFreeFormDocumentV private roomText: HTMLInputElement | undefined; @observable remoteVideoAdded: boolean = false; - componentDidMount() { - DocumentDecorations.Instance.addCloseCall(this.closeConnection); - } - - closeConnection: CloseCall = () => { - hangup(); - } - @action changeUILook = () => { this.remoteVideoAdded = true; @@ -47,34 +46,30 @@ export class DashWebRTCVideo extends React.Component<CollectionFreeFormDocumentV public static LayoutString(fieldKey: string) { return FieldView.LayoutString(DashWebRTCVideo, fieldKey); } - _ignore = 0; - onPreWheel = (e: React.WheelEvent) => { - this._ignore = e.timeStamp; - } - onPrePointer = (e: React.PointerEvent) => { - this._ignore = e.timeStamp; - } - onPostPointer = (e: React.PointerEvent) => { - if (this._ignore !== e.timeStamp) { - e.stopPropagation(); - } + @action + onClickRefresh = () => { + refreshVideos(); } - onPostWheel = (e: React.WheelEvent) => { - if (this._ignore !== e.timeStamp) { - e.stopPropagation(); - } + + onClickHangUp = () => { + hangup(); } render() { let content = - <div className="webcam-cont" style={{ width: "100%", height: "100%" }} onWheel={this.onPostWheel} onPointerDown={this.onPostPointer} onPointerMove={this.onPostPointer} onPointerUp={this.onPostPointer}> + <div className="webcam-cont" style={{ width: "100%", height: "100%" }}> <div className="webcam-header">DashWebRTC</div> <input id="roomName" type="text" placeholder="Enter room name" ref={(e) => this.roomText = e!} onKeyDown={this.onEnterKeyDown} /> - <video id="localVideo" className={"RTCVideo" + (this.remoteVideoAdded ? " side" : " main")} autoPlay playsInline muted ref={(e) => { - }}></video> - <video id="remoteVideo" className="RTCVideo main" autoPlay playsInline ref={(e) => { - }}></video> - + <div className="videoContainer"> + <video id="localVideo" className={"RTCVideo" + (this.remoteVideoAdded ? " side" : " main")} autoPlay playsInline muted ref={(e) => { + }}></video> + <video id="remoteVideo" className="RTCVideo main" autoPlay playsInline ref={(e) => { + }}></video> + </div> + <div className="buttonContainer"> + <div className="videoButtons" style={{ background: "red" }} onClick={this.onClickHangUp}><FontAwesomeIcon icon={faPhoneSlash} color="white" /></div> + <div className="videoButtons" style={{ background: "green" }} onClick={this.onClickRefresh}><FontAwesomeIcon icon={faSync} color="white" /></div> + </div> </div >; let frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting; @@ -86,7 +81,7 @@ export class DashWebRTCVideo extends React.Component<CollectionFreeFormDocumentV <div className={classname} > {content} </div> - {!frozen ? (null) : <div className="webBox-overlay" onWheel={this.onPreWheel} onPointerDown={this.onPrePointer} onPointerMove={this.onPrePointer} onPointerUp={this.onPrePointer} />} + {!frozen ? (null) : <div className="webBox-overlay" />} </>); } diff --git a/src/client/views/webcam/WebCamLogic.js b/src/client/views/webcam/WebCamLogic.js index 3dfb82465..f542fb983 100644 --- a/src/client/views/webcam/WebCamLogic.js +++ b/src/client/views/webcam/WebCamLogic.js @@ -277,4 +277,16 @@ function handleRemoteHangup() { function sendMessage(message) { console.log('Client sending message: ', message); socket.emit('message', message, room); -};
\ No newline at end of file +}; + +export function refreshVideos() { + var localVideo = document.querySelector('#localVideo'); + var remoteVideo = document.querySelector('#remoteVideo'); + if (localVideo) { + localVideo.srcObject = localStream; + } + if (remoteVideo) { + remoteVideo.srcObject = remoteStream; + } + +}
\ No newline at end of file diff --git a/src/scraping/buxton/final/BuxtonImporter.ts b/src/scraping/buxton/final/BuxtonImporter.ts index f9726872c..098671942 100644 --- a/src/scraping/buxton/final/BuxtonImporter.ts +++ b/src/scraping/buxton/final/BuxtonImporter.ts @@ -11,7 +11,7 @@ import { strictEqual } from "assert"; interface DocumentContents { body: string; - imageUrls: string[]; + imageData: ImageData[]; hyperlinks: string[]; captions: string[]; embeddedFileNames: string[]; @@ -29,7 +29,7 @@ export interface DeviceDocument { primaryKey: string; secondaryKey: string; attribute: string; - __images: string[]; + __images: ImageData[]; hyperlinks: string[]; captions: string[]; embeddedFileNames: string[]; @@ -57,6 +57,12 @@ interface Processor<T> { required?: boolean; } +interface ImageData { + url: string; + nativeWidth: number; + nativeHeight: number; +} + namespace Utilities { export function numberValue(raw: string) { @@ -265,12 +271,12 @@ async function extractFileContents(pathToDocument: string): Promise<DocumentCont console.log("Text extracted."); console.log("Beginning image extraction..."); - const imageUrls = await writeImages(zip); - console.log(`Extracted ${imageUrls.length} images.`); + const imageData = await writeImages(zip); + console.log(`Extracted ${imageData.length} images.`); zip.close(); - return { body, imageUrls, captions, embeddedFileNames, hyperlinks }; + return { body, imageData, captions, embeddedFileNames, hyperlinks }; } const imageEntry = /^word\/media\/\w+\.(jpeg|jpg|png|gif)/; @@ -281,11 +287,11 @@ interface Dimensions { type: string; } -async function writeImages(zip: any): Promise<string[]> { +async function writeImages(zip: any): Promise<ImageData[]> { const allEntries = Object.values<any>(zip.entries()).map(({ name }) => name); const imageEntries = allEntries.filter(name => imageEntry.test(name)); - const imageUrls: string[] = []; + const imageUrls: ImageData[] = []; for (const mediaPath of imageEntries) { const streamImage = () => new Promise<any>((resolve, reject) => { zip.stream(mediaPath, (error: any, stream: any) => error ? reject(error) : resolve(stream)); @@ -308,19 +314,23 @@ async function writeImages(zip: any): Promise<string[]> { await DashUploadUtils.outputResizedImages(streamImage, imageDir, generatedFileName, ext); - imageUrls.push(`/files/images/buxton/${generatedFileName}`); + imageUrls.push({ + url: `/files/images/buxton/${generatedFileName}`, + nativeWidth: width, + nativeHeight: height + }); } return imageUrls; } function analyze(fileName: string, contents: DocumentContents): AnalysisResult { - const { body, imageUrls, captions, hyperlinks, embeddedFileNames } = contents; + const { body, imageData, captions, hyperlinks, embeddedFileNames } = contents; const device: any = { hyperlinks, captions, embeddedFileNames, - __images: imageUrls + __images: imageData }; const errors: { [key: string]: string } = { fileName }; diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index 0f1758c26..9ccc860f1 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -97,7 +97,7 @@ export namespace DashUploadUtils { } console.log(red(`Ignoring unsupported file (${name}) with upload type (${type}).`)); - return { accessPaths: undefined }; + return { accessPaths: {} }; } async function UploadPdf(absolutePath: string) { @@ -216,13 +216,15 @@ export namespace DashUploadUtils { }; }; - export async function MoveParsedFile(absolutePath: string, destination: Directory): Promise<Opt<AccessPathInfo>> { - return new Promise<Opt<AccessPathInfo>>(resolve => { + export async function MoveParsedFile(absolutePath: string, destination: Directory): Promise<Opt<{ accessPaths: AccessPathInfo }>> { + return new Promise(resolve => { const filename = basename(absolutePath); const destinationPath = serverPathToFile(destination, filename); rename(absolutePath, destinationPath, error => { resolve(error ? undefined : { - agnostic: getAccessPaths(destination, filename) + accessPaths: { + agnostic: getAccessPaths(destination, filename) + } }); }); }); |