aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.DS_Storebin8196 -> 8196 bytes
-rw-r--r--src/client/ClientRecommender.tsx421
-rw-r--r--src/client/cognitive_services/CognitiveServices.ts3
-rw-r--r--src/client/documents/Documents.ts7
-rw-r--r--src/client/util/CurrentUserUtils.ts6
-rw-r--r--src/client/util/History.ts6
-rw-r--r--src/client/util/Import & Export/DirectoryImportBox.tsx4
-rw-r--r--src/client/util/UndoManager.ts3
-rw-r--r--src/client/views/DocumentDecorations.tsx7
-rw-r--r--src/client/views/MainView.tsx45
-rw-r--r--src/client/views/PropertiesView.tsx5
-rw-r--r--src/client/views/animationtimeline/Timeline.tsx9
-rw-r--r--src/client/views/animationtimeline/TimelineMenu.tsx5
-rw-r--r--src/client/views/collections/CollectionSubView.tsx4
-rw-r--r--src/client/views/nodes/ImageBox.tsx8
-rw-r--r--src/client/views/nodes/MapBox/MapBox.tsx2
-rw-r--r--src/client/views/nodes/PDFBox.tsx6
-rw-r--r--src/client/views/nodes/ScriptingBox.tsx4
-rw-r--r--src/client/views/nodes/VideoBox.tsx10
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx14
-rw-r--r--src/client/views/pdf/PDFViewer.tsx3
-rw-r--r--src/client/views/webcam/DashWebRTCVideo.tsx5
-rw-r--r--src/mobile/MobileInterface.tsx4
-rw-r--r--src/server/ApiManagers/PDFManager.ts5
-rw-r--r--src/server/ApiManagers/UploadManager.ts20
-rw-r--r--src/server/DashUploadUtils.ts7
-rw-r--r--src/server/RouteManager.ts2
-rw-r--r--src/server/authentication/AuthenticationManager.ts15
-rw-r--r--src/server/authentication/Passport.ts6
-rw-r--r--src/server/server_Initialization.ts2
30 files changed, 105 insertions, 533 deletions
diff --git a/src/.DS_Store b/src/.DS_Store
index 04487bc70..9ca6c8d2b 100644
--- a/src/.DS_Store
+++ b/src/.DS_Store
Binary files differ
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 {