diff options
Diffstat (limited to 'src')
30 files changed, 105 insertions, 533 deletions
diff --git a/src/.DS_Store b/src/.DS_Store Binary files differindex 04487bc70..9ca6c8d2b 100644 --- a/src/.DS_Store +++ b/src/.DS_Store diff --git a/src/client/ClientRecommender.tsx b/src/client/ClientRecommender.tsx deleted file mode 100644 index 1d4653471..000000000 --- a/src/client/ClientRecommender.tsx +++ /dev/null @@ -1,421 +0,0 @@ -import { Doc, FieldResult } from "../fields/Doc"; -import { StrCast, Cast } from "../fields/Types"; -import { List } from "../fields/List"; -import { CognitiveServices, Confidence, Tag, Service } from "./cognitive_services/CognitiveServices"; -import React = require("react"); -import { observer } from "mobx-react"; -import { observable, action, computed, reaction } from "mobx"; -// var assert = require('assert'); -// var sw = require('stopword'); -// var FeedParser = require('feedparser'); -// var https = require('https'); -import "./ClientRecommender.scss"; -import { JSXElement } from "babel-types"; -import { RichTextField } from "../fields/RichTextField"; -import { ToPlainText } from "../fields/FieldSymbols"; -import { listSpec } from "../fields/Schema"; -import { ComputedField } from "../fields/ScriptField"; -import { ImageField } from "../fields/URLField"; -import { KeyphraseQueryView } from "./views/KeyphraseQueryView"; -import { Networking } from "./Network"; - -export interface RecommenderProps { - title: string; -} - -/** - * actualDoc: datadoc - * vectorDoc: mean vector of text - * score: similarity score to main doc - */ - -export interface RecommenderDocument { - actualDoc: Doc; - vectorDoc: number[]; - score: number; -} - -const fieldkey = "data"; - -@observer -export class ClientRecommender extends React.Component<RecommenderProps> { - - static Instance: ClientRecommender; - private mainDoc?: RecommenderDocument; - private docVectors: Set<RecommenderDocument> = new Set(); - public _queries: string[] = []; - - @observable private corr_matrix = [[0, 0], [0, 0]]; // for testing - - constructor(props: RecommenderProps) { - super(props); - if (!ClientRecommender.Instance) ClientRecommender.Instance = this; - ClientRecommender.Instance.docVectors = new Set(); - //ClientRecommender.Instance.corr_matrix = [[0, 0], [0, 0]]; - } - - @action - public reset_docs() { - ClientRecommender.Instance.docVectors = new Set(); - ClientRecommender.Instance.mainDoc = undefined; - ClientRecommender.Instance.corr_matrix = [[0, 0], [0, 0]]; - } - - /*** - * Computes the cosine similarity between two vectors in Euclidean space. - */ - - private distance(vector1: number[], vector2: number[], metric: string = "cosine") { - // assert(vector1.length === vector2.length, "Vectors are not the same length"); - let similarity: number; - switch (metric) { - case "cosine": - var dotproduct = 0; - var mA = 0; - var mB = 0; - for (let i = 0; i < vector1.length; i++) { // here you missed the i++ - dotproduct += (vector1[i] * vector2[i]); - mA += (vector1[i] * vector1[i]); - mB += (vector2[i] * vector2[i]); - } - mA = Math.sqrt(mA); - mB = Math.sqrt(mB); - similarity = (dotproduct) / ((mA) * (mB)); // here you needed extra brackets - return similarity; - case "euclidian": - var sum = 0; - for (let i = 0; i < vector1.length; i++) { - sum += Math.pow(vector1[i] - vector2[i], 2); - } - similarity = Math.sqrt(sum); - return similarity; - default: - return 0; - } - } - - /** - * Returns list of {doc, similarity (to main doc)} in increasing score - */ - - public computeSimilarities(distance_metric: string) { - const parameters: any = {}; - Networking.PostToServer("/IBMAnalysis", parameters).then(response => { - console.log("ANALYSIS RESULTS! ", response); - }); - ClientRecommender.Instance.docVectors.forEach((doc: RecommenderDocument) => { - if (ClientRecommender.Instance.mainDoc) { - const distance = ClientRecommender.Instance.distance(ClientRecommender.Instance.mainDoc.vectorDoc, doc.vectorDoc, distance_metric); - doc.score = distance; - } - } - ); - const doclist = Array.from(ClientRecommender.Instance.docVectors); - if (distance_metric === "euclidian") { - doclist.sort((a: RecommenderDocument, b: RecommenderDocument) => a.score - b.score); - } - else { - doclist.sort((a: RecommenderDocument, b: RecommenderDocument) => b.score - a.score); - } - return doclist; - } - - /*** - * Computes the mean of a set of vectors - */ - - public mean(paragraph: Set<number[]>) { - const n = 512; - const num_words = paragraph.size; - let meanVector = new Array<number>(n).fill(0); // mean vector - if (num_words > 0) { // check to see if paragraph actually was vectorized - paragraph.forEach((wordvec: number[]) => { - for (let i = 0; i < n; i++) { - meanVector[i] += wordvec[i]; - } - }); - meanVector = meanVector.map(x => x / num_words); - } - return meanVector; - } - - /*** - * Processes sentence vector as Recommender Document, adds to Doc Set. - */ - - public processVector(vector: number[], dataDoc: Doc, isMainDoc: boolean) { - if (vector.length > 0) { - const internalDoc: RecommenderDocument = { actualDoc: dataDoc, vectorDoc: vector, score: 0 }; - ClientRecommender.Instance.addToDocSet(internalDoc, isMainDoc); - } - } - - /*** - * Adds to Doc set. Updates mainDoc (one clicked) if necessary. - */ - - private addToDocSet(internalDoc: RecommenderDocument, isMainDoc: boolean) { - if (ClientRecommender.Instance.docVectors) { - if (isMainDoc) ClientRecommender.Instance.mainDoc = internalDoc; - ClientRecommender.Instance.docVectors.add(internalDoc); - } - } - - /*** - * Generates tags for an image using Cognitive Services - */ - - generateMetadata = async (dataDoc: Doc, extDoc: Doc, threshold: Confidence = Confidence.Excellent) => { - const converter = (results: any) => { - const tagDoc = new Doc; - const tagsList = new List(); - results.tags.map((tag: Tag) => { - tagsList.push(tag.name); - const sanitized = tag.name.replace(" ", "_"); - tagDoc[sanitized] = ComputedField.MakeFunction(`(${tag.confidence} >= this.confidence) ? ${tag.confidence} : "${ComputedField.undefined}"`); - }); - extDoc.generatedTags = tagsList; - tagDoc.title = "Generated Tags Doc"; - tagDoc.confidence = threshold; - return tagDoc; - }; - const url = this.url(dataDoc); - if (url) { - return CognitiveServices.Image.Appliers.ProcessImage(extDoc, ["generatedTagsDoc"], url, Service.ComputerVision, converter); - } - } - - /*** - * Gets URL of image - */ - - private url(dataDoc: Doc) { - const data = Cast(Doc.GetProto(dataDoc)[fieldkey], ImageField); - return data ? data.url.href : undefined; - } - - /*** - * Uses Cognitive Services to extract keywords from a document - */ - - public async extractText(dataDoc: Doc, extDoc: Doc, internal: boolean = true, api: string = "bing", isMainDoc: boolean = false, image: boolean = false) { - // STEP 1. Consolidate data of document. Depends on type of document. - let data: string = ""; - let taglist: FieldResult<List<string>> = undefined; - if (image) { - if (!extDoc.generatedTags) await this.generateMetadata(dataDoc, extDoc); // TODO: Automatically generate tags. Need to ask Sam about this. - if (extDoc.generatedTags) { - taglist = Cast(extDoc.generatedTags, listSpec("string")); - taglist!.forEach(tag => { - data += tag + ", "; - }); - } - } - else { - const fielddata = Cast(dataDoc.data, RichTextField, null); - data = fielddata?.Text || ""; - } - - // STEP 2. Upon receiving response from Text Cognitive Services, do additional processing on keywords. - // Currently we are still using Cognitive Services for internal recommendations, but in the future this might not be necessary. - - const converter = async (results: any, data: string, isImage: boolean = false) => { - let keyterms = new List<string>(); // raw keywords - let kp_string: string = ""; // keywords*frequency concatenated into a string. input into TF - let highKP: string[] = [""]; // most frequent keyphrase - let high = 0; - - if (isImage) { // no keyphrase processing necessary - kp_string = data; - if (taglist) { - keyterms = taglist; - highKP = [taglist[0]]; - } - } - else { // text processing - results.documents.forEach((doc: any) => { - const keyPhrases = doc.keyPhrases; // returned by Cognitive Services - keyPhrases.map((kp: string) => { - keyterms.push(kp); - const frequency = this.countFrequencies(kp, data); // frequency of keyphrase in paragraph - kp_string += kp + ", "; // ensures that if frequency is 0 for some reason kp is still added - for (let i = 0; i < frequency - 1; i++) { - kp_string += kp + ", "; // weights repeated keywords higher - } - // replaces highKP with new one - if (frequency > high) { - high = frequency; - highKP = [kp]; - } - // appends to current highKP phrase - else if (frequency === high) { - highKP.push(kp); - } - }); - }); - } - if (kp_string.length > 2) kp_string = kp_string.substring(0, kp_string.length - 2); // strips extra comma and space if there are a lot of keywords - console.log("kp_string: ", kp_string); - - let ext_recs = ""; - // Pushing keyword extraction to IBM for external recommendations. Should shift to internal eventually. - if (!internal) { - const parameters: any = { - 'language': 'en', - 'text': data, - 'features': { - 'keywords': { - 'sentiment': true, - 'emotion': true, - 'limit': 3 - } - } - }; - await Networking.PostToServer("/IBMAnalysis", parameters).then(response => { - const sorted_keywords = response.result.keywords; - if (sorted_keywords.length > 0) { - console.log("IBM keyphrase", sorted_keywords[0]); - highKP = []; - for (let i = 0; i < 5; i++) { - if (sorted_keywords[i]) { - highKP.push(sorted_keywords[i].text); - } - } - keyterms = new List<string>(highKP); - } - }); - //let kpqv = new KeyphraseQueryView({ keyphrases: ["hello"] }); - ext_recs = await this.sendRequest([highKP[0]], api); - } - - // keyterms: list for extDoc, kp_string: input to TF, ext_recs: {titles, urls} of retrieved results from highKP query - return { keyterms: keyterms, external_recommendations: ext_recs, kp_string: [kp_string] }; - }; - - // STEP 3: Start recommendation pipeline. Branches off into internal and external in Cognitive Services - if (data !== "") { - return CognitiveServices.Text.Appliers.analyzer(dataDoc, extDoc, ["key words"], data, converter, isMainDoc, internal); - } - return; - } - - /** - * - * Counts frequencies of keyphrase in paragraph. - */ - - private countFrequencies(keyphrase: string, paragraph: string) { - const data = paragraph.split(/ |\n/); // splits by new lines and spaces - const kp_array = keyphrase.split(" "); - const num_keywords = kp_array.length; - const par_length = data.length; - let frequency = 0; - // slides keyphrase windows across paragraph and checks if it matches with corresponding paragraph slice - for (let i = 0; i <= par_length - num_keywords; i++) { - const window = data.slice(i, i + num_keywords); - if (JSON.stringify(window).toLowerCase() === JSON.stringify(kp_array).toLowerCase() || kp_array.every(val => window.includes(val))) { - frequency++; - } - } - return frequency; - } - - /** - * - * API for sending arXiv request. - */ - - private async sendRequest(keywords: string[], api: string) { - let query = ""; - keywords.forEach((kp: string) => query += " " + kp); - if (api === "arxiv") { - return new Promise<any>(resolve => { - this.arxivrequest(query).then(resolve); - }); - } - else if (api === "bing") { - return new Promise<any>(resolve => { - this.bingWebSearch(query).then(resolve); - }); - } - else { - console.log("no api specified :("); - } - - } - - /** - * Request to Bing API. Most of code is in Cognitive Services. - */ - - bingWebSearch = async (query: string) => { - const converter = async (results: any) => { - const title_vals: string[] = []; - const url_vals: string[] = []; - results.webPages.value.forEach((doc: any) => { - title_vals.push(doc.name); - url_vals.push(doc.url); - }); - return { title_vals, url_vals }; - }; - return CognitiveServices.BingSearch.Appliers.analyzer(query, converter); - } - - /** - * Actual request to the arXiv server for ML articles. - */ - - arxivrequest = async (query: string) => { - const xhttp = new XMLHttpRequest(); - const serveraddress = "http://export.arxiv.org/api"; - const maxresults = 5; - const endpoint = serveraddress + "/query?search_query=all:" + query + "&start=0&max_results=" + maxresults.toString(); - const promisified = (resolve: any, reject: any) => { - xhttp.onreadystatechange = function () { - if (this.readyState === 4) { - const result = xhttp.response; - const xml = xhttp.responseXML; - console.log("arXiv Result: ", xml); - switch (this.status) { - case 200: - const title_vals: string[] = []; - const url_vals: string[] = []; - if (xml) { - const titles = xml.getElementsByTagName("title"); - let counter = 1; - if (titles && titles.length > 1) { - while (counter <= maxresults) { - const title = titles[counter].childNodes[0].nodeValue!; - title_vals.push(title); - counter++; - } - } - const ids = xml.getElementsByTagName("id"); - counter = 1; - if (ids && ids.length > 1) { - while (counter <= maxresults) { - const url = ids[counter].childNodes[0].nodeValue!; - url_vals.push(url); - counter++; - } - } - } - return resolve({ title_vals, url_vals }); - case 400: - default: - return reject(result); - } - } - }; - xhttp.open("GET", endpoint, true); - xhttp.send(); - }; - return new Promise<any>(promisified); - } - - render() { - return (<div className="wrapper"> - </div>); - } - -}
\ No newline at end of file diff --git a/src/client/cognitive_services/CognitiveServices.ts b/src/client/cognitive_services/CognitiveServices.ts index 80961af14..2b2931a97 100644 --- a/src/client/cognitive_services/CognitiveServices.ts +++ b/src/client/cognitive_services/CognitiveServices.ts @@ -6,7 +6,6 @@ import { InkData } from "../../fields/InkField"; import { UndoManager } from "../util/UndoManager"; import requestPromise = require("request-promise"); import { List } from "../../fields/List"; -import { ClientRecommender } from "../ClientRecommender"; type APIManager<D> = { converter: BodyConverter<D>, requester: RequestExecutor }; type RequestExecutor = (apiKey: string, body: string, service: Service) => Promise<string>; @@ -379,7 +378,7 @@ export namespace CognitiveServices { indices.forEach((ind: any) => { vectorValues.push(wordvecs[ind]); }); - ClientRecommender.Instance.processVector(vectorValues, dataDoc, mainDoc); + //ClientRecommender.Instance.processVector(vectorValues, dataDoc, mainDoc); } // adds document to internal doc set else { console.log("unsuccessful :( word(s) not in vocabulary"); diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 12b57351d..279916bac 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -61,7 +61,6 @@ import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo"; import { DocumentType } from "./DocumentTypes"; import { IconProp } from "@fortawesome/fontawesome-svg-core"; import { MapBox } from "../views/nodes/MapBox/MapBox"; -const path = require('path'); const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", "")); class EmptyBox { @@ -663,7 +662,7 @@ export namespace Docs { export function ImageDocument(url: string, options: DocumentOptions = {}) { const imgField = new ImageField(url); - return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: path.basename(url), ...options }); + return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: url.replace(/.*\//, "") /* path.basename(url)*/, ...options }); } export function PresDocument(initial: List<Doc> = new List(), options: DocumentOptions = {}) { @@ -1480,14 +1479,14 @@ export namespace DocUtils { export async function uploadYoutubeVideo(videoId: string, options: DocumentOptions) { const generatedDocuments: Doc[] = []; for (const { source: { name, type }, result } of await Networking.UploadYoutubeToServer(videoId)) { - processFileupload(generatedDocuments, name, type, result, options); + name && type && processFileupload(generatedDocuments, name, type, result, options); } return generatedDocuments; } export async function uploadFilesToDocs(files: File[], options: DocumentOptions) { const generatedDocuments: Doc[] = []; for (const { source: { name, type }, result } of await Networking.UploadFilesToServer(files)) { - processFileupload(generatedDocuments, name, type, result, options); + name && type && processFileupload(generatedDocuments, name, type, result, options); } return generatedDocuments; } diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index fd4b01753..6e2a72f3a 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -1,5 +1,4 @@ import { computed, observable, reaction } from "mobx"; -import * as rp from 'request-promise'; import { DataSym, Doc, DocListCast, DocListCastAsync } from "../../fields/Doc"; import { Id } from "../../fields/FieldSymbols"; import { InkTool } from "../../fields/InkField"; @@ -16,9 +15,7 @@ import { Utils } from "../../Utils"; import { DocServer } from "../DocServer"; import { Docs, DocumentOptions, DocUtils } from "../documents/Documents"; import { DocumentType } from "../documents/DocumentTypes"; -import { Networking } from "../Network"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; -import { DimUnit } from "../views/collections/collectionMulticolumn/CollectionMulticolumnView"; import { CollectionView, CollectionViewType } from "../views/collections/CollectionView"; import { TreeView } from "../views/collections/TreeView"; import { Colors } from "../views/global/globalEnums"; @@ -39,6 +36,7 @@ import { ColorScheme } from "./SettingsManager"; import { SharingManager } from "./SharingManager"; import { SnappingManager } from "./SnappingManager"; import { UndoManager } from "./UndoManager"; +import * as rp from 'request-promise'; interface Button { title?: string; @@ -1386,7 +1384,7 @@ export class CurrentUserUtils { if (response) { const result: { id: string, email: string, cacheDocumentIds: string } = JSON.parse(response); Doc.CurrentUserEmail = result.email; - resolvedPorts = JSON.parse(await Networking.FetchFromServer("/resolvedPorts")); + resolvedPorts = JSON.parse(await (await fetch("/resolvedPorts")).text()); DocServer.init(window.location.protocol, window.location.hostname, resolvedPorts.socket, result.email); result.cacheDocumentIds && (await DocServer.GetRefFields(result.cacheDocumentIds.split(";"))); return result; diff --git a/src/client/util/History.ts b/src/client/util/History.ts index cbe36b401..e6f75a7db 100644 --- a/src/client/util/History.ts +++ b/src/client/util/History.ts @@ -103,8 +103,7 @@ export namespace HistoryUtil { return undefined; } const parser = requiredFields[required]; - let value = opts[required]; - value = parse(parser, value); + const value = parse(parser, opts[required]); if (value !== null && value !== undefined) { current[required] = value; } @@ -114,8 +113,7 @@ export namespace HistoryUtil { continue; } const parser = optionalFields[opt]; - let value = opts[opt]; - value = parse(parser, value); + const value = parse(parser, opts[opt]); if (value !== undefined) { current[opt] = value; } diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index 925b74efa..cf72cd0df 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -86,7 +86,7 @@ export class DirectoryImportBox extends React.Component<FieldViewProps> { for (let i = 0; i < files.length; i++) { const file = files.item(i); if (file && !unsupported.includes(file.type)) { - const ext = path.extname(file.name).toLowerCase(); + const ext = file.name.replace(/.*\./, "").toLowerCase(); // path.extname(file.name).toLowerCase(); if (AcceptableMedia.imageFormats.includes(ext)) { validated.push(file); } @@ -120,7 +120,7 @@ export class DirectoryImportBox extends React.Component<FieldViewProps> { } const { accessPaths, exifData } = result; const path = Utils.prepend(accessPaths.agnostic.client); - const document = await DocUtils.DocumentFromType(type, path, { _width: 300, title: name }); + const document = type && await DocUtils.DocumentFromType(type, path, { _width: 300, title: name }); const { data, error } = exifData; if (document) { Doc.GetProto(document).exif = error || Doc.Get.FromJson({ data }); diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts index 44e44d335..d1f1a0099 100644 --- a/src/client/util/UndoManager.ts +++ b/src/client/util/UndoManager.ts @@ -1,5 +1,4 @@ import { observable, action, runInAction } from "mobx"; -import 'source-map-support/register'; import { Without } from "../../Utils"; function getBatchName(target: any, key: string | symbol): string { @@ -107,7 +106,7 @@ export namespace UndoManager { } export function FilterBatches(fieldTypes: string[]) { const fieldCounts: { [key: string]: number } = {}; - const lastStack = UndoManager.undoStack.lastElement(); + const lastStack = UndoManager.undoStack.slice(-1)[0];//.lastElement(); if (lastStack) { lastStack.forEach(ev => fieldTypes.includes(ev.prop) && (fieldCounts[ev.prop] = (fieldCounts[ev.prop] || 0) + 1)); const fieldCount2: { [key: string]: number } = {}; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index d85709f31..245960da8 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -22,13 +22,12 @@ import { CollectionDockingView } from './collections/CollectionDockingView'; import { DocumentButtonBar } from './DocumentButtonBar'; import './DocumentDecorations.scss'; import { KeyManager } from './GlobalKeyHandler'; +import { InkingStroke } from './InkingStroke'; import { InkStrokeProperties } from './InkStrokeProperties'; import { LightboxView } from './LightboxView'; import { DocumentView } from "./nodes/DocumentView"; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import React = require("react"); -import { InkingStroke } from './InkingStroke'; -import e = require('express'); @observer export class DocumentDecorations extends React.Component<{ PanelWidth: number, PanelHeight: number, boundsLeft: number, boundsTop: number }, { value: string }> { @@ -148,7 +147,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P pageY: e.pageY, preventDefault: emptyFunction, button: 0 - }, [SelectionManager.Views().lastElement().rootDoc]); + }, [SelectionManager.Views().slice(-1)[0].rootDoc]); return true; }, emptyFunction, this.onMaximizeClick, false, false); } @@ -424,7 +423,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P render() { const bounds = this.Bounds; - const seldoc = SelectionManager.Views().lastElement(); + const seldoc = SelectionManager.Views().slice(-1)[0]; if (SnappingManager.GetIsDragging() || bounds.r - bounds.x < 1 || bounds.x === Number.MAX_VALUE || !seldoc || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) { return (null); } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 1478da1f7..7f1dd0c7d 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -5,7 +5,6 @@ import * as fa from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; -import "normalize.css"; import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; @@ -165,28 +164,28 @@ export class MainView extends React.Component { } } - library.add(fa.faEdit, fa.faTrash, fa.faTrashAlt, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faCalendar, - fa.faSquare, far.faSquare as any, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faMapMarker, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, - fa.faLock, fa.faLaptopCode, fa.faMale, fa.faCopy, fa.faHandPointLeft, fa.faHandPointRight, fa.faCompass, fa.faSnowflake, fa.faMicrophone, fa.faKeyboard, - fa.faQuestion, fa.faTasks, fa.faPalette, fa.faAngleLeft, fa.faAngleRight, fa.faBell, fa.faCamera, fa.faExpand, fa.faCaretDown, fa.faCaretLeft, fa.faCaretRight, - fa.faCaretSquareDown, fa.faCaretSquareRight, fa.faArrowsAltH, fa.faPlus, fa.faMinus, fa.faTerminal, fa.faToggleOn, fa.faFile, fa.faLocationArrow, - fa.faSearch, fa.faFileDownload, fa.faFileUpload, fa.faStop, fa.faCalculator, fa.faWindowMaximize, fa.faAddressCard, fa.faQuestionCircle, fa.faArrowLeft, - fa.faArrowRight, fa.faArrowDown, fa.faArrowUp, fa.faBolt, fa.faBullseye, fa.faCaretUp, fa.faCat, fa.faCheck, fa.faChevronRight, fa.faChevronLeft, fa.faChevronDown, fa.faChevronUp, - fa.faClone, fa.faCloudUploadAlt, fa.faCommentAlt, fa.faCompressArrowsAlt, fa.faCut, fa.faEllipsisV, fa.faEraser, fa.faExclamation, fa.faFileAlt, - fa.faFileAudio, fa.faFileVideo, fa.faFilePdf, fa.faFilm, fa.faFilter, fa.faFont, fa.faGlobeAmericas, fa.faGlobeAsia, fa.faHighlighter, fa.faLongArrowAltRight, fa.faMousePointer, - fa.faMusic, fa.faObjectGroup, fa.faPause, fa.faPen, fa.faPenNib, fa.faPhone, fa.faPlay, fa.faPortrait, fa.faRedoAlt, fa.faStamp, fa.faStickyNote, fa.faArrowsAltV, - fa.faTimesCircle, fa.faThumbtack, fa.faTree, fa.faTv, fa.faUndoAlt, fa.faVideo, fa.faAsterisk, fa.faBrain, fa.faImage, fa.faPaintBrush, fa.faTimes, - fa.faEye, fa.faArrowsAlt, fa.faQuoteLeft, fa.faSortAmountDown, fa.faAlignLeft, fa.faAlignCenter, fa.faAlignRight, fa.faHeading, fa.faRulerCombined, - fa.faFillDrip, fa.faLink, fa.faUnlink, fa.faBold, fa.faItalic, fa.faClipboard, fa.faUnderline, fa.faStrikethrough, fa.faSuperscript, fa.faSubscript, - fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper as any, - fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive, fa.faBezierCurve, fa.faCircle, far.faCircle as any, - fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer as any, fa.faExpand, fa.faUndo, fa.faSlidersH, fa.faAngleDoubleLeft, fa.faAngleUp, - fa.faAngleDown, fa.faPlayCircle, fa.faClock, fa.faRocket, fa.faExchangeAlt, fa.faHashtag, fa.faAlignJustify, fa.faCheckSquare, fa.faListUl, - fa.faWindowMinimize, fa.faWindowRestore, fa.faTextWidth, fa.faTextHeight, fa.faClosedCaptioning, fa.faInfoCircle, fa.faTag, fa.faSyncAlt, fa.faPhotoVideo, - fa.faArrowAltCircleDown, fa.faArrowAltCircleUp, fa.faArrowAltCircleLeft, fa.faArrowAltCircleRight, fa.faStopCircle, fa.faCheckCircle, fa.faGripVertical, - fa.faSortUp, fa.faSortDown, fa.faTable, fa.faTh, fa.faThList, fa.faProjectDiagram, fa.faSignature, fa.faColumns, fa.faChevronCircleUp, fa.faUpload, fa.faBorderAll, - fa.faBraille, fa.faChalkboard, fa.faPencilAlt, fa.faEyeSlash, fa.faSmile, fa.faIndent, fa.faOutdent, fa.faChartBar, fa.faBan, fa.faPhoneSlash, fa.faGripLines, - fa.faSave, fa.faBookmark, fa.faList, fa.faListOl, fa.faFolderPlus, fa.faLightbulb, fa.faBookOpen, fa.faMapMarkerAlt); + library.add(...[fa.faEdit, fa.faTrash, fa.faTrashAlt, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faCalendar, + fa.faSquare, far.faSquare as any, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faMapMarker, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, + fa.faLock, fa.faLaptopCode, fa.faMale, fa.faCopy, fa.faHandPointLeft, fa.faHandPointRight, fa.faCompass, fa.faSnowflake, fa.faMicrophone, fa.faKeyboard, + fa.faQuestion, fa.faTasks, fa.faPalette, fa.faAngleLeft, fa.faAngleRight, fa.faBell, fa.faCamera, fa.faExpand, fa.faCaretDown, fa.faCaretLeft, fa.faCaretRight, + fa.faCaretSquareDown, fa.faCaretSquareRight, fa.faArrowsAltH, fa.faPlus, fa.faMinus, fa.faTerminal, fa.faToggleOn, fa.faFile, fa.faLocationArrow, + fa.faSearch, fa.faFileDownload, fa.faFileUpload, fa.faStop, fa.faCalculator, fa.faWindowMaximize, fa.faAddressCard, fa.faQuestionCircle, fa.faArrowLeft, + fa.faArrowRight, fa.faArrowDown, fa.faArrowUp, fa.faBolt, fa.faBullseye, fa.faCaretUp, fa.faCat, fa.faCheck, fa.faChevronRight, fa.faChevronLeft, fa.faChevronDown, fa.faChevronUp, + fa.faClone, fa.faCloudUploadAlt, fa.faCommentAlt, fa.faCompressArrowsAlt, fa.faCut, fa.faEllipsisV, fa.faEraser, fa.faExclamation, fa.faFileAlt, + fa.faFileAudio, fa.faFileVideo, fa.faFilePdf, fa.faFilm, fa.faFilter, fa.faFont, fa.faGlobeAmericas, fa.faGlobeAsia, fa.faHighlighter, fa.faLongArrowAltRight, fa.faMousePointer, + fa.faMusic, fa.faObjectGroup, fa.faPause, fa.faPen, fa.faPenNib, fa.faPhone, fa.faPlay, fa.faPortrait, fa.faRedoAlt, fa.faStamp, fa.faStickyNote, fa.faArrowsAltV, + fa.faTimesCircle, fa.faThumbtack, fa.faTree, fa.faTv, fa.faUndoAlt, fa.faVideo, fa.faAsterisk, fa.faBrain, fa.faImage, fa.faPaintBrush, fa.faTimes, + fa.faEye, fa.faArrowsAlt, fa.faQuoteLeft, fa.faSortAmountDown, fa.faAlignLeft, fa.faAlignCenter, fa.faAlignRight, fa.faHeading, fa.faRulerCombined, + fa.faFillDrip, fa.faLink, fa.faUnlink, fa.faBold, fa.faItalic, fa.faClipboard, fa.faUnderline, fa.faStrikethrough, fa.faSuperscript, fa.faSubscript, + fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper as any, + fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive, fa.faBezierCurve, fa.faCircle, far.faCircle as any, + fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer as any, fa.faExpand, fa.faUndo, fa.faSlidersH, fa.faAngleDoubleLeft, fa.faAngleUp, + fa.faAngleDown, fa.faPlayCircle, fa.faClock, fa.faRocket, fa.faExchangeAlt, fa.faHashtag, fa.faAlignJustify, fa.faCheckSquare, fa.faListUl, + fa.faWindowMinimize, fa.faWindowRestore, fa.faTextWidth, fa.faTextHeight, fa.faClosedCaptioning, fa.faInfoCircle, fa.faTag, fa.faSyncAlt, fa.faPhotoVideo, + fa.faArrowAltCircleDown, fa.faArrowAltCircleUp, fa.faArrowAltCircleLeft, fa.faArrowAltCircleRight, fa.faStopCircle, fa.faCheckCircle, fa.faGripVertical, + fa.faSortUp, fa.faSortDown, fa.faTable, fa.faTh, fa.faThList, fa.faProjectDiagram, fa.faSignature, fa.faColumns, fa.faChevronCircleUp, fa.faUpload, fa.faBorderAll, + fa.faBraille, fa.faChalkboard, fa.faPencilAlt, fa.faEyeSlash, fa.faSmile, fa.faIndent, fa.faOutdent, fa.faChartBar, fa.faBan, fa.faPhoneSlash, fa.faGripLines, + fa.faSave, fa.faBookmark, fa.faList, fa.faListOl, fa.faFolderPlus, fa.faLightbulb, fa.faBookOpen, fa.faMapMarkerAlt]); this.initAuthenticationRouters(); } diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index f53944805..47a5cd07e 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -33,6 +33,7 @@ import { PropertiesDocContextSelector } from "./PropertiesDocContextSelector"; import "./PropertiesView.scss"; import { DefaultStyleProvider } from "./StyleProvider"; import { PresBox } from "./nodes/trails"; +import { IconLookup } from "@fortawesome/fontawesome-svg-core"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -1301,7 +1302,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { onPointerDown={this.toggleAnchor} onClick={e => e.stopPropagation()} className="propertiesButton" > - <FontAwesomeIcon className="fa-icon" icon={faAnchor} size="lg" /> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> </button> </div> <div className="propertiesView-input inline" id="propertiesView-displayArrow"> @@ -1311,7 +1312,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { onPointerDown={this.toggleArrow} onClick={e => e.stopPropagation()} className="propertiesButton" > - <FontAwesomeIcon className="fa-icon" icon={faArrowRight} size="lg" /> + <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> </button> </div> </div> diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx index c7e62c15d..e80ba6f36 100644 --- a/src/client/views/animationtimeline/Timeline.tsx +++ b/src/client/views/animationtimeline/Timeline.tsx @@ -13,6 +13,7 @@ import { TimelineOverview } from "./TimelineOverview"; import { Track } from "./Track"; import clamp from "../../util/clamp"; import { DocumentType } from "../../documents/DocumentTypes"; +import { IconLookup } from "@fortawesome/fontawesome-svg-core"; /** * Timeline class controls most of timeline functions besides individual keyframe and track mechanism. Main functions are @@ -346,9 +347,9 @@ export class Timeline extends React.Component<FieldViewProps> { return ( <div key="timeline_toolbox" className="timeline-toolbox" style={{ height: `${size}px` }}> <div className="playbackControls"> - <div className="timeline-icon" key="timeline_windBack" onClick={this.windBackward} title="Slow Down Animation"> <FontAwesomeIcon icon={faBackward} style={{ height: `${iconSize}px`, width: `${iconSize}px` }} /> </div> - <div className="timeline-icon" key=" timeline_play" onClick={this.onPlay} title="Play/Pause"> <FontAwesomeIcon icon={this._playButton} style={{ height: `${iconSize}px`, width: `${iconSize}px` }} /> </div> - <div className="timeline-icon" key="timeline_windForward" onClick={this.windForward} title="Speed Up Animation"> <FontAwesomeIcon icon={faForward} style={{ height: `${iconSize}px`, width: `${iconSize}px` }} /> </div> + <div className="timeline-icon" key="timeline_windBack" onClick={this.windBackward} title="Slow Down Animation"> <FontAwesomeIcon icon={faBackward as IconLookup} style={{ height: `${iconSize}px`, width: `${iconSize}px` }} /> </div> + <div className="timeline-icon" key=" timeline_play" onClick={this.onPlay} title="Play/Pause"> <FontAwesomeIcon icon={this._playButton as IconLookup} style={{ height: `${iconSize}px`, width: `${iconSize}px` }} /> </div> + <div className="timeline-icon" key="timeline_windForward" onClick={this.windForward} title="Speed Up Animation"> <FontAwesomeIcon icon={faForward as IconLookup} style={{ height: `${iconSize}px`, width: `${iconSize}px` }} /> </div> </div> <div className="grid-box overview-tool"> <div className="overview-box"> @@ -506,7 +507,7 @@ export class Timeline extends React.Component<FieldViewProps> { {this.children.map(doc => <div style={{ height: `${(this._titleHeight)}px` }} className="datapane" onPointerOver={() => { Doc.BrushDoc(doc); }} onPointerOut={() => { Doc.UnBrushDoc(doc); }}><p>{doc.title}</p></div>)} </div> <div key="timeline_resize" onPointerDown={this.onResizeDown}> - <FontAwesomeIcon className="resize" icon={faGripLines} /> + <FontAwesomeIcon className="resize" icon={faGripLines as IconLookup} /> </div> </div> </div> diff --git a/src/client/views/animationtimeline/TimelineMenu.tsx b/src/client/views/animationtimeline/TimelineMenu.tsx index 53ca9acad..aa422c092 100644 --- a/src/client/views/animationtimeline/TimelineMenu.tsx +++ b/src/client/views/animationtimeline/TimelineMenu.tsx @@ -5,6 +5,7 @@ import "./TimelineMenu.scss"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faChartLine, faRoad, faClipboard, faPen, faTrash, faTable } from "@fortawesome/free-solid-svg-icons"; import { Utils } from "../../../Utils"; +import { IconLookup } from "@fortawesome/fontawesome-svg-core"; @observer @@ -41,7 +42,7 @@ export class TimelineMenu extends React.Component { if (type === "input") { const inputRef = React.createRef<HTMLInputElement>(); let text = ""; - this._currentMenu.push(<div key={Utils.GenerateGuid()} className="timeline-menu-item"><FontAwesomeIcon icon={faClipboard} size="lg" /><input className="timeline-menu-input" ref={inputRef} placeholder={title} onChange={(e) => { + this._currentMenu.push(<div key={Utils.GenerateGuid()} className="timeline-menu-item"><FontAwesomeIcon icon={faClipboard as IconLookup} size="lg" /><input className="timeline-menu-input" ref={inputRef} placeholder={title} onChange={(e) => { e.stopPropagation(); text = e.target.value; }} onKeyDown={(e) => { @@ -52,7 +53,7 @@ export class TimelineMenu extends React.Component { } }} /></div>); } else if (type === "button") { - this._currentMenu.push(<div key={Utils.GenerateGuid()} className="timeline-menu-item"><FontAwesomeIcon icon={faChartLine} size="lg" /><p className="timeline-menu-desc" onClick={(e) => { + this._currentMenu.push(<div key={Utils.GenerateGuid()} className="timeline-menu-item"><FontAwesomeIcon icon={faChartLine as IconLookup} size="lg" /><p className="timeline-menu-desc" onClick={(e) => { e.preventDefault(); e.stopPropagation(); event(e); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 1e700f250..b7e0fecee 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -10,14 +10,14 @@ import { Cast, ScriptCast, NumCast, StrCast } from "../../../fields/Types"; import { GestureUtils } from "../../../pen-gestures/GestureUtils"; import { Utils, returnFalse, returnEmptyFilter } from "../../../Utils"; import { DocServer } from "../../DocServer"; -import { Networking } from "../../Network"; import { ImageUtils } from "../../util/Import & Export/ImageUtils"; import { InteractionUtils } from "../../util/InteractionUtils"; import { undoBatch, UndoManager } from "../../util/UndoManager"; import { DocComponent } from "../DocComponent"; import React = require("react"); -import * as rp from 'request-promise'; import ReactLoading from 'react-loading'; +import * as rp from 'request-promise'; +import { Networking } from "../../Network"; export interface SubCollectionViewProps extends CollectionViewProps { diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 89f70985c..5d122ed54 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -29,8 +29,6 @@ import { FaceRectangles } from './FaceRectangles'; import { FieldView, FieldViewProps } from './FieldView'; import "./ImageBox.scss"; import React = require("react"); -import { SnappingManager } from '../../util/SnappingManager'; -const path = require('path'); export const pageSchema = createSchema({ googlePhotosUrl: "string", @@ -190,7 +188,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp if (url.href.indexOf(window.location.origin) === -1) return Utils.CorsProxy(url.href); if (!/\.(png|jpg|jpeg|gif|webp)$/.test(lower)) return url.href; //Why is this here - const ext = path.extname(url.href); + const ext = url.href.replace(/.*\./, "");//path.extname(url.href); return url.href.replace(ext, this._curSuffix + ext); } @@ -286,7 +284,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp } return <div className="imageBox-cont" key={this.layoutDoc[Id]} ref={this.createDropTarget} onPointerDown={this.marqueeDown}> - <div className="imageBox-fader" style={{ overflow: this.props.docViewPath?.().lastElement().fitWidth ? "auto" : undefined }} > + <div className="imageBox-fader" style={{ overflow: Array.from(this.props.docViewPath?.()).slice(-1)[0].fitWidth ? "auto" : undefined }} > <img key="paths" ref={this._imgRef} src={srcpath} style={{ transform, transformOrigin }} @@ -376,7 +374,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp scrollTop={0} down={this._marqueeing} scaling={this.props.scaling} - docView={this.props.docViewPath().lastElement()} + docView={this.props.docViewPath().slice(-1)[0]} addDocument={this.addDocument} finishMarquee={this.finishMarquee} savedAnnotations={this._savedAnnotations} diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 50444c73a..2c09a7b90 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -1,6 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Autocomplete, GoogleMap, GoogleMapProps, Marker } from '@react-google-maps/api'; -import * as dotenv from 'dotenv'; import { action, computed, IReactionDisposer, observable, ObservableMap } from 'mobx'; import { observer } from "mobx-react"; import * as React from "react"; @@ -59,7 +58,6 @@ const mapOptions = { fullscreenControl: false, }; -dotenv.config({ path: __dirname + '/.env' }); const apiKey = process.env.GOOGLE_MAPS; const script = document.createElement('script'); diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index d54b65d92..ebbcc67c6 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -54,7 +54,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps !this.Document._fitWidth && (this.Document._height = this.Document[WidthSym]() * (nh / nw)); if (this.pdfUrl) { if (PDFBox.pdfcache.get(this.pdfUrl.url.href)) runInAction(() => this._pdf = PDFBox.pdfcache.get(this.pdfUrl!.url.href)); - else if (PDFBox.pdfpromise.get(this.pdfUrl.url.href)) PDFBox.pdfpromise.get(this.pdfUrl.url.href)?.then(action(pdf => this._pdf = pdf)); + else if (PDFBox.pdfpromise.get(this.pdfUrl.url.href)) PDFBox.pdfpromise.get(this.pdfUrl.url.href)?.then(action((pdf: any) => this._pdf = pdf)); } } @@ -307,7 +307,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps } static pdfcache = new Map<string, Pdfjs.PDFDocumentProxy>(); - static pdfpromise = new Map<string, Pdfjs.PDFPromise<Pdfjs.PDFDocumentProxy>>(); + static pdfpromise = new Map<string, Promise<Pdfjs.PDFDocumentProxy>>(); render() { TraceMobx(); if (this._pdf) return this.renderPdfView; @@ -317,7 +317,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps if (PDFBox.pdfcache.get(href)) setTimeout(action(() => this._pdf = PDFBox.pdfcache.get(href))); else { if (!PDFBox.pdfpromise.get(href)) PDFBox.pdfpromise.set(href, Pdfjs.getDocument(href).promise); - PDFBox.pdfpromise.get(href)?.then(action(pdf => PDFBox.pdfcache.set(href, this._pdf = pdf))); + PDFBox.pdfpromise.get(href)?.then(action((pdf: any) => PDFBox.pdfcache.set(href, this._pdf = pdf))); } } return this.renderTitleBox; diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx index 183140cd7..e0cd6bae1 100644 --- a/src/client/views/nodes/ScriptingBox.tsx +++ b/src/client/views/nodes/ScriptingBox.tsx @@ -577,8 +577,8 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable </div>; } - renderFuncListElement(value: string) { - return <div> + renderFuncListElement(value: string | object) { + return (typeof value !== "string") ? (null) : <div> <div style={{ fontSize: "14px" }}> {value} </div> diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 3f3de9da3..956fcfbb9 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -31,7 +31,6 @@ import { DocumentManager } from "../../util/DocumentManager"; import { DocumentType } from "../../documents/DocumentTypes"; import { Tooltip } from "@material-ui/core"; import { AnchorMenu } from "../pdf/AnchorMenu"; -const path = require('path'); type VideoDocument = makeInterface<[typeof documentSchema]>; const VideoDocument = makeInterface(documentSchema); @@ -175,7 +174,8 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp const dataUrl = canvas.toDataURL('image/png'); // can also use 'image/png' // if you want to preview the captured image, const retitled = StrCast(this.rootDoc.title).replace(/[ -\.]/g, ""); - const filename = path.basename(encodeURIComponent("snapshot" + retitled + "_" + (this.layoutDoc._currentTimecode || 0).toString().replace(/\./, "_"))); + const encodedFilename = encodeURIComponent("snapshot" + retitled + "_" + (this.layoutDoc._currentTimecode || 0).toString().replace(/\./, "_")); + const filename = encodedFilename.replace(/.*\//, ""); // path.basename(); VideoBox.convertDataUri(dataUrl, filename).then((returnedFilename: string) => returnedFilename && this.createRealSummaryLink(returnedFilename, downX, downY)); } @@ -568,7 +568,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp this.props.select(true); }); - @computed get fitWidth() { return this.props.docViewPath?.().lastElement().fitWidth; } + @computed get fitWidth() { return this.props.docViewPath?.().slice(-1)[0].fitWidth; } contentFunc = () => [this.youtubeVideoId ? this.youtubeContent : this.content]; scaling = () => this.props.scaling?.() || 1; panelWidth = (): number => this.fitWidth ? this.props.PanelWidth() : (Doc.NativeAspect(this.rootDoc) || 1) * this.panelHeight(); @@ -587,7 +587,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp style={{ pointerEvents: this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined, borderRadius, - overflow: this.props.docViewPath?.().lastElement().fitWidth ? "auto" : undefined + overflow: this.props.docViewPath?.().slice(-1)[0].fitWidth ? "auto" : undefined }} onWheel={e => { e.stopPropagation(); e.preventDefault(); }}> <div className="videoBox-viewer" onPointerDown={this.marqueeDown} > <div style={{ @@ -623,7 +623,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp scrollTop={0} down={this._marqueeing} scaling={this.marqueeFitScaling} - docView={this.props.docViewPath().lastElement()} + docView={this.props.docViewPath().slice(-1)[0]} containerOffset={this.marqueeOffset} addDocument={this.addDocWithTimecode} finishMarquee={this.finishMarquee} diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 311d52afa..d4ff40e8f 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1130,13 +1130,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp }, dispatchTransaction: this.dispatchTransaction, nodeViews: { - dashComment(node, view, getPos) { return new DashDocCommentView(node, view, getPos); }, - dashDoc(node, view, getPos) { return new DashDocView(node, view, getPos, self); }, - dashField(node, view, getPos) { return new DashFieldView(node, view, getPos, self); }, - equation(node, view, getPos) { return new EquationView(node, view, getPos, self); }, - summary(node, view, getPos) { return new SummaryView(node, view, getPos); }, - ordered_list(node, view, getPos) { return new OrderedListView(); }, - footnote(node, view, getPos) { return new FootnoteView(node, view, getPos); } + dashComment(node: any, view: any, getPos: any) { return new DashDocCommentView(node, view, getPos); }, + dashDoc(node: any, view: any, getPos: any) { return new DashDocView(node, view, getPos, self); }, + dashField(node: any, view: any, getPos: any) { return new DashFieldView(node, view, getPos, self); }, + equation(node: any, view: any, getPos: any) { return new EquationView(node, view, getPos, self); }, + summary(node: any, view: any, getPos: any) { return new SummaryView(node, view, getPos); }, + ordered_list(node: any, view: any, getPos: any) { return new OrderedListView(); }, + footnote(node: any, view: any, getPos: any) { return new FootnoteView(node, view, getPos); } }, clipboardTextSerializer: this.clipboardTextSerializer, handlePaste: this.handlePaste, diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 3f7f38bdf..de23ac74d 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -26,7 +26,6 @@ import { StyleProp } from "../StyleProvider"; import { AnchorMenu } from "./AnchorMenu"; import { Annotation } from "./Annotation"; import "./PDFViewer.scss"; -const pdfjs = require('pdfjs-dist/es5/build/pdf.js'); import React = require("react"); const PDFJSViewer = require("pdfjs-dist/web/pdf_viewer"); const pdfjsLib = require("pdfjs-dist"); @@ -159,7 +158,7 @@ export class PDFViewer extends React.Component<IViewerProps> { initialLoad = async () => { if (this._pageSizes.length === 0) { this._pageSizes = Array<{ width: number, height: number }>(this.props.pdf.numPages); - await Promise.all(this._pageSizes.map<Pdfjs.PDFPromise<any>>((val, i) => + await Promise.all(this._pageSizes.map((val, i) => this.props.pdf.getPage(i + 1).then(action((page: Pdfjs.PDFPageProxy) => { const page0or180 = page.rotate === 0 || page.rotate === 180; this._pageSizes.splice(i, 1, { diff --git a/src/client/views/webcam/DashWebRTCVideo.tsx b/src/client/views/webcam/DashWebRTCVideo.tsx index 505a8da7e..e0d328c89 100644 --- a/src/client/views/webcam/DashWebRTCVideo.tsx +++ b/src/client/views/webcam/DashWebRTCVideo.tsx @@ -12,6 +12,7 @@ import "./DashWebRTCVideo.scss"; import { hangup, initialize, refreshVideos } from "./WebCamLogic"; import React = require("react"); import { CurrentUserUtils } from "../../util/CurrentUserUtils"; +import { IconLookup } from "@fortawesome/fontawesome-svg-core"; /** @@ -64,8 +65,8 @@ export class DashWebRTCVideo extends React.Component<CollectionFreeFormDocumentV }}></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 className="videoButtons" style={{ background: "red" }} onClick={this.onClickHangUp}><FontAwesomeIcon icon={faPhoneSlash as IconLookup} color="white" /></div> + <div className="videoButtons" style={{ background: "green" }} onClick={this.onClickRefresh}><FontAwesomeIcon icon={faSync as IconLookup} color="white" /></div> </div> </div >; diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index d732a6e2f..036738b9e 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -39,13 +39,13 @@ import "./AudioUpload.scss"; import "./ImageUpload.scss"; import "./MobileInterface.scss"; -library.add(faTasks, faReply, faQuoteLeft, faHandPointLeft, faFolderOpen, faAngleDoubleLeft, faExternalLinkSquareAlt, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus, +library.add(...[faTasks, faReply, faQuoteLeft, faHandPointLeft, faFolderOpen, faAngleDoubleLeft, faExternalLinkSquareAlt, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus, faTerminal, faToggleOn, fileSolid, faExternalLinkAlt, faLocationArrow, faSearch, faFileDownload, faStop, faCalculator, faWindowMaximize, faAddressCard, faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt, faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faThumbtack, faTree, faTv, faUndoAlt, faBook, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faHome, faLongArrowAltLeft, faBars, faTh, faChevronLeft, - faAlignLeft, faAlignRight); + faAlignLeft, faAlignRight].map(m => m as any)); @observer diff --git a/src/server/ApiManagers/PDFManager.ts b/src/server/ApiManagers/PDFManager.ts index 2b4212588..e419d3ac4 100644 --- a/src/server/ApiManagers/PDFManager.ts +++ b/src/server/ApiManagers/PDFManager.ts @@ -2,8 +2,7 @@ import ApiManager, { Registration } from "./ApiManager"; import { Method } from "../RouteManager"; import RouteSubscriber from "../RouteSubscriber"; import { existsSync, createReadStream, createWriteStream } from "fs"; -const pdfjs = require('pdfjs-dist/es5/build/pdf.js'); -import * as Pdfjs from 'pdfjs-dist'; +import * as Pdfjs from 'pdfjs-dist/legacy/build/pdf'; import { createCanvas } from "canvas"; const imageSize = require("probe-image-size"); import * as express from "express"; @@ -84,7 +83,7 @@ async function CreateThumbnail(coreFilename: string, pageNum: number, res: expre }); } -function dispatchThumbnail(res: express.Response, { width, height }: Pdfjs.PDFPageViewport, thumbnailName: string) { +function dispatchThumbnail(res: express.Response, { width, height }: Pdfjs.PageViewport, thumbnailName: string) { res.send({ path: clientPathToFile(Directory.pdf_thumbnails, thumbnailName), width, diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts index 597ff1ce0..8da08fe33 100644 --- a/src/server/ApiManagers/UploadManager.ts +++ b/src/server/ApiManagers/UploadManager.ts @@ -48,15 +48,19 @@ export default class UploadManager extends ApiManager { method: Method.POST, subscription: "/uploadFormData", secureHandler: async ({ req, res }) => { - const form = new formidable.IncomingForm(); - form.uploadDir = pathToDirectory(Directory.parsed_files); - form.keepExtensions = true; + const form = new formidable.IncomingForm({ + keepExtensions: true, + uploadDir: pathToDirectory(Directory.parsed_files) + }); return new Promise<void>(resolve => { form.parse(req, async (_err, _fields, files) => { const results: Upload.FileResponse[] = []; for (const key in files) { - const result = await DashUploadUtils.upload(files[key]); - result && !(result.result instanceof Error) && results.push(result); + const f = files[key]; + if (!Array.isArray(f)) { + const result = await DashUploadUtils.upload(f); + result && !(result.result instanceof Error) && results.push(result); + } } _success(res, results); resolve(); @@ -140,8 +144,7 @@ export default class UploadManager extends ApiManager { subscription: "/uploadDoc", secureHandler: ({ req, res }) => { - const form = new formidable.IncomingForm(); - form.keepExtensions = true; + const form = new formidable.IncomingForm({ keepExtensions: true }); // let path = req.body.path; const ids: { [id: string]: string } = {}; let remap = true; @@ -192,7 +195,8 @@ export default class UploadManager extends ApiManager { let id: string = ""; try { for (const name in files) { - const path_2 = files[name].path; + const f = files[name]; + const path_2 = Array.isArray(f) ? "" : f.path; const zip = new AdmZip(path_2); zip.getEntries().forEach((entry: any) => { if (!entry.entryName.startsWith("files/")) return; diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index 800717d99..7073ee90b 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -16,6 +16,7 @@ import { clientPathToFile, Directory, pathToDirectory, serverPathToFile } from ' import { resolvedServerUrl } from "./server_Initialization"; import { AcceptableMedia, Upload } from './SharedMediaTypes'; import request = require('request-promise'); +import formidable = require('formidable'); const { exec } = require("child_process"); const parse = require('pdf-parse'); const ffmpeg = require("fluent-ffmpeg"); @@ -70,7 +71,7 @@ export namespace DashUploadUtils { else { console.log(`stdout: ${stdout}`); const data = { size: 0, path: videoId + ".mp4", name: videoId, type: "video/mp4" }; - const file = { ...data, toJSON: () => data }; + const file = { ...data, toJSON: () => ({ ...data, filename: data.path.replace(/.*\//, ""), mtime: null, length: 0, mime: "", toJson: () => undefined as any }) }; res(MoveParsedFile(file, Directory.videos)); } }); @@ -79,7 +80,7 @@ export namespace DashUploadUtils { export async function upload(file: File): Promise<Upload.FileResponse> { const { type, path, name } = file; - const types = type.split("/"); + const types = type?.split("/") ?? []; const category = types[0]; let format = `.${types[1]}`; @@ -273,7 +274,7 @@ export namespace DashUploadUtils { * @param suffix If the file doesn't have a suffix and you want to provide it one * to appear in the new location */ - export async function MoveParsedFile(file: File, destination: Directory, suffix: string | undefined = undefined, text?: string): Promise<Upload.FileResponse> { + export async function MoveParsedFile(file: formidable.File, destination: Directory, suffix: string | undefined = undefined, text?: string): Promise<Upload.FileResponse> { const { path: sourcePath } = file; let name = path.basename(sourcePath); suffix && (name += suffix); diff --git a/src/server/RouteManager.ts b/src/server/RouteManager.ts index 78b75d6be..aa9bfcfa7 100644 --- a/src/server/RouteManager.ts +++ b/src/server/RouteManager.ts @@ -124,7 +124,7 @@ export default class RouteManager { } await tryExecute(secureHandler, { ...core, user }); } else { - req.session!.target = target; + //req.session!.target = target; if (publicHandler) { await tryExecute(publicHandler, core); if (!res.headersSent) { diff --git a/src/server/authentication/AuthenticationManager.ts b/src/server/authentication/AuthenticationManager.ts index 3fbd4b3a7..b736f0d35 100644 --- a/src/server/authentication/AuthenticationManager.ts +++ b/src/server/authentication/AuthenticationManager.ts @@ -55,7 +55,7 @@ export let postSignup = (req: Request, res: Response, next: NextFunction) => { const user = new User(model); - User.findOne({ email }, (err, existingUser) => { + User.findOne({ email }, (err: any, existingUser: any) => { if (err) { return next(err); } if (existingUser) { return res.redirect("/login"); @@ -72,9 +72,8 @@ export let postSignup = (req: Request, res: Response, next: NextFunction) => { }; const tryRedirectToTarget = (req: Request, res: Response) => { - if (req.session && req.session.target) { - const target = req.session.target; - req.session.target = undefined; + const target = (req.session as any)?.target; + if (req.session && target) { res.redirect(target); } else { res.redirect("/home"); @@ -88,7 +87,7 @@ const tryRedirectToTarget = (req: Request, res: Response) => { */ export let getLogin = (req: Request, res: Response) => { if (req.user) { - req.session!.target = undefined; + //req.session.target = undefined; return res.redirect("/home"); } res.render("login.pug", { @@ -160,7 +159,7 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio }); }, function (token: string, done: any) { - User.findOne({ email }, function (err, user: DashUserModel) { + User.findOne({ email }, function (err: any, user: DashUserModel) { if (!user) { // NO ACCOUNT WITH SUBMITTED EMAIL res.redirect("/forgotPassword"); @@ -202,7 +201,7 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio }; export let getReset = function (req: Request, res: Response) { - User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }, function (err, user: DashUserModel) { + User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }, function (err: any, user: DashUserModel) { if (!user || err) { return res.redirect("/forgotPassword"); } @@ -216,7 +215,7 @@ export let getReset = function (req: Request, res: Response) { export let postReset = function (req: Request, res: Response) { async.waterfall([ function (done: any) { - User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }, function (err, user: DashUserModel) { + User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }, function (err: any, user: DashUserModel) { if (!user || err) { return res.redirect('back'); } diff --git a/src/server/authentication/Passport.ts b/src/server/authentication/Passport.ts index 9b0069414..d7f891c34 100644 --- a/src/server/authentication/Passport.ts +++ b/src/server/authentication/Passport.ts @@ -4,12 +4,12 @@ import { default as User } from './DashUserModel'; const LocalStrategy = passportLocal.Strategy; -passport.serializeUser<any, any>((user, done) => { - done(undefined, user.id); +passport.serializeUser<any, any>((req, user, done) => { + done(undefined, (user as any)?.id); }); passport.deserializeUser<any, any>((id, done) => { - User.findById(id, (err, user) => { + User.findById(id, (err: any, user: any) => { done(err, user); }); }); diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts index d1b9d8cf2..06c701468 100644 --- a/src/server/server_Initialization.ts +++ b/src/server/server_Initialization.ts @@ -92,7 +92,7 @@ function buildWithMiddleware(server: express.Express) { passport.session(), (req: express.Request, res: express.Response, next: express.NextFunction) => { res.locals.user = req.user; - if (req.originalUrl.endsWith(".png") && req.method === 'GET') { + if ((req.originalUrl.endsWith(".png") /*|| req.originalUrl.endsWith(".js")*/) && req.method === 'GET') { const period = 30000; res.set('Cache-control', `public, max-age=${period}`); } else { |