diff options
author | Sam Wilkins <samwilkins333@gmail.com> | 2019-12-03 01:46:36 -0500 |
---|---|---|
committer | Sam Wilkins <samwilkins333@gmail.com> | 2019-12-03 01:46:36 -0500 |
commit | ef94ad7df2a087141ddb8d347d3e3c484ff7609b (patch) | |
tree | a7c16be04ff4050da1ff03e02f59df6da4f5f7e2 /src | |
parent | 62c888ad25c5580441eaf947a1a0f1638939b868 (diff) |
const linter rule and restored google docs push, fixed routing
Diffstat (limited to 'src')
138 files changed, 2424 insertions, 2393 deletions
diff --git a/src/Utils.ts b/src/Utils.ts index 2543743a4..7401ef981 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -54,7 +54,7 @@ export namespace Utils { } export function CopyText(text: string) { - var textArea = document.createElement("textarea"); + const textArea = document.createElement("textarea"); textArea.value = text; document.body.appendChild(textArea); textArea.focus(); @@ -66,14 +66,14 @@ export namespace Utils { } export function fromRGBAstr(rgba: string) { - let rm = rgba.match(/rgb[a]?\(([ 0-9]+)/); - let r = rm ? Number(rm[1]) : 0; - let gm = rgba.match(/rgb[a]?\([ 0-9]+,([ 0-9]+)/); - let g = gm ? Number(gm[1]) : 0; - let bm = rgba.match(/rgb[a]?\([ 0-9]+,[ 0-9]+,([ 0-9]+)/); - let b = bm ? Number(bm[1]) : 0; - let am = rgba.match(/rgba?\([ 0-9]+,[ 0-9]+,[ 0-9]+,([ .0-9]+)/); - let a = am ? Number(am[1]) : 1; + const rm = rgba.match(/rgb[a]?\(([ 0-9]+)/); + const r = rm ? Number(rm[1]) : 0; + const gm = rgba.match(/rgb[a]?\([ 0-9]+,([ 0-9]+)/); + const g = gm ? Number(gm[1]) : 0; + const bm = rgba.match(/rgb[a]?\([ 0-9]+,[ 0-9]+,([ 0-9]+)/); + const b = bm ? Number(bm[1]) : 0; + const am = rgba.match(/rgba?\([ 0-9]+,[ 0-9]+,[ 0-9]+,([ .0-9]+)/); + const a = am ? Number(am[1]) : 1; return { r: r, g: g, b: b, a: a }; } @@ -86,10 +86,10 @@ export namespace Utils { // s /= 100; // l /= 100; - let c = (1 - Math.abs(2 * l - 1)) * s, + const c = (1 - Math.abs(2 * l - 1)) * s, x = c * (1 - Math.abs((h / 60) % 2 - 1)), - m = l - c / 2, - r = 0, + m = l - c / 2; + let r = 0, g = 0, b = 0; if (0 <= h && h < 60) { @@ -118,10 +118,10 @@ export namespace Utils { b /= 255; // Find greatest and smallest channel values - let cmin = Math.min(r, g, b), + const cmin = Math.min(r, g, b), cmax = Math.max(r, g, b), - delta = cmax - cmin, - h = 0, + delta = cmax - cmin; + let h = 0, s = 0, l = 0; // Calculate hue @@ -173,11 +173,11 @@ export namespace Utils { function project(px: number, py: number, ax: number, ay: number, bx: number, by: number) { if (ax === bx && ay === by) return { point: { x: ax, y: ay }, left: false, dot: 0, t: 0 }; - var atob = { x: bx - ax, y: by - ay }; - var atop = { x: px - ax, y: py - ay }; - var len = atob.x * atob.x + atob.y * atob.y; + const atob = { x: bx - ax, y: by - ay }; + const atop = { x: px - ax, y: py - ay }; + const len = atob.x * atob.x + atob.y * atob.y; var dot = atop.x * atob.x + atop.y * atob.y; - var t = Math.min(1, Math.max(0, dot / len)); + const t = Math.min(1, Math.max(0, dot / len)); dot = (bx - ax) * (py - ay) - (by - ay) * (px - ax); @@ -195,38 +195,38 @@ export namespace Utils { export function closestPtBetweenRectangles(l: number, t: number, w: number, h: number, l1: number, t1: number, w1: number, h1: number, x: number, y: number) { - var r = l + w, + const r = l + w, b = t + h; - var r1 = l1 + w1, + const r1 = l1 + w1, b1 = t1 + h1; - let hsegs = [[l, r, t, l1, r1, t1], [l, r, b, l1, r1, t1], [l, r, t, l1, r1, b1], [l, r, b, l1, r1, b1]]; - let vsegs = [[l, t, b, l1, t1, b1], [r, t, b, l1, t1, b1], [l, t, b, r1, t1, b1], [r, t, b, r1, t1, b1]]; - let res = hsegs.reduce((closest, seg) => { - let res = distanceBetweenHorizontalLines(seg[0], seg[1], seg[2], seg[3], seg[4], seg[5]); + const hsegs = [[l, r, t, l1, r1, t1], [l, r, b, l1, r1, t1], [l, r, t, l1, r1, b1], [l, r, b, l1, r1, b1]]; + const vsegs = [[l, t, b, l1, t1, b1], [r, t, b, l1, t1, b1], [l, t, b, r1, t1, b1], [r, t, b, r1, t1, b1]]; + const res = hsegs.reduce((closest, seg) => { + const res = distanceBetweenHorizontalLines(seg[0], seg[1], seg[2], seg[3], seg[4], seg[5]); return (res[0] < closest[0]) ? res : closest; }, [Number.MAX_VALUE, []] as [number, number[]]); - let fres = vsegs.reduce((closest, seg) => { - let res = distanceBetweenVerticalLines(seg[0], seg[1], seg[2], seg[3], seg[4], seg[5]); + const fres = vsegs.reduce((closest, seg) => { + const res = distanceBetweenVerticalLines(seg[0], seg[1], seg[2], seg[3], seg[4], seg[5]); return (res[0] < closest[0]) ? res : closest; }, res); - let near = project(x, y, fres[1][0], fres[1][1], fres[1][2], fres[1][3]); + const near = project(x, y, fres[1][0], fres[1][1], fres[1][2], fres[1][3]); return project(near.point.x, near.point.y, fres[1][0], fres[1][1], fres[1][2], fres[1][3]); } export function getNearestPointInPerimeter(l: number, t: number, w: number, h: number, x: number, y: number) { - var r = l + w, + const r = l + w, b = t + h; - var x = clamp(x, l, r), + x = clamp(x, l, r), y = clamp(y, t, b); - var dl = Math.abs(x - l), + const dl = Math.abs(x - l), dr = Math.abs(x - r), dt = Math.abs(y - t), db = Math.abs(y - b); - var m = Math.min(dl, dr, dt, db); + const m = Math.min(dl, dr, dt, db); return (m === dt) ? [x, t] : (m === db) ? [x, b] : @@ -234,7 +234,7 @@ export namespace Utils { } export function GetClipboardText(): string { - var textArea = document.createElement("textarea"); + const textArea = document.createElement("textarea"); document.body.appendChild(textArea); textArea.focus(); textArea.select(); @@ -257,7 +257,7 @@ export namespace Utils { if (logFilter !== undefined && logFilter !== message.type) { return; } - let idString = (message.id || "").padStart(36, ' '); + const idString = (message.id || "").padStart(36, ' '); prefix = prefix.padEnd(16, ' '); console.log(`${prefix}: ${idString}, ${receiving ? 'receiving' : 'sending'} ${messageName} with data ${JSON.stringify(message)} `); } @@ -309,18 +309,18 @@ export function OmitKeys(obj: any, keys: string[], addKeyFunc?: (dup: any) => vo } export function WithKeys(obj: any, keys: string[], addKeyFunc?: (dup: any) => void) { - var dup: any = {}; + const dup: any = {}; keys.forEach(key => dup[key] = obj[key]); addKeyFunc && addKeyFunc(dup); return dup; } export function timenow() { - var now = new Date(); + const now = new Date(); let ampm = 'am'; let h = now.getHours(); let m: any = now.getMinutes(); - let s: any = now.getSeconds(); + const s: any = now.getSeconds(); if (h >= 12) { if (h > 12) h -= 12; ampm = 'pm'; @@ -331,8 +331,8 @@ export function timenow() { export function aggregateBounds(boundsList: { x: number, y: number, width: number, height: number }[]) { return boundsList.reduce((bounds, b) => { - var [sptX, sptY] = [b.x, b.y]; - let [bptX, bptY] = [sptX + b.width, sptY + b.height]; + const [sptX, sptY] = [b.x, b.y]; + const [bptX, bptY] = [sptX + b.width, sptY + b.height]; return { x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y), r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b) @@ -371,10 +371,11 @@ export type Without<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; export type Predicate<K, V> = (entry: [K, V]) => boolean; export function DeepCopy<K, V>(source: Map<K, V>, predicate?: Predicate<K, V>) { - let deepCopy = new Map<K, V>(); - let entries = source.entries(), next = entries.next(); + const deepCopy = new Map<K, V>(); + const entries = source.entries(); + let next = entries.next(); while (!next.done) { - let entry = next.value; + const entry = next.value; if (!predicate || predicate(entry)) { deepCopy.set(entry[0], entry[1]); } @@ -427,13 +428,13 @@ export function smoothScroll(duration: number, element: HTMLElement, to: number) animateScroll(); } export function addStyleSheet(styleType: string = "text/css") { - let style = document.createElement("style"); + const style = document.createElement("style"); style.type = styleType; - var sheets = document.head.appendChild(style); + const sheets = document.head.appendChild(style); return (sheets as any).sheet; } export function addStyleSheetRule(sheet: any, selector: any, css: any) { - var propText = typeof css === "string" ? css : Object.keys(css).map(p => p + ":" + (p === "content" ? "'" + css[p] + "'" : css[p])).join(";"); + const propText = typeof css === "string" ? css : Object.keys(css).map(p => p + ":" + (p === "content" ? "'" + css[p] + "'" : css[p])).join(";"); return sheet.insertRule("." + selector + "{" + propText + "}", sheet.cssRules.length); } export function removeStyleSheetRule(sheet: any, rule: number) { diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index 2cec1046b..e4b183715 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -1,5 +1,5 @@ import * as OpenSocket from 'socket.io-client'; -import { MessageStore, Diff, YoutubeQueryTypes } from "./../server/Message"; +import { MessageStore, YoutubeQueryTypes } from "./../server/Message"; import { Opt, Doc } from '../new_fields/Doc'; import { Utils, emptyFunction } from '../Utils'; import { SerializationHelper } from './util/SerializationHelper'; @@ -148,7 +148,7 @@ export namespace DocServer { // an initial pass through the cache to determine whether the document needs to be fetched, // is already in the process of being fetched or already exists in the // cache - let cached = _cache[id]; + const cached = _cache[id]; if (cached === undefined) { // NOT CACHED => we'll have to send a request to the server @@ -195,7 +195,7 @@ export namespace DocServer { } export async function getYoutubeChannels() { - let apiKey = await Utils.EmitCallback(_socket, MessageStore.YoutubeApiQuery, { type: YoutubeQueryTypes.Channels }); + const apiKey = await Utils.EmitCallback(_socket, MessageStore.YoutubeApiQuery, { type: YoutubeQueryTypes.Channels }); return apiKey; } @@ -255,7 +255,7 @@ export namespace DocServer { for (const field of fields) { if (field !== undefined) { // deserialize - let prom = SerializationHelper.Deserialize(field).then(deserialized => { + const prom = SerializationHelper.Deserialize(field).then(deserialized => { fieldMap[field.id] = deserialized; //overwrite or delete any promises (that we inserted as flags @@ -411,7 +411,7 @@ export namespace DocServer { } let _RespondToUpdate = _respondToUpdateImpl; - let _respondToDelete = _respondToDeleteImpl; + const _respondToDelete = _respondToDeleteImpl; function respondToUpdate(diff: any) { _RespondToUpdate(diff); diff --git a/src/client/Network.ts b/src/client/Network.ts index f9ef27267..ccf60f199 100644 --- a/src/client/Network.ts +++ b/src/client/Network.ts @@ -8,7 +8,7 @@ export namespace Networking { } export async function PostToServer(relativeRoute: string, body?: any) { - let options = { + const options = { uri: Utils.prepend(relativeRoute), method: "POST", body, diff --git a/src/client/apis/GoogleAuthenticationManager.tsx b/src/client/apis/GoogleAuthenticationManager.tsx index ae77c4b7b..ce1277667 100644 --- a/src/client/apis/GoogleAuthenticationManager.tsx +++ b/src/client/apis/GoogleAuthenticationManager.tsx @@ -30,7 +30,7 @@ export default class GoogleAuthenticationManager extends React.Component<{}> { } public fetchOrGenerateAccessToken = async () => { - let response = await Networking.FetchFromServer("/readGoogleAccessToken"); + const response = await Networking.FetchFromServer("/readGoogleAccessToken"); // if this is an authentication url, activate the UI to register the new access token if (new RegExp(AuthenticationUrl).test(response)) { this.isOpen = true; diff --git a/src/client/apis/google_docs/GoogleApiClientUtils.ts b/src/client/apis/google_docs/GoogleApiClientUtils.ts index 26c7f8d2e..d2a79f189 100644 --- a/src/client/apis/google_docs/GoogleApiClientUtils.ts +++ b/src/client/apis/google_docs/GoogleApiClientUtils.ts @@ -1,4 +1,4 @@ -import { docs_v1, slides_v1 } from "googleapis"; +import { docs_v1 } from "googleapis"; import { Opt } from "../../../new_fields/Doc"; import { isArray } from "util"; import { EditorState } from "prosemirror-state"; @@ -94,7 +94,7 @@ export namespace GoogleApiClientUtils { export type ExtractResult = { text: string, paragraphs: DeconstructedParagraph[] }; export const extractText = (document: docs_v1.Schema$Document, removeNewlines = false): ExtractResult => { - let paragraphs = extractParagraphs(document); + const paragraphs = extractParagraphs(document); let text = paragraphs.map(paragraph => paragraph.contents.filter(content => !("inlineObjectId" in content)).map(run => run as docs_v1.Schema$TextRun).join("")).join(""); text = text.substring(0, text.length - 1); removeNewlines && text.ReplaceAll("\n", ""); @@ -107,14 +107,14 @@ export namespace GoogleApiClientUtils { const fragments: DeconstructedParagraph[] = []; if (document.body && document.body.content) { for (const element of document.body.content) { - let runs: ContentArray = []; + const runs: ContentArray = []; let bullet: Opt<number>; if (element.paragraph) { if (element.paragraph.elements) { for (const inner of element.paragraph.elements) { if (inner) { if (inner.textRun) { - let run = inner.textRun; + const run = inner.textRun; (run.content || !filterEmpty) && runs.push(inner.textRun); } else if (inner.inlineObjectElement) { runs.push(inner.inlineObjectElement); @@ -182,8 +182,8 @@ export namespace GoogleApiClientUtils { export const read = async (options: ReadOptions): Promise<Opt<ReadResult>> => { return retrieve({ documentId: options.documentId }).then(document => { if (document) { - let title = document.title!; - let body = Utils.extractText(document, options.removeNewlines).text; + const title = document.title!; + const body = Utils.extractText(document, options.removeNewlines).text; return { title, body }; } }); @@ -192,7 +192,7 @@ export namespace GoogleApiClientUtils { export const readLines = async (options: ReadOptions): Promise<Opt<ReadLinesResult>> => { return retrieve({ documentId: options.documentId }).then(document => { if (document) { - let title = document.title; + const title = document.title; let bodyLines = Utils.extractText(document).text.split("\n"); options.removeNewlines && (bodyLines = bodyLines.filter(line => line.length)); return { title, bodyLines }; @@ -201,7 +201,7 @@ export namespace GoogleApiClientUtils { }; export const setStyle = async (options: UpdateOptions) => { - let replies: any = await update({ + const replies: any = await update({ documentId: options.documentId, requests: options.requests }); @@ -221,7 +221,7 @@ export namespace GoogleApiClientUtils { let index = options.index; const mode = options.mode; if (!(index && mode === WriteMode.Insert)) { - let schema = await retrieve({ documentId }); + const schema = await retrieve({ documentId }); if (!schema || !(index = Utils.endOf(schema))) { return undefined; } @@ -248,7 +248,7 @@ export namespace GoogleApiClientUtils { return undefined; } requests.push(...options.content.requests); - let replies: any = await update({ documentId: documentId, requests }); + const replies: any = await update({ documentId: documentId, requests }); if ("errors" in replies) { console.log("Write operation failed:"); console.log(replies.errors.map((error: any) => error.message)); diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts index bf8897061..966d8053a 100644 --- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts +++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts @@ -128,10 +128,10 @@ export namespace GooglePhotos { export const CollectionFromSearch = async (constructor: CollectionConstructor, requested: Opt<Partial<Query.SearchOptions>>): Promise<Doc> => { await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken(); - let response = await Query.ContentSearch(requested); - let uploads = await Transactions.WriteMediaItemsToServer(response); + const response = await Query.ContentSearch(requested); + const uploads = await Transactions.WriteMediaItemsToServer(response); const children = uploads.map((upload: Transactions.UploadInformation) => { - let document = Docs.Create.ImageDocument(Utils.fileUrl(upload.fileNames.clean)); + const document = Docs.Create.ImageDocument(Utils.fileUrl(upload.fileNames.clean)); document.fillColumn = true; document.contentSize = upload.contentSize; return document; @@ -157,12 +157,12 @@ export namespace GooglePhotos { const images = (await DocListCastAsync(collection.data))!.map(Doc.GetProto); images && images.forEach(image => tagMapping.set(image[Id], ContentCategories.NONE)); const values = Object.values(ContentCategories); - for (let value of values) { + for (const value of values) { if (value !== ContentCategories.NONE) { const results = await ContentSearch({ included: [value] }); if (results.mediaItems) { const ids = results.mediaItems.map(item => item.id); - for (let id of ids) { + for (const id of ids) { const image = await Cast(idMapping[id], Doc); if (image) { const key = image[Id]; @@ -220,9 +220,9 @@ export namespace GooglePhotos { export const AlbumSearch = async (albumId: string, pageSize = 100): Promise<MediaItem[]> => { const photos = await endpoint(); - let mediaItems: MediaItem[] = []; + const mediaItems: MediaItem[] = []; let nextPageTokenStored: Opt<string> = undefined; - let found = 0; + const found = 0; do { const response: any = await photos.mediaItems.search(albumId, pageSize, nextPageTokenStored); mediaItems.push(...response.mediaItems); @@ -332,7 +332,7 @@ export namespace GooglePhotos { album = await Create.Album(album.title); } const media: MediaInput[] = []; - for (let source of sources) { + for (const source of sources) { const data = Cast(Doc.GetProto(source).data, ImageField); if (!data) { return; diff --git a/src/client/apis/youtube/YoutubeBox.tsx b/src/client/apis/youtube/YoutubeBox.tsx index bed812852..fd3d9e2f1 100644 --- a/src/client/apis/youtube/YoutubeBox.tsx +++ b/src/client/apis/youtube/YoutubeBox.tsx @@ -48,44 +48,44 @@ export class YoutubeBox extends React.Component<FieldViewProps> { */ async componentWillMount() { //DocServer.getYoutubeChannels(); - let castedSearchBackUp = Cast(this.props.Document.cachedSearchResults, Doc); - let awaitedBackUp = await castedSearchBackUp; - let castedDetailBackUp = Cast(this.props.Document.cachedDetails, Doc); - let awaitedDetails = await castedDetailBackUp; + const castedSearchBackUp = Cast(this.props.Document.cachedSearchResults, Doc); + const awaitedBackUp = await castedSearchBackUp; + const castedDetailBackUp = Cast(this.props.Document.cachedDetails, Doc); + const awaitedDetails = await castedDetailBackUp; if (awaitedBackUp) { - let jsonList = await DocListCastAsync(awaitedBackUp.json); - let jsonDetailList = await DocListCastAsync(awaitedDetails!.json); + const jsonList = await DocListCastAsync(awaitedBackUp.json); + const jsonDetailList = await DocListCastAsync(awaitedDetails!.json); if (jsonList!.length !== 0) { runInAction(() => this.searchResultsFound = true); let index = 0; //getting the necessary information from backUps and building templates that will be used to map in render - for (let video of jsonList!) { - - let videoId = await Cast(video.id, Doc); - let id = StrCast(videoId!.videoId); - let snippet = await Cast(video.snippet, Doc); - let videoTitle = this.filterYoutubeTitleResult(StrCast(snippet!.title)); - let thumbnail = await Cast(snippet!.thumbnails, Doc); - let thumbnailMedium = await Cast(thumbnail!.medium, Doc); - let thumbnailUrl = StrCast(thumbnailMedium!.url); - let videoDescription = StrCast(snippet!.description); - let pusblishDate = (this.roundPublishTime(StrCast(snippet!.publishedAt)))!; - let channelTitle = StrCast(snippet!.channelTitle); + for (const video of jsonList!) { + + const videoId = await Cast(video.id, Doc); + const id = StrCast(videoId!.videoId); + const snippet = await Cast(video.snippet, Doc); + const videoTitle = this.filterYoutubeTitleResult(StrCast(snippet!.title)); + const thumbnail = await Cast(snippet!.thumbnails, Doc); + const thumbnailMedium = await Cast(thumbnail!.medium, Doc); + const thumbnailUrl = StrCast(thumbnailMedium!.url); + const videoDescription = StrCast(snippet!.description); + const pusblishDate = (this.roundPublishTime(StrCast(snippet!.publishedAt)))!; + const channelTitle = StrCast(snippet!.channelTitle); let duration: string = ""; let viewCount: string = ""; if (jsonDetailList!.length !== 0) { - let contentDetails = await Cast(jsonDetailList![index].contentDetails, Doc); - let statistics = await Cast(jsonDetailList![index].statistics, Doc); + const contentDetails = await Cast(jsonDetailList![index].contentDetails, Doc); + const statistics = await Cast(jsonDetailList![index].statistics, Doc); duration = this.convertIsoTimeToDuration(StrCast(contentDetails!.duration)); viewCount = this.abbreviateViewCount(parseInt(StrCast(statistics!.viewCount)))!; } index = index + 1; - let newTemplate: VideoTemplate = { videoId: id, videoTitle: videoTitle, thumbnailUrl: thumbnailUrl, publishDate: pusblishDate, channelTitle: channelTitle, videoDescription: videoDescription, duration: duration, viewCount: viewCount }; + const newTemplate: VideoTemplate = { videoId: id, videoTitle: videoTitle, thumbnailUrl: thumbnailUrl, publishDate: pusblishDate, channelTitle: channelTitle, videoDescription: videoDescription, duration: duration, viewCount: viewCount }; runInAction(() => this.curVideoTemplates.push(newTemplate)); } } @@ -115,7 +115,7 @@ export class YoutubeBox extends React.Component<FieldViewProps> { */ onEnterKeyDown = (e: React.KeyboardEvent) => { if (e.keyCode === 13) { - let submittedTitle = this.YoutubeSearchElement!.value; + const submittedTitle = this.YoutubeSearchElement!.value; this.YoutubeSearchElement!.value = ""; this.YoutubeSearchElement!.blur(); DocServer.getYoutubeVideos(submittedTitle, this.processesVideoResults); @@ -184,23 +184,23 @@ export class YoutubeBox extends React.Component<FieldViewProps> { * difference between today's date and that date, in terms of "ago" to imitate youtube. */ roundPublishTime = (publishTime: string) => { - let date = new Date(publishTime).getTime(); - let curDate = new Date().getTime(); - let timeDif = curDate - date; - let totalSeconds = timeDif / 1000; - let totalMin = totalSeconds / 60; - let totalHours = totalMin / 60; - let totalDays = totalHours / 24; - let totalMonths = totalDays / 30.417; - let totalYears = totalMonths / 12; - - - let truncYears = Math.trunc(totalYears); - let truncMonths = Math.trunc(totalMonths); - let truncDays = Math.trunc(totalDays); - let truncHours = Math.trunc(totalHours); - let truncMin = Math.trunc(totalMin); - let truncSec = Math.trunc(totalSeconds); + const date = new Date(publishTime).getTime(); + const curDate = new Date().getTime(); + const timeDif = curDate - date; + const totalSeconds = timeDif / 1000; + const totalMin = totalSeconds / 60; + const totalHours = totalMin / 60; + const totalDays = totalHours / 24; + const totalMonths = totalDays / 30.417; + const totalYears = totalMonths / 12; + + + const truncYears = Math.trunc(totalYears); + const truncMonths = Math.trunc(totalMonths); + const truncDays = Math.trunc(totalDays); + const truncHours = Math.trunc(totalHours); + const truncMin = Math.trunc(totalMin); + const truncSec = Math.trunc(totalSeconds); let pluralCase = ""; @@ -230,7 +230,7 @@ export class YoutubeBox extends React.Component<FieldViewProps> { */ convertIsoTimeToDuration = (isoDur: string) => { - let convertedTime = isoDur.replace(/D|H|M/g, ":").replace(/P|T|S/g, "").split(":"); + const convertedTime = isoDur.replace(/D|H|M/g, ":").replace(/P|T|S/g, "").split(":"); if (1 === convertedTime.length) { 2 !== convertedTime[0].length && (convertedTime[0] = "0" + convertedTime[0]), convertedTime[0] = "0:" + convertedTime[0]; @@ -269,10 +269,10 @@ export class YoutubeBox extends React.Component<FieldViewProps> { if (this.searchResults.length !== 0) { return <ul> {this.searchResults.map((video, index) => { - let filteredTitle = this.filterYoutubeTitleResult(video.snippet.title); - let channelTitle = video.snippet.channelTitle; - let videoDescription = video.snippet.description; - let pusblishDate = this.roundPublishTime(video.snippet.publishedAt); + const filteredTitle = this.filterYoutubeTitleResult(video.snippet.title); + const channelTitle = video.snippet.channelTitle; + const videoDescription = video.snippet.description; + const pusblishDate = this.roundPublishTime(video.snippet.publishedAt); let duration; let viewCount; if (this.videoDetails.length !== 0) { @@ -331,26 +331,26 @@ export class YoutubeBox extends React.Component<FieldViewProps> { */ @action embedVideoOnClick = (videoId: string, filteredTitle: string) => { - let embeddedUrl = "https://www.youtube.com/embed/" + videoId; + const embeddedUrl = "https://www.youtube.com/embed/" + videoId; this.selectedVideoUrl = embeddedUrl; - let addFunction = this.props.addDocument!; - let newVideoX = NumCast(this.props.Document.x); - let newVideoY = NumCast(this.props.Document.y) + NumCast(this.props.Document.height); + const addFunction = this.props.addDocument!; + const newVideoX = NumCast(this.props.Document.x); + const newVideoY = NumCast(this.props.Document.y) + NumCast(this.props.Document.height); addFunction(Docs.Create.VideoDocument(embeddedUrl, { title: filteredTitle, width: 400, height: 315, x: newVideoX, y: newVideoY })); this.videoClicked = true; } render() { - let content = + const content = <div className="youtubeBox-cont" style={{ width: "100%", height: "100%", position: "absolute" }} onWheel={this.onPostWheel} onPointerDown={this.onPostPointer} onPointerMove={this.onPostPointer} onPointerUp={this.onPostPointer}> <input type="text" placeholder="Search for a video" onKeyDown={this.onEnterKeyDown} style={{ height: 40, width: "100%", border: "1px solid black", padding: 5, textAlign: "center" }} ref={(e) => this.YoutubeSearchElement = e!} /> {this.renderSearchResultsOrVideo()} </div>; - let frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting; + const frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting; - let classname = "webBox-cont" + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !DocumentDecorations.Instance.Interacting ? "-interactive" : ""); + const classname = "webBox-cont" + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !DocumentDecorations.Instance.Interacting ? "-interactive" : ""); return ( <> <div className={classname} > diff --git a/src/client/cognitive_services/CognitiveServices.ts b/src/client/cognitive_services/CognitiveServices.ts index 5a7f5e991..02eff3b25 100644 --- a/src/client/cognitive_services/CognitiveServices.ts +++ b/src/client/cognitive_services/CognitiveServices.ts @@ -1,5 +1,5 @@ import * as request from "request-promise"; -import { Doc, Field, Opt } from "../../new_fields/Doc"; +import { Doc, Field } from "../../new_fields/Doc"; import { Cast } from "../../new_fields/Types"; import { Docs } from "../documents/Documents"; import { Utils } from "../../Utils"; @@ -101,14 +101,14 @@ export namespace CognitiveServices { export namespace Appliers { export const ProcessImage: AnalysisApplier<string> = async (target: Doc, keys: string[], url: string, service: Service, converter: Converter) => { - let batch = UndoManager.StartBatch("Image Analysis"); + const batch = UndoManager.StartBatch("Image Analysis"); - let storageKey = keys[0]; + const storageKey = keys[0]; if (!url || await Cast(target[storageKey], Doc)) { return; } let toStore: any; - let results = await ExecuteQuery(service, Manager, url); + const results = await ExecuteQuery(service, Manager, url); if (!results) { toStore = "Cognitive Services could not process the given image URL."; } else { @@ -131,36 +131,32 @@ export namespace CognitiveServices { export namespace Inking { - export const Manager: APIManager<InkData> = { - - converter: (inkData: InkData): string => { - let entries = inkData.entries(), next = entries.next(); - let strokes: AzureStrokeData[] = [], id = 0; - while (!next.done) { - strokes.push({ - id: id++, - points: next.value[1].pathData.map(point => `${point.x},${point.y}`).join(","), - language: "en-US" - }); - next = entries.next(); - } + export const Manager: APIManager<InkData[]> = { + + converter: (inkData: InkData[]): string => { + let id = 0; + const strokes: AzureStrokeData[] = inkData.map(points => ({ + id: id++, + points: points.map(({ x, y }) => `${x},${y}`).join(","), + language: "en-US" + })); return JSON.stringify({ version: 1, language: "en-US", unit: "mm", - strokes: strokes + strokes }); }, requester: async (apiKey: string, body: string) => { - let xhttp = new XMLHttpRequest(); - let serverAddress = "https://api.cognitive.microsoft.com"; - let endpoint = serverAddress + "/inkrecognizer/v1.0-preview/recognize"; + const xhttp = new XMLHttpRequest(); + const serverAddress = "https://api.cognitive.microsoft.com"; + const endpoint = serverAddress + "/inkrecognizer/v1.0-preview/recognize"; - let promisified = (resolve: any, reject: any) => { + const promisified = (resolve: any, reject: any) => { xhttp.onreadystatechange = function () { if (this.readyState === 4) { - let result = xhttp.responseText; + const result = xhttp.responseText; switch (this.status) { case 200: return resolve(result); @@ -184,15 +180,15 @@ export namespace CognitiveServices { export namespace Appliers { - export const ConcatenateHandwriting: AnalysisApplier<InkData> = async (target: Doc, keys: string[], inkData: InkData) => { - let batch = UndoManager.StartBatch("Ink Analysis"); + export const ConcatenateHandwriting: AnalysisApplier<InkData[]> = async (target: Doc, keys: string[], inkData: InkData[]) => { + const batch = UndoManager.StartBatch("Ink Analysis"); let results = await ExecuteQuery(Service.Handwriting, Manager, inkData); if (results) { results.recognitionUnits && (results = results.recognitionUnits); target[keys[0]] = Docs.Get.DocumentHierarchyFromJson(results, "Ink Analysis"); - let recognizedText = results.map((item: any) => item.recognizedText); - let individualWords = recognizedText.filter((text: string) => text && text.split(" ").length === 1); + const recognizedText = results.map((item: any) => item.recognizedText); + const individualWords = recognizedText.filter((text: string) => text && text.split(" ").length === 1); target[keys[1]] = individualWords.join(" "); } diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d1e3ea708..e0f2858ba 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -35,10 +35,10 @@ import { CollectionDockingView } from "../views/collections/CollectionDockingVie import { LinkManager } from "../util/LinkManager"; import { DocumentManager } from "../util/DocumentManager"; import DirectoryImportBox from "../util/Import & Export/DirectoryImportBox"; -import { Scripting, CompileScript } from "../util/Scripting"; +import { Scripting } from "../util/Scripting"; import { ButtonBox } from "../views/nodes/ButtonBox"; import { FontIconBox } from "../views/nodes/FontIconBox"; -import { SchemaHeaderField, RandomPastel } from "../../new_fields/SchemaHeaderField"; +import { SchemaHeaderField } from "../../new_fields/SchemaHeaderField"; import { PresBox } from "../views/nodes/PresBox"; import { ComputedField, ScriptField } from "../../new_fields/ScriptField"; import { ProxyField } from "../../new_fields/Proxy"; @@ -50,8 +50,8 @@ import { ColorBox } from "../views/nodes/ColorBox"; import { DocuLinkBox } from "../views/nodes/DocuLinkBox"; import { InkingStroke } from "../views/InkingStroke"; import { InkField } from "../../new_fields/InkField"; -var requestImageSize = require('../util/request-image-size'); -var path = require('path'); +const requestImageSize = require('../util/request-image-size'); +const path = require('path'); export interface DocumentOptions { x?: number; @@ -239,16 +239,16 @@ export namespace Docs { ProxyField.initPlugin(); ComputedField.initPlugin(); // non-guid string ids for each document prototype - let prototypeIds = Object.values(DocumentType).filter(type => type !== DocumentType.NONE).map(type => type + suffix); + const prototypeIds = Object.values(DocumentType).filter(type => type !== DocumentType.NONE).map(type => type + suffix); // fetch the actual prototype documents from the server - let actualProtos = await DocServer.GetRefFields(prototypeIds); + const actualProtos = await DocServer.GetRefFields(prototypeIds); // update this object to include any default values: DocumentOptions for all prototypes prototypeIds.map(id => { - let existing = actualProtos[id] as Doc; - let type = id.replace(suffix, "") as DocumentType; + const existing = actualProtos[id] as Doc; + const type = id.replace(suffix, "") as DocumentType; // get or create prototype of the specified type... - let target = existing || buildPrototype(type, id); + const target = existing || buildPrototype(type, id); // ...and set it if not undefined (can be undefined only if TemplateMap does not contain // an entry dedicated to the given DocumentType) target && PrototypeMap.set(type, target); @@ -287,17 +287,17 @@ export namespace Docs { */ function buildPrototype(type: DocumentType, prototypeId: string): Opt<Doc> { // load template from type - let template = TemplateMap.get(type); + const template = TemplateMap.get(type); if (!template) { return undefined; } - let layout = template.layout; + const layout = template.layout; // create title - let upper = suffix.toUpperCase(); - let title = prototypeId.toUpperCase().replace(upper, `_${upper}`); + const upper = suffix.toUpperCase(); + const title = prototypeId.toUpperCase().replace(upper, `_${upper}`); // synthesize the default options, the type and title from computed values and // whatever options pertain to this specific prototype - let options = { title, type, baseProto: true, ...defaultOptions, ...(template.options || {}) }; + const options = { title, type, baseProto: true, ...defaultOptions, ...(template.options || {}) }; options.layout = layout.view.LayoutString(layout.dataField); return Doc.assign(new Doc(prototypeId, true), { ...options }); } @@ -343,8 +343,8 @@ export namespace Docs { protoProps.isPrototype = true; - let dataDoc = MakeDataDelegate(proto, protoProps, data); - let viewDoc = Doc.MakeDelegate(dataDoc, delegId); + const dataDoc = MakeDataDelegate(proto, protoProps, data); + const viewDoc = Doc.MakeDelegate(dataDoc, delegId); AudioBox.ActiveRecordings.map(d => DocUtils.MakeLink({ doc: viewDoc }, { doc: d }, "audio link", "link to audio: " + d.title)); @@ -370,16 +370,16 @@ export namespace Docs { } export function ImageDocument(url: string, options: DocumentOptions = {}) { - let imgField = new ImageField(new URL(url)); - let inst = InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: path.basename(url), ...options }); + const imgField = new ImageField(new URL(url)); + const inst = InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: path.basename(url), ...options }); let target = imgField.url.href; if (new RegExp(window.location.origin).test(target)) { - let extension = path.extname(target); + const extension = path.extname(target); target = `${target.substring(0, target.length - extension.length)}_o${extension}`; } requestImageSize(target) .then((size: any) => { - let aspect = size.height / size.width; + const aspect = size.height / size.width; if (!inst.nativeWidth) { inst.nativeWidth = size.width; } @@ -423,7 +423,7 @@ export namespace Docs { } export function InkDocument(color: string, tool: number, strokeWidth: number, points: { x: number, y: number }[], options: DocumentOptions = {}) { - let doc = InstanceFromProto(Prototypes.get(DocumentType.INK), new InkField(points), options); + const doc = InstanceFromProto(Prototypes.get(DocumentType.INK), new InkField(points), options); doc.color = color; doc.strokeWidth = strokeWidth; doc.tool = tool; @@ -439,12 +439,12 @@ export namespace Docs { } export async function DBDocument(url: string, options: DocumentOptions = {}, columnOptions: DocumentOptions = {}) { - let schemaName = options.title ? options.title : "-no schema-"; - let ctlog = await Gateway.Instance.GetSchema(url, schemaName); + const schemaName = options.title ? options.title : "-no schema-"; + const ctlog = await Gateway.Instance.GetSchema(url, schemaName); if (ctlog && ctlog.schemas) { - let schema = ctlog.schemas[0]; - let schemaDoc = Docs.Create.TreeDocument([], { ...options, nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: schema.displayName! }); - let schemaDocuments = Cast(schemaDoc.data, listSpec(Doc), []); + const schema = ctlog.schemas[0]; + const schemaDoc = Docs.Create.TreeDocument([], { ...options, nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: schema.displayName! }); + const schemaDocuments = Cast(schemaDoc.data, listSpec(Doc), []); if (!schemaDocuments) { return; } @@ -455,8 +455,8 @@ export namespace Docs { if (field instanceof Doc) { docs.push(field); } else { - var atmod = new ColumnAttributeModel(attr); - let histoOp = new HistogramOperation(schema.displayName!, + const atmod = new ColumnAttributeModel(attr); + const histoOp = new HistogramOperation(schema.displayName!, new AttributeTransformationModel(atmod, AggregateFunction.None), new AttributeTransformationModel(atmod, AggregateFunction.Count), new AttributeTransformationModel(atmod, AggregateFunction.Count)); @@ -523,7 +523,7 @@ export namespace Docs { } export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) { - let inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }, id); + const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }, id); Doc.GetProto(inst).data = new List<Doc>(documents); return inst; } @@ -538,7 +538,7 @@ export namespace Docs { }; export function StandardCollectionDockingDocument(configs: Array<DocConfig>, options: DocumentOptions, id?: string, type: string = "row") { - let layoutConfig = { + const layoutConfig = { content: [ { type: type, @@ -603,7 +603,8 @@ export namespace Docs { * might involve arbitrary recursion (since toField might itself call convertObject) */ const convertObject = (object: any, title?: string): Doc => { - let target = new Doc(), result: Opt<Field>; + const target = new Doc(); + let result: Opt<Field>; Object.keys(object).map(key => (result = toField(object[key], key)) && (target[key] = result)); title && !target.title && (target.title = title); return target; @@ -617,7 +618,8 @@ export namespace Docs { * might involve arbitrary recursion (since toField might itself call convertList) */ const convertList = (list: Array<any>): List<Field> => { - let target = new List(), result: Opt<Field>; + const target = new List(); + let result: Opt<Field>; list.map(item => (result = toField(item)) && target.push(result)); return target; }; @@ -658,11 +660,11 @@ export namespace Docs { } if (type.indexOf("html") !== -1) { if (path.includes(window.location.hostname)) { - let s = path.split('/'); - let id = s[s.length - 1]; + const s = path.split('/'); + const id = s[s.length - 1]; return DocServer.GetRefField(id).then(field => { if (field instanceof Doc) { - let alias = Doc.MakeAlias(field); + const alias = Doc.MakeAlias(field); alias.x = options.x || 0; alias.y = options.y || 0; alias.width = options.width || 300; @@ -699,9 +701,9 @@ export namespace DocUtils { DocListCastAsync(promoteDoc.links).then(links => { links && links.map(async link => { if (link) { - let a1 = await Cast(link.anchor1, Doc); + const a1 = await Cast(link.anchor1, Doc); if (a1 && Doc.AreProtosEqual(a1, promoteDoc)) link.anchor1 = copy; - let a2 = await Cast(link.anchor2, Doc); + const a2 = await Cast(link.anchor2, Doc); if (a2 && Doc.AreProtosEqual(a2, promoteDoc)) link.anchor2 = copy; LinkManager.Instance.deleteLink(link); LinkManager.Instance.addLink(link); @@ -714,11 +716,11 @@ export namespace DocUtils { } export function MakeLink(source: { doc: Doc, ctx?: Doc }, target: { doc: Doc, ctx?: Doc }, title: string = "", description: string = "", id?: string) { - let sv = DocumentManager.Instance.getDocumentView(source.doc); + const sv = DocumentManager.Instance.getDocumentView(source.doc); if (sv && sv.props.ContainingCollectionDoc === target.doc) return; if (target.doc === CurrentUserUtils.UserDocument) return undefined; - let linkDocProto = new Doc(id, true); + const linkDocProto = new Doc(id, true); UndoManager.RunInBatch(() => { linkDocProto.type = DocumentType.LINK; diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts index e6f32272e..f3365e73d 100644 --- a/src/client/northstar/dash-fields/HistogramField.ts +++ b/src/client/northstar/dash-fields/HistogramField.ts @@ -10,7 +10,7 @@ import { Deserializable } from "../../util/SerializationHelper"; import { Copy, ToScriptString } from "../../../new_fields/FieldSymbols"; function serialize(field: HistogramField) { - let obj = OmitKeys(field, ['Links', 'BrushLinks', 'Result', 'BrushColors', 'FilterModels', 'FilterOperand']).omit; + const obj = OmitKeys(field, ['Links', 'BrushLinks', 'Result', 'BrushColors', 'FilterModels', 'FilterOperand']).omit; return obj; } @@ -19,7 +19,7 @@ function deserialize(jp: any) { let Y: AttributeTransformationModel | undefined; let V: AttributeTransformationModel | undefined; - let schema = CurrentUserUtils.GetNorthstarSchema(jp.SchemaName); + const schema = CurrentUserUtils.GetNorthstarSchema(jp.SchemaName); if (schema) { CurrentUserUtils.GetAllNorthstarColumnAttributes(schema).map(attr => { if (attr.displayName === jp.X.AttributeModel.Attribute.DisplayName) { @@ -52,8 +52,8 @@ export class HistogramField extends ObjectField { } [Copy]() { - let y = this.HistoOp; - let z = this.HistoOp.Copy; + // const y = this.HistoOp; + // const z = this.HistoOp.Copy; return new HistogramField(HistogramOperation.Duplicate(this.HistoOp)); } diff --git a/src/client/northstar/model/binRanges/QuantitativeVisualBinRange.ts b/src/client/northstar/model/binRanges/QuantitativeVisualBinRange.ts index c579c8e5f..7bc097e1d 100644 --- a/src/client/northstar/model/binRanges/QuantitativeVisualBinRange.ts +++ b/src/client/northstar/model/binRanges/QuantitativeVisualBinRange.ts @@ -37,7 +37,7 @@ export class QuantitativeVisualBinRange extends VisualBinRange { } public GetBins(): number[] { - let bins = new Array<number>(); + const bins = new Array<number>(); for (let v: number = this.DataBinRange.minValue!; v < this.DataBinRange.maxValue!; v += this.DataBinRange.step!) { bins.push(v); @@ -46,8 +46,8 @@ export class QuantitativeVisualBinRange extends VisualBinRange { } public static Initialize(dataMinValue: number, dataMaxValue: number, targetBinNumber: number, isIntegerRange: boolean): QuantitativeVisualBinRange { - let extent = QuantitativeVisualBinRange.getExtent(dataMinValue, dataMaxValue, targetBinNumber, isIntegerRange); - let dataBinRange = new QuantitativeBinRange(); + const extent = QuantitativeVisualBinRange.getExtent(dataMinValue, dataMaxValue, targetBinNumber, isIntegerRange); + const dataBinRange = new QuantitativeBinRange(); dataBinRange.minValue = extent[0]; dataBinRange.maxValue = extent[1]; dataBinRange.step = extent[2]; @@ -60,10 +60,10 @@ export class QuantitativeVisualBinRange extends VisualBinRange { // dataMin -= 0.1; dataMax += 0.1; } - let span = dataMax - dataMin; + const span = dataMax - dataMin; let step = Math.pow(10, Math.floor(Math.log10(span / m))); - let err = m / span * step; + const err = m / span * step; if (err <= .15) { step *= 10; @@ -78,9 +78,9 @@ export class QuantitativeVisualBinRange extends VisualBinRange { if (isIntegerRange) { step = Math.ceil(step); } - let ret: number[] = new Array<number>(3); - let minDivStep = Math.floor(dataMin / step); - let maxDivStep = Math.floor(dataMax / step); + const ret: number[] = new Array<number>(3); + const minDivStep = Math.floor(dataMin / step); + const maxDivStep = Math.floor(dataMax / step); ret[0] = minDivStep * step; // Math.floor(Math.Round(dataMin, 8)/step)*step; ret[1] = maxDivStep * step + step; // Math.floor(Math.Round(dataMax, 8)/step)*step + step; ret[2] = step; diff --git a/src/client/northstar/operations/BaseOperation.ts b/src/client/northstar/operations/BaseOperation.ts index 0d1361ebf..013f2244e 100644 --- a/src/client/northstar/operations/BaseOperation.ts +++ b/src/client/northstar/operations/BaseOperation.ts @@ -44,12 +44,12 @@ export abstract class BaseOperation { } } - let operationParameters = this.CreateOperationParameters(); + const operationParameters = this.CreateOperationParameters(); if (this.Result) { this.Result.progress = 0; } // bcz: used to set Result to undefined, but that causes the display to blink this.Error = ""; - let salt = Math.random().toString(); + const salt = Math.random().toString(); this.RequestSalt = salt; if (!operationParameters) { @@ -59,27 +59,27 @@ export abstract class BaseOperation { this.ComputationStarted = true; //let start = performance.now(); - let promise = Gateway.Instance.StartOperation(operationParameters.toJSON()); + const promise = Gateway.Instance.StartOperation(operationParameters.toJSON()); promise.catch(err => { action(() => { this.Error = err; console.error(err); }); }); - let operationReference = await promise; + const operationReference = await promise; if (operationReference) { this.OperationReference = operationReference; - let resultParameters = new ResultParameters(); + const resultParameters = new ResultParameters(); resultParameters.operationReference = operationReference; - let pollPromise = new PollPromise(salt, operationReference); + const pollPromise = new PollPromise(salt, operationReference); BaseOperation._currentOperations.set(this.Id, pollPromise); pollPromise.Start(async () => { - let result = await Gateway.Instance.GetResult(resultParameters.toJSON()); + const result = await Gateway.Instance.GetResult(resultParameters.toJSON()); if (result instanceof ErrorResult) { throw new Error((result).message); } diff --git a/src/client/northstar/utils/MathUtil.ts b/src/client/northstar/utils/MathUtil.ts index 4b44f40c3..5def5e704 100644 --- a/src/client/northstar/utils/MathUtil.ts +++ b/src/client/northstar/utils/MathUtil.ts @@ -92,37 +92,37 @@ export class MathUtil { public static DistToLineSegment(v: PIXIPoint, w: PIXIPoint, p: PIXIPoint) { // Return minimum distance between line segment vw and point p - var l2 = MathUtil.DistSquared(v, w); // i.e. |w-v|^2 - avoid a sqrt + const l2 = MathUtil.DistSquared(v, w); // i.e. |w-v|^2 - avoid a sqrt if (l2 === 0.0) return MathUtil.Dist(p, v); // v === w case // Consider the line extending the segment, parameterized as v + t (w - v). // We find projection of point p onto the line. // It falls where t = [(p-v) . (w-v)] / |w-v|^2 // We clamp t from [0,1] to handle points outside the segment vw. - var dot = MathUtil.Dot( + const dot = MathUtil.Dot( MathUtil.SubtractPoint(p, v), MathUtil.SubtractPoint(w, v)) / l2; - var t = Math.max(0, Math.min(1, dot)); + const t = Math.max(0, Math.min(1, dot)); // Projection falls on the segment - var projection = MathUtil.AddPoint(v, + const projection = MathUtil.AddPoint(v, MathUtil.MultiplyConstant( MathUtil.SubtractPoint(w, v), t)); return MathUtil.Dist(p, projection); } public static LineSegmentIntersection(ps1: PIXIPoint, pe1: PIXIPoint, ps2: PIXIPoint, pe2: PIXIPoint): PIXIPoint | undefined { - var a1 = pe1.y - ps1.y; - var b1 = ps1.x - pe1.x; + const a1 = pe1.y - ps1.y; + const b1 = ps1.x - pe1.x; - var a2 = pe2.y - ps2.y; - var b2 = ps2.x - pe2.x; + const a2 = pe2.y - ps2.y; + const b2 = ps2.x - pe2.x; - var delta = a1 * b2 - a2 * b1; + const delta = a1 * b2 - a2 * b1; if (delta === 0) { return undefined; } - var c2 = a2 * ps2.x + b2 * ps2.y; - var c1 = a1 * ps1.x + b1 * ps1.y; - var invdelta = 1 / delta; + const c2 = a2 * ps2.x + b2 * ps2.y; + const c1 = a1 * ps1.x + b1 * ps1.y; + const invdelta = 1 / delta; return new PIXIPoint((b2 * c1 - b1 * c2) * invdelta, (a1 * c2 - a2 * c1) * invdelta); } @@ -144,13 +144,13 @@ export class MathUtil { } public static LinePIXIRectangleIntersection(lineFrom: PIXIPoint, lineTo: PIXIPoint, rect: PIXIRectangle): Array<PIXIPoint> { - var r1 = new PIXIPoint(rect.left, rect.top); - var r2 = new PIXIPoint(rect.right, rect.top); - var r3 = new PIXIPoint(rect.right, rect.bottom); - var r4 = new PIXIPoint(rect.left, rect.bottom); - var ret = new Array<PIXIPoint>(); - var dist = this.Dist(lineFrom, lineTo); - var inter = this.LineSegmentIntersection(lineFrom, lineTo, r1, r2); + const r1 = new PIXIPoint(rect.left, rect.top); + const r2 = new PIXIPoint(rect.right, rect.top); + const r3 = new PIXIPoint(rect.right, rect.bottom); + const r4 = new PIXIPoint(rect.left, rect.bottom); + const ret = new Array<PIXIPoint>(); + const dist = this.Dist(lineFrom, lineTo); + let inter = this.LineSegmentIntersection(lineFrom, lineTo, r1, r2); if (inter && this.PointInPIXIRectangle(inter, rect) && this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist) { ret.push(inter); @@ -190,7 +190,7 @@ export class MathUtil { } public static Normalize(p1: PIXIPoint) { - var d = this.Length(p1); + const d = this.Length(p1); return new PIXIPoint(p1.x / d, p1.y / d); } @@ -236,8 +236,8 @@ export class MathUtil { } public static Combinations<T>(chars: T[]) { - let result = new Array<T>(); - let f = (prefix: any, chars: any) => { + const result = new Array<T>(); + const f = (prefix: any, chars: any) => { for (let i = 0; i < chars.length; i++) { result.push(prefix.concat(chars[i])); f(prefix.concat(chars[i]), chars.slice(i + 1)); diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index 6bbd3d0ed..3d8f2d234 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -11,7 +11,6 @@ import { Cast, CastCtor } from "../../new_fields/Types"; import { listSpec } from "../../new_fields/Schema"; import { AudioField, ImageField } from "../../new_fields/URLField"; import { HistogramField } from "../northstar/dash-fields/HistogramField"; -import { MainView } from "../views/MainView"; import { Utils } from "../../Utils"; import { RichTextField } from "../../new_fields/RichTextField"; import { DictationOverlay } from "../views/DictationOverlay"; @@ -48,7 +47,7 @@ export namespace DictationManager { export const Infringed = "unable to process: dictation manager still involved in previous session"; const browser = (() => { - let identifier = navigator.userAgent.toLowerCase(); + const identifier = navigator.userAgent.toLowerCase(); if (identifier.indexOf("safari") >= 0) { return "Safari"; } @@ -90,7 +89,7 @@ export namespace DictationManager { export const listen = async (options?: Partial<ListeningOptions>) => { let results: string | undefined; - let overlay = options !== undefined && options.useOverlay; + const overlay = options !== undefined && options.useOverlay; if (overlay) { DictationOverlay.Instance.dictationOverlayVisible = true; DictationOverlay.Instance.isListening = { interim: false }; @@ -102,7 +101,7 @@ export namespace DictationManager { Utils.CopyText(results); if (overlay) { DictationOverlay.Instance.isListening = false; - let execute = options && options.tryExecute; + const execute = options && options.tryExecute; DictationOverlay.Instance.dictatedPhrase = execute ? results.toLowerCase() : results; DictationOverlay.Instance.dictationSuccess = execute ? await DictationManager.Commands.execute(results) : true; } @@ -131,12 +130,12 @@ export namespace DictationManager { } isListening = true; - let handler = options ? options.interimHandler : undefined; - let continuous = options ? options.continuous : undefined; - let indefinite = continuous && continuous.indefinite; - let language = options ? options.language : undefined; - let intra = options && options.delimiters ? options.delimiters.intra : undefined; - let inter = options && options.delimiters ? options.delimiters.inter : undefined; + const handler = options ? options.interimHandler : undefined; + const continuous = options ? options.continuous : undefined; + const indefinite = continuous && continuous.indefinite; + const language = options ? options.language : undefined; + const intra = options && options.delimiters ? options.delimiters.intra : undefined; + const inter = options && options.delimiters ? options.delimiters.inter : undefined; recognizer.onstart = () => console.log("initiating speech recognition session..."); recognizer.interimResults = handler !== undefined; @@ -177,7 +176,7 @@ export namespace DictationManager { recognizer.start(); }; - let complete = () => { + const complete = () => { if (indefinite) { current && sessionResults.push(current); sessionResults.length && resolve(sessionResults.join(inter || interSession)); @@ -213,8 +212,8 @@ export namespace DictationManager { }; const synthesize = (e: SpeechRecognitionEvent, delimiter?: string) => { - let results = e.results; - let transcripts: string[] = []; + const results = e.results; + const transcripts: string[] = []; for (let i = 0; i < results.length; i++) { transcripts.push(results.item(i).item(0).transcript.trim()); } @@ -238,18 +237,18 @@ export namespace DictationManager { export const execute = async (phrase: string) => { return UndoManager.RunInBatch(async () => { - let targets = SelectionManager.SelectedDocuments(); + const targets = SelectionManager.SelectedDocuments(); if (!targets || !targets.length) { return; } phrase = phrase.toLowerCase(); - let entry = Independent.get(phrase); + const entry = Independent.get(phrase); if (entry) { let success = false; - let restrictTo = entry.restrictTo; - for (let target of targets) { + const restrictTo = entry.restrictTo; + for (const target of targets) { if (!restrictTo || validate(target, restrictTo)) { await entry.action(target); success = true; @@ -258,14 +257,14 @@ export namespace DictationManager { return success; } - for (let entry of Dependent) { - let regex = entry.expression; - let matches = regex.exec(phrase); + for (const entry of Dependent) { + const regex = entry.expression; + const matches = regex.exec(phrase); regex.lastIndex = 0; if (matches !== null) { let success = false; - let restrictTo = entry.restrictTo; - for (let target of targets) { + const restrictTo = entry.restrictTo; + for (const target of targets) { if (!restrictTo || validate(target, restrictTo)) { await entry.action(target, matches); success = true; @@ -289,7 +288,7 @@ export namespace DictationManager { ]); const tryCast = (view: DocumentView, type: DocumentType) => { - let ctor = ConstructorMap.get(type); + const ctor = ConstructorMap.get(type); if (!ctor) { return false; } @@ -297,7 +296,7 @@ export namespace DictationManager { }; const validate = (target: DocumentView, types: DocumentType[]) => { - for (let type of types) { + for (const type of types) { if (tryCast(target, type)) { return true; } @@ -306,11 +305,11 @@ export namespace DictationManager { }; const interpretNumber = (number: string) => { - let initial = parseInt(number); + const initial = parseInt(number); if (!isNaN(initial)) { return initial; } - let converted = interpreter.wordsToNumbers(number, { fuzzy: true }); + const converted = interpreter.wordsToNumbers(number, { fuzzy: true }); if (converted === null) { return NaN; } @@ -326,20 +325,20 @@ export namespace DictationManager { ["open fields", { action: (target: DocumentView) => { - let kvp = Docs.Create.KVPDocument(target.props.Document, { width: 300, height: 300 }); + const kvp = Docs.Create.KVPDocument(target.props.Document, { width: 300, height: 300 }); target.props.addDocTab(kvp, target.props.DataDoc, "onRight"); } }], ["new outline", { action: (target: DocumentView) => { - let newBox = Docs.Create.TextDocument({ width: 400, height: 200, title: "My Outline" }); + const newBox = Docs.Create.TextDocument({ width: 400, height: 200, title: "My Outline" }); newBox.autoHeight = true; - let proto = newBox.proto!; - let prompt = "Press alt + r to start dictating here..."; - let head = 3; - let anchor = head + prompt.length; - let proseMirrorState = `{"doc":{"type":"doc","content":[{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"type":"text","text":"${prompt}"}]}]}]}]},"selection":{"type":"text","anchor":${anchor},"head":${head}}}`; + const proto = newBox.proto!; + const prompt = "Press alt + r to start dictating here..."; + const head = 3; + const anchor = head + prompt.length; + const proseMirrorState = `{"doc":{"type":"doc","content":[{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"type":"text","text":"${prompt}"}]}]}]}]},"selection":{"type":"text","anchor":${anchor},"head":${head}}}`; proto.data = new RichTextField(proseMirrorState); proto.backgroundColor = "#eeffff"; target.props.addDocTab(newBox, proto, "onRight"); @@ -353,10 +352,10 @@ export namespace DictationManager { { expression: /create (\w+) documents of type (image|nested collection)/g, action: (target: DocumentView, matches: RegExpExecArray) => { - let count = interpretNumber(matches[1]); - let what = matches[2]; - let dataDoc = Doc.GetProto(target.props.Document); - let fieldKey = "data"; + const count = interpretNumber(matches[1]); + const what = matches[2]; + const dataDoc = Doc.GetProto(target.props.Document); + const fieldKey = "data"; if (isNaN(count)) { return; } @@ -379,7 +378,7 @@ export namespace DictationManager { { expression: /view as (freeform|stacking|masonry|schema|tree)/g, action: (target: DocumentView, matches: RegExpExecArray) => { - let mode = CollectionViewType.valueOf(matches[1]); + const mode = CollectionViewType.valueOf(matches[1]); mode && (target.props.Document.viewType = mode); }, restrictTo: [DocumentType.COL] diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 346e88f40..d491cd1b1 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -33,7 +33,7 @@ export class DocumentManager { //gets all views public getDocumentViewsById(id: string) { - let toReturn: DocumentView[] = []; + const toReturn: DocumentView[] = []; DocumentManager.Instance.DocumentViews.map(view => { if (view.props.Document[Id] === id) { toReturn.push(view); @@ -41,7 +41,7 @@ export class DocumentManager { }); if (toReturn.length === 0) { DocumentManager.Instance.DocumentViews.map(view => { - let doc = view.props.Document.proto; + const doc = view.props.Document.proto; if (doc && doc[Id] && doc[Id] === id) { toReturn.push(view); } @@ -57,9 +57,9 @@ export class DocumentManager { public getDocumentViewById(id: string, preferredCollection?: CollectionView): DocumentView | undefined { let toReturn: DocumentView | undefined; - let passes = preferredCollection ? [preferredCollection, undefined] : [undefined]; + const passes = preferredCollection ? [preferredCollection, undefined] : [undefined]; - for (let pass of passes) { + for (const pass of passes) { DocumentManager.Instance.DocumentViews.map(view => { if (view.props.Document[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { toReturn = view; @@ -68,7 +68,7 @@ export class DocumentManager { }); if (!toReturn) { DocumentManager.Instance.DocumentViews.map(view => { - let doc = view.props.Document.proto; + const doc = view.props.Document.proto; if (doc && doc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { toReturn = view; } @@ -90,7 +90,7 @@ export class DocumentManager { return views.length ? views[0] : undefined; } public getDocumentViews(toFind: Doc): DocumentView[] { - let toReturn: DocumentView[] = []; + const toReturn: DocumentView[] = []; DocumentManager.Instance.DocumentViews.map(view => Doc.AreProtosEqual(view.props.Document, toFind) && toReturn.push(view)); @@ -100,17 +100,17 @@ export class DocumentManager { @computed public get LinkedDocumentViews() { - let pairs = DocumentManager.Instance.DocumentViews.filter(dv => + const pairs = DocumentManager.Instance.DocumentViews.filter(dv => (dv.isSelected() || Doc.IsBrushed(dv.props.Document)) // draw links from DocumentViews that are selected or brushed OR || DocumentManager.Instance.DocumentViews.some(dv2 => { // Documentviews which - let rest = DocListCast(dv2.props.Document.links).some(l => Doc.AreProtosEqual(l, dv.props.Document));// are link doc anchors - let init = (dv2.isSelected() || Doc.IsBrushed(dv2.props.Document)) && dv2.Document.type !== DocumentType.AUDIO; // on a view that is selected or brushed + const rest = DocListCast(dv2.props.Document.links).some(l => Doc.AreProtosEqual(l, dv.props.Document));// are link doc anchors + const init = (dv2.isSelected() || Doc.IsBrushed(dv2.props.Document)) && dv2.Document.type !== DocumentType.AUDIO; // on a view that is selected or brushed return init && rest; }) ).reduce((pairs, dv) => { - let linksList = LinkManager.Instance.getAllRelatedLinks(dv.props.Document); + const linksList = LinkManager.Instance.getAllRelatedLinks(dv.props.Document); pairs.push(...linksList.reduce((pairs, link) => { - let linkToDoc = link && LinkManager.Instance.getOppositeAnchor(link, dv.props.Document); + const linkToDoc = link && LinkManager.Instance.getOppositeAnchor(link, dv.props.Document); linkToDoc && DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => { if (dv.props.Document.type !== DocumentType.LINK || dv.props.layoutKey !== docView1.props.layoutKey) { pairs.push({ a: dv, b: docView1, l: link }); @@ -125,7 +125,7 @@ export class DocumentManager { } public jumpToDocument = async (targetDoc: Doc, willZoom: boolean, dockFunc?: (doc: Doc) => void, docContext?: Doc, linkId?: string, closeContextIfNotFound: boolean = false): Promise<void> => { - let highlight = () => { + const highlight = () => { const finalDocView = DocumentManager.Instance.getFirstDocumentView(targetDoc); finalDocView && (finalDocView.Document.scrollToLinkID = linkId); finalDocView && Doc.linkFollowHighlight(finalDocView.props.Document); @@ -199,12 +199,12 @@ export class DocumentManager { @action zoomIntoScale = (docDelegate: Doc, scale: number) => { - let docView = DocumentManager.Instance.getDocumentView(Doc.GetProto(docDelegate)); + const docView = DocumentManager.Instance.getDocumentView(Doc.GetProto(docDelegate)); docView && docView.props.zoomToScale(scale); } getScaleOfDocView = (docDelegate: Doc) => { - let doc = Doc.GetProto(docDelegate); + const doc = Doc.GetProto(docDelegate); const docView = DocumentManager.Instance.getDocumentView(doc); if (docView) { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index bbc29585c..b681387d1 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,7 +1,6 @@ import { action, runInAction } from "mobx"; import { Doc, Field } from "../../new_fields/Doc"; -import { Cast, StrCast, ScriptCast } from "../../new_fields/Types"; -import { URLField } from "../../new_fields/URLField"; +import { Cast, ScriptCast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import * as globalCssVariables from "../views/globalCssVariables.scss"; @@ -27,14 +26,14 @@ export function SetupDrag( dontHideOnDrop?: boolean, dragStarted?: () => void ) { - let onRowMove = async (e: PointerEvent) => { + const onRowMove = async (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); document.removeEventListener("pointermove", onRowMove); document.removeEventListener('pointerup', onRowUp); - let doc = await docFunc(); - var dragData = new DragManager.DocumentDragData([doc]); + const doc = await docFunc(); + const dragData = new DragManager.DocumentDragData([doc]); dragData.dropAction = dropAction; dragData.moveDocument = moveFunc; dragData.options = options; @@ -42,11 +41,11 @@ export function SetupDrag( DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y); dragStarted && dragStarted(); }; - let onRowUp = (): void => { + const onRowUp = (): void => { document.removeEventListener("pointermove", onRowMove); document.removeEventListener('pointerup', onRowUp); }; - let onItemDown = async (e: React.PointerEvent) => { + const onItemDown = async (e: React.PointerEvent) => { if (e.button === 0) { e.stopPropagation(); if (e.shiftKey && CollectionDockingView.Instance) { @@ -74,11 +73,11 @@ function moveLinkedDocument(doc: Doc, targetCollection: Doc, addDocument: (doc: } export async function DragLinkAsDocument(dragEle: HTMLElement, x: number, y: number, linkDoc: Doc, sourceDoc: Doc) { - let draggeddoc = LinkManager.Instance.getOppositeAnchor(linkDoc, sourceDoc); + const draggeddoc = LinkManager.Instance.getOppositeAnchor(linkDoc, sourceDoc); if (draggeddoc) { - let moddrag = await Cast(draggeddoc.annotationOn, Doc); - let dragdocs = moddrag ? [moddrag] : [draggeddoc]; - let dragData = new DragManager.DocumentDragData(dragdocs); + const moddrag = await Cast(draggeddoc.annotationOn, Doc); + const dragdocs = moddrag ? [moddrag] : [draggeddoc]; + const dragData = new DragManager.DocumentDragData(dragdocs); dragData.moveDocument = moveLinkedDocument; DragManager.StartLinkedDocumentDrag([dragEle], dragData, x, y, { handlers: { @@ -90,26 +89,26 @@ export async function DragLinkAsDocument(dragEle: HTMLElement, x: number, y: num } export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Doc, singleLink?: Doc) { - let srcTarg = sourceDoc.proto; + const srcTarg = sourceDoc.proto; let draggedDocs: Doc[] = []; if (srcTarg) { - let linkDocs = singleLink ? [singleLink] : LinkManager.Instance.getAllRelatedLinks(srcTarg); + const linkDocs = singleLink ? [singleLink] : LinkManager.Instance.getAllRelatedLinks(srcTarg); if (linkDocs) { draggedDocs = linkDocs.map(link => { - let opp = LinkManager.Instance.getOppositeAnchor(link, sourceDoc); + const opp = LinkManager.Instance.getOppositeAnchor(link, sourceDoc); if (opp) return opp; }) as Doc[]; } } if (draggedDocs.length) { - let moddrag: Doc[] = []; + const moddrag: Doc[] = []; for (const draggedDoc of draggedDocs) { - let doc = await Cast(draggedDoc.annotationOn, Doc); + const doc = await Cast(draggedDoc.annotationOn, Doc); if (doc) moddrag.push(doc); } - let dragdocs = moddrag.length ? moddrag : draggedDocs; - let dragData = new DragManager.DocumentDragData(dragdocs); + const dragdocs = moddrag.length ? moddrag : draggedDocs; + const dragData = new DragManager.DocumentDragData(dragdocs); dragData.moveDocument = moveLinkedDocument; DragManager.StartLinkedDocumentDrag([dragEle], dragData, x, y, { handlers: { @@ -254,11 +253,11 @@ export namespace DragManager { } export function StartButtonDrag(eles: HTMLElement[], script: string, title: string, vars: { [name: string]: Field }, params: string[], initialize: (button: Doc) => void, downX: number, downY: number, options?: DragOptions) { - let dragData = new DragManager.DocumentDragData([]); + const dragData = new DragManager.DocumentDragData([]); runInAction(() => StartDragFunctions.map(func => func())); StartDrag(eles, dragData, downX, downY, options, options && options.finishDrag ? options.finishDrag : (dropData: { [id: string]: any }) => { - let bd = Docs.Create.ButtonDocument({ width: 150, height: 50, title: title }); + const bd = Docs.Create.ButtonDocument({ width: 150, height: 50, title: title }); bd.onClick = ScriptField.MakeScript(script); params.map(p => Object.keys(vars).indexOf(p) !== -1 && (Doc.GetProto(bd)[p] = new PrefetchProxy(vars[p] as Doc))); initialize && initialize(bd); @@ -273,11 +272,11 @@ export namespace DragManager { runInAction(() => StartDragFunctions.map(func => func())); StartDrag(eles, dragData, downX, downY, options, (dropData: { [id: string]: any }) => { - let droppedDocuments: Doc[] = dragData.draggedDocuments.reduce((droppedDocs: Doc[], d) => { - let dvs = DocumentManager.Instance.getDocumentViews(d); + const droppedDocuments: Doc[] = dragData.draggedDocuments.reduce((droppedDocs: Doc[], d) => { + const dvs = DocumentManager.Instance.getDocumentViews(d); if (dvs.length) { - let containingView = SelectionManager.SelectedDocuments()[0] ? SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView : undefined; - let inContext = dvs.filter(dv => dv.props.ContainingCollectionView === containingView); + const containingView = SelectionManager.SelectedDocuments()[0] ? SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView : undefined; + const inContext = dvs.filter(dv => dv.props.ContainingCollectionView === containingView); if (inContext.length) { inContext.forEach(dv => droppedDocs.push(dv.props.Document)); } else { @@ -336,26 +335,26 @@ export namespace DragManager { DragManager.Root().appendChild(dragDiv); } SelectionManager.SetIsDragging(true); - let scaleXs: number[] = []; - let scaleYs: number[] = []; - let xs: number[] = []; - let ys: number[] = []; + const scaleXs: number[] = []; + const scaleYs: number[] = []; + const xs: number[] = []; + const ys: number[] = []; const docs = dragData instanceof DocumentDragData ? dragData.draggedDocuments : dragData instanceof AnnotationDragData ? [dragData.dragDocument] : []; - let dragElements = eles.map(ele => { + const dragElements = eles.map(ele => { const w = ele.offsetWidth, h = ele.offsetHeight; const rect = ele.getBoundingClientRect(); const scaleX = rect.width / w, scaleY = rect.height / h; - let x = rect.left, + const x = rect.left, y = rect.top; xs.push(x); ys.push(y); scaleXs.push(scaleX); scaleYs.push(scaleY); - let dragElement = ele.cloneNode(true) as HTMLElement; + const dragElement = ele.cloneNode(true) as HTMLElement; dragElement.style.opacity = "0.7"; dragElement.style.borderRadius = getComputedStyle(ele).borderRadius; dragElement.style.position = "absolute"; @@ -372,25 +371,25 @@ export namespace DragManager { dragElement.style.height = `${rect.height / scaleY}px`; if (docs.length) { - var pdfBox = dragElement.getElementsByTagName("canvas"); - var pdfBoxSrc = ele.getElementsByTagName("canvas"); + const pdfBox = dragElement.getElementsByTagName("canvas"); + const pdfBoxSrc = ele.getElementsByTagName("canvas"); Array.from(pdfBox).map((pb, i) => pb.getContext('2d')!.drawImage(pdfBoxSrc[i], 0, 0)); - var pdfView = dragElement.getElementsByClassName("pdfViewer-viewer"); - var pdfViewSrc = ele.getElementsByClassName("pdfViewer-viewer"); - let tops = Array.from(pdfViewSrc).map(p => p.scrollTop); - let oldopacity = dragElement.style.opacity; + const pdfView = dragElement.getElementsByClassName("pdfViewer-viewer"); + const pdfViewSrc = ele.getElementsByClassName("pdfViewer-viewer"); + const tops = Array.from(pdfViewSrc).map(p => p.scrollTop); + const oldopacity = dragElement.style.opacity; dragElement.style.opacity = "0"; setTimeout(() => { dragElement.style.opacity = oldopacity; Array.from(pdfView).map((v, i) => v.scrollTo({ top: tops[i] })); }, 0); } - let set = dragElement.getElementsByTagName('*'); + const set = dragElement.getElementsByTagName('*'); if (dragElement.hasAttribute("style")) (dragElement as any).style.pointerEvents = "none"; // tslint:disable-next-line: prefer-for-of for (let i = 0; i < set.length; i++) { if (set[i].hasAttribute("style")) { - let s = set[i]; + const s = set[i]; (s as any).style.pointerEvents = "none"; } } @@ -429,8 +428,8 @@ export namespace DragManager { }, dragData.droppedDocuments); } //TODO: Why can't we use e.movementX and e.movementY? - let moveX = e.pageX - lastX; - let moveY = e.pageY - lastY; + const moveX = e.pageX - lastX; + const moveY = e.pageY - lastY; lastX = e.pageX; lastY = e.pageY; dragElements.map((dragElement, i) => (dragElement.style.transform = @@ -438,11 +437,11 @@ export namespace DragManager { ); }; - let hideDragShowOriginalElements = () => { + const hideDragShowOriginalElements = () => { dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement)); eles.map(ele => ele.hidden = false); }; - let endDrag = () => { + const endDrag = () => { document.removeEventListener("pointermove", moveHandler, true); document.removeEventListener("pointerup", upHandler); if (options) { @@ -466,17 +465,17 @@ export namespace DragManager { } function dispatchDrag(dragEles: HTMLElement[], e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions, finishDrag?: (dragData: { [index: string]: any }) => void) { - let removed = dragData.dontHideOnDrop ? [] : dragEles.map(dragEle => { + const removed = dragData.dontHideOnDrop ? [] : dragEles.map(dragEle => { // let parent = dragEle.parentElement; // if (parent) parent.removeChild(dragEle); - let ret = [dragEle, dragEle.style.width, dragEle.style.height]; + const ret = [dragEle, dragEle.style.width, dragEle.style.height]; dragEle.style.width = "0"; dragEle.style.height = "0"; return ret; }); const target = document.elementFromPoint(e.x, e.y); removed.map(r => { - let dragEle = r[0] as HTMLElement; + const dragEle = r[0] as HTMLElement; dragEle.style.width = r[1] as string; dragEle.style.height = r[2] as string; // let parent = r[1]; diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index 6b53333d7..b2c720d5d 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -9,10 +9,10 @@ import { ScriptField } from "../../new_fields/ScriptField"; function makeTemplate(doc: Doc): boolean { - let layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateField ? doc.layout : doc; - let layout = StrCast(layoutDoc.layout).match(/fieldKey={"[^"]*"}/)![0]; - let fieldKey = layout.replace('fieldKey={"', "").replace(/"}$/, ""); - let docs = DocListCast(layoutDoc[fieldKey]); + const layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateField ? doc.layout : doc; + const layout = StrCast(layoutDoc.layout).match(/fieldKey={"[^"]*"}/)![0]; + const fieldKey = layout.replace('fieldKey={"', "").replace(/"}$/, ""); + const docs = DocListCast(layoutDoc[fieldKey]); let any = false; docs.map(d => { if (!StrCast(d.title).startsWith("-")) { @@ -28,7 +28,7 @@ export function convertDropDataToButtons(data: DragManager.DocumentDragData) { data && data.draggedDocuments.map((doc, i) => { let dbox = doc; if (!doc.onDragStart && !doc.onClick && doc.viewType !== CollectionViewType.Linear) { - let layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateField ? doc.layout : doc; + const layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateField ? doc.layout : doc; if (layoutDoc.type === DocumentType.COL) { layoutDoc.isTemplateDoc = makeTemplate(layoutDoc); } else { diff --git a/src/client/util/History.ts b/src/client/util/History.ts index 1c51236cb..545e8acb4 100644 --- a/src/client/util/History.ts +++ b/src/client/util/History.ts @@ -1,4 +1,4 @@ -import { Doc, Opt, Field } from "../../new_fields/Doc"; +import { Doc } from "../../new_fields/Doc"; import { DocServer } from "../DocServer"; import { MainView } from "../views/MainView"; import * as qs from 'query-string'; @@ -53,7 +53,7 @@ export namespace HistoryUtil { } export function getState(): ParsedUrl { - let state = copyState(history.state); + const state = copyState(history.state); state.initializers = state.initializers || {}; return state; } @@ -160,7 +160,7 @@ export namespace HistoryUtil { const pathname = location.pathname.substring(1); const search = location.search; const opts = search.length ? qs.parse(search, { sort: false }) : {}; - let pathnameSplit = pathname.split("/"); + const pathnameSplit = pathname.split("/"); const type = pathnameSplit[0]; diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index 104d9e099..e6a215b2c 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -1,7 +1,7 @@ import "fs"; import React = require("react"); import { Doc, DocListCast, DocListCastAsync, Opt } from "../../../new_fields/Doc"; -import { action, observable, autorun, runInAction, computed, reaction, IReactionDisposer } from "mobx"; +import { action, observable, runInAction, computed, reaction, IReactionDisposer } from "mobx"; import { FieldViewProps, FieldView } from "../../views/nodes/FieldView"; import Measure, { ContentRect } from "react-measure"; import { library } from '@fortawesome/fontawesome-svg-core'; @@ -48,7 +48,7 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> constructor(props: FieldViewProps) { super(props); library.add(faTag, faPlus); - let doc = this.props.Document; + const doc = this.props.Document; this.editingMetadata = this.editingMetadata || false; this.persistent = this.persistent || false; !Cast(doc.data, listSpec(Doc)) && (doc.data = new List<Doc>()); @@ -78,16 +78,16 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> this.phase = "Initializing download..."; }); - let docs: Doc[] = []; + const docs: Doc[] = []; - let files = e.target.files; + const files = e.target.files; if (!files || files.length === 0) return; - let directory = (files.item(0) as any).webkitRelativePath.split("/", 1)[0]; + const directory = (files.item(0) as any).webkitRelativePath.split("/", 1)[0]; - let validated: File[] = []; + const validated: File[] = []; for (let i = 0; i < files.length; i++) { - let file = files.item(i); + const file = files.item(i); if (file && !unsupported.includes(file.type)) { const ext = path.extname(file.name).toLowerCase(); if (AcceptibleMedia.imageFormats.includes(ext)) { @@ -101,8 +101,8 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> this.completed = 0; }); - let sizes: number[] = []; - let modifiedDates: number[] = []; + const sizes: number[] = []; + const modifiedDates: number[] = []; runInAction(() => this.phase = `Internal: uploading ${this.quota - this.completed} files to Dash...`); @@ -136,26 +136,26 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> })); for (let i = 0; i < docs.length; i++) { - let doc = docs[i]; + const doc = docs[i]; doc.size = sizes[i]; doc.modified = modifiedDates[i]; this.entries.forEach(entry => { - let target = entry.onDataDoc ? Doc.GetProto(doc) : doc; + const target = entry.onDataDoc ? Doc.GetProto(doc) : doc; target[entry.key] = entry.value; }); } - let doc = this.props.Document; - let height: number = NumCast(doc.height) || 0; - let offset: number = this.persistent ? (height === 0 ? 0 : height + 30) : 0; - let options: DocumentOptions = { + const doc = this.props.Document; + const height: number = NumCast(doc.height) || 0; + const offset: number = this.persistent ? (height === 0 ? 0 : height + 30) : 0; + const options: DocumentOptions = { title: `Import of ${directory}`, width: 1105, height: 500, x: NumCast(doc.x), y: NumCast(doc.y) + offset }; - let parent = this.props.ContainingCollectionView; + const parent = this.props.ContainingCollectionView; if (parent) { let importContainer: Doc; if (docs.length < 50) { @@ -194,18 +194,18 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> @action preserveCentering = (rect: ContentRect) => { - let bounds = rect.offset!; + const bounds = rect.offset!; if (bounds.width === 0 || bounds.height === 0) { return; } - let offset = this.dimensions / 2; + const offset = this.dimensions / 2; this.left = bounds.width / 2 - offset; this.top = bounds.height / 2 - offset; } @action addMetadataEntry = async () => { - let entryDoc = new Doc(); + const entryDoc = new Doc(); entryDoc.checked = false; entryDoc.key = keyPlaceholder; entryDoc.value = valuePlaceholder; @@ -214,7 +214,7 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> @action remove = async (entry: ImportMetadataEntry) => { - let metadata = await DocListCastAsync(this.props.Document.data); + const metadata = await DocListCastAsync(this.props.Document.data); if (metadata) { let index = this.entries.indexOf(entry); if (index !== -1) { @@ -228,18 +228,18 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> } render() { - let dimensions = 50; - let entries = DocListCast(this.props.Document.data); - let isEditing = this.editingMetadata; - let completed = this.completed; - let quota = this.quota; - let uploading = this.uploading; - let showRemoveLabel = this.removeHover; - let persistent = this.persistent; + const dimensions = 50; + const entries = DocListCast(this.props.Document.data); + const isEditing = this.editingMetadata; + const completed = this.completed; + const quota = this.quota; + const uploading = this.uploading; + const showRemoveLabel = this.removeHover; + const persistent = this.persistent; let percent = `${completed / quota * 100}`; percent = percent.split(".")[0]; percent = percent.startsWith("100") ? "99" : percent; - let marginOffset = (percent.length === 1 ? 5 : 0) - 1.6; + const marginOffset = (percent.length === 1 ? 5 : 0) - 1.6; const message = <span className={"phase"}>{this.phase}</span>; const centerPiece = this.phase.includes("Google Photos") ? <img src={"/assets/google_photos.png"} style={{ diff --git a/src/client/util/Import & Export/ImportMetadataEntry.tsx b/src/client/util/Import & Export/ImportMetadataEntry.tsx index f5198c39b..8e1c50bea 100644 --- a/src/client/util/Import & Export/ImportMetadataEntry.tsx +++ b/src/client/util/Import & Export/ImportMetadataEntry.tsx @@ -1,11 +1,11 @@ import React = require("react"); import { observer } from "mobx-react"; import { EditableView } from "../../views/EditableView"; -import { observable, action, computed } from "mobx"; +import { action, computed } from "mobx"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faPlus } from "@fortawesome/free-solid-svg-icons"; import { library } from '@fortawesome/fontawesome-svg-core'; -import { Opt, Doc } from "../../../new_fields/Doc"; +import { Doc } from "../../../new_fields/Doc"; import { StrCast, BoolCast } from "../../../new_fields/Types"; interface KeyValueProps { @@ -85,7 +85,7 @@ export default class ImportMetadataEntry extends React.Component<KeyValueProps> } render() { - let keyValueStyle: React.CSSProperties = { + const keyValueStyle: React.CSSProperties = { paddingLeft: 10, width: "50%", opacity: this.valid ? 1 : 0.5, diff --git a/src/client/util/InteractionUtils.ts b/src/client/util/InteractionUtils.ts index b7738e862..0c3de66ed 100644 --- a/src/client/util/InteractionUtils.ts +++ b/src/client/util/InteractionUtils.ts @@ -29,8 +29,8 @@ export namespace InteractionUtils { * @param pts - n-arbitrary long list of points */ export function CenterPoint(pts: React.Touch[]): { X: number, Y: number } { - let centerX = pts.map(pt => pt.clientX).reduce((a, b) => a + b, 0) / pts.length; - let centerY = pts.map(pt => pt.clientY).reduce((a, b) => a + b, 0) / pts.length; + const centerX = pts.map(pt => pt.clientX).reduce((a, b) => a + b, 0) / pts.length; + const centerY = pts.map(pt => pt.clientY).reduce((a, b) => a + b, 0) / pts.length; return { X: centerX, Y: centerY }; } @@ -42,9 +42,9 @@ export namespace InteractionUtils { * @param oldPoint2 - previous point 2 */ export function Pinching(pt1: React.Touch, pt2: React.Touch, oldPoint1: React.Touch, oldPoint2: React.Touch): number { - let threshold = 4; - let oldDist = TwoPointEuclidist(oldPoint1, oldPoint2); - let newDist = TwoPointEuclidist(pt1, pt2); + const threshold = 4; + const oldDist = TwoPointEuclidist(oldPoint1, oldPoint2); + const newDist = TwoPointEuclidist(pt1, pt2); /** if they have the same sign, then we are either pinching in or out. * threshold it by 10 (it has to be pinching by at least threshold to be a valid pinch) @@ -64,12 +64,12 @@ export namespace InteractionUtils { * @param oldPoint2 - previous point 2 */ export function Pinning(pt1: React.Touch, pt2: React.Touch, oldPoint1: React.Touch, oldPoint2: React.Touch): number { - let threshold = 4; + const threshold = 4; - let pt1Dist = TwoPointEuclidist(oldPoint1, pt1); - let pt2Dist = TwoPointEuclidist(oldPoint2, pt2); + const pt1Dist = TwoPointEuclidist(oldPoint1, pt1); + const pt2Dist = TwoPointEuclidist(oldPoint2, pt2); - let pinching = Pinching(pt1, pt2, oldPoint1, oldPoint2); + const pinching = Pinching(pt1, pt2, oldPoint1, oldPoint2); if (pinching !== 0) { if ((pt1Dist < threshold && pt2Dist > threshold) || (pt1Dist > threshold && pt2Dist < threshold)) { diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index eedc4967d..fb6f27478 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -38,16 +38,16 @@ export class LinkManager { } public getAllLinks(): Doc[] { - let ldoc = LinkManager.Instance.LinkManagerDoc; + const ldoc = LinkManager.Instance.LinkManagerDoc; if (ldoc) { - let docs = DocListCast(ldoc.allLinks); + const docs = DocListCast(ldoc.allLinks); return docs; } return []; } public addLink(linkDoc: Doc): boolean { - let linkList = LinkManager.Instance.getAllLinks(); + const linkList = LinkManager.Instance.getAllLinks(); linkList.push(linkDoc); if (LinkManager.Instance.LinkManagerDoc) { LinkManager.Instance.LinkManagerDoc.allLinks = new List<Doc>(linkList); @@ -57,8 +57,8 @@ export class LinkManager { } public deleteLink(linkDoc: Doc): boolean { - let linkList = LinkManager.Instance.getAllLinks(); - let index = LinkManager.Instance.getAllLinks().indexOf(linkDoc); + const linkList = LinkManager.Instance.getAllLinks(); + const index = LinkManager.Instance.getAllLinks().indexOf(linkDoc); if (index > -1) { linkList.splice(index, 1); if (LinkManager.Instance.LinkManagerDoc) { @@ -71,23 +71,23 @@ export class LinkManager { // finds all links that contain the given anchor public getAllRelatedLinks(anchor: Doc): Doc[] {//List<Doc> { - let related = LinkManager.Instance.getAllLinks().filter(link => { - let protomatch1 = Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, null)); - let protomatch2 = Doc.AreProtosEqual(anchor, Cast(link.anchor2, Doc, null)); + const related = LinkManager.Instance.getAllLinks().filter(link => { + const protomatch1 = Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, null)); + const protomatch2 = Doc.AreProtosEqual(anchor, Cast(link.anchor2, Doc, null)); return protomatch1 || protomatch2 || Doc.AreProtosEqual(link, anchor); }); return related; } public deleteAllLinksOnAnchor(anchor: Doc) { - let related = LinkManager.Instance.getAllRelatedLinks(anchor); + const related = LinkManager.Instance.getAllRelatedLinks(anchor); related.forEach(linkDoc => LinkManager.Instance.deleteLink(linkDoc)); } public addGroupType(groupType: string): boolean { if (LinkManager.Instance.LinkManagerDoc) { LinkManager.Instance.LinkManagerDoc[groupType] = new List<string>([]); - let groupTypes = LinkManager.Instance.getAllGroupTypes(); + const groupTypes = LinkManager.Instance.getAllGroupTypes(); groupTypes.push(groupType); LinkManager.Instance.LinkManagerDoc.allGroupTypes = new List<string>(groupTypes); return true; @@ -99,8 +99,8 @@ export class LinkManager { public deleteGroupType(groupType: string): boolean { if (LinkManager.Instance.LinkManagerDoc) { if (LinkManager.Instance.LinkManagerDoc[groupType]) { - let groupTypes = LinkManager.Instance.getAllGroupTypes(); - let index = groupTypes.findIndex(type => type.toUpperCase() === groupType.toUpperCase()); + const groupTypes = LinkManager.Instance.getAllGroupTypes(); + const index = groupTypes.findIndex(type => type.toUpperCase() === groupType.toUpperCase()); if (index > -1) groupTypes.splice(index, 1); LinkManager.Instance.LinkManagerDoc.allGroupTypes = new List<string>(groupTypes); LinkManager.Instance.LinkManagerDoc[groupType] = undefined; @@ -146,8 +146,8 @@ export class LinkManager { } public addGroupToAnchor(linkDoc: Doc, anchor: Doc, groupDoc: Doc, replace: boolean = false) { - let groups = LinkManager.Instance.getAnchorGroups(linkDoc, anchor); - let index = groups.findIndex(gDoc => { + const groups = LinkManager.Instance.getAnchorGroups(linkDoc, anchor); + const index = groups.findIndex(gDoc => { return StrCast(groupDoc.type).toUpperCase() === StrCast(gDoc.type).toUpperCase(); }); if (index > -1 && replace) { @@ -161,32 +161,32 @@ export class LinkManager { // removes group doc of given group type only from given anchor on given link public removeGroupFromAnchor(linkDoc: Doc, anchor: Doc, groupType: string) { - let groups = LinkManager.Instance.getAnchorGroups(linkDoc, anchor); - let newGroups = groups.filter(groupDoc => StrCast(groupDoc.type).toUpperCase() !== groupType.toUpperCase()); + const groups = LinkManager.Instance.getAnchorGroups(linkDoc, anchor); + const newGroups = groups.filter(groupDoc => StrCast(groupDoc.type).toUpperCase() !== groupType.toUpperCase()); LinkManager.Instance.setAnchorGroups(linkDoc, anchor, newGroups); } // returns map of group type to anchor's links in that group type public getRelatedGroupedLinks(anchor: Doc): Map<string, Array<Doc>> { - let related = this.getAllRelatedLinks(anchor); - let anchorGroups = new Map<string, Array<Doc>>(); + const related = this.getAllRelatedLinks(anchor); + const anchorGroups = new Map<string, Array<Doc>>(); related.forEach(link => { - let groups = LinkManager.Instance.getAnchorGroups(link, anchor); + const groups = LinkManager.Instance.getAnchorGroups(link, anchor); if (groups.length > 0) { groups.forEach(groupDoc => { - let groupType = StrCast(groupDoc.type); + const groupType = StrCast(groupDoc.type); if (groupType === "") { - let group = anchorGroups.get("*"); + const group = anchorGroups.get("*"); anchorGroups.set("*", group ? [...group, link] : [link]); } else { - let group = anchorGroups.get(groupType); + const group = anchorGroups.get(groupType); anchorGroups.set(groupType, group ? [...group, link] : [link]); } }); } else { // if link is in no groups then put it in default group - let group = anchorGroups.get("*"); + const group = anchorGroups.get("*"); anchorGroups.set("*", group ? [...group, link] : [link]); } @@ -212,11 +212,11 @@ export class LinkManager { // returns a list of all metadata docs associated with the given group type public getAllMetadataDocsInGroup(groupType: string): Array<Doc> { - let md: Doc[] = []; - let allLinks = LinkManager.Instance.getAllLinks(); + const md: Doc[] = []; + const allLinks = LinkManager.Instance.getAllLinks(); allLinks.forEach(linkDoc => { - let anchor1Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor1, Doc, null)); - let anchor2Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor2, Doc, null)); + const anchor1Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor1, Doc, null)); + const anchor2Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor2, Doc, null)); anchor1Groups.forEach(groupDoc => { if (StrCast(groupDoc.type).toUpperCase() === groupType.toUpperCase()) { const meta = Cast(groupDoc.metadata, Doc, null); meta && md.push(meta); } }); anchor2Groups.forEach(groupDoc => { if (StrCast(groupDoc.type).toUpperCase() === groupType.toUpperCase()) { const meta = Cast(groupDoc.metadata, Doc, null); meta && md.push(meta); } }); }); @@ -225,8 +225,8 @@ export class LinkManager { // checks if a link with the given anchors exists public doesLinkExist(anchor1: Doc, anchor2: Doc): boolean { - let allLinks = LinkManager.Instance.getAllLinks(); - let index = allLinks.findIndex(linkDoc => { + const allLinks = LinkManager.Instance.getAllLinks(); + const index = allLinks.findIndex(linkDoc => { return (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, null), anchor1) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, null), anchor2)) || (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, null), anchor2) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, null), anchor1)); }); @@ -237,8 +237,8 @@ export class LinkManager { //TODO This should probably return undefined if there isn't an opposite anchor //TODO This should also await the return value of the anchor so we don't filter out promises public getOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc | undefined { - let a1 = Cast(linkDoc.anchor1, Doc, null); - let a2 = Cast(linkDoc.anchor2, Doc, null); + const a1 = Cast(linkDoc.anchor1, Doc, null); + const a2 = Cast(linkDoc.anchor2, Doc, null); if (Doc.AreProtosEqual(anchor, a1)) return a2; if (Doc.AreProtosEqual(anchor, a2)) return a1; if (Doc.AreProtosEqual(anchor, linkDoc)) return linkDoc; diff --git a/src/client/util/ProsemirrorExampleTransfer.ts b/src/client/util/ProsemirrorExampleTransfer.ts index 003ff6272..f1fa6f11d 100644 --- a/src/client/util/ProsemirrorExampleTransfer.ts +++ b/src/client/util/ProsemirrorExampleTransfer.ts @@ -4,7 +4,7 @@ import { undoInputRule } from "prosemirror-inputrules"; import { Schema } from "prosemirror-model"; import { liftListItem, sinkListItem } from "./prosemirrorPatches.js"; import { splitListItem, wrapInList, } from "prosemirror-schema-list"; -import { EditorState, Transaction, TextSelection, NodeSelection } from "prosemirror-state"; +import { EditorState, Transaction, TextSelection } from "prosemirror-state"; import { TooltipTextMenu } from "./TooltipTextMenu"; const mac = typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false; @@ -15,22 +15,22 @@ export let updateBullets = (tx2: Transaction, schema: Schema, mapStyle?: string) let fontSize: number | undefined = undefined; tx2.doc.descendants((node: any, offset: any, index: any) => { if (node.type === schema.nodes.ordered_list || node.type === schema.nodes.list_item) { - let path = (tx2.doc.resolve(offset) as any).path; + const path = (tx2.doc.resolve(offset) as any).path; let depth = Array.from(path).reduce((p: number, c: any) => p + (c.hasOwnProperty("type") && c.type === schema.nodes.ordered_list ? 1 : 0), 0); if (node.type === schema.nodes.ordered_list) depth++; fontSize = depth === 1 && node.attrs.setFontSize ? Number(node.attrs.setFontSize) : fontSize; - let fsize = fontSize && node.type === schema.nodes.ordered_list ? Math.max(6, fontSize - (depth - 1) * 4) : undefined; + const fsize = fontSize && node.type === schema.nodes.ordered_list ? Math.max(6, fontSize - (depth - 1) * 4) : undefined; tx2.setNodeMarkup(offset, node.type, { ...node.attrs, mapStyle: mapStyle ? mapStyle : node.attrs.mapStyle, bulletStyle: depth, inheritedFontSize: fsize }, node.marks); } }); return tx2; }; export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?: KeyMap): KeyMap { - let keys: { [key: string]: any } = {}, type; + const keys: { [key: string]: any } = {}; function bind(key: string, cmd: any) { if (mapKeys) { - let mapped = mapKeys[key]; + const mapped = mapKeys[key]; if (mapped === false) return; if (mapped) key = mapped; } @@ -79,7 +79,7 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?: // }); - let cmd = chainCommands(exitCode, (state, dispatch) => { + const cmd = chainCommands(exitCode, (state, dispatch) => { if (dispatch) { dispatch(state.tr.replaceSelectionWith(schema.nodes.hard_break.create()).scrollIntoView()); return true; @@ -99,7 +99,7 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?: bind("Shift-Ctrl-" + i, setBlockType(schema.nodes.heading, { level: i })); } - let hr = schema.nodes.horizontal_rule; + const hr = schema.nodes.horizontal_rule; bind("Mod-_", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => { dispatch(state.tr.replaceSelectionWith(hr.create()).scrollIntoView()); return true; @@ -108,18 +108,18 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?: bind("Mod-s", TooltipTextMenu.insertStar); bind("Tab", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => { - var ref = state.selection; - var range = ref.$from.blockRange(ref.$to); - var marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); + const ref = state.selection; + const range = ref.$from.blockRange(ref.$to); + const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); if (!sinkListItem(schema.nodes.list_item)(state, (tx2: Transaction) => { - let tx3 = updateBullets(tx2, schema); + const tx3 = updateBullets(tx2, schema); marks && tx3.ensureMarks([...marks]); marks && tx3.setStoredMarks([...marks]); dispatch(tx3); })) { // couldn't sink into an existing list, so wrap in a new one - let newstate = state.applyTransaction(state.tr.setSelection(TextSelection.create(state.doc, range!.start, range!.end))); + const newstate = state.applyTransaction(state.tr.setSelection(TextSelection.create(state.doc, range!.start, range!.end))); if (!wrapInList(schema.nodes.ordered_list)(newstate.state, (tx2: Transaction) => { - let tx3 = updateBullets(tx2, schema); + const tx3 = updateBullets(tx2, schema); // when promoting to a list, assume list will format things so don't copy the stored marks. marks && tx3.ensureMarks([...marks]); marks && tx3.setStoredMarks([...marks]); @@ -131,10 +131,10 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?: }); bind("Shift-Tab", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => { - var marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); + const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); if (!liftListItem(schema.nodes.list_item)(state.tr, (tx2: Transaction) => { - let tx3 = updateBullets(tx2, schema); + const tx3 = updateBullets(tx2, schema); marks && tx3.ensureMarks([...marks]); marks && tx3.setStoredMarks([...marks]); dispatch(tx3); @@ -143,14 +143,14 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?: } }); - let splitMetadata = (marks: any, tx: Transaction) => { + const splitMetadata = (marks: any, tx: Transaction) => { marks && tx.ensureMarks(marks.filter((val: any) => val.type !== schema.marks.metadata && val.type !== schema.marks.metadataKey && val.type !== schema.marks.metadataVal)); marks && tx.setStoredMarks(marks.filter((val: any) => val.type !== schema.marks.metadata && val.type !== schema.marks.metadataKey && val.type !== schema.marks.metadataVal)); return tx; }; - bind("Enter", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => { - var marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); - if (!splitListItem(schema.nodes.list_item)(state, (tx3: Transaction) => dispatch(tx3))) { + bind("Enter", (state: EditorState<S>, dispatch: (tx: Transaction<Schema<any, any>>) => void) => { + const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); + if (!splitListItem(schema.nodes.list_item)(state, dispatch)) { if (!splitBlockKeepMarks(state, (tx3: Transaction) => { splitMetadata(marks, tx3); if (!liftListItem(schema.nodes.list_item)(tx3, dispatch as ((tx: Transaction<Schema<any, any>>) => void))) { @@ -163,18 +163,18 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?: return true; }); bind("Space", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => { - var marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); + const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); dispatch(splitMetadata(marks, state.tr)); return false; }); bind(":", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => { - let range = state.selection.$from.blockRange(state.selection.$to, (node: any) => { + const range = state.selection.$from.blockRange(state.selection.$to, (node: any) => { return !node.marks || !node.marks.find((m: any) => m.type === schema.marks.metadata); }); - let path = (state.doc.resolve(state.selection.from - 1) as any).path; - let spaceSeparator = path[path.length - 3].childCount > 1 ? 0 : -1; - let textsel = TextSelection.create(state.doc, range!.end - path[path.length - 3].lastChild.nodeSize + spaceSeparator, range!.end); - let text = range ? state.doc.textBetween(textsel.from, textsel.to) : ""; + const path = (state.doc.resolve(state.selection.from - 1) as any).path; + const spaceSeparator = path[path.length - 3].childCount > 1 ? 0 : -1; + const textsel = TextSelection.create(state.doc, range!.end - path[path.length - 3].lastChild.nodeSize + spaceSeparator, range!.end); + const text = range ? state.doc.textBetween(textsel.from, textsel.to) : ""; let whitespace = text.length - 1; for (; whitespace >= 0 && text[whitespace] !== " "; whitespace--) { } if (text.endsWith(":")) { diff --git a/src/client/util/RichTextRules.ts b/src/client/util/RichTextRules.ts index f4c44e5ce..1a637df32 100644 --- a/src/client/util/RichTextRules.ts +++ b/src/client/util/RichTextRules.ts @@ -62,109 +62,109 @@ export const inpRules = { new InputRule( new RegExp(/^#([0-9]+)\s$/), (state, match, start, end) => { - let size = Number(match[1]); - let ruleProvider = FormattedTextBox.InputBoxOverlay!.props.ruleProvider; - let heading = NumCast(FormattedTextBox.InputBoxOverlay!.props.Document.heading); + const size = Number(match[1]); + const ruleProvider = FormattedTextBox.InputBoxOverlay!.props.ruleProvider; + const heading = NumCast(FormattedTextBox.InputBoxOverlay!.props.Document.heading); if (ruleProvider && heading) { - (Cast(FormattedTextBox.InputBoxOverlay!.props.Document, Doc) as Doc).heading = Number(match[1]); + (Cast(FormattedTextBox.InputBoxOverlay!.props.Document, Doc) as Doc).heading = size; return state.tr.deleteRange(start, end); } - return state.tr.deleteRange(start, end).addStoredMark(schema.marks.pFontSize.create({ fontSize: Number(match[1]) })); + return state.tr.deleteRange(start, end).addStoredMark(schema.marks.pFontSize.create({ fontSize: size })); }), new InputRule( new RegExp(/t/), (state, match, start, end) => { if (state.selection.to === state.selection.from) return null; - let node = (state.doc.resolve(start) as any).nodeAfter; + const node = (state.doc.resolve(start) as any).nodeAfter; return node ? state.tr.addMark(start, end, schema.marks.user_tag.create({ userid: Doc.CurrentUserEmail, tag: "todo", modified: Math.round(Date.now() / 1000 / 60) })) : state.tr; }), new InputRule( new RegExp(/i/), (state, match, start, end) => { if (state.selection.to === state.selection.from) return null; - let node = (state.doc.resolve(start) as any).nodeAfter; + const node = (state.doc.resolve(start) as any).nodeAfter; return node ? state.tr.addMark(start, end, schema.marks.user_tag.create({ userid: Doc.CurrentUserEmail, tag: "ignore", modified: Math.round(Date.now() / 1000 / 60) })) : state.tr; }), new InputRule( new RegExp(/\!/), (state, match, start, end) => { if (state.selection.to === state.selection.from) return null; - let node = (state.doc.resolve(start) as any).nodeAfter; + const node = (state.doc.resolve(start) as any).nodeAfter; return node ? state.tr.addMark(start, end, schema.marks.user_tag.create({ userid: Doc.CurrentUserEmail, tag: "important", modified: Math.round(Date.now() / 1000 / 60) })) : state.tr; }), new InputRule( new RegExp(/\x/), (state, match, start, end) => { if (state.selection.to === state.selection.from) return null; - let node = (state.doc.resolve(start) as any).nodeAfter; + const node = (state.doc.resolve(start) as any).nodeAfter; return node ? state.tr.addMark(start, end, schema.marks.user_tag.create({ userid: Doc.CurrentUserEmail, tag: "disagree", modified: Math.round(Date.now() / 1000 / 60) })) : state.tr; }), new InputRule( new RegExp(/^\^\^\s$/), (state, match, start, end) => { - let node = (state.doc.resolve(start) as any).nodeAfter; - let sm = state.storedMarks || undefined; - let ruleProvider = FormattedTextBox.InputBoxOverlay!.props.ruleProvider; - let heading = NumCast(FormattedTextBox.InputBoxOverlay!.props.Document.heading); + const node = (state.doc.resolve(start) as any).nodeAfter; + const sm = state.storedMarks || undefined; + const ruleProvider = FormattedTextBox.InputBoxOverlay!.props.ruleProvider; + const heading = NumCast(FormattedTextBox.InputBoxOverlay!.props.Document.heading); if (ruleProvider && heading) { ruleProvider["ruleAlign_" + heading] = "center"; return node ? state.tr.deleteRange(start, end).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; } - let replaced = node ? state.tr.replaceRangeWith(start, end, schema.nodes.paragraph.create({ align: "center" })).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : + const replaced = node ? state.tr.replaceRangeWith(start, end, schema.nodes.paragraph.create({ align: "center" })).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; return replaced.setSelection(new TextSelection(replaced.doc.resolve(end - 2))); }), new InputRule( new RegExp(/^\[\[\s$/), (state, match, start, end) => { - let node = (state.doc.resolve(start) as any).nodeAfter; - let sm = state.storedMarks || undefined; - let ruleProvider = FormattedTextBox.InputBoxOverlay!.props.ruleProvider; - let heading = NumCast(FormattedTextBox.InputBoxOverlay!.props.Document.heading); + const node = (state.doc.resolve(start) as any).nodeAfter; + const sm = state.storedMarks || undefined; + const ruleProvider = FormattedTextBox.InputBoxOverlay!.props.ruleProvider; + const heading = NumCast(FormattedTextBox.InputBoxOverlay!.props.Document.heading); if (ruleProvider && heading) { ruleProvider["ruleAlign_" + heading] = "left"; return node ? state.tr.deleteRange(start, end).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; } - let replaced = node ? state.tr.replaceRangeWith(start, end, schema.nodes.paragraph.create({ align: "left" })).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : + const replaced = node ? state.tr.replaceRangeWith(start, end, schema.nodes.paragraph.create({ align: "left" })).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; return replaced.setSelection(new TextSelection(replaced.doc.resolve(end - 2))); }), new InputRule( new RegExp(/^\]\]\s$/), (state, match, start, end) => { - let node = (state.doc.resolve(start) as any).nodeAfter; - let sm = state.storedMarks || undefined; - let ruleProvider = FormattedTextBox.InputBoxOverlay!.props.ruleProvider; - let heading = NumCast(FormattedTextBox.InputBoxOverlay!.props.Document.heading); + const node = (state.doc.resolve(start) as any).nodeAfter; + const sm = state.storedMarks || undefined; + const ruleProvider = FormattedTextBox.InputBoxOverlay!.props.ruleProvider; + const heading = NumCast(FormattedTextBox.InputBoxOverlay!.props.Document.heading); if (ruleProvider && heading) { ruleProvider["ruleAlign_" + heading] = "right"; return node ? state.tr.deleteRange(start, end).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; } - let replaced = node ? state.tr.replaceRangeWith(start, end, schema.nodes.paragraph.create({ align: "right" })).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : + const replaced = node ? state.tr.replaceRangeWith(start, end, schema.nodes.paragraph.create({ align: "right" })).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; return replaced.setSelection(new TextSelection(replaced.doc.resolve(end - 2))); }), new InputRule( new RegExp(/##\s$/), (state, match, start, end) => { - let target = Docs.Create.TextDocument({ width: 75, height: 35, autoHeight: true, fontSize: 9, title: "inline comment" }); - let node = (state.doc.resolve(start) as any).nodeAfter; - let newNode = schema.nodes.dashComment.create({ docid: target[Id] }); - let dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: "dashDoc", docid: target[Id], float: "right" }); - let sm = state.storedMarks || undefined; - let replaced = node ? state.tr.insert(start, newNode).replaceRangeWith(start + 1, end + 1, dashDoc).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : + const target = Docs.Create.TextDocument({ width: 75, height: 35, autoHeight: true, fontSize: 9, title: "inline comment" }); + const node = (state.doc.resolve(start) as any).nodeAfter; + const newNode = schema.nodes.dashComment.create({ docid: target[Id] }); + const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: "dashDoc", docid: target[Id], float: "right" }); + const sm = state.storedMarks || undefined; + const replaced = node ? state.tr.insert(start, newNode).replaceRangeWith(start + 1, end + 1, dashDoc).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; return replaced;//.setSelection(new NodeSelection(replaced.doc.resolve(end))); }), new InputRule( new RegExp(/\(\(/), (state, match, start, end) => { - let node = (state.doc.resolve(start) as any).nodeAfter; - let sm = state.storedMarks || undefined; - let mark = state.schema.marks.highlight.create(); - let selected = state.tr.setSelection(new TextSelection(state.doc.resolve(start), state.doc.resolve(end))).addMark(start, end, mark); - let content = selected.selection.content(); - let replaced = node ? selected.replaceRangeWith(start, start, + const node = (state.doc.resolve(start) as any).nodeAfter; + const sm = state.storedMarks || undefined; + const mark = state.schema.marks.highlight.create(); + const selected = state.tr.setSelection(new TextSelection(state.doc.resolve(start), state.doc.resolve(end))).addMark(start, end, mark); + const content = selected.selection.content(); + const replaced = node ? selected.replaceRangeWith(start, start, schema.nodes.star.create({ visibility: true, text: content, textslice: content.toJSON() })).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; return replaced.setSelection(new TextSelection(replaced.doc.resolve(end + 1))); @@ -172,14 +172,14 @@ export const inpRules = { new InputRule( new RegExp(/\)\)/), (state, match, start, end) => { - let mark = state.schema.marks.highlight.create(); + const mark = state.schema.marks.highlight.create(); return state.tr.removeStoredMark(mark); }), new InputRule( new RegExp(/\^f\s$/), (state, match, start, end) => { - let newNode = schema.nodes.footnote.create({}); - let tr = state.tr; + const newNode = schema.nodes.footnote.create({}); + const tr = state.tr; tr.deleteRange(start, end).replaceSelectionWith(newNode); // replace insertion with a footnote. return tr.setSelection(new NodeSelection( // select the footnote node to open its display tr.doc.resolve( // get the location of the footnote node by subtracting the nodesize of the footnote from the current insertion point anchor (which will be immediately after the footnote node) diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 522232e9f..cb03892f3 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -1,4 +1,4 @@ -import { action, observable, runInAction, reaction, IReactionDisposer } from "mobx"; +import { reaction, IReactionDisposer } from "mobx"; import { baseKeymap, toggleMark } from "prosemirror-commands"; import { redo, undo } from "prosemirror-history"; import { keymap } from "prosemirror-keymap"; @@ -257,9 +257,9 @@ export const nodes: { [index: string]: NodeSpec } = { if (node.attrs.mapStyle === "bullet") return ['ul', 0]; const decMap = bs ? "decimal" + bs : ""; const multiMap = bs === 1 ? "decimal1" : bs === 2 ? "upper-alpha" : bs === 3 ? "lower-roman" : bs === 4 ? "lower-alpha" : ""; - let map = node.attrs.mapStyle === "decimal" ? decMap : multiMap; - let fsize = node.attrs.setFontSize ? node.attrs.setFontSize : node.attrs.inheritedFontSize; - let ffam = node.attrs.setFontFamily; + const map = node.attrs.mapStyle === "decimal" ? decMap : multiMap; + const fsize = node.attrs.setFontSize ? node.attrs.setFontSize : node.attrs.inheritedFontSize; + const ffam = node.attrs.setFontFamily; return node.attrs.visibility ? ['ol', { class: `${map}-ol`, style: `list-style: none; font-size: ${fsize}; font-family: ${ffam}` }, 0] : ['ol', { class: `${map}-ol`, style: `list-style: none; font-size: ${fsize}; font-family: ${ffam}` }]; } @@ -287,7 +287,7 @@ export const nodes: { [index: string]: NodeSpec } = { const bs = node.attrs.bulletStyle; const decMap = bs ? "decimal" + bs : ""; const multiMap = bs === 1 ? "decimal1" : bs === 2 ? "upper-alpha" : bs === 3 ? "lower-roman" : bs === 4 ? "lower-alpha" : ""; - let map = node.attrs.mapStyle === "decimal" ? decMap : node.attrs.mapStyle === "multi" ? multiMap : ""; + const map = node.attrs.mapStyle === "decimal" ? decMap : node.attrs.mapStyle === "multi" ? multiMap : ""; return node.attrs.visibility ? ["li", { class: `${map}` }, 0] : ["li", { class: `${map}` }, "..."]; //return ["li", { class: `${map}` }, 0]; } @@ -432,7 +432,7 @@ export const marks: { [index: string]: MarkSpec } = { tag: "span", getAttrs: (p: any) => { if (typeof (p) !== "string") { - let style = getComputedStyle(p); + const style = getComputedStyle(p); if (style.textDecoration === "underline") return null; if (p.parentElement.outerHTML.indexOf("text-decoration: underline") !== -1 && p.parentElement.outerHTML.indexOf("text-decoration-style: dotted") !== -1) { @@ -457,7 +457,7 @@ export const marks: { [index: string]: MarkSpec } = { tag: "span", getAttrs: (p: any) => { if (typeof (p) !== "string") { - let style = getComputedStyle(p); + const style = getComputedStyle(p); if (style.textDecoration === "underline" || p.parentElement.outerHTML.indexOf("text-decoration-style:line") !== -1) { return null; } @@ -493,11 +493,11 @@ export const marks: { [index: string]: MarkSpec } = { }, group: "inline", toDOM(node: any) { - let uid = node.attrs.userid.replace(".", "").replace("@", ""); - let min = Math.round(node.attrs.modified / 12); - let hr = Math.round(min / 60); - let day = Math.round(hr / 60 / 24); - let remote = node.attrs.userid !== Doc.CurrentUserEmail ? " userMark-remote" : ""; + const uid = node.attrs.userid.replace(".", "").replace("@", ""); + const min = Math.round(node.attrs.modified / 12); + const hr = Math.round(min / 60); + const day = Math.round(hr / 60 / 24); + const remote = node.attrs.userid !== Doc.CurrentUserEmail ? " userMark-remote" : ""; return node.attrs.opened ? ['span', { class: "userMark-" + uid + remote + " userMark-min-" + min + " userMark-hr-" + hr + " userMark-day-" + day }, 0] : ['span', { class: "userMark-" + uid + remote + " userMark-min-" + min + " userMark-hr-" + hr + " userMark-day-" + day }, ['span', 0]]; @@ -513,7 +513,7 @@ export const marks: { [index: string]: MarkSpec } = { }, group: "inline", toDOM(node: any) { - let uid = node.attrs.userid.replace(".", "").replace("@", ""); + const uid = node.attrs.userid.replace(".", "").replace("@", ""); return node.attrs.opened ? ['span', { class: "userTag-" + uid + " userTag-" + node.attrs.tag }, 0] : ['span', { class: "userTag-" + uid + " userTag-" + node.attrs.tag }, ['span', 0]]; @@ -534,7 +534,7 @@ export const marks: { [index: string]: MarkSpec } = { }, parseDOM: [{ tag: "span", getAttrs(dom: any) { - let cstyle = getComputedStyle(dom); + const cstyle = getComputedStyle(dom); if (cstyle.font) { if (cstyle.font.indexOf("Times New Roman") !== -1) return { family: "Times New Roman" }; if (cstyle.font.indexOf("Arial") !== -1) return { family: "Arial" }; @@ -599,7 +599,7 @@ export class ImageResizeView { this._handle.style.display = "none"; this._handle.style.bottom = "-10px"; this._handle.style.right = "-10px"; - let self = this; + const self = this; this._img.onclick = function (e: any) { e.stopPropagation(); e.preventDefault(); @@ -620,8 +620,8 @@ export class ImageResizeView { this._handle.onpointerdown = function (e: any) { e.preventDefault(); e.stopPropagation(); - let wid = Number(getComputedStyle(self._img).width.replace(/px/, "")); - let hgt = Number(getComputedStyle(self._img).height.replace(/px/, "")); + const wid = Number(getComputedStyle(self._img).width.replace(/px/, "")); + const hgt = Number(getComputedStyle(self._img).height.replace(/px/, "")); const startX = e.pageX; const startWidth = parseFloat(node.attrs.width); const onpointermove = (e: any) => { @@ -634,7 +634,7 @@ export class ImageResizeView { const onpointerup = () => { document.removeEventListener("pointermove", onpointermove); document.removeEventListener("pointerup", onpointerup); - let pos = view.state.selection.from; + const pos = view.state.selection.from; view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, { ...node.attrs, width: self._outer.style.width, height: self._outer.style.height })); view.dispatch(view.state.tr.setSelection(new NodeSelection(view.state.doc.resolve(pos)))); }; @@ -671,19 +671,19 @@ export class DashDocCommentView { this._collapsed.id = "DashDocCommentView-" + node.attrs.docid; this._view = view; this._collapsed.onpointerdown = (e: any) => { - let node = view.state.doc.nodeAt(getPos() + 1); + const node = view.state.doc.nodeAt(getPos() + 1); view.dispatch(view.state.tr. setNodeMarkup(getPos() + 1, undefined, { ...node.attrs, hidden: node.attrs.hidden ? false : true })); // update the attrs setTimeout(() => node.attrs.hidden && DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)), 100); - } + }; this._collapsed.onpointerenter = (e: any) => { - let node = view.state.doc.nodeAt(getPos() + 1); + const node = view.state.doc.nodeAt(getPos() + 1); DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)); e.preventDefault(); e.stopPropagation(); }; this._collapsed.onpointerleave = (e: any) => { - let node = view.state.doc.nodeAt(getPos() + 1); + const node = view.state.doc.nodeAt(getPos() + 1); DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowUnhighlight()); e.preventDefault(); e.stopPropagation(); @@ -701,7 +701,7 @@ export class DashDocView { _textBox: FormattedTextBox; getDocTransform = () => { - let { scale, translateX, translateY } = Utils.GetScreenTransform(this._outer); + const { scale, translateX, translateY } = Utils.GetScreenTransform(this._outer); return new Transform(-translateX, -translateY, 1).scale(1 / this.contentScaling() / scale); } contentScaling = () => NumCast(this._dashDoc!.nativeWidth) > 0 && !this._dashDoc!.ignoreAspect ? this._dashDoc![WidthSym]() / NumCast(this._dashDoc!.nativeWidth) : 1; @@ -721,24 +721,24 @@ export class DashDocView { this._dashSpan.style.position = "absolute"; this._dashSpan.style.display = "inline-block"; this._dashSpan.style.borderWidth = "4"; - let removeDoc = () => { - let pos = getPos(); - let ns = new NodeSelection(view.state.doc.resolve(pos)); + const removeDoc = () => { + const pos = getPos(); + const ns = new NodeSelection(view.state.doc.resolve(pos)); view.dispatch(view.state.tr.setSelection(ns).deleteSelection()); return true; }; this._dashSpan.onpointerleave = () => { - let ele = document.getElementById("DashDocCommentView-" + node.attrs.docid); + const ele = document.getElementById("DashDocCommentView-" + node.attrs.docid); if (ele) { (ele as HTMLDivElement).style.backgroundColor = ""; } - } + }; this._dashSpan.onpointerenter = () => { - let ele = document.getElementById("DashDocCommentView-" + node.attrs.docid); + const ele = document.getElementById("DashDocCommentView-" + node.attrs.docid); if (ele) { (ele as HTMLDivElement).style.backgroundColor = "orange"; } - } + }; DocServer.GetRefField(node.attrs.docid).then(async dashDoc => { if (dashDoc instanceof Doc) { self._dashDoc = dashDoc; @@ -777,7 +777,7 @@ export class DashDocView { />, this._dashSpan); } }); - let self = this; + const self = this; this._dashSpan.onkeydown = function (e: any) { e.stopPropagation(); }; this._dashSpan.onkeypress = function (e: any) { e.stopPropagation(); }; this._dashSpan.onwheel = function (e: any) { e.preventDefault(); }; @@ -830,7 +830,7 @@ export class FootnoteView { } open() { // Append a tooltip to the outer node - let tooltip = this.dom.appendChild(document.createElement("div")); + const tooltip = this.dom.appendChild(document.createElement("div")); tooltip.className = "footnote-tooltip"; // And put a sub-ProseMirror into that this.innerView = new EditorView(tooltip, { @@ -885,14 +885,14 @@ export class FootnoteView { this.dom.textContent = ""; } dispatchInner(tr: any) { - let { state, transactions } = this.innerView.state.applyTransaction(tr); + const { state, transactions } = this.innerView.state.applyTransaction(tr); this.innerView.updateState(state); if (!tr.getMeta("fromOutside")) { - let outerTr = this.outerView.state.tr, offsetMap = StepMap.offset(this.getPos() + 1); - for (let transaction of transactions) { - let steps = transaction.steps; - for (let step of steps) { + const outerTr = this.outerView.state.tr, offsetMap = StepMap.offset(this.getPos() + 1); + for (const transaction of transactions) { + const steps = transaction.steps; + for (const step of steps) { outerTr.step(step.map(offsetMap)); } } @@ -903,11 +903,11 @@ export class FootnoteView { if (!node.sameMarkup(this.node)) return false; this.node = node; if (this.innerView) { - let state = this.innerView.state; - let start = node.content.findDiffStart(state.doc.content); + const state = this.innerView.state; + const start = node.content.findDiffStart(state.doc.content); if (start !== null) { let { a: endA, b: endB } = node.content.findDiffEnd(state.doc.content); - let overlap = start - Math.min(endA, endB); + const overlap = start - Math.min(endA, endB); if (overlap > 0) { endA += overlap; endB += overlap; } this.innerView.dispatch( state.tr @@ -967,10 +967,10 @@ export class SummarizedView { className = (visible: boolean) => "formattedTextBox-summarizer" + (visible ? "" : "-collapsed"); updateSummarizedText(start?: any) { - let mark = this._view.state.schema.marks.highlight.create(); + const mark = this._view.state.schema.marks.highlight.create(); let endPos = start; - let visited = new Set(); + const visited = new Set(); for (let i: number = start + 1; i < this._view.state.doc.nodeSize - 1; i++) { let skip = false; this._view.state.doc.nodesBetween(start, i, (node: Node, pos: number, parent: Node, index: number) => { @@ -999,7 +999,7 @@ export const schema = new Schema({ nodes, marks }); const fromJson = schema.nodeFromJSON; schema.nodeFromJSON = (json: any) => { - let node = fromJson(json); + const node = fromJson(json); if (json.type === "star") { node.attrs.text = Slice.fromJSON(schema, node.attrs.textslice); } diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index ff4451824..0fa96963e 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -94,16 +94,16 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an return { compiled: false, errors: diagnostics }; } - let paramNames = Object.keys(scriptingGlobals); - let params = paramNames.map(key => scriptingGlobals[key]); + const paramNames = Object.keys(scriptingGlobals); + const params = paramNames.map(key => scriptingGlobals[key]); // let fieldTypes = [Doc, ImageField, PdfField, VideoField, AudioField, List, RichTextField, ScriptField, ComputedField, CompileScript]; // let paramNames = ["Docs", ...fieldTypes.map(fn => fn.name)]; // let params: any[] = [Docs, ...fieldTypes]; - let compiledFunction = new Function(...paramNames, `return ${script}`); - let { capturedVariables = {} } = options; - let run = (args: { [name: string]: any } = {}, onError?: (e: any) => void, errorVal?: any): ScriptResult => { - let argsArray: any[] = []; - for (let name of customParams) { + const compiledFunction = new Function(...paramNames, `return ${script}`); + const { capturedVariables = {} } = options; + const run = (args: { [name: string]: any } = {}, onError?: (e: any) => void, errorVal?: any): ScriptResult => { + const argsArray: any[] = []; + for (const name of customParams) { if (name === "this") { continue; } @@ -113,7 +113,7 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an argsArray.push(capturedVariables[name]); } } - let thisParam = args.this || capturedVariables.this; + const thisParam = args.this || capturedVariables.this; let batch: { end(): void } | undefined = undefined; try { if (!options.editable) { @@ -146,7 +146,7 @@ class ScriptingCompilerHost { // getSourceFile(fileName: string, languageVersion: ts.ScriptTarget, onError?: ((message: string) => void) | undefined, shouldCreateNewSourceFile?: boolean | undefined): ts.SourceFile | undefined { getSourceFile(fileName: string, languageVersion: any, onError?: ((message: string) => void) | undefined, shouldCreateNewSourceFile?: boolean | undefined): any | undefined { - let contents = this.readFile(fileName); + const contents = this.readFile(fileName); if (contents !== undefined) { return ts.createSourceFile(fileName, contents, languageVersion, true); } @@ -180,7 +180,7 @@ class ScriptingCompilerHost { return this.files.some(file => file.fileName === fileName); } readFile(fileName: string): string | undefined { - let file = this.files.find(file => file.fileName === fileName); + const file = this.files.find(file => file.fileName === fileName); if (file) { return file.content; } @@ -218,7 +218,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp if (options.globals) { Scripting.setScriptingGlobals(options.globals); } - let host = new ScriptingCompilerHost; + const host = new ScriptingCompilerHost; if (options.traverser) { const sourceFile = ts.createSourceFile('script.ts', script, ts.ScriptTarget.ES2015, true); const onEnter = typeof options.traverser === "object" ? options.traverser.onEnter : options.traverser; @@ -240,7 +240,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp script = printer.printFile(transformed[0]); result.dispose(); } - let paramNames: string[] = []; + const paramNames: string[] = []; if ("this" in params || "this" in capturedVariables) { paramNames.push("this"); } @@ -248,7 +248,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp if (key === "this") continue; paramNames.push(key); } - let paramList = paramNames.map(key => { + const paramList = paramNames.map(key => { const val = params[key]; return `${key}: ${val}`; }); @@ -258,18 +258,18 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp paramNames.push(key); paramList.push(`${key}: ${typeof val === "object" ? Object.getPrototypeOf(val).constructor.name : typeof val}`); } - let paramString = paramList.join(", "); - let funcScript = `(function(${paramString})${requiredType ? `: ${requiredType}` : ''} { + const paramString = paramList.join(", "); + const funcScript = `(function(${paramString})${requiredType ? `: ${requiredType}` : ''} { ${addReturn ? `return ${script};` : script} })`; host.writeFile("file.ts", funcScript); if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib); - let program = ts.createProgram(["file.ts"], {}, host); - let testResult = program.emit(); - let outputText = host.readFile("file.js"); + const program = ts.createProgram(["file.ts"], {}, host); + const testResult = program.emit(); + const outputText = host.readFile("file.js"); - let diagnostics = ts.getPreEmitDiagnostics(program).concat(testResult.diagnostics); + const diagnostics = ts.getPreEmitDiagnostics(program).concat(testResult.diagnostics); const result = Run(outputText, paramNames, diagnostics, script, options); diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index 2cf13680a..7a9176bec 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -34,36 +34,36 @@ export namespace SearchUtil { export function Search(query: string, returnDocs: false, options?: SearchParams): Promise<IdSearchResult>; export async function Search(query: string, returnDocs: boolean, options: SearchParams = {}) { query = query || "*"; //If we just have a filter query, search for * as the query - let result: IdSearchResult = JSON.parse(await rp.get(Utils.prepend("/search"), { + const result: IdSearchResult = JSON.parse(await rp.get(Utils.prepend("/search"), { qs: { ...options, q: query }, })); if (!returnDocs) { return result; } - let { ids, numFound, highlighting } = result; + const { ids, highlighting } = result; - let txtresult = query !== "*" && JSON.parse(await rp.get(Utils.prepend("/textsearch"), { + const txtresult = query !== "*" && JSON.parse(await rp.get(Utils.prepend("/textsearch"), { qs: { ...options, q: query }, })); - let fileids = txtresult ? txtresult.ids : []; - let newIds: string[] = []; - let newLines: string[][] = []; + const fileids = txtresult ? txtresult.ids : []; + const newIds: string[] = []; + const newLines: string[][] = []; await Promise.all(fileids.map(async (tr: string, i: number) => { - let docQuery = "fileUpload_t:" + tr.substr(0, 7); //If we just have a filter query, search for * as the query - let docResult = JSON.parse(await rp.get(Utils.prepend("/search"), { qs: { ...options, q: docQuery } })); + const docQuery = "fileUpload_t:" + tr.substr(0, 7); //If we just have a filter query, search for * as the query + const docResult = JSON.parse(await rp.get(Utils.prepend("/search"), { qs: { ...options, q: docQuery } })); newIds.push(...docResult.ids); newLines.push(...docResult.ids.map((dr: any) => txtresult.lines[i])); })); - let theDocs: Doc[] = []; - let theLines: string[][] = []; + const theDocs: Doc[] = []; + const theLines: string[][] = []; const textDocMap = await DocServer.GetRefFields(newIds); const textDocs = newIds.map((id: string) => textDocMap[id]).map(doc => doc as Doc); for (let i = 0; i < textDocs.length; i++) { - let testDoc = textDocs[i]; + const testDoc = textDocs[i]; if (testDoc instanceof Doc && testDoc.type !== DocumentType.KVP && theDocs.findIndex(d => Doc.AreProtosEqual(d, testDoc)) === -1) { theDocs.push(Doc.GetProto(testDoc)); theLines.push(newLines[i].map(line => line.replace(query, query.toUpperCase()))); @@ -73,7 +73,7 @@ export namespace SearchUtil { const docMap = await DocServer.GetRefFields(ids); const docs = ids.map((id: string) => docMap[id]).map(doc => doc as Doc); for (let i = 0; i < ids.length; i++) { - let testDoc = docs[i]; + const testDoc = docs[i]; if (testDoc instanceof Doc && testDoc.type !== DocumentType.KVP && (options.allowAliases || theDocs.findIndex(d => Doc.AreProtosEqual(d, testDoc)) === -1)) { theDocs.push(testDoc); theLines.push([]); diff --git a/src/client/util/SerializationHelper.ts b/src/client/util/SerializationHelper.ts index ff048f647..1f6b939d3 100644 --- a/src/client/util/SerializationHelper.ts +++ b/src/client/util/SerializationHelper.ts @@ -1,7 +1,6 @@ -import { PropSchema, serialize, deserialize, custom, setDefaultModelSchema, getDefaultModelSchema, primitive, SKIP } from "serializr"; -import { Field, Doc } from "../../new_fields/Doc"; +import { PropSchema, serialize, deserialize, custom, setDefaultModelSchema, getDefaultModelSchema } from "serializr"; +import { Field } from "../../new_fields/Doc"; import { ClientUtils } from "./ClientUtils"; -import { emptyFunction } from "../../Utils"; let serializing = 0; export function afterDocDeserialize(cb: (err: any, val: any) => void, err: any, newValue: any) { @@ -65,8 +64,8 @@ export namespace SerializationHelper { } } -let serializationTypes: { [name: string]: { ctor: { new(): any }, afterDeserialize?: (obj: any) => void | Promise<any> } } = {}; -let reverseMap: { [ctor: string]: string } = {}; +const serializationTypes: { [name: string]: { ctor: { new(): any }, afterDeserialize?: (obj: any) => void | Promise<any> } } = {}; +const reverseMap: { [ctor: string]: string } = {}; export interface DeserializableOpts { (constructor: { new(...args: any[]): any }): void; diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index cc1d628b1..7496ac73c 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -9,7 +9,6 @@ import { Utils } from "../../Utils"; import "./SharingManager.scss"; import { Id } from "../../new_fields/FieldSymbols"; import { observer } from "mobx-react"; -import { MainView } from "../views/MainView"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { library } from '@fortawesome/fontawesome-svg-core'; import * as fa from '@fortawesome/free-solid-svg-icons'; @@ -103,10 +102,10 @@ export default class SharingManager extends React.Component<{}> { } populateUsers = async () => { - let userList = await RequestPromise.get(Utils.prepend("/getUsers")); + const userList = await RequestPromise.get(Utils.prepend("/getUsers")); const raw = JSON.parse(userList) as User[]; const evaluating = raw.map(async user => { - let isCandidate = user.email !== Doc.CurrentUserEmail; + const isCandidate = user.email !== Doc.CurrentUserEmail; if (isCandidate) { const userDocument = await DocServer.GetRefField(user.userDocumentId); if (userDocument instanceof Doc) { @@ -130,7 +129,7 @@ export default class SharingManager extends React.Component<{}> { if (state === SharingPermissions.None) { const metadata = (await DocCastAsync(manager[key])); if (metadata) { - let sharedAlias = (await DocCastAsync(metadata.sharedAlias))!; + const sharedAlias = (await DocCastAsync(metadata.sharedAlias))!; Doc.RemoveDocFromList(notificationDoc, storage, sharedAlias); manager[key] = undefined; } @@ -145,7 +144,7 @@ export default class SharingManager extends React.Component<{}> { } private setExternalSharing = (state: string) => { - let sharingDoc = this.sharingDoc; + const sharingDoc = this.sharingDoc; if (!sharingDoc) { return; } @@ -156,7 +155,7 @@ export default class SharingManager extends React.Component<{}> { if (!this.targetDoc) { return undefined; } - let baseUrl = Utils.prepend("/doc/" + this.targetDoc[Id]); + const baseUrl = Utils.prepend("/doc/" + this.targetDoc[Id]); return `${baseUrl}?sharing=true`; } @@ -178,7 +177,7 @@ export default class SharingManager extends React.Component<{}> { } private focusOn = (contents: string) => { - let title = this.targetDoc ? StrCast(this.targetDoc.title) : ""; + const title = this.targetDoc ? StrCast(this.targetDoc.title) : ""; return ( <span className={"focus-span"} diff --git a/src/client/util/TooltipLinkingMenu.tsx b/src/client/util/TooltipLinkingMenu.tsx index e6d6c471f..b46675a04 100644 --- a/src/client/util/TooltipLinkingMenu.tsx +++ b/src/client/util/TooltipLinkingMenu.tsx @@ -2,10 +2,6 @@ import { EditorState } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import { FieldViewProps } from "../views/nodes/FieldView"; import "./TooltipTextMenu.scss"; -import React = require("react"); -const { toggleMark, setBlockType, wrapIn } = require("prosemirror-commands"); - -const SVG = "http://www.w3.org/2000/svg"; //appears above a selection of text in a RichTextBox to give user options such as Bold, Italics, etc. export class TooltipLinkingMenu { @@ -23,9 +19,9 @@ export class TooltipLinkingMenu { //add the div which is the tooltip view.dom.parentNode!.parentNode!.appendChild(this.tooltip); - let target = "https://www.google.com"; + const target = "https://www.google.com"; - let link = document.createElement("a"); + const link = document.createElement("a"); link.href = target; link.textContent = target; link.target = "_blank"; @@ -37,7 +33,7 @@ export class TooltipLinkingMenu { //updates the tooltip menu when the selection changes update(view: EditorView, lastState: EditorState | undefined) { - let state = view.state; + const state = view.state; // Don't do anything if the document/selection didn't change if (lastState && lastState.doc.eq(state.doc) && lastState.selection.eq(state.selection)) return; @@ -53,16 +49,16 @@ export class TooltipLinkingMenu { // Otherwise, reposition it and update its content this.tooltip.style.display = ""; - let { from, to } = state.selection; - let start = view.coordsAtPos(from), end = view.coordsAtPos(to); + const { from, to } = state.selection; + const start = view.coordsAtPos(from), end = view.coordsAtPos(to); // The box in which the tooltip is positioned, to use as base - let box = this.tooltip.offsetParent!.getBoundingClientRect(); + const box = this.tooltip.offsetParent!.getBoundingClientRect(); // Find a center-ish x position from the selection endpoints (when // crossing lines, end may be more to the left) - let left = Math.max((start.left + end.left) / 2, start.left + 3); + const left = Math.max((start.left + end.left) / 2, start.left + 3); this.tooltip.style.left = (left - box.left) * this.editorProps.ScreenToLocalTransform().Scale + "px"; - let width = Math.abs(start.left - end.left) / 2 * this.editorProps.ScreenToLocalTransform().Scale; - let mid = Math.min(start.left, end.left) + width; + const width = Math.abs(start.left - end.left) / 2 * this.editorProps.ScreenToLocalTransform().Scale; + const mid = Math.min(start.left, end.left) + width; this.tooltip.style.width = "auto"; this.tooltip.style.bottom = (box.bottom - start.top) * this.editorProps.ScreenToLocalTransform().Scale + "px"; diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 5136089b3..5e777cef9 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -2,7 +2,7 @@ import { action } from "mobx"; import { Dropdown, icons, MenuItem } from "prosemirror-menu"; //no import css import { Mark, MarkType, Node as ProsNode, NodeType, ResolvedPos, Schema } from "prosemirror-model"; import { wrapInList } from 'prosemirror-schema-list'; -import { EditorState, NodeSelection, TextSelection, Transaction } from "prosemirror-state"; +import { EditorState, NodeSelection, TextSelection } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import { Doc, Field, Opt } from "../../new_fields/Doc"; import { Id } from "../../new_fields/FieldSymbols"; @@ -86,7 +86,7 @@ export class TooltipTextMenu { this.basicTools.className = "basic-tools"; // init buttons to the tooltip -- paths to svgs are obtained from fontawesome - let items = [ + const items = [ { command: toggleMark(schema.marks.strong), dom: this.svgIcon("strong", "Bold", "M333.49 238a122 122 0 0 0 27-65.21C367.87 96.49 308 32 233.42 32H34a16 16 0 0 0-16 16v48a16 16 0 0 0 16 16h31.87v288H34a16 16 0 0 0-16 16v48a16 16 0 0 0 16 16h209.32c70.8 0 134.14-51.75 141-122.4 4.74-48.45-16.39-92.06-50.83-119.6zM145.66 112h87.76a48 48 0 0 1 0 96h-87.76zm87.76 288h-87.76V288h87.76a56 56 0 0 1 0 112z") }, { command: toggleMark(schema.marks.em), dom: this.svgIcon("em", "Italic", "M320 48v32a16 16 0 0 1-16 16h-62.76l-80 320H208a16 16 0 0 1 16 16v32a16 16 0 0 1-16 16H16a16 16 0 0 1-16-16v-32a16 16 0 0 1 16-16h62.76l80-320H112a16 16 0 0 1-16-16V48a16 16 0 0 1 16-16h192a16 16 0 0 1 16 16z") }, { command: toggleMark(schema.marks.underline), dom: this.svgIcon("underline", "Underline", "M32 64h32v160c0 88.22 71.78 160 160 160s160-71.78 160-160V64h32a16 16 0 0 0 16-16V16a16 16 0 0 0-16-16H272a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h32v160a80 80 0 0 1-160 0V64h32a16 16 0 0 0 16-16V16a16 16 0 0 0-16-16H32a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16zm400 384H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z") }, @@ -145,7 +145,7 @@ export class TooltipTextMenu { // link menu this.updateLinkMenu(); - let dropdown = await this.createLinkDropdown(); + const dropdown = await this.createLinkDropdown(); this._linkDropdownDom = dropdown.render(this.view).dom; this.tooltip.appendChild(this._linkDropdownDom); @@ -209,17 +209,17 @@ export class TooltipTextMenu { // creates dragger element that allows dragging and collapsing (on double click) // of editor and appends it to the wrapper createDragger() { - let draggerWrapper = document.createElement("div"); + const draggerWrapper = document.createElement("div"); draggerWrapper.className = "dragger-wrapper"; - let dragger = document.createElement("div"); + const dragger = document.createElement("div"); dragger.className = "dragger"; - let line1 = document.createElement("span"); + const line1 = document.createElement("span"); line1.className = "dragger-line"; - let line2 = document.createElement("span"); + const line2 = document.createElement("span"); line2.className = "dragger-line"; - let line3 = document.createElement("span"); + const line3 = document.createElement("span"); line3.className = "dragger-line"; dragger.appendChild(line1); @@ -293,12 +293,12 @@ export class TooltipTextMenu { //label of dropdown will change to given label updateFontSizeDropdown(label: string) { //font SIZES - let fontSizeBtns: MenuItem[] = []; + const fontSizeBtns: MenuItem[] = []; this.fontSizes.forEach(mark => { fontSizeBtns.push(this.dropdownFontSizeBtn(String(mark.attrs.fontSize), "color: black; width: 50px;", mark, this.view, this.changeToFontSize)); }); - let newfontSizeDom = (new Dropdown(fontSizeBtns, { + const newfontSizeDom = (new Dropdown(fontSizeBtns, { label: label, css: "color:black; min-width: 60px;" }) as MenuItem).render(this.view).dom; @@ -312,12 +312,12 @@ export class TooltipTextMenu { //label of dropdown will change to given label updateFontStyleDropdown(label: string) { //font STYLES - let fontBtns: MenuItem[] = []; + const fontBtns: MenuItem[] = []; this.fontStyles.forEach((mark) => { fontBtns.push(this.dropdownFontFamilyBtn(mark.attrs.family, "color: black; font-family: " + mark.attrs.family + ", sans-serif; width: 125px;", mark, this.view, this.changeToFontFamily)); }); - let newfontStyleDom = (new Dropdown(fontBtns, { + const newfontStyleDom = (new Dropdown(fontBtns, { label: label, css: "color:black; width: 125px;" }) as MenuItem).render(this.view).dom; @@ -339,19 +339,19 @@ export class TooltipTextMenu { this.linkText.style.overflow = "hidden"; this.linkText.style.color = "white"; this.linkText.onpointerdown = (e: PointerEvent) => { e.stopPropagation(); }; - let linkBtn = document.createElement("div"); + const linkBtn = document.createElement("div"); linkBtn.textContent = ">>"; linkBtn.style.width = "10px"; linkBtn.style.height = "10px"; linkBtn.style.color = "white"; linkBtn.style.cssFloat = "left"; linkBtn.onpointerdown = (e: PointerEvent) => { - let node = this.view.state.selection.$from.nodeAfter; - let link = node && node.marks.find(m => m.type.name === "link"); + const node = this.view.state.selection.$from.nodeAfter; + const link = node && node.marks.find(m => m.type.name === "link"); if (link) { - let href: string = link.attrs.href; + const href: string = link.attrs.href; if (href.indexOf(Utils.prepend("/doc/")) === 0) { - let docid = href.replace(Utils.prepend("/doc/"), ""); + const docid = href.replace(Utils.prepend("/doc/"), ""); DocServer.GetRefField(docid).then(action((f: Opt<Field>) => { if (f instanceof Doc) { if (DocumentManager.Instance.getDocumentView(f)) { @@ -374,23 +374,23 @@ export class TooltipTextMenu { this.linkDrag.id = "link-drag"; this.linkDrag.onpointerdown = (e: PointerEvent) => { if (!this.editorProps) return; - let dragData = new DragManager.LinkDragData(this.editorProps.Document); + const dragData = new DragManager.LinkDragData(this.editorProps.Document); dragData.dontClearTextBox = true; // hack to get source context -sy - let docView = DocumentManager.Instance.getDocumentView(this.editorProps.Document); + const docView = DocumentManager.Instance.getDocumentView(this.editorProps.Document); e.stopPropagation(); - let ctrlKey = e.ctrlKey; + const ctrlKey = e.ctrlKey; DragManager.StartLinkDrag(this.linkDrag!, dragData, e.clientX, e.clientY, { handlers: { dragComplete: action(() => { if (dragData.linkDocument) { - let linkDoc = dragData.linkDocument; - let proto = Doc.GetProto(linkDoc); + const linkDoc = dragData.linkDocument; + const proto = Doc.GetProto(linkDoc); if (proto && docView) { proto.sourceContext = docView.props.ContainingCollectionDoc; } - let text = this.makeLink(linkDoc, StrCast(linkDoc.anchor2.title), ctrlKey ? "onRight" : "inTab"); + const text = this.makeLink(linkDoc, StrCast(linkDoc.anchor2.title), ctrlKey ? "onRight" : "inTab"); if (linkDoc instanceof Doc && linkDoc.anchor2 instanceof Doc) { proto.title = text === "" ? proto.title : text + " to " + linkDoc.anchor2.title; // TODODO open to more descriptive descriptions of following in text link } @@ -406,8 +406,8 @@ export class TooltipTextMenu { this.tooltip.appendChild(this.linkEditor); } - let node = this.view.state.selection.$from.nodeAfter; - let link = node && node.marks.find(m => m.type.name === "link"); + const node = this.view.state.selection.$from.nodeAfter; + const link = node && node.marks.find(m => m.type.name === "link"); this.linkText.textContent = link ? link.attrs.href : "-empty-"; this.linkText.onkeydown = (e: KeyboardEvent) => { @@ -420,19 +420,19 @@ export class TooltipTextMenu { } async getTextLinkTargetTitle() { - let node = this.view.state.selection.$from.nodeAfter; - let link = node && node.marks.find(m => m.type.name === "link"); + const node = this.view.state.selection.$from.nodeAfter; + const link = node && node.marks.find(m => m.type.name === "link"); if (link) { - let href = link.attrs.href; + const href = link.attrs.href; if (href) { if (href.indexOf(Utils.prepend("/doc/")) === 0) { const linkclicked = href.replace(Utils.prepend("/doc/"), "").split("?")[0]; if (linkclicked) { - let linkDoc = await DocServer.GetRefField(linkclicked); + const linkDoc = await DocServer.GetRefField(linkclicked); if (linkDoc instanceof Doc) { - let anchor1 = await Cast(linkDoc.anchor1, Doc); - let anchor2 = await Cast(linkDoc.anchor2, Doc); - let currentDoc = SelectionManager.SelectedDocuments().length && SelectionManager.SelectedDocuments()[0].props.Document; + const anchor1 = await Cast(linkDoc.anchor1, Doc); + const anchor2 = await Cast(linkDoc.anchor2, Doc); + const currentDoc = SelectionManager.SelectedDocuments().length && SelectionManager.SelectedDocuments()[0].props.Document; if (currentDoc && anchor1 && anchor2) { if (Doc.AreProtosEqual(currentDoc, anchor1)) { return StrCast(anchor2.title); @@ -453,18 +453,18 @@ export class TooltipTextMenu { } async createLinkDropdown() { - let targetTitle = await this.getTextLinkTargetTitle(); - let input = document.createElement("input"); + const targetTitle = await this.getTextLinkTargetTitle(); + const input = document.createElement("input"); // menu item for input for hyperlink url // TODO: integrate search to allow users to search for a doc to link to - let linkInfo = new MenuItem({ + const linkInfo = new MenuItem({ title: "", execEvent: "", class: "button-setting-disabled", css: "", render() { - let p = document.createElement("p"); + const p = document.createElement("p"); p.textContent = "Linked to:"; input.type = "text"; @@ -475,7 +475,7 @@ export class TooltipTextMenu { input.focus(); }; - let div = document.createElement("div"); + const div = document.createElement("div"); div.appendChild(p); div.appendChild(input); return div; @@ -487,13 +487,13 @@ export class TooltipTextMenu { }); // menu item to update/apply the hyperlink to the selected text - let linkApply = new MenuItem({ + const linkApply = new MenuItem({ title: "", execEvent: "", class: "", css: "", render() { - let button = document.createElement("button"); + const button = document.createElement("button"); button.className = "link-url-button"; button.textContent = "Apply hyperlink"; return button; @@ -507,17 +507,17 @@ export class TooltipTextMenu { // menu item to remove the link // TODO: allow this to be undoable - let self = this; - let deleteLink = new MenuItem({ + const self = this; + const deleteLink = new MenuItem({ title: "Delete link", execEvent: "", class: "separated-button", css: "", render() { - let button = document.createElement("button"); + const button = document.createElement("button"); button.textContent = "Remove link"; - let wrapper = document.createElement("div"); + const wrapper = document.createElement("div"); wrapper.appendChild(button); return wrapper; }, @@ -525,15 +525,15 @@ export class TooltipTextMenu { async run() { self.deleteLink(); // update link dropdown - let dropdown = await self.createLinkDropdown(); - let newLinkDropdowndom = dropdown.render(self.view).dom; + const dropdown = await self.createLinkDropdown(); + const newLinkDropdowndom = dropdown.render(self.view).dom; self._linkDropdownDom && self.tooltip.replaceChild(newLinkDropdowndom, self._linkDropdownDom); self._linkDropdownDom = newLinkDropdowndom; } }); - let linkDropdown = new Dropdown(targetTitle ? [linkInfo, linkApply, deleteLink] : [linkInfo, linkApply], { class: "buttonSettings-dropdown" }) as MenuItem; + const linkDropdown = new Dropdown(targetTitle ? [linkInfo, linkApply, deleteLink] : [linkInfo, linkApply], { class: "buttonSettings-dropdown" }) as MenuItem; return linkDropdown; } @@ -542,10 +542,10 @@ export class TooltipTextMenu { // } makeLink = (targetDoc: Doc, title: string, location: string): string => { - let link = this.view.state.schema.marks.link.create({ href: Utils.prepend("/doc/" + targetDoc[Id]), title: title, location: location }); + const link = this.view.state.schema.marks.link.create({ href: Utils.prepend("/doc/" + targetDoc[Id]), title: title, location: location }); this.view.dispatch(this.view.state.tr.removeMark(this.view.state.selection.from, this.view.state.selection.to, this.view.state.schema.marks.link). addMark(this.view.state.selection.from, this.view.state.selection.to, link)); - let node = this.view.state.selection.$from.nodeAfter; + const node = this.view.state.selection.$from.nodeAfter; if (node && node.text) { return node.text; } @@ -562,9 +562,9 @@ export class TooltipTextMenu { } deleteLink = () => { - let node = this.view.state.selection.$from.nodeAfter; - let link = node && node.marks.find(m => m.type === this.view.state.schema.marks.link); - let href = link!.attrs.href; + const node = this.view.state.selection.$from.nodeAfter; + const link = node && node.marks.find(m => m.type === this.view.state.schema.marks.link); + const href = link!.attrs.href; if (href) { if (href.indexOf(Utils.prepend("/doc/")) === 0) { const linkclicked = href.replace(Utils.prepend("/doc/"), "").split("?")[0]; @@ -599,7 +599,7 @@ export class TooltipTextMenu { } createLink() { - let markType = schema.marks.link; + const markType = schema.marks.link; return new MenuItem({ title: "Add or remove link", label: "Add or remove link", @@ -613,8 +613,8 @@ export class TooltipTextMenu { let curLink = ""; if (this.markActive(state, markType)) { - let { from, $from, to, empty } = state.selection; - let node = state.doc.nodeAt(from); + const { from, $from, to, empty } = state.selection; + const node = state.doc.nodeAt(from); node && node.marks.map(m => { m.type === markType && (curLink = m.attrs.href); }); @@ -649,7 +649,7 @@ export class TooltipTextMenu { if (listTypeBtn) { this.tooltip.removeChild(listTypeBtn); } //Make a dropdown of all list types - let toAdd: MenuItem[] = []; + const toAdd: MenuItem[] = []; this.listTypeToIcon.forEach((icon, type) => { toAdd.push(this.dropdownNodeBtn(icon, "color: black; width: 40px;", type, this.view, this.listTypes, this.changeToNodeType)); }); @@ -683,22 +683,22 @@ export class TooltipTextMenu { public static insertStar(state: EditorState<any>, dispatch: any) { if (state.selection.empty) return false; - let mark = state.schema.marks.highlight.create(); - let tr = state.tr; + const mark = state.schema.marks.highlight.create(); + const tr = state.tr; tr.addMark(state.selection.from, state.selection.to, mark); - let content = tr.selection.content(); - let newNode = state.schema.nodes.star.create({ visibility: false, text: content, textslice: content.toJSON() }); + const content = tr.selection.content(); + const newNode = state.schema.nodes.star.create({ visibility: false, text: content, textslice: content.toJSON() }); dispatch && dispatch(tr.replaceSelectionWith(newNode).removeMark(tr.selection.from - 1, tr.selection.from, mark)); return true; } public static insertComment(state: EditorState<any>, dispatch: any) { if (state.selection.empty) return false; - let mark = state.schema.marks.highlight.create(); - let tr = state.tr; + const mark = state.schema.marks.highlight.create(); + const tr = state.tr; tr.addMark(state.selection.from, state.selection.to, mark); - let content = tr.selection.content(); - let newNode = state.schema.nodes.star.create({ visibility: false, text: content, textslice: content.toJSON() }); + const content = tr.selection.content(); + const newNode = state.schema.nodes.star.create({ visibility: false, text: content, textslice: content.toJSON() }); dispatch && dispatch(tr.replaceSelectionWith(newNode).removeMark(tr.selection.from - 1, tr.selection.from, mark)); return true; } @@ -710,17 +710,17 @@ export class TooltipTextMenu { class: "menuicon", execEvent: "", render() { - let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute("viewBox", "-100 -100 650 650"); - let path = document.createElementNS('http://www.w3.org/2000/svg', "path"); + const path = document.createElementNS('http://www.w3.org/2000/svg', "path"); path.setAttributeNS(null, "d", "M0 479.98L99.92 512l35.45-35.45-67.04-67.04L0 479.98zm124.61-240.01a36.592 36.592 0 0 0-10.79 38.1l13.05 42.83-50.93 50.94 96.23 96.23 50.86-50.86 42.74 13.08c13.73 4.2 28.65-.01 38.15-10.78l35.55-41.64-173.34-173.34-41.52 35.44zm403.31-160.7l-63.2-63.2c-20.49-20.49-53.38-21.52-75.12-2.35L190.55 183.68l169.77 169.78L530.27 154.4c19.18-21.74 18.15-54.63-2.35-75.13z"); svg.appendChild(path); - let color = document.createElement("div"); + const color = document.createElement("div"); color.className = "buttonColor"; color.style.backgroundColor = TooltipTextMenuManager.Instance.highlight.toString(); - let wrapper = document.createElement("div"); + const wrapper = document.createElement("div"); wrapper.id = "colorPicker"; wrapper.appendChild(svg); wrapper.appendChild(color); @@ -735,26 +735,26 @@ export class TooltipTextMenu { public static insertHighlight(color: String, state: EditorState<any>, dispatch: any) { if (state.selection.empty) return false; - let highlightMark = state.schema.mark(state.schema.marks.marker, { highlight: color }); + const highlightMark = state.schema.mark(state.schema.marks.marker, { highlight: color }); dispatch(state.tr.addMark(state.selection.from, state.selection.to, highlightMark)); } createHighlightDropdown() { // menu item for color picker - let self = this; - let colors = new MenuItem({ + const self = this; + const colors = new MenuItem({ title: "", execEvent: "", class: "button-setting-disabled", css: "", render() { - let p = document.createElement("p"); + const p = document.createElement("p"); p.textContent = "Change highlight:"; - let colorsWrapper = document.createElement("div"); + const colorsWrapper = document.createElement("div"); colorsWrapper.className = "colorPicker-wrapper"; - let colors = [ + const colors = [ PastelSchemaPalette.get("pink2"), PastelSchemaPalette.get("purple4"), PastelSchemaPalette.get("bluegreen1"), @@ -768,7 +768,7 @@ export class TooltipTextMenu { ]; colors.forEach(color => { - let button = document.createElement("button"); + const button = document.createElement("button"); button.className = color === TooltipTextMenuManager.Instance.highlight ? "colorPicker active" : "colorPicker"; if (color) { button.style.backgroundColor = color; @@ -779,8 +779,8 @@ export class TooltipTextMenu { TooltipTextMenu.insertHighlight(TooltipTextMenuManager.Instance.highlight, self.view.state, self.view.dispatch); // update color menu - let highlightDom = self.createHighlightTool().render(self.view).dom; - let highlightDropdownDom = self.createHighlightDropdown().render(self.view).dom; + const highlightDom = self.createHighlightTool().render(self.view).dom; + const highlightDropdownDom = self.createHighlightDropdown().render(self.view).dom; self.highlightDom && self.tooltip.replaceChild(highlightDom, self.highlightDom); self.highlightDropdownDom && self.tooltip.replaceChild(highlightDropdownDom, self.highlightDropdownDom); self.highlightDom = highlightDom; @@ -790,7 +790,7 @@ export class TooltipTextMenu { colorsWrapper.appendChild(button); }); - let div = document.createElement("div"); + const div = document.createElement("div"); div.appendChild(p); div.appendChild(colorsWrapper); return div; @@ -801,7 +801,7 @@ export class TooltipTextMenu { } }); - let colorDropdown = new Dropdown([colors], { class: "buttonSettings-dropdown" }) as MenuItem; + const colorDropdown = new Dropdown([colors], { class: "buttonSettings-dropdown" }) as MenuItem; return colorDropdown; } @@ -812,17 +812,17 @@ export class TooltipTextMenu { class: "menuicon", execEvent: "", render() { - let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute("viewBox", "-100 -100 650 650"); - let path = document.createElementNS('http://www.w3.org/2000/svg', "path"); + const path = document.createElementNS('http://www.w3.org/2000/svg', "path"); path.setAttributeNS(null, "d", "M204.3 5C104.9 24.4 24.8 104.3 5.2 203.4c-37 187 131.7 326.4 258.8 306.7 41.2-6.4 61.4-54.6 42.5-91.7-23.1-45.4 9.9-98.4 60.9-98.4h79.7c35.8 0 64.8-29.6 64.9-65.3C511.5 97.1 368.1-26.9 204.3 5zM96 320c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm32-128c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm128-64c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm128 64c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32z"); svg.appendChild(path); - let color = document.createElement("div"); + const color = document.createElement("div"); color.className = "buttonColor"; color.style.backgroundColor = TooltipTextMenuManager.Instance.color.toString(); - let wrapper = document.createElement("div"); + const wrapper = document.createElement("div"); wrapper.id = "colorPicker"; wrapper.appendChild(svg); wrapper.appendChild(color); @@ -837,26 +837,26 @@ export class TooltipTextMenu { public static insertColor(color: String, state: EditorState<any>, dispatch: any) { if (state.selection.empty) return false; - let colorMark = state.schema.mark(state.schema.marks.color, { color: color }); + const colorMark = state.schema.mark(state.schema.marks.color, { color: color }); dispatch(state.tr.addMark(state.selection.from, state.selection.to, colorMark)); } createColorDropdown() { // menu item for color picker - let self = this; - let colors = new MenuItem({ + const self = this; + const colors = new MenuItem({ title: "", execEvent: "", class: "button-setting-disabled", css: "", render() { - let p = document.createElement("p"); + const p = document.createElement("p"); p.textContent = "Change color:"; - let colorsWrapper = document.createElement("div"); + const colorsWrapper = document.createElement("div"); colorsWrapper.className = "colorPicker-wrapper"; - let colors = [ + const colors = [ DarkPastelSchemaPalette.get("pink2"), DarkPastelSchemaPalette.get("purple4"), DarkPastelSchemaPalette.get("bluegreen1"), @@ -870,7 +870,7 @@ export class TooltipTextMenu { ]; colors.forEach(color => { - let button = document.createElement("button"); + const button = document.createElement("button"); button.className = color === TooltipTextMenuManager.Instance.color ? "colorPicker active" : "colorPicker"; if (color) { button.style.backgroundColor = color; @@ -880,8 +880,8 @@ export class TooltipTextMenu { TooltipTextMenu.insertColor(TooltipTextMenuManager.Instance.color, self.view.state, self.view.dispatch); // update color menu - let colorDom = self.createColorTool().render(self.view).dom; - let colorDropdownDom = self.createColorDropdown().render(self.view).dom; + const colorDom = self.createColorTool().render(self.view).dom; + const colorDropdownDom = self.createColorDropdown().render(self.view).dom; self.colorDom && self.tooltip.replaceChild(colorDom, self.colorDom); self.colorDropdownDom && self.tooltip.replaceChild(colorDropdownDom, self.colorDropdownDom); self.colorDom = colorDom; @@ -891,7 +891,7 @@ export class TooltipTextMenu { colorsWrapper.appendChild(button); }); - let div = document.createElement("div"); + const div = document.createElement("div"); div.appendChild(p); div.appendChild(colorsWrapper); return div; @@ -902,7 +902,7 @@ export class TooltipTextMenu { } }); - let colorDropdown = new Dropdown([colors], { class: "buttonSettings-dropdown" }) as MenuItem; + const colorDropdown = new Dropdown([colors], { class: "buttonSettings-dropdown" }) as MenuItem; return colorDropdown; } @@ -911,7 +911,7 @@ export class TooltipTextMenu { height: 32, width: 32, path: "M30.828 1.172c-1.562-1.562-4.095-1.562-5.657 0l-5.379 5.379-3.793-3.793-4.243 4.243 3.326 3.326-14.754 14.754c-0.252 0.252-0.358 0.592-0.322 0.921h-0.008v5c0 0.552 0.448 1 1 1h5c0 0 0.083 0 0.125 0 0.288 0 0.576-0.11 0.795-0.329l14.754-14.754 3.326 3.326 4.243-4.243-3.793-3.793 5.379-5.379c1.562-1.562 1.562-4.095 0-5.657zM5.409 30h-3.409v-3.409l14.674-14.674 3.409 3.409-14.674 14.674z" }; - let self = this; + const self = this; return new MenuItem({ title: "Brush tool", label: "Brush tool", @@ -923,7 +923,7 @@ export class TooltipTextMenu { this.brush_function(state, dispatch); // update dropdown with marks - let newBrushDropdowndom = self.createBrushDropdown().render(self.view).dom; + const newBrushDropdowndom = self.createBrushDropdown().render(self.view).dom; self._brushDropdownDom && self.tooltip.replaceChild(newBrushDropdowndom, self._brushDropdownDom); self._brushDropdownDom = newBrushDropdowndom; }, @@ -947,7 +947,7 @@ export class TooltipTextMenu { } } else { - let { from, to, $from } = this.view.state.selection; + const { from, to, $from } = this.view.state.selection; if (this._brushdom) { if (!this.view.state.selection.empty && $from && $from.nodeAfter) { if (TooltipTextMenuManager.Instance._brushMarks && to - from > 0) { @@ -982,7 +982,7 @@ export class TooltipTextMenu { } - let brushInfo = new MenuItem({ + const brushInfo = new MenuItem({ title: "", label: label, execEvent: "", @@ -994,17 +994,17 @@ export class TooltipTextMenu { } }); - let self = this; - let clearBrush = new MenuItem({ + const self = this; + const clearBrush = new MenuItem({ title: "Clear brush", execEvent: "", class: "separated-button", css: "", render() { - let button = document.createElement("button"); + const button = document.createElement("button"); button.textContent = "Clear brush"; - let wrapper = document.createElement("div"); + const wrapper = document.createElement("div"); wrapper.appendChild(button); return wrapper; }, @@ -1015,24 +1015,24 @@ export class TooltipTextMenu { // update brush tool // TODO: this probably isn't very clean - let newBrushdom = self.createBrush().render(self.view).dom; + const newBrushdom = self.createBrush().render(self.view).dom; self._brushdom && self.tooltip.replaceChild(newBrushdom, self._brushdom); self._brushdom = newBrushdom; - let newBrushDropdowndom = self.createBrushDropdown().render(self.view).dom; + const newBrushDropdowndom = self.createBrushDropdown().render(self.view).dom; self._brushDropdownDom && self.tooltip.replaceChild(newBrushDropdowndom, self._brushDropdownDom); self._brushDropdownDom = newBrushDropdowndom; } }); - let hasMarks = TooltipTextMenuManager.Instance._brushMarks && TooltipTextMenuManager.Instance._brushMarks.size > 0; - let brushDom = new Dropdown(hasMarks ? [brushInfo, clearBrush] : [brushInfo], { class: "buttonSettings-dropdown" }) as MenuItem; + const hasMarks = TooltipTextMenuManager.Instance._brushMarks && TooltipTextMenuManager.Instance._brushMarks.size > 0; + const brushDom = new Dropdown(hasMarks ? [brushInfo, clearBrush] : [brushInfo], { class: "buttonSettings-dropdown" }) as MenuItem; return brushDom; } //for a specific grouping of marks (passed in), remove all and apply the passed-in one to the selected textchangeToMarkInGroup = (markType: MarkType | undefined, view: EditorView, fontMarks: MarkType[]) => { changeToMarkInGroup = (markType: MarkType | undefined, view: EditorView, fontMarks: MarkType[]) => { - let { $cursor, ranges } = view.state.selection as TextSelection; - let state = view.state; - let dispatch = view.dispatch; + const { $cursor, ranges } = view.state.selection as TextSelection; + const state = view.state; + const dispatch = view.dispatch; //remove all other active font marks fontMarks.forEach((type) => { @@ -1044,10 +1044,10 @@ export class TooltipTextMenu { } else { let has = false; for (let i = 0; !has && i < ranges.length; i++) { - let { $from, $to } = ranges[i]; + const { $from, $to } = ranges[i]; has = state.doc.rangeHasMark($from.pos, $to.pos, type); } - for (let i of ranges) { + for (const i of ranges) { if (has) { toggleMark(type)(view.state, view.dispatch, view); } @@ -1059,7 +1059,7 @@ export class TooltipTextMenu { if (markType) { //actually apply font if ((view.state.selection as any).node && (view.state.selection as any).node.type === view.state.schema.nodes.ordered_list) { - let status = updateBullets(view.state.tr.setNodeMarkup(view.state.selection.from, (view.state.selection as any).node.type, + const status = updateBullets(view.state.tr.setNodeMarkup(view.state.selection.from, (view.state.selection as any).node.type, { ...(view.state.selection as NodeSelection).node.attrs, setFontFamily: markType.name, setFontSize: Number(markType.name.replace(/p/, "")) }), view.state.schema); view.dispatch(status.setSelection(new NodeSelection(status.doc.resolve(view.state.selection.from)))); } @@ -1068,9 +1068,9 @@ export class TooltipTextMenu { } changeToFontFamily = (mark: Mark, view: EditorView) => { - let { $cursor, ranges } = view.state.selection as TextSelection; - let state = view.state; - let dispatch = view.dispatch; + const { $cursor, ranges } = view.state.selection as TextSelection; + const state = view.state; + const dispatch = view.dispatch; //remove all other active font marks if ($cursor) { @@ -1080,28 +1080,28 @@ export class TooltipTextMenu { } else { let has = false; for (let i = 0; !has && i < ranges.length; i++) { - let { $from, $to } = ranges[i]; + const { $from, $to } = ranges[i]; has = state.doc.rangeHasMark($from.pos, $to.pos, view.state.schema.marks.pFontFamily); } - for (let i of ranges) { + for (const i of ranges) { if (has) { toggleMark(view.state.schema.marks.pFontFamily)(view.state, view.dispatch, view); } } } - let fontName = mark.attrs.family; + const fontName = mark.attrs.family; if (fontName) { this.updateFontStyleDropdown(fontName); } if (this.editorProps) { - let ruleProvider = this.editorProps.ruleProvider; - let heading = NumCast(this.editorProps.Document.heading); + const ruleProvider = this.editorProps.ruleProvider; + const heading = NumCast(this.editorProps.Document.heading); if (ruleProvider && heading) { ruleProvider["ruleFont_" + heading] = fontName; } } //actually apply font if ((view.state.selection as any).node && (view.state.selection as any).node.type === view.state.schema.nodes.ordered_list) { - let status = updateBullets(view.state.tr.setNodeMarkup(view.state.selection.from, (view.state.selection as any).node.type, + const status = updateBullets(view.state.tr.setNodeMarkup(view.state.selection.from, (view.state.selection as any).node.type, { ...(view.state.selection as NodeSelection).node.attrs, setFontFamily: fontName }), view.state.schema); view.dispatch(status.setSelection(new NodeSelection(status.doc.resolve(view.state.selection.from)))); } @@ -1110,9 +1110,9 @@ export class TooltipTextMenu { } changeToFontSize = (mark: Mark, view: EditorView) => { - let { $cursor, ranges } = view.state.selection as TextSelection; - let state = view.state; - let dispatch = view.dispatch; + const { $cursor, ranges } = view.state.selection as TextSelection; + const state = view.state; + const dispatch = view.dispatch; //remove all other active font marks if ($cursor) { @@ -1122,28 +1122,28 @@ export class TooltipTextMenu { } else { let has = false; for (let i = 0; !has && i < ranges.length; i++) { - let { $from, $to } = ranges[i]; + const { $from, $to } = ranges[i]; has = state.doc.rangeHasMark($from.pos, $to.pos, view.state.schema.marks.pFontSize); } - for (let i of ranges) { + for (const i of ranges) { if (has) { toggleMark(view.state.schema.marks.pFontSize)(view.state, view.dispatch, view); } } } - let size = mark.attrs.fontSize; + const size = mark.attrs.fontSize; if (size) { this.updateFontSizeDropdown(String(size) + " pt"); } if (this.editorProps) { - let ruleProvider = this.editorProps.ruleProvider; - let heading = NumCast(this.editorProps.Document.heading); + const ruleProvider = this.editorProps.ruleProvider; + const heading = NumCast(this.editorProps.Document.heading); if (ruleProvider && heading) { ruleProvider["ruleSize_" + heading] = size; } } //actually apply font if ((view.state.selection as any).node && (view.state.selection as any).node.type === view.state.schema.nodes.ordered_list) { - let status = updateBullets(view.state.tr.setNodeMarkup(view.state.selection.from, (view.state.selection as any).node.type, + const status = updateBullets(view.state.tr.setNodeMarkup(view.state.selection.from, (view.state.selection as any).node.type, { ...(view.state.selection as NodeSelection).node.attrs, setFontSize: size }), view.state.schema); view.dispatch(status.setSelection(new NodeSelection(status.doc.resolve(view.state.selection.from)))); } @@ -1154,20 +1154,20 @@ export class TooltipTextMenu { //remove all node typeand apply the passed-in one to the selected text changeToNodeType = (nodeType: NodeType | undefined) => { //remove oldif (nodeType) { //add new - let view = this.view; + const view = this.view; if (nodeType === schema.nodes.bullet_list) { wrapInList(nodeType)(view.state, view.dispatch); } else { - var marks = view.state.storedMarks || (view.state.selection.$to.parentOffset && view.state.selection.$from.marks()); + const marks = view.state.storedMarks || (view.state.selection.$to.parentOffset && view.state.selection.$from.marks()); if (!wrapInList(schema.nodes.ordered_list)(view.state, (tx2: any) => { - let tx3 = updateBullets(tx2, schema, nodeType && (nodeType as any).attrs.mapStyle); + const tx3 = updateBullets(tx2, schema, nodeType && (nodeType as any).attrs.mapStyle); marks && tx3.ensureMarks([...marks]); marks && tx3.setStoredMarks([...marks]); view.dispatch(tx2); })) { - let tx2 = view.state.tr; - let tx3 = updateBullets(tx2, schema, nodeType && (nodeType as any).attrs.mapStyle); + const tx2 = view.state.tr; + const tx3 = updateBullets(tx2, schema, nodeType && (nodeType as any).attrs.mapStyle); marks && tx3.ensureMarks([...marks]); marks && tx3.setStoredMarks([...marks]); @@ -1223,15 +1223,15 @@ export class TooltipTextMenu { }); } - markActive = function(state: EditorState<any>, type: MarkType<Schema<string, string>>) { - let { from, $from, to, empty } = state.selection; + markActive = function (state: EditorState<any>, type: MarkType<Schema<string, string>>) { + const { from, $from, to, empty } = state.selection; if (empty) return type.isInSet(state.storedMarks || $from.marks()); else return state.doc.rangeHasMark(from, to, type); }; // Helper function to create menu icons icon(text: string, name: string, title: string = name) { - let span = document.createElement("span"); + const span = document.createElement("span"); span.className = name + " menuicon"; span.title = title; span.textContent = text; @@ -1240,13 +1240,13 @@ export class TooltipTextMenu { } svgIcon(name: string, title: string = name, dpath: string) { - let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute("viewBox", "-100 -100 650 650"); - let path = document.createElementNS('http://www.w3.org/2000/svg', "path"); + const path = document.createElementNS('http://www.w3.org/2000/svg', "path"); path.setAttributeNS(null, "d", dpath); svg.appendChild(path); - let span = document.createElement("span"); + const span = document.createElement("span"); span.className = name + " menuicon"; span.title = title; span.appendChild(svg); @@ -1256,9 +1256,9 @@ export class TooltipTextMenu { //method for checking whether node can be inserted canInsert(state: EditorState, nodeType: NodeType<Schema<string, string>>) { - let $from = state.selection.$from; + const $from = state.selection.$from; for (let d = $from.depth; d >= 0; d--) { - let index = $from.index(d); + const index = $from.index(d); if ($from.node(d).canReplaceWith(index, index, nodeType)) return true; } return false; @@ -1267,13 +1267,13 @@ export class TooltipTextMenu { //adapted this method - use it to check if block has a tag (ie bulleting) blockActive(type: NodeType<Schema<string, string>>, state: EditorState) { - let attrs = {}; + const attrs = {}; if (state.selection instanceof NodeSelection) { const sel: NodeSelection = state.selection; - let $from = sel.$from; - let to = sel.to; - let node = sel.node; + const $from = sel.$from; + const to = sel.to; + const node = sel.node; if (node) { return node.hasMarkup(type, attrs); @@ -1292,10 +1292,10 @@ export class TooltipTextMenu { } getMarksInSelection(state: EditorState<any>) { - let found = new Set<Mark>(); - let { from, to } = state.selection as TextSelection; + const found = new Set<Mark>(); + const { from, to } = state.selection as TextSelection; state.doc.nodesBetween(from, to, (node) => { - let marks = node.marks; + const marks = node.marks; if (marks) { marks.forEach(m => { found.add(m); @@ -1306,7 +1306,7 @@ export class TooltipTextMenu { } reset_mark_doms() { - let iterator = this._marksToDoms.values(); + const iterator = this._marksToDoms.values(); let next = iterator.next(); while (!next.done) { next.value.style.color = "white"; @@ -1322,7 +1322,7 @@ export class TooltipTextMenu { return; } this.view = view; - let state = view.state; + const state = view.state; DocumentDecorations.Instance.showTextBar(); props && (this.editorProps = props); // Don't do anything if the document/selection didn't change @@ -1338,13 +1338,13 @@ export class TooltipTextMenu { } // update link dropdown - let linkDropdown = await this.createLinkDropdown(); - let newLinkDropdowndom = linkDropdown.render(this.view).dom; + const linkDropdown = await this.createLinkDropdown(); + const newLinkDropdowndom = linkDropdown.render(this.view).dom; this._linkDropdownDom && this.tooltip.replaceChild(newLinkDropdowndom, this._linkDropdownDom); this._linkDropdownDom = newLinkDropdowndom; //UPDATE FONT STYLE DROPDOWN - let activeStyles = this.activeFontFamilyOnSelection(); + const activeStyles = this.activeFontFamilyOnSelection(); if (activeStyles !== undefined) { if (activeStyles.length === 1) { console.log("updating font style dropdown", activeStyles[0]); @@ -1353,7 +1353,7 @@ export class TooltipTextMenu { } //UPDATE FONT SIZE DROPDOWN - let activeSizes = this.activeFontSizeOnSelection(); + const activeSizes = this.activeFontSizeOnSelection(); if (activeSizes !== undefined) { if (activeSizes.length === 1) { //if there's only one active font size activeSizes[0] && this.updateFontSizeDropdown(String(activeSizes[0]) + " pt"); @@ -1366,7 +1366,7 @@ export class TooltipTextMenu { this.reset_mark_doms(); this._activeMarks.forEach((mark) => { if (this._marksToDoms.has(mark)) { - let dom = this._marksToDoms.get(mark); + const dom = this._marksToDoms.get(mark); if (dom) dom.style.color = "greenyellow"; } }); @@ -1385,8 +1385,8 @@ export class TooltipTextMenu { //finds fontSize at start of selection activeFontSizeOnSelection() { //current selection - let state = this.view.state; - let activeSizes: number[] = []; + const state = this.view.state; + const activeSizes: number[] = []; const pos = this.view.state.selection.$from; const ref_node: ProsNode = this.reference_node(pos); if (ref_node && ref_node !== this.view.state.doc && ref_node.isText) { @@ -1397,8 +1397,8 @@ export class TooltipTextMenu { //finds fontSize at start of selection activeFontFamilyOnSelection() { //current selection - let state = this.view.state; - let activeFamilies: string[] = []; + const state = this.view.state; + const activeFamilies: string[] = []; const pos = this.view.state.selection.$from; const ref_node: ProsNode = this.reference_node(pos); if (ref_node && ref_node !== this.view.state.doc && ref_node.isText) { @@ -1409,15 +1409,15 @@ export class TooltipTextMenu { //finds all active marks on selection in given group activeMarksOnSelection(markGroup: MarkType[]) { //current selection - let { empty, ranges, $to } = this.view.state.selection as TextSelection; - let state = this.view.state; - let dispatch = this.view.dispatch; + const { empty, ranges, $to } = this.view.state.selection as TextSelection; + const state = this.view.state; + const dispatch = this.view.dispatch; let activeMarks: MarkType[]; if (!empty) { activeMarks = markGroup.filter(mark => { - let has = false; + const has = false; for (let i = 0; !has && i < ranges.length; i++) { - let { $from, $to } = ranges[i]; + const { $from, $to } = ranges[i]; return state.doc.rangeHasMark($from.pos, $to.pos, mark); } return false; @@ -1440,7 +1440,7 @@ export class TooltipTextMenu { if (mark_type === state.schema.marks.pFontSize) { return ref_node.marks.some(m => m.type.name === state.schema.marks.pFontSize.name); } - let mark = state.schema.mark(mark_type); + const mark = state.schema.mark(mark_type); return ref_node.marks.includes(mark); return false; }); diff --git a/src/client/util/TypedEvent.ts b/src/client/util/TypedEvent.ts index 532ba78eb..90fd299c1 100644 --- a/src/client/util/TypedEvent.ts +++ b/src/client/util/TypedEvent.ts @@ -1,40 +1,40 @@ export interface Listener<T> { - (event: T): any; + (event: T): any; } export interface Disposable { - dispose(): void; + dispose(): void; } /** passes through events as they happen. You will not get events from before you start listening */ export class TypedEvent<T> { - private listeners: Listener<T>[] = []; - private listenersOncer: Listener<T>[] = []; - - on = (listener: Listener<T>): Disposable => { - this.listeners.push(listener); - return { - dispose: () => this.off(listener) - }; - } - - once = (listener: Listener<T>): void => { - this.listenersOncer.push(listener); - } - - off = (listener: Listener<T>) => { - var callbackIndex = this.listeners.indexOf(listener); - if (callbackIndex > -1) this.listeners.splice(callbackIndex, 1); - } - - emit = (event: T) => { - /** Update any general listeners */ - this.listeners.forEach((listener) => listener(event)); - - /** Clear the `once` queue */ - this.listenersOncer.forEach((listener) => listener(event)); - this.listenersOncer = []; - } - - pipe = (te: TypedEvent<T>): Disposable => this.on((e) => te.emit(e)); + private listeners: Listener<T>[] = []; + private listenersOncer: Listener<T>[] = []; + + on = (listener: Listener<T>): Disposable => { + this.listeners.push(listener); + return { + dispose: () => this.off(listener) + }; + } + + once = (listener: Listener<T>): void => { + this.listenersOncer.push(listener); + } + + off = (listener: Listener<T>) => { + const callbackIndex = this.listeners.indexOf(listener); + if (callbackIndex > -1) this.listeners.splice(callbackIndex, 1); + } + + emit = (event: T) => { + /** Update any general listeners */ + this.listeners.forEach((listener) => listener(event)); + + /** Clear the `once` queue */ + this.listenersOncer.forEach((listener) => listener(event)); + this.listenersOncer = []; + } + + pipe = (te: TypedEvent<T>): Disposable => this.on((e) => te.emit(e)); }
\ No newline at end of file diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts index 472afac1d..314b52bf3 100644 --- a/src/client/util/UndoManager.ts +++ b/src/client/util/UndoManager.ts @@ -3,7 +3,7 @@ import 'source-map-support/register'; import { Without } from "../../Utils"; function getBatchName(target: any, key: string | symbol): string { - let keyName = key.toString(); + const keyName = key.toString(); if (target && target.constructor && target.constructor.name) { return `${target.constructor.name}.${keyName}`; } @@ -23,7 +23,7 @@ function propertyDecorator(target: any, key: string | symbol) { writable: true, configurable: true, value: function (...args: any[]) { - let batch = UndoManager.StartBatch(getBatchName(target, key)); + const batch = UndoManager.StartBatch(getBatchName(target, key)); try { return value.apply(this, args); } finally { @@ -40,7 +40,7 @@ export function undoBatch(fn: (...args: any[]) => any): (...args: any[]) => any; export function undoBatch(target: any, key?: string | symbol, descriptor?: TypedPropertyDescriptor<any>): any { if (!key) { return function () { - let batch = UndoManager.StartBatch(""); + const batch = UndoManager.StartBatch(""); try { return target.apply(undefined, arguments); } finally { @@ -55,7 +55,7 @@ export function undoBatch(target: any, key?: string | symbol, descriptor?: Typed const oldFunction = descriptor.value; descriptor.value = function (...args: any[]) { - let batch = UndoManager.StartBatch(getBatchName(target, key)); + const batch = UndoManager.StartBatch(getBatchName(target, key)); try { return oldFunction.apply(this, args); } finally { @@ -98,7 +98,7 @@ export namespace UndoManager { GetOpenBatches().forEach(batch => console.log(batch.batchName)); } - let openBatches: Batch[] = []; + const openBatches: Batch[] = []; export function GetOpenBatches(): Without<Batch, 'end'>[] { return openBatches; } @@ -146,7 +146,7 @@ export namespace UndoManager { //TODO Make this return the return value export function RunInBatch<T>(fn: () => T, batchName: string) { - let batch = StartBatch(batchName); + const batch = StartBatch(batchName); try { return runInAction(fn); } finally { @@ -159,7 +159,7 @@ export namespace UndoManager { return; } - let commands = undoStack.pop(); + const commands = undoStack.pop(); if (!commands) { return; } @@ -178,7 +178,7 @@ export namespace UndoManager { return; } - let commands = redoStack.pop(); + const commands = redoStack.pop(); if (!commands) { return; } diff --git a/src/client/views/CollectionLinearView.tsx b/src/client/views/CollectionLinearView.tsx index f718735a8..09e4ef99c 100644 --- a/src/client/views/CollectionLinearView.tsx +++ b/src/client/views/CollectionLinearView.tsx @@ -48,12 +48,12 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { dimension = () => NumCast(this.props.Document.height); // 2 * the padding getTransform = (ele: React.RefObject<HTMLDivElement>) => () => { if (!ele.current) return Transform.Identity(); - let { scale, translateX, translateY } = Utils.GetScreenTransform(ele.current); + const { scale, translateX, translateY } = Utils.GetScreenTransform(ele.current); return new Transform(-translateX, -translateY, 1 / scale); } render() { - let guid = Utils.GenerateGuid(); + const guid = Utils.GenerateGuid(); return <div className="collectionLinearView-outer"> <div className="collectionLinearView" ref={this.createDropTarget} > <input id={`${guid}`} type="checkbox" checked={BoolCast(this.props.Document.isExpanded)} ref={this.addMenuToggle} @@ -62,10 +62,10 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { <div className="collectionLinearView-content" style={{ height: this.dimension(), width: NumCast(this.props.Document.width, 25) }}> {this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => { - let nested = pair.layout.viewType === CollectionViewType.Linear; - let dref = React.createRef<HTMLDivElement>(); - let nativeWidth = NumCast(pair.layout.nativeWidth, this.dimension()); - let deltaSize = nativeWidth * .15 / 2; + const nested = pair.layout.viewType === CollectionViewType.Linear; + const dref = React.createRef<HTMLDivElement>(); + const nativeWidth = NumCast(pair.layout.nativeWidth, this.dimension()); + const deltaSize = nativeWidth * .15 / 2; return <div className={`collectionLinearView-docBtn` + (pair.layout.onClick || pair.layout.onDragStart ? "-scalable" : "")} key={pair.layout[Id]} ref={dref} style={{ width: nested ? pair.layout[WidthSym]() : this.dimension() - deltaSize, diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 5d452e72e..937aff0d6 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -49,8 +49,8 @@ export class ContextMenu extends React.Component { @action onPointerUp = (e: PointerEvent) => { this._mouseDown = false; - let curX = e.clientX; - let curY = e.clientY; + const curX = e.clientX; + const curY = e.clientY; if (this._mouseX !== curX || this._mouseY !== curY) { this._shouldDisplay = false; } @@ -208,7 +208,7 @@ export class ContextMenu extends React.Component { if (!this._display) { return null; } - let style = this._yRelativeToTop ? { left: this.pageX, top: this.pageY } : + const style = this._yRelativeToTop ? { left: this.pageX, top: this.pageY } : { left: this.pageX, bottom: this.pageY }; const contents = ( diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 330b94afa..fef9e5f60 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -88,7 +88,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select </div> ); } else if ("subitems" in this.props) { - let submenu = !this.overItem ? (null) : + const submenu = !this.overItem ? (null) : <div className="contextMenu-subMenu-cont" style={{ marginLeft: "25%", left: "0px" }}> {this._items.map(prop => <ContextMenuItem {...prop} key={prop.description} closeMenu={this.props.closeMenu} />)} </div>; diff --git a/src/client/views/DictationOverlay.tsx b/src/client/views/DictationOverlay.tsx index 2accf9bfd..65770c0bb 100644 --- a/src/client/views/DictationOverlay.tsx +++ b/src/client/views/DictationOverlay.tsx @@ -24,7 +24,7 @@ export class DictationOverlay extends React.Component { } public initiateDictationFade = () => { - let duration = DictationManager.Commands.dictationFadeDuration; + const duration = DictationManager.Commands.dictationFadeDuration; this.overlayTimeout = setTimeout(() => { this.dictationOverlayVisible = false; this.dictationSuccess = undefined; @@ -50,14 +50,14 @@ export class DictationOverlay extends React.Component { public set isListening(value: DictationManager.Controls.ListeningUIStatus) { runInAction(() => this._dictationListeningState = value); } render() { - let success = this.dictationSuccess; - let result = this.isListening && !this.isListening.interim ? DictationManager.placeholder : `"${this.dictatedPhrase}"`; - let dialogueBoxStyle = { + const success = this.dictationSuccess; + const result = this.isListening && !this.isListening.interim ? DictationManager.placeholder : `"${this.dictatedPhrase}"`; + const dialogueBoxStyle = { background: success === undefined ? "gainsboro" : success ? "lawngreen" : "red", borderColor: this.isListening ? "red" : "black", fontStyle: "italic" }; - let overlayStyle = { + const overlayStyle = { backgroundColor: this.isListening ? "red" : "darkslategrey" }; return (<MainViewModal diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index b3a130b33..27ee9f122 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import { Doc } from '../../new_fields/Doc'; import { Touchable } from './Touchable'; import { computed, action, observable } from 'mobx'; @@ -65,8 +64,8 @@ export function DocAnnotatableComponent<P extends DocAnnotatableProps, T>(schema @action.bound removeDocument(doc: Doc): boolean { Doc.GetProto(doc).annotationOn = undefined; - let value = this.extensionDoc && Cast(this.extensionDoc[this.annotationsKey], listSpec(Doc), []); - let index = value ? Doc.IndexOf(doc, value.map(d => d as Doc), true) : -1; + const value = this.extensionDoc && Cast(this.extensionDoc[this.annotationsKey], listSpec(Doc), []); + const index = value ? Doc.IndexOf(doc, value.map(d => d as Doc), true) : -1; return index !== -1 && value && value.splice(index, 1) ? true : false; } // if the moved document is already in this overlay collection nothing needs to be done. diff --git a/src/client/views/DocumentButtonBar.scss b/src/client/views/DocumentButtonBar.scss index db6bf2ba0..c2ca93900 100644 --- a/src/client/views/DocumentButtonBar.scss +++ b/src/client/views/DocumentButtonBar.scss @@ -17,6 +17,7 @@ $linkGap : 3px; transform: scale(1.05); cursor: pointer; } + .documentButtonBar-linkButton-empty, .documentButtonBar-linkButton-nonempty { height: 20px; @@ -74,6 +75,31 @@ $linkGap : 3px; } -@-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } } -@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } } -@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } }
\ No newline at end of file +@-moz-keyframes spin { + 100% { + -moz-transform: rotate(360deg); + } +} + +@-webkit-keyframes spin { + 100% { + -webkit-transform: rotate(360deg); + } +} + +@keyframes spin { + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes shadow-pulse { + 0% { + box-shadow: 0 0 0 0px rgba(0, 0, 0, 0.8); + } + + 100% { + box-shadow: 0 0 0 10px rgba(0, 255, 0, 0); + } +}
\ No newline at end of file diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 1fefc70f1..15cbd2788 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -21,6 +21,7 @@ import React = require("react"); import { DocumentView } from './nodes/DocumentView'; import { ParentDocSelector } from './collections/ParentDocumentSelector'; import { CollectionDockingView } from './collections/CollectionDockingView'; +import { DocumentDecorations } from './DocumentDecorations'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -51,7 +52,9 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[], @observable private pushIcon: IconProp = "arrow-alt-circle-up"; @observable private pullIcon: IconProp = "arrow-alt-circle-down"; @observable private pullColor: string = "white"; - @observable private isAnimatingFetch = false; + @observable public isAnimatingFetch = false; + @observable public isAnimatingPulse = false; + @observable private openHover = false; public static Instance: DocumentButtonBar; @@ -75,6 +78,7 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[], }); public startPushOutcome = action((success: boolean) => { + this.isAnimatingPulse = false; if (!this._pushAnimating) { this._pushAnimating = true; this.pushIcon = success ? "check-circle" : "stop-circle"; @@ -99,27 +103,26 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[], this._pullColorAnimating = false; }); - @action onLinkButtonMoved = (e: PointerEvent): void => { if (this._linkButton.current !== null && (Math.abs(e.clientX - this._downX) > 3 || Math.abs(e.clientY - this._downY) > 3)) { document.removeEventListener("pointermove", this.onLinkButtonMoved); document.removeEventListener("pointerup", this.onLinkButtonUp); - let docView = this.props.views[0]; - let container = docView.props.ContainingCollectionDoc?.proto; - let dragData = new DragManager.LinkDragData(docView.props.Document, container ? [container] : []); - let linkDrag = UndoManager.StartBatch("Drag Link"); + const docView = this.props.views[0]; + const container = docView.props.ContainingCollectionDoc?.proto; + const dragData = new DragManager.LinkDragData(docView.props.Document, container ? [container] : []); + const linkDrag = UndoManager.StartBatch("Drag Link"); DragManager.StartLinkDrag(this._linkButton.current, dragData, e.pageX, e.pageY, { handlers: { dragComplete: () => { - let tooltipmenu = FormattedTextBox.ToolTipTextMenu; - let linkDoc = dragData.linkDocument; + const tooltipmenu = FormattedTextBox.ToolTipTextMenu; + const linkDoc = dragData.linkDocument; if (linkDoc && tooltipmenu) { - let proto = Doc.GetProto(linkDoc); + const proto = Doc.GetProto(linkDoc); if (proto && docView) { proto.sourceContext = docView.props.ContainingCollectionDoc; } - let text = tooltipmenu.makeLink(linkDoc, StrCast(linkDoc.anchor2.title), e.ctrlKey ? "onRight" : "inTab"); + const text = tooltipmenu.makeLink(linkDoc, StrCast(linkDoc.anchor2.title), e.ctrlKey ? "onRight" : "inTab"); if (linkDoc instanceof Doc && linkDoc.anchor2 instanceof Doc) { proto.title = text === "" ? proto.title : text + " to " + linkDoc.anchor2.title; // TODODO open to more descriptive descriptions of following in text link } @@ -152,21 +155,27 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[], @computed get considerGoogleDocsPush() { - let targetDoc = this.props.views[0].props.Document; - let published = Doc.GetProto(targetDoc)[GoogleRef] !== undefined; - return <div title={`${published ? "Push" : "Publish"} to Google Docs`} className="documentButtonBar-linker" onClick={() => { - DocumentButtonBar.hasPushedHack = false; - targetDoc[Pushes] = NumCast(targetDoc[Pushes]) + 1; - }}> + const targetDoc = this.props.views[0].props.Document; + const published = Doc.GetProto(targetDoc)[GoogleRef] !== undefined; + const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none"; + return <div + title={`${published ? "Push" : "Publish"} to Google Docs`} + className="documentButtonBar-linker" + style={{ animation }} + onClick={() => { + !published && runInAction(() => this.isAnimatingPulse = true); + DocumentButtonBar.hasPushedHack = false; + targetDoc[Pushes] = NumCast(targetDoc[Pushes]) + 1; + }}> <FontAwesomeIcon className="documentdecorations-icon" icon={published ? (this.pushIcon as any) : cloud} size={published ? "sm" : "xs"} /> </div>; } @computed get considerGoogleDocsPull() { - let targetDoc = this.props.views[0].props.Document; - let dataDoc = Doc.GetProto(targetDoc); - let animation = this.isAnimatingFetch ? "spin 0.5s linear infinite" : "none"; + const targetDoc = this.props.views[0].props.Document; + const dataDoc = Doc.GetProto(targetDoc); + const animation = this.isAnimatingFetch ? "spin 0.5s linear infinite" : "none"; return !dataDoc[GoogleRef] ? (null) : <div className="documentButtonBar-linker" title={`${!dataDoc.unchanged ? "Pull from" : "Fetch"} Google Docs`} style={{ backgroundColor: this.pullColor }} @@ -192,7 +201,7 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[], @computed get linkButton() { - let linkCount = LinkManager.Instance.getAllRelatedLinks(this.props.views[0].props.Document).length; + const linkCount = LinkManager.Instance.getAllRelatedLinks(this.props.views[0].props.Document).length; return <div title="Drag(create link) Tap(view links)" className="documentButtonBar-linkFlyout" ref={this._linkButton}> <Flyout anchorPoint={anchorPoints.RIGHT_TOP} content={<LinkMenu docView={this.props.views[0]} addDocTab={this.props.views[0].props.addDocTab} changeFlyout={emptyFunction} />}> @@ -214,13 +223,13 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[], } render() { - let templates: Map<Template, boolean> = new Map(); + const templates: Map<Template, boolean> = new Map(); Array.from(Object.values(Templates.TemplateList)).map(template => templates.set(template, this.props.views.reduce((checked, doc) => checked || doc.getLayoutPropStr("show" + template.Name) ? true : false, false as boolean))); - let isText = this.props.views[0].props.Document.data instanceof RichTextField; // bcz: Todo - can't assume layout is using the 'data' field. need to add fieldKey to DocumentView - let considerPull = isText && this.considerGoogleDocsPull; - let considerPush = isText && this.considerGoogleDocsPush; + const isText = this.props.views[0].props.Document.data instanceof RichTextField; // bcz: Todo - can't assume layout is using the 'data' field. need to add fieldKey to DocumentView + const considerPull = isText && this.considerGoogleDocsPull; + const considerPush = isText && this.considerGoogleDocsPush; return <div className="documentButtonBar"> <div className="documentButtonBar-button"> {this.linkButton} diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 66f47147f..7b0c31e37 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -24,7 +24,6 @@ import { DocumentView } from "./nodes/DocumentView"; import { FieldView } from "./nodes/FieldView"; import { IconBox } from "./nodes/IconBox"; import React = require("react"); -import { PointData } from '../../new_fields/InkField'; import { DocumentType } from '../documents/DocumentTypes'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; @@ -68,8 +67,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> @observable public pushIcon: IconProp = "arrow-alt-circle-up"; @observable public pullIcon: IconProp = "arrow-alt-circle-down"; @observable public pullColor: string = "white"; - @observable public isAnimatingFetch = false; - @observable public isAnimatingPulse = false; @observable public openHover = false; constructor(props: Readonly<{}>) { @@ -82,25 +79,25 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> @action titleChanged = (event: any) => { this._title = event.target.value; }; @action titleBlur = () => { this._edtingTitle = false; }; @action titleEntered = (e: any) => { - var key = e.keyCode || e.which; + const key = e.keyCode || e.which; // enter pressed if (key === 13) { - var text = e.target.value; + const text = e.target.value; if (text[0] === '#') { this._fieldKey = text.slice(1, text.length); this._title = this.selectionTitle; } else if (text.startsWith("::")) { - let targetID = text.slice(2, text.length); - let promoteDoc = SelectionManager.SelectedDocuments()[0]; + const targetID = text.slice(2, text.length); + const promoteDoc = SelectionManager.SelectedDocuments()[0]; DocUtils.Publish(promoteDoc.props.Document, targetID, promoteDoc.props.addDocument, promoteDoc.props.removeDocument); } else if (text.startsWith(">")) { - let fieldTemplateView = SelectionManager.SelectedDocuments()[0]; + const fieldTemplateView = SelectionManager.SelectedDocuments()[0]; SelectionManager.DeselectAll(); - let fieldTemplate = fieldTemplateView.props.Document; - let containerView = fieldTemplateView.props.ContainingCollectionView; - let docTemplate = fieldTemplateView.props.ContainingCollectionDoc; + const fieldTemplate = fieldTemplateView.props.Document; + const containerView = fieldTemplateView.props.ContainingCollectionView; + const docTemplate = fieldTemplateView.props.ContainingCollectionDoc; if (containerView && docTemplate) { - let metaKey = text.startsWith(">>") ? text.slice(2, text.length) : text.slice(1, text.length); + const metaKey = text.startsWith(">>") ? text.slice(2, text.length) : text.slice(1, text.length); if (metaKey !== containerView.props.fieldKey && containerView.props.DataDoc) { const fd = fieldTemplate.data; fd instanceof ObjectField && (Doc.GetProto(containerView.props.DataDoc)[metaKey] = ObjectField.MakeCopy(fd)); @@ -115,15 +112,15 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> else { if (SelectionManager.SelectedDocuments().length > 0) { SelectionManager.SelectedDocuments()[0].props.Document.customTitle = !this._title.startsWith("-"); - let field = SelectionManager.SelectedDocuments()[0].props.Document[this._fieldKey]; + const field = SelectionManager.SelectedDocuments()[0].props.Document[this._fieldKey]; if (typeof field === "number") { SelectionManager.SelectedDocuments().forEach(d => { - let doc = d.props.Document.proto ? d.props.Document.proto : d.props.Document; + const doc = d.props.Document.proto ? d.props.Document.proto : d.props.Document; doc[this._fieldKey] = +this._title; }); } else { SelectionManager.SelectedDocuments().forEach(d => { - let doc = d.props.Document.proto ? d.props.Document.proto : d.props.Document; + const doc = d.props.Document.proto ? d.props.Document.proto : d.props.Document; doc[this._fieldKey] = this._title; }); } @@ -165,11 +162,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> Doc.AreProtosEqual(documentView.props.Document, CurrentUserUtils.UserDocument)) { return bounds; } - let transform = (documentView.props.ScreenToLocalTransform().scale(documentView.props.ContentScaling())).inverse(); + const transform = (documentView.props.ScreenToLocalTransform().scale(documentView.props.ContentScaling())).inverse(); var [sptX, sptY] = transform.transformPoint(0, 0); let [bptX, bptY] = transform.transformPoint(documentView.props.PanelWidth(), documentView.props.PanelHeight()); if (documentView.props.Document.type === DocumentType.LINK) { - let rect = documentView.ContentDiv!.getElementsByClassName("docuLinkBox-cont")[0].getBoundingClientRect(); + const rect = documentView.ContentDiv!.getElementsByClassName("docuLinkBox-cont")[0].getBoundingClientRect(); sptX = rect.left; sptY = rect.top; bptX = rect.right; @@ -192,8 +189,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> @action onBackgroundMove = (e: PointerEvent): void => { - let dragDocView = SelectionManager.SelectedDocuments()[0]; - let dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document)); + const dragDocView = SelectionManager.SelectedDocuments()[0]; + const dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document)); const [left, top] = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.props.ContentScaling()).inverse().transformPoint(0, 0); dragData.offset = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.props.ContentScaling()).transformDirection(e.x - left, e.y - top); dragData.moveDocument = SelectionManager.SelectedDocuments()[0].props.moveDocument; @@ -256,8 +253,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> this._downX = e.pageX; this._downY = e.pageY; this._removeIcon = false; - let selDoc = SelectionManager.SelectedDocuments()[0]; - let selDocPos = selDoc.props.ScreenToLocalTransform().scale(selDoc.props.ContentScaling()).inverse().transformPoint(0, 0); + const selDoc = SelectionManager.SelectedDocuments()[0]; + const selDocPos = selDoc.props.ScreenToLocalTransform().scale(selDoc.props.ContentScaling()).inverse().transformPoint(0, 0); this._minimizedX = selDocPos[0] + 12; this._minimizedY = selDocPos[1] + 12; document.removeEventListener("pointermove", this.onMinimizeMove); @@ -272,12 +269,12 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> e.stopPropagation(); if (Math.abs(e.pageX - this._downX) > Utils.DRAG_THRESHOLD || Math.abs(e.pageY - this._downY) > Utils.DRAG_THRESHOLD) { - let selDoc = SelectionManager.SelectedDocuments()[0]; - let selDocPos = selDoc.props.ScreenToLocalTransform().scale(selDoc.props.ContentScaling()).inverse().transformPoint(0, 0); - let snapped = Math.abs(e.pageX - selDocPos[0]) < 20 && Math.abs(e.pageY - selDocPos[1]) < 20; + const selDoc = SelectionManager.SelectedDocuments()[0]; + const selDocPos = selDoc.props.ScreenToLocalTransform().scale(selDoc.props.ContentScaling()).inverse().transformPoint(0, 0); + const snapped = Math.abs(e.pageX - selDocPos[0]) < 20 && Math.abs(e.pageY - selDocPos[1]) < 20; this._minimizedX = snapped ? selDocPos[0] + 4 : e.clientX; this._minimizedY = snapped ? selDocPos[1] - 18 : e.clientY; - let selectedDocs = SelectionManager.SelectedDocuments().map(sd => sd); + const selectedDocs = SelectionManager.SelectedDocuments().map(sd => sd); if (selectedDocs.length > 1) { this._iconDoc = this._iconDoc ? this._iconDoc : this.createIcon(SelectionManager.SelectedDocuments(), CollectionView.LayoutString("")); @@ -295,15 +292,15 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (e.button === 0) { document.removeEventListener("pointermove", this.onMinimizeMove); document.removeEventListener("pointerup", this.onMinimizeUp); - let selectedDocs = SelectionManager.SelectedDocuments().map(sd => sd); + const selectedDocs = SelectionManager.SelectedDocuments().map(sd => sd); if (this._iconDoc && selectedDocs.length === 1 && this._removeIcon) { selectedDocs[0].props.removeDocument && selectedDocs[0].props.removeDocument(this._iconDoc); } if (!this._removeIcon && selectedDocs.length === 1) { // if you click on the top-left button when just 1 doc is selected, then collapse it. not sure why we don't do it for multiple selections this.getIconDoc(selectedDocs[0]).then(async icon => { - let minimizedDoc = await Cast(selectedDocs[0].props.Document.minimizedDoc, Doc); + const minimizedDoc = await Cast(selectedDocs[0].props.Document.minimizedDoc, Doc); if (minimizedDoc) { - let scrpt = selectedDocs[0].props.ScreenToLocalTransform().scale(selectedDocs[0].props.ContentScaling()).inverse().transformPoint( + const scrpt = selectedDocs[0].props.ScreenToLocalTransform().scale(selectedDocs[0].props.ContentScaling()).inverse().transformPoint( NumCast(minimizedDoc.x) - NumCast(selectedDocs[0].Document.x), NumCast(minimizedDoc.y) - NumCast(selectedDocs[0].Document.y)); SelectionManager.DeselectAll(); DocumentManager.Instance.animateBetweenPoint(scrpt, await DocListCastAsync(minimizedDoc.maximizedDocs)); @@ -317,8 +314,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> @undoBatch @action createIcon = (selected: DocumentView[], layoutString: string): Doc => { - let doc = selected[0].props.Document; - let iconDoc = Docs.Create.IconDocument(layoutString); + const doc = selected[0].props.Document; + const iconDoc = Docs.Create.IconDocument(layoutString); iconDoc.isButton = true; IconBox.AutomaticTitle(iconDoc); @@ -334,7 +331,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } @action public getIconDoc = async (docView: DocumentView): Promise<Doc | undefined> => { - let doc = docView.props.Document; + const doc = docView.props.Document; let iconDoc: Doc | undefined = await Cast(doc.minimizedDoc, Doc); if (!iconDoc || !DocumentManager.Instance.getDocumentView(iconDoc)) { @@ -344,8 +341,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> return iconDoc; } moveIconDoc(iconDoc: Doc) { - let selView = SelectionManager.SelectedDocuments()[0]; - let where = (selView.props.ScreenToLocalTransform()).scale(selView.props.ContentScaling()). + const selView = SelectionManager.SelectedDocuments()[0]; + const where = (selView.props.ScreenToLocalTransform()).scale(selView.props.ContentScaling()). transformPoint(this._minimizedX - 12, this._minimizedY - 12); iconDoc.x = where[0] + NumCast(selView.props.Document.x); iconDoc.y = where[1] + NumCast(selView.props.Document.y); @@ -370,8 +367,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> dist = dist < 3 ? 0 : dist; let usingRule = false; SelectionManager.SelectedDocuments().map(dv => { - let ruleProvider = dv.props.ruleProvider; - let heading = NumCast(dv.props.Document.heading); + const ruleProvider = dv.props.ruleProvider; + const heading = NumCast(dv.props.Document.heading); ruleProvider && heading && (Doc.GetProto(ruleProvider)["ruleRounding_" + heading] = `${Math.min(100, dist)}%`); usingRule = usingRule || (ruleProvider && heading ? true : false); }); @@ -419,8 +416,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let dX = 0, dY = 0, dW = 0, dH = 0; - let moveX = e.clientX - this._lastX; // e.movementX; - let moveY = e.clientY - this._lastY; // e.movementY; + const moveX = e.clientX - this._lastX; // e.movementX; + const moveY = e.clientY - this._lastY; // e.movementY; this._lastX = e.clientX; this._lastY = e.clientY; @@ -465,18 +462,18 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => { if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) { - let doc = PositionDocument(element.props.Document); - let layoutDoc = PositionDocument(Doc.Layout(element.props.Document)); + const doc = PositionDocument(element.props.Document); + const layoutDoc = PositionDocument(Doc.Layout(element.props.Document)); let nwidth = layoutDoc.nativeWidth || 0; let nheight = layoutDoc.nativeHeight || 0; - let width = (layoutDoc.width || 0); - let height = (layoutDoc.height || (nheight / nwidth * width)); - let scale = element.props.ScreenToLocalTransform().Scale * element.props.ContentScaling(); - let actualdW = Math.max(width + (dW * scale), 20); - let actualdH = Math.max(height + (dH * scale), 20); + const width = (layoutDoc.width || 0); + const height = (layoutDoc.height || (nheight / nwidth * width)); + const scale = element.props.ScreenToLocalTransform().Scale * element.props.ContentScaling(); + const actualdW = Math.max(width + (dW * scale), 20); + const actualdH = Math.max(height + (dH * scale), 20); doc.x = (doc.x || 0) + dX * (actualdW - width); doc.y = (doc.y || 0) + dY * (actualdH - height); - let fixedAspect = e.ctrlKey || (!layoutDoc.ignoreAspect && nwidth && nheight); + const fixedAspect = e.ctrlKey || (!layoutDoc.ignoreAspect && nwidth && nheight); if (fixedAspect && e.ctrlKey && layoutDoc.ignoreAspect) { layoutDoc.ignoreAspect = false; layoutDoc.nativeWidth = nwidth = layoutDoc.width || 0; @@ -529,8 +526,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> @computed get selectionTitle(): string { if (SelectionManager.SelectedDocuments().length === 1) { - let selected = SelectionManager.SelectedDocuments()[0]; - let field = selected.props.Document[this._fieldKey]; + const selected = SelectionManager.SelectedDocuments()[0]; + const field = selected.props.Document[this._fieldKey]; if (typeof field === "string") { return field; } @@ -555,12 +552,12 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } } render() { - var bounds = this.Bounds; - let seldoc = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined; + const bounds = this.Bounds; + const seldoc = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined; if (SelectionManager.GetIsDragging() || bounds.x === Number.MAX_VALUE || !seldoc || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) { return (null); } - let minimizeIcon = ( + const minimizeIcon = ( <div className="documentDecorations-minimizeButton" onPointerDown={this.onMinimizeDown}> {/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/} {SelectionManager.SelectedDocuments().length === 1 ? IconBox.DocumentIcon(StrCast(SelectionManager.SelectedDocuments()[0].props.Document.layout, "...")) : "..."} diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 8f397e331..edc7df12a 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -25,7 +25,7 @@ export default class KeyManager { private router = new Map<string, KeyHandler>(); constructor() { - let isMac = navigator.platform.toLowerCase().indexOf("mac") >= 0; + const isMac = navigator.platform.toLowerCase().indexOf("mac") >= 0; // SHIFT CONTROL ALT META this.router.set("0000", this.unmodified); @@ -36,22 +36,22 @@ export default class KeyManager { } public handle = async (e: KeyboardEvent) => { - let keyname = e.key && e.key.toLowerCase(); + const keyname = e.key && e.key.toLowerCase(); this.handleGreedy(keyname); if (modifiers.includes(keyname)) { return; } - let bit = (value: boolean) => value ? "1" : "0"; - let modifierIndex = bit(e.shiftKey) + bit(e.ctrlKey) + bit(e.altKey) + bit(e.metaKey); + const bit = (value: boolean) => value ? "1" : "0"; + const modifierIndex = bit(e.shiftKey) + bit(e.ctrlKey) + bit(e.altKey) + bit(e.metaKey); - let handleConstrained = this.router.get(modifierIndex); + const handleConstrained = this.router.get(modifierIndex); if (!handleConstrained) { return; } - let control = await handleConstrained(keyname, e); + const control = await handleConstrained(keyname, e); control.stopPropagation && e.stopPropagation(); control.preventDefault && e.preventDefault(); @@ -65,7 +65,7 @@ export default class KeyManager { private unmodified = action((keyname: string, e: KeyboardEvent) => { switch (keyname) { case "escape": - let main = MainView.Instance; + const main = MainView.Instance; InkingControl.Instance.switchTool(InkTool.None); if (main.isPointerDown) { DragManager.AbortDrag(); @@ -89,8 +89,8 @@ export default class KeyManager { } UndoManager.RunInBatch(() => { SelectionManager.SelectedDocuments().map(docView => { - let doc = docView.props.Document; - let remove = docView.props.removeDocument; + const doc = docView.props.Document; + const remove = docView.props.removeDocument; remove && remove(doc); }); }, "delete"); @@ -121,8 +121,8 @@ export default class KeyManager { } private alt = action((keyname: string) => { - let stopPropagation = true; - let preventDefault = true; + const stopPropagation = true; + const preventDefault = true; switch (keyname) { // case "n": @@ -190,7 +190,7 @@ export default class KeyManager { } break; case "o": - let target = SelectionManager.SelectedDocuments()[0]; + const target = SelectionManager.SelectedDocuments()[0]; target && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(target); break; case "r": @@ -220,12 +220,12 @@ export default class KeyManager { }); async printClipboard() { - let text: string = await navigator.clipboard.readText(); + const text: string = await navigator.clipboard.readText(); } private ctrl_shift = action((keyname: string) => { - let stopPropagation = true; - let preventDefault = true; + const stopPropagation = true; + const preventDefault = true; switch (keyname) { case "z": diff --git a/src/client/views/InkSelectDecorations.tsx b/src/client/views/InkSelectDecorations.tsx index d40df9b75..3ad50762d 100644 --- a/src/client/views/InkSelectDecorations.tsx +++ b/src/client/views/InkSelectDecorations.tsx @@ -29,10 +29,10 @@ export default class InkSelectDecorations extends Touchable { @computed get Bounds(): { x: number, y: number, b: number, r: number } { - let left = Number.MAX_VALUE; - let top = Number.MAX_VALUE; - let right = -Number.MAX_VALUE; - let bottom = -Number.MAX_VALUE; + const left = Number.MAX_VALUE; + const top = Number.MAX_VALUE; + const right = -Number.MAX_VALUE; + const bottom = -Number.MAX_VALUE; this._selectedInkNodes.forEach((value: PointData, key: string) => { // value.pathData.map(val => { // left = Math.min(val.x, left); @@ -45,7 +45,7 @@ export default class InkSelectDecorations extends Touchable { } render() { - let bounds = this.Bounds; + const bounds = this.Bounds; return <div style={{ top: bounds.y, left: bounds.x, height: bounds.b - bounds.y, diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index 75faa9641..e33f193b8 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -1,5 +1,5 @@ import { action, computed, observable } from "mobx"; -import { ColorResult } from 'react-color'; +import { ColorState } from 'react-color'; import { Doc } from "../../new_fields/Doc"; import { InkTool } from "../../new_fields/InkField"; import { List } from "../../new_fields/List"; @@ -35,16 +35,16 @@ export class InkingControl { } @undoBatch - switchColor = action((color: ColorResult): void => { + switchColor = action((color: ColorState): void => { this._selectedColor = color.hex + (color.rgb.a !== undefined ? this.decimalToHexString(Math.round(color.rgb.a * 255)) : "ff"); if (InkingControl.Instance.selectedTool === InkTool.None) { - let selected = SelectionManager.SelectedDocuments(); - let oldColors = selected.map(view => { - let targetDoc = view.props.Document.dragFactory instanceof Doc ? view.props.Document.dragFactory : + const selected = SelectionManager.SelectedDocuments(); + const oldColors = selected.map(view => { + const targetDoc = view.props.Document.dragFactory instanceof Doc ? view.props.Document.dragFactory : view.props.Document.layout instanceof Doc ? view.props.Document.layout : view.props.Document.isTemplateField ? view.props.Document : Doc.GetProto(view.props.Document); - let sel = window.getSelection(); + const sel = window.getSelection(); if (StrCast(targetDoc.layout).indexOf("FormattedTextBox") !== -1 && (!sel || sel.toString() !== "")) { targetDoc.color = this._selectedColor; return { @@ -52,24 +52,24 @@ export class InkingControl { previous: StrCast(targetDoc.color) }; } - let oldColor = StrCast(targetDoc.backgroundColor); + const oldColor = StrCast(targetDoc.backgroundColor); let matchedColor = this._selectedColor; const cvd = view.props.ContainingCollectionDoc; let ruleProvider = view.props.ruleProvider; if (cvd) { if (!cvd.colorPalette) { - let defaultPalette = ["rg(114,229,239)", "rgb(255,246,209)", "rgb(255,188,156)", "rgb(247,220,96)", "rgb(122,176,238)", + const defaultPalette = ["rg(114,229,239)", "rgb(255,246,209)", "rgb(255,188,156)", "rgb(247,220,96)", "rgb(122,176,238)", "rgb(209,150,226)", "rgb(127,235,144)", "rgb(252,188,189)", "rgb(247,175,81)",]; - let colorPalette = Cast(cvd.colorPalette, listSpec("string")); + const colorPalette = Cast(cvd.colorPalette, listSpec("string")); if (!colorPalette) cvd.colorPalette = new List<string>(defaultPalette); } - let cp = Cast(cvd.colorPalette, listSpec("string")) as string[]; + const cp = Cast(cvd.colorPalette, listSpec("string")) as string[]; let closest = 0; let dist = 10000000; - let ccol = Utils.fromRGBAstr(StrCast(targetDoc.backgroundColor)); + const ccol = Utils.fromRGBAstr(StrCast(targetDoc.backgroundColor)); for (let i = 0; i < cp.length; i++) { - let cpcol = Utils.fromRGBAstr(cp[i]); - let d = Math.sqrt((ccol.r - cpcol.r) * (ccol.r - cpcol.r) + (ccol.b - cpcol.b) * (ccol.b - cpcol.b) + (ccol.g - cpcol.g) * (ccol.g - cpcol.g)); + const cpcol = Utils.fromRGBAstr(cp[i]); + const d = Math.sqrt((ccol.r - cpcol.r) * (ccol.r - cpcol.r) + (ccol.b - cpcol.b) * (ccol.b - cpcol.b) + (ccol.g - cpcol.g) * (ccol.g - cpcol.g)); if (d < dist) { dist = d; closest = i; diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index a27f106e3..7cee84fc5 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -14,7 +14,7 @@ type InkDocument = makeInterface<[typeof documentSchema]>; const InkDocument = makeInterface(documentSchema); export function CreatePolyline(points: { x: number, y: number }[], left: number, top: number, color?: string, width?: number) { - let pts = points.reduce((acc: string, pt: { x: number, y: number }) => acc + `${pt.x - left},${pt.y - top} `, ""); + const pts = points.reduce((acc: string, pt: { x: number, y: number }) => acc + `${pt.x - left},${pt.y - top} `, ""); return ( <polyline points={pts} @@ -35,18 +35,18 @@ export class InkingStroke extends DocExtendableComponent<FieldViewProps, InkDocu @computed get PanelHeight() { return this.props.PanelHeight(); } render() { - let data: InkData = Cast(this.Document.data, InkField)?.inkData ?? []; - let xs = data.map(p => p.x); - let ys = data.map(p => p.y); - let left = Math.min(...xs); - let top = Math.min(...ys); - let right = Math.max(...xs); - let bottom = Math.max(...ys); - let points = CreatePolyline(data, 0, 0, this.Document.color, this.Document.strokeWidth); - let width = right - left; - let height = bottom - top; - let scaleX = this.PanelWidth / width; - let scaleY = this.PanelHeight / height; + const data: InkData = Cast(this.Document.data, InkField)?.inkData ?? []; + const xs = data.map(p => p.x); + const ys = data.map(p => p.y); + const left = Math.min(...xs); + const top = Math.min(...ys); + const right = Math.max(...xs); + const bottom = Math.max(...ys); + const points = CreatePolyline(data, 0, 0, this.Document.color, this.Document.strokeWidth); + const width = right - left; + const height = bottom - top; + const scaleX = this.PanelWidth / width; + const scaleY = this.PanelHeight / height; return ( <svg width={width} height={height} style={{ transformOrigin: "top left", diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 291781da1..bd20cbcf1 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -60,10 +60,10 @@ export class MainView extends React.Component { public isPointerDown = false; componentWillMount() { - var tag = document.createElement('script'); + const tag = document.createElement('script'); tag.src = "https://www.youtube.com/iframe_api"; - var firstScriptTag = document.getElementsByTagName('script')[0]; + const firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode!.insertBefore(tag, firstScriptTag); window.removeEventListener("keydown", KeyManager.Instance.handle); window.addEventListener("keydown", KeyManager.Instance.handle); @@ -82,9 +82,9 @@ export class MainView extends React.Component { // causes errors to be generated when modifying an observable outside of an action configure({ enforceActions: "observed" }); if (window.location.pathname !== "/home") { - let pathname = window.location.pathname.substr(1).split("/"); + const pathname = window.location.pathname.substr(1).split("/"); if (pathname.length > 1) { - let type = pathname[0]; + const type = pathname[0]; if (type === "doc") { CurrentUserUtils.MainDocId = pathname[1]; if (!this.userDoc) { @@ -158,7 +158,7 @@ export class MainView extends React.Component { initAuthenticationRouters = async () => { // Load the user's active workspace, or create a new one if initial session after signup - let received = CurrentUserUtils.MainDocId; + const received = CurrentUserUtils.MainDocId; if (received && !this.userDoc) { reaction( () => CurrentUserUtils.GuestTarget, @@ -175,7 +175,7 @@ export class MainView extends React.Component { }), ); } - let doc = this.userDoc && await Cast(this.userDoc.activeWorkspace, Doc); + const doc = this.userDoc && await Cast(this.userDoc.activeWorkspace, Doc); if (doc) { this.openWorkspace(doc); } else { @@ -186,9 +186,9 @@ export class MainView extends React.Component { @action createNewWorkspace = async (id?: string) => { - let workspaces = Cast(this.userDoc.workspaces, Doc) as Doc; - let workspaceCount = DocListCast(workspaces.data).length + 1; - let freeformOptions: DocumentOptions = { + const workspaces = Cast(this.userDoc.workspaces, Doc) as Doc; + const workspaceCount = DocListCast(workspaces.data).length + 1; + const freeformOptions: DocumentOptions = { x: 0, y: 400, width: this._panelWidth * .7, @@ -196,10 +196,10 @@ export class MainView extends React.Component { title: "Collection " + workspaceCount, backgroundColor: "white" }; - let freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); + const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); Doc.AddDocToList(Doc.GetProto(CurrentUserUtils.UserDocument.documents as Doc), "data", freeformDoc); - var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(freeformDoc, freeformDoc, 600)] }] }; - let mainDoc = Docs.Create.DockDocument([freeformDoc], JSON.stringify(dockingLayout), { title: `Workspace ${workspaceCount}` }, id); + const dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(freeformDoc, freeformDoc, 600)] }] }; + const mainDoc = Docs.Create.DockDocument([freeformDoc], JSON.stringify(dockingLayout), { title: `Workspace ${workspaceCount}` }, id); Doc.AddDocToList(workspaces, "data", mainDoc); // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) setTimeout(() => this.openWorkspace(mainDoc), 0); @@ -213,7 +213,7 @@ export class MainView extends React.Component { !("presentationView" in doc) && (doc.presentationView = new List<Doc>([Docs.Create.TreeDocument([], { title: "Presentation" })])); this.userDoc ? (this.userDoc.activeWorkspace = doc) : (CurrentUserUtils.GuestWorkspace = doc); } - let state = this._urlState; + const state = this._urlState; if (state.sharing === true && !this.userDoc) { DocServer.Control.makeReadOnly(); } else { @@ -263,8 +263,8 @@ export class MainView extends React.Component { @computed get dockingContent() { const mainContainer = this.mainContainer; - let flyoutWidth = this.flyoutWidth; // bcz: need to be here because Measure messes with observables. - let flyoutTranslate = this._flyoutTranslate; + const flyoutWidth = this.flyoutWidth; // bcz: need to be here because Measure messes with observables. + const flyoutTranslate = this._flyoutTranslate; return <Measure offset onResize={this.onResize}> {({ measureRef }) => <div ref={measureRef} id="mainContent-div" style={{ width: `calc(100% - ${flyoutTranslate ? flyoutWidth : 0}px`, transform: `translate(${flyoutTranslate ? flyoutWidth : 0}px, 0px)` }} onDrop={this.onDrop}> @@ -352,11 +352,11 @@ export class MainView extends React.Component { mainContainerXf = () => new Transform(0, -this._buttonBarHeight, 1); @computed get flyout() { - let sidebarContent = this.userDoc && this.userDoc.sidebarContainer; + const sidebarContent = this.userDoc && this.userDoc.sidebarContainer; if (!(sidebarContent instanceof Doc)) { return (null); } - let sidebarButtonsDoc = Cast(CurrentUserUtils.UserDocument.sidebarButtons, Doc) as Doc; + const sidebarButtonsDoc = Cast(CurrentUserUtils.UserDocument.sidebarButtons, Doc) as Doc; sidebarButtonsDoc.columnWidth = this.flyoutWidth / 3 - 30; return <div className="mainView-flyoutContainer" > <div className="mainView-tabButtons" style={{ height: `${this._buttonBarHeight}px` }}> @@ -463,7 +463,7 @@ export class MainView extends React.Component { buttonBarXf = () => { if (!this._docBtnRef.current) return Transform.Identity(); - let { scale, translateX, translateY } = Utils.GetScreenTransform(this._docBtnRef.current); + const { scale, translateX, translateY } = Utils.GetScreenTransform(this._docBtnRef.current); return new Transform(-translateX, -translateY, 1 / scale); } @computed get docButtons() { diff --git a/src/client/views/MainViewModal.tsx b/src/client/views/MainViewModal.tsx index 221a0260a..9198fe3e3 100644 --- a/src/client/views/MainViewModal.tsx +++ b/src/client/views/MainViewModal.tsx @@ -14,9 +14,9 @@ export interface MainViewOverlayProps { export default class MainViewModal extends React.Component<MainViewOverlayProps> { render() { - let p = this.props; - let dialogueOpacity = p.dialogueBoxDisplayedOpacity || 1; - let overlayOpacity = p.overlayDisplayedOpacity || 0.4; + const p = this.props; + const dialogueOpacity = p.dialogueBoxDisplayedOpacity || 1; + const overlayOpacity = p.overlayDisplayedOpacity || 0.4; return !p.isDisplayed ? (null) : ( <div style={{ pointerEvents: p.isDisplayed ? p.interactive ? "all" : "none" : "none" }}> <div diff --git a/src/client/views/MetadataEntryMenu.tsx b/src/client/views/MetadataEntryMenu.tsx index 41453f8b2..8859c14cb 100644 --- a/src/client/views/MetadataEntryMenu.tsx +++ b/src/client/views/MetadataEntryMenu.tsx @@ -99,8 +99,8 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{ } else { let childSuccess = true; if (this._addChildren) { - for (let document of doc) { - let collectionChildren = await DocListCastAsync(document.data); + for (const document of doc) { + const collectionChildren = await DocListCastAsync(document.data); if (collectionChildren) { childSuccess = collectionChildren.every(c => KeyValueBox.ApplyKVPScript(c, this._currentKey, script)); } diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 9869e24d1..32ada293c 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -148,7 +148,7 @@ export class OverlayView extends React.Component { return CurrentUserUtils.UserDocument.overlays instanceof Doc && DocListCast(CurrentUserUtils.UserDocument.overlays.data).map(d => { d.inOverlay = true; let offsetx = 0, offsety = 0; - let onPointerMove = action((e: PointerEvent) => { + const onPointerMove = action((e: PointerEvent) => { if (e.buttons === 1) { d.x = e.clientX + offsetx; d.y = e.clientY + offsety; @@ -156,14 +156,14 @@ export class OverlayView extends React.Component { e.preventDefault(); } }); - let onPointerUp = action((e: PointerEvent) => { + const onPointerUp = action((e: PointerEvent) => { document.removeEventListener("pointermove", onPointerMove); document.removeEventListener("pointerup", onPointerUp); e.stopPropagation(); e.preventDefault(); }); - let onPointerDown = (e: React.PointerEvent) => { + const onPointerDown = (e: React.PointerEvent) => { offsetx = NumCast(d.x) - e.clientX; offsety = NumCast(d.y) - e.clientY; e.stopPropagation(); diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 136a272ab..fd0287b6c 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -26,7 +26,7 @@ export class PreviewCursor extends React.Component<{}> { paste = (e: ClipboardEvent) => { if (PreviewCursor.Visible) { if (e.clipboardData) { - let newPoint = PreviewCursor._getTransform().transformPoint(PreviewCursor._clickPoint[0], PreviewCursor._clickPoint[1]); + const newPoint = PreviewCursor._getTransform().transformPoint(PreviewCursor._clickPoint[0], PreviewCursor._clickPoint[1]); runInAction(() => { PreviewCursor.Visible = false; }); @@ -44,7 +44,7 @@ export class PreviewCursor extends React.Component<{}> { } // tests for URL and makes web document - let re: any = /^https?:\/\//g; + const re: any = /^https?:\/\//g; if (re.test(e.clipboardData.getData("text/plain"))) { const url = e.clipboardData.getData("text/plain"); PreviewCursor._addDocument(Docs.Create.WebDocument(url, { @@ -56,7 +56,7 @@ export class PreviewCursor extends React.Component<{}> { } // creates text document - let newBox = Docs.Create.TextDocument({ + const newBox = Docs.Create.TextDocument({ width: 200, height: 100, x: newPoint[0], y: newPoint[1], @@ -69,10 +69,10 @@ export class PreviewCursor extends React.Component<{}> { } //pasting in images if (e.clipboardData.getData("text/html") !== "" && e.clipboardData.getData("text/html").includes("<img src=")) { - let re: any = /<img src="(.*?)"/g; - let arr: any[] = re.exec(e.clipboardData.getData("text/html")); + const re: any = /<img src="(.*?)"/g; + const arr: any[] = re.exec(e.clipboardData.getData("text/html")); - let img: Doc = Docs.Create.ImageDocument( + const img: Doc = Docs.Create.ImageDocument( arr[1], { width: 300, title: arr[1], x: newPoint[0], diff --git a/src/client/views/ScriptBox.tsx b/src/client/views/ScriptBox.tsx index 8ef9f3be6..65d96f364 100644 --- a/src/client/views/ScriptBox.tsx +++ b/src/client/views/ScriptBox.tsx @@ -59,7 +59,7 @@ export class ScriptBox extends React.Component<ScriptBoxProps> { onFocus = this.onFocus; onBlur = this.onBlur; } - let params = <EditableView + const params = <EditableView contents={""} display={"block"} maxHeight={72} @@ -96,9 +96,9 @@ export class ScriptBox extends React.Component<ScriptBoxProps> { } } // tslint:disable-next-line: no-unnecessary-callback-wrapper - let params: string[] = []; - let setParams = (p: string[]) => params.splice(0, params.length, ...p); - let scriptingBox = <ScriptBox initialText={originalText} setParams={setParams} onCancel={overlayDisposer} onSave={(text, onError) => { + const params: string[] = []; + const setParams = (p: string[]) => params.splice(0, params.length, ...p); + const scriptingBox = <ScriptBox initialText={originalText} setParams={setParams} onCancel={overlayDisposer} onSave={(text, onError) => { if (prewrapper) { text = prewrapper + text + (postwrapper ? postwrapper : ""); } diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index c65b338b4..e6116ca09 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -61,19 +61,19 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> { toggleFloat = (e: React.ChangeEvent<HTMLInputElement>): void => { SelectionManager.DeselectAll(); - let topDocView = this.props.docs[0]; - let topDoc = topDocView.props.Document; - let xf = topDocView.props.ScreenToLocalTransform(); - let ex = e.target.clientLeft; - let ey = e.target.clientTop; + const topDocView = this.props.docs[0]; + const topDoc = topDocView.props.Document; + const xf = topDocView.props.ScreenToLocalTransform(); + const ex = e.target.clientLeft; + const ey = e.target.clientTop; undoBatch(action(() => topDoc.z = topDoc.z ? 0 : 1))(); if (e.target.checked) { setTimeout(() => { - let newDocView = DocumentManager.Instance.getDocumentView(topDoc); + const newDocView = DocumentManager.Instance.getDocumentView(topDoc); if (newDocView) { - let de = new DragManager.DocumentDragData([topDoc]); + const de = new DragManager.DocumentDragData([topDoc]); de.moveDocument = topDocView.props.moveDocument; - let xf = newDocView.ContentDiv!.getBoundingClientRect(); + const xf = newDocView.ContentDiv!.getBoundingClientRect(); DragManager.StartDocumentDrag([newDocView.ContentDiv!], de, ex, ey, { offsetX: (ex - xf.left), offsetY: (ey - xf.top), handlers: { dragComplete: () => { }, }, @@ -82,9 +82,9 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> { } }, 10); } else if (topDocView.props.ContainingCollectionView) { - let collView = topDocView.props.ContainingCollectionView; - let [sx, sy] = xf.inverse().transformPoint(0, 0); - let [x, y] = collView.props.ScreenToLocalTransform().transformPoint(sx, sy); + const collView = topDocView.props.ContainingCollectionView; + const [sx, sy] = xf.inverse().transformPoint(0, 0); + const [x, y] = collView.props.ScreenToLocalTransform().transformPoint(sx, sy); topDoc.x = x; topDoc.y = y; } @@ -122,7 +122,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> { @action toggleChrome = (): void => { this.props.docs.map(dv => { - let layout = Doc.Layout(dv.Document); + const layout = Doc.Layout(dv.Document); layout.chromeStatus = (layout.chromeStatus !== "disabled" ? "disabled" : "enabled"); }); } @@ -147,8 +147,8 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> { document.removeEventListener("pointermove", this.onAliasButtonMoved); document.removeEventListener("pointerup", this.onAliasButtonUp); - let dragDocView = this.props.docs[0]; - let dragData = new DragManager.DocumentDragData([dragDocView.props.Document]); + const dragDocView = this.props.docs[0]; + const dragData = new DragManager.DocumentDragData([dragDocView.props.Document]); const [left, top] = dragDocView.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); dragData.embedDoc = true; dragData.dropAction = "alias"; @@ -165,8 +165,8 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> { } render() { - let layout = Doc.Layout(this.props.docs[0].Document); - let templateMenu: Array<JSX.Element> = []; + const layout = Doc.Layout(this.props.docs[0].Document); + const templateMenu: Array<JSX.Element> = []; this.props.templates.forEach((checked, template) => templateMenu.push(<TemplateToggle key={template.Name} template={template} checked={checked} toggle={this.toggleTemplate} />)); templateMenu.push(<OtherToggle key={"float"} name={"Float"} checked={this.props.docs[0].Document.z ? true : false} toggle={this.toggleFloat} />); diff --git a/src/client/views/Touchable.tsx b/src/client/views/Touchable.tsx index 0056a1d96..183d3e4e8 100644 --- a/src/client/views/Touchable.tsx +++ b/src/client/views/Touchable.tsx @@ -17,7 +17,7 @@ export abstract class Touchable<T = {}> extends React.Component<T> { @action protected onTouchStart = (e: React.TouchEvent): void => { for (let i = 0; i < e.targetTouches.length; i++) { - let pt: any = e.targetTouches.item(i); + const pt: any = e.targetTouches.item(i); // pen is also a touch, but with a radius of 0.5 (at least with the surface pens). i doubt anyone's fingers are 2 pixels wide, // and this seems to be the only way of differentiating pen and touch on touch events if (pt.radiusX > 2 && pt.radiusY > 2) { @@ -59,7 +59,7 @@ export abstract class Touchable<T = {}> extends React.Component<T> { } for (let i = 0; i < e.targetTouches.length; i++) { - let pt = e.targetTouches.item(i); + const pt = e.targetTouches.item(i); if (pt) { if (this.prevPoints.has(pt.identifier)) { this.prevPoints.set(pt.identifier, pt); @@ -78,7 +78,7 @@ export abstract class Touchable<T = {}> extends React.Component<T> { // remove all the touches associated with the event for (let i = 0; i < e.targetTouches.length; i++) { - let pt = e.targetTouches.item(i); + const pt = e.targetTouches.item(i); if (pt) { if (this.prevPoints.has(pt.identifier)) { this.prevPoints.delete(pt.identifier); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 3040e74b0..77e6e1c93 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -96,13 +96,13 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp @undoBatch @action public OpenFullScreen(docView: DocumentView) { - let document = Doc.MakeAlias(docView.props.Document); - let dataDoc = docView.props.DataDoc; - let newItemStackConfig = { + const document = Doc.MakeAlias(docView.props.Document); + const dataDoc = docView.props.DataDoc; + const newItemStackConfig = { type: 'stack', content: [CollectionDockingView.makeDocumentConfig(document, dataDoc)] }; - var docconfig = this._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, this._goldenLayout); + const docconfig = this._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, this._goldenLayout); this._goldenLayout.root.contentItems[0].addChild(docconfig); docconfig.callDownwards('_$init'); this._goldenLayout._$maximiseItem(docconfig); @@ -113,7 +113,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp } public CloseFullScreen = () => { - let target = this._goldenLayout._maximisedItem; + const target = this._goldenLayout._maximisedItem; if (target !== null && this._maximizedSrc) { this._goldenLayout._maximisedItem.remove(); SelectionManager.SelectDoc(this._maximizedSrc, false); @@ -130,7 +130,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp @action public static CloseRightSplit(document: Doc): boolean { if (!CollectionDockingView.Instance) return false; - let instance = CollectionDockingView.Instance; + const instance = CollectionDockingView.Instance; let retVal = false; if (instance._goldenLayout.root.contentItems[0].isRow) { retVal = Array.from(instance._goldenLayout.root.contentItems[0].contentItems).some((child: any) => { @@ -176,21 +176,21 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp @action public static AddRightSplit(document: Doc, dataDoc: Doc | undefined, minimize: boolean = false) { if (!CollectionDockingView.Instance) return false; - let instance = CollectionDockingView.Instance; - let newItemStackConfig = { + const instance = CollectionDockingView.Instance; + const newItemStackConfig = { type: 'stack', content: [CollectionDockingView.makeDocumentConfig(document, dataDoc)] }; - var newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout); + const newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout); if (instance._goldenLayout.root.contentItems.length === 0) { instance._goldenLayout.root.addChild(newContentItem); } else if (instance._goldenLayout.root.contentItems[0].isRow) { instance._goldenLayout.root.contentItems[0].addChild(newContentItem); } else { - var collayout = instance._goldenLayout.root.contentItems[0]; - var newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout); + const collayout = instance._goldenLayout.root.contentItems[0]; + const newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout); collayout.parent.replaceChild(collayout, newRow); newRow.addChild(newContentItem, undefined, true); @@ -213,7 +213,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp @action public AddTab = (stack: any, document: Doc, dataDocument: Doc | undefined) => { Doc.GetProto(document).lastOpened = new DateField; - let docContentConfig = CollectionDockingView.makeDocumentConfig(document, dataDocument); + const docContentConfig = CollectionDockingView.makeDocumentConfig(document, dataDocument); if (stack === undefined) { let stack: any = this._goldenLayout.root; while (!stack.isStack) { @@ -236,7 +236,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp } setupGoldenLayout() { - var config = StrCast(this.props.Document.dockingConfig); + const config = StrCast(this.props.Document.dockingConfig); if (config) { if (!this._goldenLayout) { runInAction(() => this._goldenLayout = new GoldenLayout(JSON.parse(config))); @@ -280,7 +280,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp // Because this is in a set timeout, if this component unmounts right after mounting, // we will leak a GoldenLayout, because we try to destroy it before we ever create it setTimeout(() => this.setupGoldenLayout(), 1); - let userDoc = CurrentUserUtils.UserDocument; + const userDoc = CurrentUserUtils.UserDocument; userDoc && DocListCast((userDoc.workspaces as Doc).data).map(d => d.workspaceBrush = false); this.props.Document.workspaceBrush = true; } @@ -311,7 +311,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp } @action onResize = (event: any) => { - var cur = this._containerRef.current; + const cur = this._containerRef.current; // bcz: since GoldenLayout isn't a React component itself, we need to notify it to resize when its document container's size has changed this._goldenLayout && this._goldenLayout.updateSize(cur!.getBoundingClientRect().width, cur!.getBoundingClientRect().height); @@ -330,19 +330,19 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp @action onPointerDown = (e: React.PointerEvent): void => { this._isPointerDown = true; - let onPointerUp = action(() => { + const onPointerUp = action(() => { window.removeEventListener("pointerup", onPointerUp); this._isPointerDown = false; }); window.addEventListener("pointerup", onPointerUp); - var className = (e.target as any).className; + const className = (e.target as any).className; if (className === "messageCounter") { e.stopPropagation(); e.preventDefault(); - let x = e.clientX; - let y = e.clientY; - let docid = (e.target as any).DashDocId; - let tab = (e.target as any).parentElement as HTMLElement; + const x = e.clientX; + const y = e.clientY; + const docid = (e.target as any).DashDocId; + const tab = (e.target as any).parentElement as HTMLElement; DocServer.GetRefField(docid).then(action(async (sourceDoc: Opt<Field>) => (sourceDoc instanceof Doc) && DragLinksAsDocuments(tab, x, y, sourceDoc))); } @@ -352,18 +352,18 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp } updateDataField = async (json: string) => { - let matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g); - let docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", "")); + const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g); + const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", "")); if (docids) { - let docs = (await Promise.all(docids.map(id => DocServer.GetRefField(id)))).filter(f => f).map(f => f as Doc); + const docs = (await Promise.all(docids.map(id => DocServer.GetRefField(id)))).filter(f => f).map(f => f as Doc); Doc.GetProto(this.props.Document)[this.props.fieldKey] = new List<Doc>(docs); } } @undoBatch stateChanged = () => { - var json = JSON.stringify(this._goldenLayout.toConfig()); + const json = JSON.stringify(this._goldenLayout.toConfig()); this.props.Document.dockingConfig = json; this.updateDataField(json); @@ -380,7 +380,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp } htmlToElement(html: string) { - var template = document.createElement('template'); + const template = document.createElement('template'); html = html.trim(); // Never return a text node of whitespace as the result template.innerHTML = html; return template.content.firstChild; @@ -392,24 +392,24 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp tab.contentItem.parent.config.fixed = true; } - let doc = await DocServer.GetRefField(tab.contentItem.config.props.documentId) as Doc; - let dataDoc = await DocServer.GetRefField(tab.contentItem.config.props.dataDocumentId) as Doc; + const doc = await DocServer.GetRefField(tab.contentItem.config.props.documentId) as Doc; + const dataDoc = await DocServer.GetRefField(tab.contentItem.config.props.dataDocumentId) as Doc; if (doc instanceof Doc) { - let dragSpan = document.createElement("span"); + const dragSpan = document.createElement("span"); dragSpan.style.position = "relative"; dragSpan.style.bottom = "6px"; dragSpan.style.paddingLeft = "4px"; dragSpan.style.paddingRight = "2px"; - let gearSpan = document.createElement("span"); + const gearSpan = document.createElement("span"); gearSpan.style.position = "relative"; gearSpan.style.paddingLeft = "0px"; gearSpan.style.paddingRight = "12px"; - let upDiv = document.createElement("span"); + const upDiv = document.createElement("span"); const stack = tab.contentItem.parent; // shifts the focus to this tab when another tab is dragged over it tab.element[0].onmouseenter = (e: any) => { if (!this._isPointerDown || !SelectionManager.GetIsDragging()) return; - var activeContentItem = tab.header.parent.getActiveContentItem(); + const activeContentItem = tab.header.parent.getActiveContentItem(); if (tab.contentItem !== activeContentItem) { tab.header.parent.setActiveContentItem(tab.contentItem); } @@ -447,12 +447,12 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp tab.closeElement.off('click') //unbind the current click handler .click(async function () { tab.reactionDisposer && tab.reactionDisposer(); - let doc = await DocServer.GetRefField(tab.contentItem.config.props.documentId); + const doc = await DocServer.GetRefField(tab.contentItem.config.props.documentId); if (doc instanceof Doc) { - let theDoc = doc; + const theDoc = doc; CollectionDockingView.Instance._removedDocs.push(theDoc); - let userDoc = CurrentUserUtils.UserDocument; + const userDoc = CurrentUserUtils.UserDocument; let recent: Doc | undefined; if (userDoc && (recent = await Cast(CurrentUserUtils.UserDocument.recentlyClosed, Doc))) { Doc.AddDocToList(recent, "data", doc, undefined, true, true); @@ -489,13 +489,13 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp stack.remove(); stack.contentItems.forEach(async (contentItem: any) => { - let doc = await DocServer.GetRefField(contentItem.config.props.documentId); + const doc = await DocServer.GetRefField(contentItem.config.props.documentId); if (doc instanceof Doc) { let recent: Doc | undefined; if (CurrentUserUtils.UserDocument && (recent = await Cast(CurrentUserUtils.UserDocument.recentlyClosed, Doc))) { Doc.AddDocToList(recent, "data", doc, undefined, true, true); } - let theDoc = doc; + const theDoc = doc; CollectionDockingView.Instance._removedDocs.push(theDoc); } }); @@ -505,7 +505,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp .off('click') //unbind the current click handler .click(action(function () { stack.config.fixed = !stack.config.fixed; - // var url = Utils.prepend("/doc/" + stack.contentItems[0].tab.contentItem.config.props.documentId); + // const url = Utils.prepend("/doc/" + stack.contentItems[0].tab.contentItem.config.props.documentId); // let win = window.open(url, stack.contentItems[0].tab.title, "width=300,height=400"); })); } @@ -563,9 +563,9 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> { @action public PinDoc(doc: Doc) { //add this new doc to props.Document - let curPres = Cast(CurrentUserUtils.UserDocument.curPresentation, Doc) as Doc; + const curPres = Cast(CurrentUserUtils.UserDocument.curPresentation, Doc) as Doc; if (curPres) { - let pinDoc = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent" }); + const pinDoc = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent" }); Doc.GetProto(pinDoc).presentationTargetDoc = doc; Doc.GetProto(pinDoc).title = ComputedField.MakeFunction('(this.presentationTargetDoc instanceof Doc) && this.presentationTargetDoc.title.toString()'); const data = Cast(curPres.data, listSpec(Doc)); @@ -581,8 +581,8 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> { } componentDidMount() { - let observer = new _global.ResizeObserver(action((entries: any) => { - for (let entry of entries) { + const observer = new _global.ResizeObserver(action((entries: any) => { + for (const entry of entries) { this._panelWidth = entry.contentRect.width; this._panelHeight = entry.contentRect.height; } @@ -625,14 +625,14 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> { const nativeH = this.nativeHeight(); const nativeW = this.nativeWidth(); if (!nativeW || !nativeH) return 1; - let wscale = this.panelWidth() / nativeW; + const wscale = this.panelWidth() / nativeW; return wscale * nativeH > this._panelHeight ? this._panelHeight / nativeH : wscale; } ScreenToLocalTransform = () => { if (this._mainCont && this._mainCont.children) { - let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.children[0].firstChild as HTMLElement); - scale = Utils.GetScreenTransform(this._mainCont).scale; + const { translateX, translateY } = Utils.GetScreenTransform(this._mainCont.children[0].firstChild as HTMLElement); + const scale = Utils.GetScreenTransform(this._mainCont).scale; return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(1 / this.contentScaling() / scale); } return Transform.Identity(); @@ -657,7 +657,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> { @computed get docView() { if (!this._document) return (null); const document = this._document; - let resolvedDataDoc = document.layout instanceof Doc ? document : this._dataDoc; + const resolvedDataDoc = document.layout instanceof Doc ? document : this._dataDoc; return <DocumentView key={document[Id]} Document={document} DataDoc={resolvedDataDoc} diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index df4b00b3a..d697e721b 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -64,9 +64,9 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr if (this._collapsed) { this.props.setDocHeight(this._heading, 20); } else { - let rawHeight = this._contRef.current!.getBoundingClientRect().height + 15; //+ 15 accounts for the group header - let transformScale = this.props.screenToLocalTransform().Scale; - let trueHeight = rawHeight * transformScale; + const rawHeight = this._contRef.current!.getBoundingClientRect().height + 15; //+ 15 accounts for the group header + const transformScale = this.props.screenToLocalTransform().Scale; + const trueHeight = rawHeight * transformScale; this.props.setDocHeight(this._heading, trueHeight); } } @@ -77,8 +77,8 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr if (de.data instanceof DragManager.DocumentDragData) { (this.props.parent.Document.dropConverter instanceof ScriptField) && this.props.parent.Document.dropConverter.script.run({ dragData: de.data }); - let key = StrCast(this.props.parent.props.Document.sectionFilter); - let castedValue = this.getValue(this._heading); + const key = StrCast(this.props.parent.props.Document.sectionFilter); + const castedValue = this.getValue(this._heading); de.data.droppedDocuments.forEach(d => d[key] = castedValue); this.props.parent.drop(e, de); e.stopPropagation(); @@ -86,7 +86,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr }); getValue = (value: string): any => { - let parsed = parseInt(value); + const parsed = parseInt(value); if (!isNaN(parsed)) return parsed; if (value.toLowerCase().indexOf("true") > -1) return true; if (value.toLowerCase().indexOf("false") > -1) return false; @@ -96,8 +96,8 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr @action headingChanged = (value: string, shiftDown?: boolean) => { this._createAliasSelected = false; - let key = StrCast(this.props.parent.props.Document.sectionFilter); - let castedValue = this.getValue(value); + const key = StrCast(this.props.parent.props.Document.sectionFilter); + const castedValue = this.getValue(value); if (castedValue) { if (this.props.parent.sectionHeaders) { if (this.props.parent.sectionHeaders.map(i => i.heading).indexOf(castedValue.toString()) > -1) { @@ -135,18 +135,18 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr @action addDocument = (value: string, shiftDown?: boolean) => { this._createAliasSelected = false; - let key = StrCast(this.props.parent.props.Document.sectionFilter); - let newDoc = Docs.Create.TextDocument({ height: 18, width: 200, title: value }); + const key = StrCast(this.props.parent.props.Document.sectionFilter); + const newDoc = Docs.Create.TextDocument({ height: 18, width: 200, title: value }); newDoc[key] = this.getValue(this.props.heading); return this.props.parent.props.addDocument(newDoc); } deleteRow = undoBatch(action(() => { this._createAliasSelected = false; - let key = StrCast(this.props.parent.props.Document.sectionFilter); + const key = StrCast(this.props.parent.props.Document.sectionFilter); this.props.docList.forEach(d => d[key] = undefined); if (this.props.parent.sectionHeaders && this.props.headingObject) { - let index = this.props.parent.sectionHeaders.indexOf(this.props.headingObject); + const index = this.props.parent.sectionHeaders.indexOf(this.props.headingObject); this.props.parent.sectionHeaders.splice(index, 1); } })); @@ -162,18 +162,18 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr } startDrag = (e: PointerEvent) => { - let [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y); + const [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y); if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) { - let alias = Doc.MakeAlias(this.props.parent.props.Document); - let key = StrCast(this.props.parent.props.Document.sectionFilter); + const alias = Doc.MakeAlias(this.props.parent.props.Document); + const key = StrCast(this.props.parent.props.Document.sectionFilter); let value = this.getValue(this._heading); value = typeof value === "string" ? `"${value}"` : value; - let script = `return doc.${key} === ${value}`; - let compiled = CompileScript(script, { params: { doc: Doc.name } }); + const script = `return doc.${key} === ${value}`; + const compiled = CompileScript(script, { params: { doc: Doc.name } }); if (compiled.compiled) { - let scriptField = new ScriptField(compiled); + const scriptField = new ScriptField(compiled); alias.viewSpecScript = scriptField; - let dragData = new DragManager.DocumentDragData([alias]); + const dragData = new DragManager.DocumentDragData([alias]); DragManager.StartDocumentDrag([this._headerRef.current!], dragData, e.clientX, e.clientY); } @@ -196,7 +196,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr e.stopPropagation(); e.preventDefault(); - let [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX, e.clientY); + const [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX, e.clientY); this._startDragPosition = { x: dx, y: dy }; if (this._createAliasSelected) { @@ -209,17 +209,17 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr } renderColorPicker = () => { - let selected = this.props.headingObject ? this.props.headingObject.color : "#f1efeb"; + const selected = this.props.headingObject ? this.props.headingObject.color : "#f1efeb"; - let pink = PastelSchemaPalette.get("pink2"); - let purple = PastelSchemaPalette.get("purple4"); - let blue = PastelSchemaPalette.get("bluegreen1"); - let yellow = PastelSchemaPalette.get("yellow4"); - let red = PastelSchemaPalette.get("red2"); - let green = PastelSchemaPalette.get("bluegreen7"); - let cyan = PastelSchemaPalette.get("bluegreen5"); - let orange = PastelSchemaPalette.get("orange1"); - let gray = "#f1efeb"; + const pink = PastelSchemaPalette.get("pink2"); + const purple = PastelSchemaPalette.get("purple4"); + const blue = PastelSchemaPalette.get("bluegreen1"); + const yellow = PastelSchemaPalette.get("yellow4"); + const red = PastelSchemaPalette.get("red2"); + const green = PastelSchemaPalette.get("bluegreen7"); + const cyan = PastelSchemaPalette.get("bluegreen5"); + const orange = PastelSchemaPalette.get("orange1"); + const gray = "#f1efeb"; return ( <div className="collectionStackingView-colorPicker"> @@ -242,7 +242,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr toggleVisibility = action(() => this._collapsed = !this._collapsed); renderMenu = () => { - let selected = this._createAliasSelected; + const selected = this._createAliasSelected; return (<div className="collectionStackingView-optionPicker"> <div className="optionOptions"> <div className={"optionPicker" + (selected === true ? " active" : "")} onClick={this.toggleAlias}>Create Alias</div> @@ -258,10 +258,10 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr } @computed get contentLayout() { - let rows = Math.max(1, Math.min(this.props.docList.length, Math.floor((this.props.parent.props.PanelWidth() - 2 * this.props.parent.xMargin) / (this.props.parent.columnWidth + this.props.parent.gridGap)))); - let style = this.props.parent; const collapsed = this._collapsed; - let chromeStatus = this.props.parent.props.Document.chromeStatus; - let newEditableViewProps = { + const rows = Math.max(1, Math.min(this.props.docList.length, Math.floor((this.props.parent.props.PanelWidth() - 2 * this.props.parent.xMargin) / (this.props.parent.columnWidth + this.props.parent.gridGap)))); + const style = this.props.parent; const collapsed = this._collapsed; + const chromeStatus = this.props.parent.props.Document.chromeStatus; + const newEditableViewProps = { GetValue: () => "", SetValue: this.addDocument, contents: "+ NEW", @@ -293,10 +293,10 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr } @computed get headingView() { - let heading = this._heading; - let key = StrCast(this.props.parent.props.Document.sectionFilter); - let evContents = heading ? heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`; - let headerEditableViewProps = { + const heading = this._heading; + const key = StrCast(this.props.parent.props.Document.sectionFilter); + const evContents = heading ? heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`; + const headerEditableViewProps = { GetValue: () => evContents, SetValue: this.headingChanged, contents: evContents, @@ -343,8 +343,8 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr } render() { const background = this._background; //to account for observables in Measure - let contentlayout = this.contentLayout; - let headingview = this.headingView; + const contentlayout = this.contentLayout; + const headingview = this.headingView; return <Measure offset onResize={this.handleResize}> {({ measureRef }) => { return <div ref={measureRef}> diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 54a36f691..1700c14cf 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -1,7 +1,7 @@ import React = require("react"); -import { action, computed, observable, trace, untracked, toJS } from "mobx"; +import { action, observable } from "mobx"; import { observer } from "mobx-react"; -import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, Column } from "react-table"; +import { CellInfo } from "react-table"; import "react-table/react-table.css"; import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils"; import { Doc, DocListCast, DocListCastAsync, Field, Opt } from "../../../new_fields/Doc"; @@ -9,7 +9,7 @@ import { Id } from "../../../new_fields/FieldSymbols"; import { SetupDrag, DragManager } from "../../util/DragManager"; import { CompileScript } from "../../util/Scripting"; import { Transform } from "../../util/Transform"; -import { COLLECTION_BORDER_WIDTH, MAX_ROW_HEIGHT } from '../globalCssVariables.scss'; +import { MAX_ROW_HEIGHT } from '../globalCssVariables.scss'; import '../DocumentDecorations.scss'; import { EditableView } from "../EditableView"; import { FieldView, FieldViewProps } from "../nodes/FieldView"; @@ -89,8 +89,8 @@ export class CollectionSchemaCell extends React.Component<CellProps> { // this._isEditing = true; // this.props.setIsEditing(true); - let field = this.props.rowProps.original[this.props.rowProps.column.id!]; - let doc = FieldValue(Cast(field, Doc)); + const field = this.props.rowProps.original[this.props.rowProps.column.id!]; + const doc = FieldValue(Cast(field, Doc)); if (typeof field === "object" && doc) this.props.setPreviewDoc(doc); } @@ -106,12 +106,12 @@ export class CollectionSchemaCell extends React.Component<CellProps> { private drop = (e: Event, de: DragManager.DropEvent) => { if (de.data instanceof DragManager.DocumentDragData) { - let fieldKey = this.props.rowProps.column.id as string; + const fieldKey = this.props.rowProps.column.id as string; if (de.data.draggedDocuments.length === 1) { this._document[fieldKey] = de.data.draggedDocuments[0]; } else { - let coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title", "#f1efeb")], de.data.draggedDocuments, {}); + const coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title", "#f1efeb")], de.data.draggedDocuments, {}); this._document[fieldKey] = coll; } e.stopPropagation(); @@ -138,9 +138,9 @@ export class CollectionSchemaCell extends React.Component<CellProps> { // } renderCellWithType(type: string | undefined) { - let dragRef: React.RefObject<HTMLDivElement> = React.createRef(); + const dragRef: React.RefObject<HTMLDivElement> = React.createRef(); - let props: FieldViewProps = { + const props: FieldViewProps = { Document: this.props.rowProps.original, DataDoc: this.props.rowProps.original, fieldKey: this.props.rowProps.column.id as string, @@ -161,23 +161,23 @@ export class CollectionSchemaCell extends React.Component<CellProps> { ContentScaling: returnOne }; - let field = props.Document[props.fieldKey]; - let doc = FieldValue(Cast(field, Doc)); - let fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc); + const field = props.Document[props.fieldKey]; + const doc = FieldValue(Cast(field, Doc)); + const fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc); - let onItemDown = (e: React.PointerEvent) => { + const onItemDown = (e: React.PointerEvent) => { if (fieldIsDoc) { SetupDrag(this._focusRef, () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document, this._document[props.fieldKey] instanceof Doc ? (doc: Doc, target: Doc, addDoc: (newDoc: Doc) => any) => addDoc(doc) : this.props.moveDocument, this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e); } }; - let onPointerEnter = (e: React.PointerEvent): void => { + const onPointerEnter = (e: React.PointerEvent): void => { if (e.buttons === 1 && SelectionManager.GetIsDragging() && (type === "document" || type === undefined)) { dragRef.current!.className = "collectionSchemaView-cellContainer doc-drag-over"; } }; - let onPointerLeave = (e: React.PointerEvent): void => { + const onPointerLeave = (e: React.PointerEvent): void => { dragRef.current!.className = "collectionSchemaView-cellContainer"; }; @@ -187,7 +187,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> { if (type === "string") contents = typeof field === "string" ? (StrCast(field) === "" ? "--" : StrCast(field)) : "--" + typeof field + "--"; if (type === "boolean") contents = typeof field === "boolean" ? (BoolCast(field) ? "true" : "false") : "--" + typeof field + "--"; if (type === "document") { - let doc = FieldValue(Cast(field, Doc)); + const doc = FieldValue(Cast(field, Doc)); contents = typeof field === "object" ? doc ? StrCast(doc.title) === "" ? "--" : StrCast(doc.title) : `--${typeof field}--` : `--${typeof field}--`; } @@ -215,7 +215,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> { height={"auto"} maxHeight={Number(MAX_ROW_HEIGHT)} GetValue={() => { - let field = props.Document[props.fieldKey]; + const field = props.Document[props.fieldKey]; if (Field.IsField(field)) { return Field.toScriptString(field); } @@ -226,7 +226,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> { if (value.startsWith(":=")) { return this.props.setComputed(value.substring(2), props.Document, this.props.rowProps.column.id!, this.props.row, this.props.col); } - let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } }); + const script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } }); if (!script.compiled) { return false; } @@ -287,15 +287,15 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell { @action toggleChecked = (e: React.ChangeEvent<HTMLInputElement>) => { this._isChecked = e.target.checked; - let script = CompileScript(e.target.checked.toString(), { requiredType: "boolean", addReturn: true, params: { this: Doc.name } }); + const script = CompileScript(e.target.checked.toString(), { requiredType: "boolean", addReturn: true, params: { this: Doc.name } }); if (script.compiled) { this.applyToDoc(this._document, this.props.row, this.props.col, script.run); } } render() { - let reference = React.createRef<HTMLDivElement>(); - let onItemDown = (e: React.PointerEvent) => { + const reference = React.createRef<HTMLDivElement>(); + const onItemDown = (e: React.PointerEvent) => { (!this.props.CollectionView || !this.props.CollectionView.props.isSelected() ? undefined : SetupDrag(reference, () => this._document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); }; diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index d24f63fbb..0114342b9 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -1,5 +1,5 @@ import React = require("react"); -import { action, computed, observable, trace, untracked } from "mobx"; +import { action, observable } from "mobx"; import { observer } from "mobx-react"; import "./CollectionSchemaView.scss"; import { faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faSortAmountDown, faSortAmountUp, faTimes } from '@fortawesome/free-solid-svg-icons'; @@ -7,10 +7,8 @@ import { library, IconProp } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Flyout, anchorPoints } from "../DocumentDecorations"; import { ColumnType } from "./CollectionSchemaView"; -import { emptyFunction } from "../../../Utils"; -import { contains } from "typescript-collections/dist/lib/arrays"; import { faFile } from "@fortawesome/free-regular-svg-icons"; -import { SchemaHeaderField, RandomPastel, PastelSchemaPalette } from "../../../new_fields/SchemaHeaderField"; +import { SchemaHeaderField, PastelSchemaPalette } from "../../../new_fields/SchemaHeaderField"; import { undoBatch } from "../../util/UndoManager"; library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faFile as any, faSortAmountDown, faSortAmountUp, faTimes); @@ -32,7 +30,7 @@ export interface HeaderProps { export class CollectionSchemaHeader extends React.Component<HeaderProps> { render() { - let icon: IconProp = this.props.keyType === ColumnType.Number ? "hashtag" : this.props.keyType === ColumnType.String ? "font" : + const icon: IconProp = this.props.keyType === ColumnType.Number ? "hashtag" : this.props.keyType === ColumnType.String ? "font" : this.props.keyType === ColumnType.Boolean ? "check-square" : this.props.keyType === ColumnType.Doc ? "file" : "align-justify"; return ( <div className="collectionSchemaView-header" style={{ background: this.props.keyValue.color }}> @@ -139,7 +137,7 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps> renderTypes = () => { if (this.props.typeConst) return <></>; - let type = this.props.columnField.type; + const type = this.props.columnField.type; return ( <div className="collectionSchema-headerMenu-group"> <label>Column type:</label> @@ -170,7 +168,7 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps> } renderSorting = () => { - let sort = this.props.columnField.desc; + const sort = this.props.columnField.desc; return ( <div className="collectionSchema-headerMenu-group"> <label>Sort by:</label> @@ -193,14 +191,14 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps> } renderColors = () => { - let selected = this.props.columnField.color; + const selected = this.props.columnField.color; - let pink = PastelSchemaPalette.get("pink2"); - let purple = PastelSchemaPalette.get("purple2"); - let blue = PastelSchemaPalette.get("bluegreen1"); - let yellow = PastelSchemaPalette.get("yellow4"); - let red = PastelSchemaPalette.get("red2"); - let gray = "#f1efeb"; + const pink = PastelSchemaPalette.get("pink2"); + const purple = PastelSchemaPalette.get("purple2"); + const blue = PastelSchemaPalette.get("bluegreen1"); + const yellow = PastelSchemaPalette.get("yellow4"); + const red = PastelSchemaPalette.get("red2"); + const gray = "#f1efeb"; return ( <div className="collectionSchema-headerMenu-group"> @@ -291,8 +289,8 @@ class KeysDropdown extends React.Component<KeysDropdownProps> { @action onKeyDown = (e: React.KeyboardEvent): void => { if (e.key === "Enter") { - let keyOptions = this._searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1); - let exactFound = keyOptions.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1 || + const keyOptions = this._searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1); + const exactFound = keyOptions.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1 || this.props.existingKeys.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1; if (!exactFound && this._searchTerm !== "" && this.props.canAddNew) { @@ -334,11 +332,11 @@ class KeysDropdown extends React.Component<KeysDropdownProps> { renderOptions = (): JSX.Element[] | JSX.Element => { if (!this._isOpen) return <></>; - let keyOptions = this._searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1); - let exactFound = keyOptions.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1 || + const keyOptions = this._searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1); + const exactFound = keyOptions.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1 || this.props.existingKeys.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1; - let options = keyOptions.map(key => { + const options = keyOptions.map(key => { return <div key={key} className="key-option" onClick={() => { this.onSelect(key); this.setSearchTerm(""); }}>{key}</div>; }); diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 274c8b6d1..90320df82 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -1,18 +1,18 @@ import React = require("react"); -import { ReactTableDefaults, TableCellRenderer, ComponentPropsGetterR, ComponentPropsGetter0, RowInfo } from "react-table"; +import { ReactTableDefaults, TableCellRenderer, RowInfo } from "react-table"; import "./CollectionSchemaView.scss"; import { Transform } from "../../util/Transform"; import { Doc } from "../../../new_fields/Doc"; import { DragManager, SetupDrag } from "../../util/DragManager"; import { SelectionManager } from "../../util/SelectionManager"; -import { Cast, FieldValue, StrCast } from "../../../new_fields/Types"; +import { Cast, FieldValue } from "../../../new_fields/Types"; import { ContextMenu } from "../ContextMenu"; import { action } from "mobx"; import { library } from '@fortawesome/fontawesome-svg-core'; import { faGripVertical, faTrash } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { DocumentManager } from "../../util/DocumentManager"; -import { PastelSchemaPalette, SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; +import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { undoBatch } from "../../util/UndoManager"; library.add(faGripVertical, faTrash); @@ -43,10 +43,10 @@ export class MovableColumn extends React.Component<MovableColumnProps> { document.removeEventListener("pointermove", this.onPointerMove); } onDragMove = (e: PointerEvent): void => { - let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); - let rect = this._header!.current!.getBoundingClientRect(); - let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + ((rect.right - rect.left) / 2), rect.top); - let before = x[0] < bounds[0]; + const x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); + const rect = this._header!.current!.getBoundingClientRect(); + const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + ((rect.right - rect.left) / 2), rect.top); + const before = x[0] < bounds[0]; this._header!.current!.className = "collectionSchema-col-wrapper"; if (before) this._header!.current!.className += " col-before"; if (!before) this._header!.current!.className += " col-after"; @@ -62,10 +62,10 @@ export class MovableColumn extends React.Component<MovableColumnProps> { colDrop = (e: Event, de: DragManager.DropEvent) => { document.removeEventListener("pointermove", this.onDragMove, true); - let x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y); - let rect = this._header!.current!.getBoundingClientRect(); - let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + ((rect.right - rect.left) / 2), rect.top); - let before = x[0] < bounds[0]; + const x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y); + const rect = this._header!.current!.getBoundingClientRect(); + const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + ((rect.right - rect.left) / 2), rect.top); + const before = x[0] < bounds[0]; if (de.data instanceof DragManager.ColumnDragData) { this.props.reorderColumns(de.data.colKey, this.props.columnValue, before, this.props.allColumns); return true; @@ -74,21 +74,21 @@ export class MovableColumn extends React.Component<MovableColumnProps> { } onPointerMove = (e: PointerEvent) => { - let onRowMove = (e: PointerEvent) => { + const onRowMove = (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); document.removeEventListener("pointermove", onRowMove); document.removeEventListener('pointerup', onRowUp); - let dragData = new DragManager.ColumnDragData(this.props.columnValue); + const dragData = new DragManager.ColumnDragData(this.props.columnValue); DragManager.StartColumnDrag(this._dragRef.current!, dragData, e.x, e.y); }; - let onRowUp = (): void => { + const onRowUp = (): void => { document.removeEventListener("pointermove", onRowMove); document.removeEventListener('pointerup', onRowUp); }; if (e.buttons === 1) { - let [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y); + const [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y); if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) { document.removeEventListener("pointermove", this.onPointerMove); e.stopPropagation(); @@ -106,14 +106,14 @@ export class MovableColumn extends React.Component<MovableColumnProps> { @action onPointerDown = (e: React.PointerEvent, ref: React.RefObject<HTMLDivElement>) => { this._dragRef = ref; - let [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX, e.clientY); + const [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX, e.clientY); this._startDragPosition = { x: dx, y: dy }; document.addEventListener("pointermove", this.onPointerMove); } render() { - let reference = React.createRef<HTMLDivElement>(); + const reference = React.createRef<HTMLDivElement>(); return ( <div className="collectionSchema-col" ref={this.createColDropTarget}> @@ -152,10 +152,10 @@ export class MovableRow extends React.Component<MovableRowProps> { document.removeEventListener("pointermove", this.onDragMove, true); } onDragMove = (e: PointerEvent): void => { - let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); - let rect = this._header!.current!.getBoundingClientRect(); - let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); - let before = x[1] < bounds[1]; + const x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); + const rect = this._header!.current!.getBoundingClientRect(); + const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); + const before = x[1] < bounds[1]; this._header!.current!.className = "collectionSchema-row-wrapper"; if (before) this._header!.current!.className += " row-above"; if (!before) this._header!.current!.className += " row-below"; @@ -173,16 +173,16 @@ export class MovableRow extends React.Component<MovableRowProps> { const rowDoc = FieldValue(Cast(this.props.rowInfo.original, Doc)); if (!rowDoc) return false; - let x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y); - let rect = this._header!.current!.getBoundingClientRect(); - let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); - let before = x[1] < bounds[1]; + const x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y); + const rect = this._header!.current!.getBoundingClientRect(); + const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); + const before = x[1] < bounds[1]; if (de.data instanceof DragManager.DocumentDragData) { e.stopPropagation(); if (de.data.draggedDocuments[0] === rowDoc) return true; - let addDocument = (doc: Doc) => this.props.addDoc(doc, rowDoc, before); - let movedDocs = de.data.draggedDocuments; + const addDocument = (doc: Doc) => this.props.addDoc(doc, rowDoc, before); + const movedDocs = de.data.draggedDocuments; return (de.data.dropAction || de.data.userDropAction) ? de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false) : (de.data.moveDocument) ? @@ -193,14 +193,14 @@ export class MovableRow extends React.Component<MovableRowProps> { } onRowContextMenu = (e: React.MouseEvent): void => { - let description = this.props.rowWrapped ? "Unwrap text on row" : "Text wrap row"; + const description = this.props.rowWrapped ? "Unwrap text on row" : "Text wrap row"; ContextMenu.Instance.addItem({ description: description, event: () => this.props.textWrapRow(this.props.rowInfo.original), icon: "file-pdf" }); } @undoBatch @action move: DragManager.MoveFunction = (doc: Doc, target: Doc, addDoc) => { - let targetView = DocumentManager.Instance.getDocumentView(target); + const targetView = DocumentManager.Instance.getDocumentView(target); if (targetView && targetView.props.ContainingCollectionDoc) { return doc !== target && doc !== targetView.props.ContainingCollectionDoc && this.props.removeDoc(doc) && addDoc(doc); } @@ -217,8 +217,8 @@ export class MovableRow extends React.Component<MovableRowProps> { const doc = FieldValue(Cast(original, Doc)); if (!doc) return <></>; - let reference = React.createRef<HTMLDivElement>(); - let onItemDown = SetupDrag(reference, () => doc, this.move); + const reference = React.createRef<HTMLDivElement>(); + const onItemDown = SetupDrag(reference, () => doc, this.move); let className = "collectionSchema-row"; if (this.props.rowFocused) className += " row-focused"; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 65856cad3..f336eaf75 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -94,11 +94,11 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } @action onDividerMove = (e: PointerEvent): void => { - let nativeWidth = this._mainCont!.getBoundingClientRect(); - let minWidth = 40; - let maxWidth = 1000; - let movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]; - let width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth; + const nativeWidth = this._mainCont!.getBoundingClientRect(); + const minWidth = 40; + const maxWidth = 1000; + const movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]; + const width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth; this.props.Document.schemaPreviewWidth = width; } @action @@ -136,7 +136,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get previewPanel() { - let layoutDoc = this.previewDocument ? Doc.expandTemplateLayout(this.previewDocument, this.props.DataDoc) : undefined; + const layoutDoc = this.previewDocument ? Doc.expandTemplateLayout(this.previewDocument, this.props.DataDoc) : undefined; return <div ref={this.createTarget}> <ContentFittingDocumentView Document={layoutDoc} @@ -258,11 +258,11 @@ export class SchemaTable extends React.Component<SchemaTableProps> { @computed get childDocs() { if (this.props.childDocs) return this.props.childDocs; - let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + const doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; return DocListCast(doc[this.props.fieldKey]); } set childDocs(docs: Doc[]) { - let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + const doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; doc[this.props.fieldKey] = new List<Doc>(docs); } @@ -288,12 +288,12 @@ export class SchemaTable extends React.Component<SchemaTableProps> { @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } @computed get tableColumns(): Column<Doc>[] { - let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.heading.toUpperCase() === key.toUpperCase()) === -1); - let columns: Column<Doc>[] = []; - let tableIsFocused = this.props.isFocused(this.props.Document); - let focusedRow = this._focusedCell.row; - let focusedCol = this._focusedCell.col; - let isEditable = !this._headerIsEditing; + const possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.heading.toUpperCase() === key.toUpperCase()) === -1); + const columns: Column<Doc>[] = []; + const tableIsFocused = this.props.isFocused(this.props.Document); + const focusedRow = this._focusedCell.row; + const focusedCol = this._focusedCell.col; + const isEditable = !this._headerIsEditing; if (this.childDocs.reduce((found, doc) => found || doc.type === "collection", false)) { columns.push( @@ -313,8 +313,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> { ); } - let cols = this.columns.map(col => { - let header = <CollectionSchemaHeader + const cols = this.columns.map(col => { + const header = <CollectionSchemaHeader keyValue={col} possibleKeys={possibleKeys} existingKeys={this.columns.map(c => c.heading)} @@ -333,11 +333,11 @@ export class SchemaTable extends React.Component<SchemaTableProps> { accessor: (doc: Doc) => doc ? doc[col.heading] : 0, id: col.heading, Cell: (rowProps: CellInfo) => { - let rowIndex = rowProps.index; - let columnIndex = this.columns.map(c => c.heading).indexOf(rowProps.column.id!); - let isFocused = focusedRow === rowIndex && focusedCol === columnIndex && tableIsFocused; + const rowIndex = rowProps.index; + const columnIndex = this.columns.map(c => c.heading).indexOf(rowProps.column.id!); + const isFocused = focusedRow === rowIndex && focusedCol === columnIndex && tableIsFocused; - let props: CellProps = { + const props: CellProps = { row: rowIndex, col: columnIndex, rowProps: rowProps, @@ -358,7 +358,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { getField: this.getField, }; - let colType = this.getColumnType(col); + const colType = this.getColumnType(col); if (colType === ColumnType.Number) return <CollectionSchemaNumberCell {...props} />; if (colType === ColumnType.String) return <CollectionSchemaStringCell {...props} />; if (colType === ColumnType.Boolean) return <CollectionSchemaCheckboxCell {...props} />; @@ -384,9 +384,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> { constructor(props: SchemaTableProps) { super(props); // convert old schema columns (list of strings) into new schema columns (list of schema header fields) - let oldSchemaColumns = Cast(this.props.Document.schemaColumns, listSpec("string"), []); + const oldSchemaColumns = Cast(this.props.Document.schemaColumns, listSpec("string"), []); if (oldSchemaColumns && oldSchemaColumns.length && typeof oldSchemaColumns[0] !== "object") { - let newSchemaColumns = oldSchemaColumns.map(i => typeof i === "string" ? new SchemaHeaderField(i, "#f1efeb") : i); + const newSchemaColumns = oldSchemaColumns.map(i => typeof i === "string" ? new SchemaHeaderField(i, "#f1efeb") : i); this.props.Document.schemaColumns = new List<SchemaHeaderField>(newSchemaColumns); } } @@ -418,10 +418,10 @@ export class SchemaTable extends React.Component<SchemaTableProps> { private getTdProps: ComponentPropsGetterR = (state, rowInfo, column, instance) => { if (!rowInfo || column) return {}; - let row = rowInfo.index; + const row = rowInfo.index; //@ts-ignore - let col = this.columns.map(c => c.heading).indexOf(column!.id); - let isFocused = this._focusedCell.row === row && this._focusedCell.col === col && this.props.isFocused(this.props.Document); + const col = this.columns.map(c => c.heading).indexOf(column!.id); + const isFocused = this._focusedCell.row === row && this._focusedCell.col === col && this.props.isFocused(this.props.Document); // TODO: editing border doesn't work :( return { style: { @@ -432,7 +432,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { @action onCloseCollection = (collection: Doc): void => { - let index = this._openCollections.findIndex(col => col === collection[Id]); + const index = this._openCollections.findIndex(col => col === collection[Id]); if (index > -1) this._openCollections.splice(index, 1); } @@ -450,7 +450,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { @action onKeyDown = (e: KeyboardEvent): void => { if (!this._cellIsEditing && !this._headerIsEditing && this.props.isFocused(this.props.Document)) {// && this.props.isSelected(true)) { - let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : ""; + const direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : ""; this._focusedCell = this.changeFocusedCellByDirection(direction, this._focusedCell.row, this._focusedCell.col); const pdoc = FieldValue(this.childDocs[this._focusedCell.row]); @@ -479,7 +479,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { @undoBatch createRow = () => { - let newDoc = Docs.Create.TextDocument({ title: "", width: 100, height: 30 }); + const newDoc = Docs.Create.TextDocument({ title: "", width: 100, height: 30 }); this.props.addDocument(newDoc); } @@ -498,7 +498,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { @undoBatch @action deleteColumn = (key: string) => { - let columns = this.columns; + const columns = this.columns; if (columns === undefined) { this.columns = new List<SchemaHeaderField>([]); } else { @@ -513,7 +513,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { @undoBatch @action changeColumns = (oldKey: string, newKey: string, addNew: boolean) => { - let columns = this.columns; + const columns = this.columns; if (columns === undefined) { this.columns = new List<SchemaHeaderField>([new SchemaHeaderField(newKey, "f1efeb")]); } else { @@ -523,7 +523,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { } else { const index = columns.map(c => c.heading).indexOf(oldKey); if (index > -1) { - let column = columns[index]; + const column = columns[index]; column.setHeading(newKey); columns[index] = column; this.columns = columns; @@ -554,8 +554,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> { setColumnType = (columnField: SchemaHeaderField, type: ColumnType): void => { if (columnTypes.get(columnField.heading)) return; - let columns = this.columns; - let index = columns.indexOf(columnField); + const columns = this.columns; + const index = columns.indexOf(columnField); if (index > -1) { columnField.setType(NumCast(type)); columns[index] = columnField; @@ -575,8 +575,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> { @undoBatch setColumnColor = (columnField: SchemaHeaderField, color: string): void => { - let columns = this.columns; - let index = columns.indexOf(columnField); + const columns = this.columns; + const index = columns.indexOf(columnField); if (index > -1) { columnField.setColor(color); columns[index] = columnField; @@ -589,10 +589,10 @@ export class SchemaTable extends React.Component<SchemaTableProps> { @undoBatch reorderColumns = (toMove: SchemaHeaderField, relativeTo: SchemaHeaderField, before: boolean, columnsValues: SchemaHeaderField[]) => { - let columns = [...columnsValues]; - let oldIndex = columns.indexOf(toMove); - let relIndex = columns.indexOf(relativeTo); - let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex; + const columns = [...columnsValues]; + const oldIndex = columns.indexOf(toMove); + const relIndex = columns.indexOf(relativeTo); + const newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex; if (oldIndex === newIndex) return; @@ -603,17 +603,17 @@ export class SchemaTable extends React.Component<SchemaTableProps> { @undoBatch @action setColumnSort = (columnField: SchemaHeaderField, descending: boolean | undefined) => { - let columns = this.columns; - let index = columns.findIndex(c => c.heading === columnField.heading); - let column = columns[index]; + const columns = this.columns; + const index = columns.findIndex(c => c.heading === columnField.heading); + const column = columns[index]; column.setDesc(descending); columns[index] = column; this.columns = columns; } get documentKeys() { - let docs = this.childDocs; - let keys: { [key: string]: boolean } = {}; + const docs = this.childDocs; + const keys: { [key: string]: boolean } = {}; // bcz: ugh. this is untracked since otherwise a large collection of documents will blast the server for all their fields. // then as each document's fields come back, we update the documents _proxies. Each time we do this, the whole schema will be // invalidated and re-rendered. This workaround will inquire all of the document fields before the options button is clicked. @@ -628,8 +628,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> { @action toggleTextWrapRow = (doc: Doc): void => { - let textWrapped = this.textWrappedRows; - let index = textWrapped.findIndex(id => doc[Id] === id); + const textWrapped = this.textWrappedRows; + const index = textWrapped.findIndex(id => doc[Id] === id); index > -1 ? textWrapped.splice(index, 1) : textWrapped.push(doc[Id]); @@ -638,10 +638,10 @@ export class SchemaTable extends React.Component<SchemaTableProps> { @computed get reactTable() { - let children = this.childDocs; - let hasCollectionChild = children.reduce((found, doc) => found || doc.type === "collection", false); - let expandedRowsList = this._openCollections.map(col => children.findIndex(doc => doc[Id] === col).toString()); - let expanded = {}; + const children = this.childDocs; + const hasCollectionChild = children.reduce((found, doc) => found || doc.type === "collection", false); + const expandedRowsList = this._openCollections.map(col => children.findIndex(doc => doc[Id] === col).toString()); + const expanded = {}; //@ts-ignore expandedRowsList.forEach(row => expanded[row] = true); console.log("text wrapped rows", ...[...this.textWrappedRows]); // TODO: get component to rerender on text wrap change without needign to console.log :(((( @@ -668,10 +668,10 @@ export class SchemaTable extends React.Component<SchemaTableProps> { } onResizedChange = (newResized: Resize[], event: any) => { - let columns = this.columns; + const columns = this.columns; newResized.forEach(resized => { - let index = columns.findIndex(c => c.heading === resized.id); - let column = columns[index]; + const index = columns.findIndex(c => c.heading === resized.id); + const column = columns[index]; column.setWidth(resized.value); columns[index] = column; }); @@ -688,16 +688,16 @@ export class SchemaTable extends React.Component<SchemaTableProps> { makeDB = async () => { let csv: string = this.columns.reduce((val, col) => val + col + ",", ""); csv = csv.substr(0, csv.length - 1) + "\n"; - let self = this; + const self = this; this.childDocs.map(doc => { csv += self.columns.reduce((val, col) => val + (doc[col.heading] ? doc[col.heading]!.toString() : "0") + ",", ""); csv = csv.substr(0, csv.length - 1) + "\n"; }); csv.substring(0, csv.length - 1); - let dbName = StrCast(this.props.Document.title); - let res = await Gateway.Instance.PostSchema(csv, dbName); + const dbName = StrCast(this.props.Document.title); + const res = await Gateway.Instance.PostSchema(csv, dbName); if (self.props.CollectionView && self.props.CollectionView.props.addDocument) { - let schemaDoc = await Docs.Create.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }, { dbDoc: self.props.Document }); + const schemaDoc = await Docs.Create.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }, { dbDoc: self.props.Document }); if (schemaDoc) { //self.props.CollectionView.props.addDocument(schemaDoc, false); self.props.Document.schemaDoc = schemaDoc; @@ -706,7 +706,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { } getField = (row: number, col?: number) => { - let docs = this.childDocs; + const docs = this.childDocs; row = row % docs.length; while (row < 0) row += docs.length; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index e564f1193..955fcda80 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -1,7 +1,7 @@ import React = require("react"); import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { CursorProperty } from "csstype"; -import { action, computed, IReactionDisposer, observable, reaction, runInAction, trace } from "mobx"; +import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import Switch from 'rc-switch'; import { Doc, HeightSym, WidthSym } from "../../../new_fields/Doc"; @@ -10,7 +10,7 @@ import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { BoolCast, Cast, NumCast, StrCast, ScriptCast } from "../../../new_fields/Types"; -import { emptyFunction, Utils, numberRange } from "../../../Utils"; +import { emptyFunction, Utils } from "../../../Utils"; import { DocumentType } from "../../documents/DocumentTypes"; import { DragManager } from "../../util/DragManager"; import { Transform } from "../../util/Transform"; @@ -56,15 +56,15 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { children(docs: Doc[]) { this._docXfs.length = 0; return docs.map((d, i) => { - let pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, d); - let layoutDoc = pair.layout ? Doc.Layout(pair.layout) : d; - let width = () => Math.min(layoutDoc.nativeWidth && !layoutDoc.ignoreAspect && !this.props.Document.fillColumn ? layoutDoc[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns); - let height = () => this.getDocHeight(layoutDoc); - let dref = React.createRef<HTMLDivElement>(); - let dxf = () => this.getDocTransform(layoutDoc, dref.current!); + const pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, d); + const layoutDoc = pair.layout ? Doc.Layout(pair.layout) : d; + const width = () => Math.min(layoutDoc.nativeWidth && !layoutDoc.ignoreAspect && !this.props.Document.fillColumn ? layoutDoc[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns); + const height = () => this.getDocHeight(layoutDoc); + const dref = React.createRef<HTMLDivElement>(); + const dxf = () => this.getDocTransform(layoutDoc, dref.current!); this._docXfs.push({ dxf: dxf, width: width, height: height }); - let rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap); - let style = this.isStackingView ? { width: width(), marginTop: i === 0 ? 0 : this.gridGap, height: height() } : { gridRowEnd: `span ${rowSpan}` }; + const rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap); + const style = this.isStackingView ? { width: width(), marginTop: i === 0 ? 0 : this.gridGap, height: height() } : { gridRowEnd: `span ${rowSpan}` }; return <div className={`collectionStackingView-${this.isStackingView ? "columnDoc" : "masonryDoc"}`} key={d[Id]} ref={dref} style={style} > {this.getDisplayDoc(pair.layout || d, pair.data, dxf, width)} </div>; @@ -83,20 +83,20 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { return new Map<SchemaHeaderField, Doc[]>(); } const sectionHeaders = this.sectionHeaders; - let fields = new Map<SchemaHeaderField, Doc[]>(sectionHeaders.map(sh => [sh, []] as [SchemaHeaderField, []])); + const fields = new Map<SchemaHeaderField, Doc[]>(sectionHeaders.map(sh => [sh, []] as [SchemaHeaderField, []])); this.filteredChildren.map(d => { - let sectionValue = (d[this.sectionFilter] ? d[this.sectionFilter] : `NO ${this.sectionFilter.toUpperCase()} VALUE`) as object; + const sectionValue = (d[this.sectionFilter] ? d[this.sectionFilter] : `NO ${this.sectionFilter.toUpperCase()} VALUE`) as object; // the next five lines ensures that floating point rounding errors don't create more than one section -syip - let parsed = parseInt(sectionValue.toString()); - let castedSectionValue = !isNaN(parsed) ? parsed : sectionValue; + const parsed = parseInt(sectionValue.toString()); + const castedSectionValue = !isNaN(parsed) ? parsed : sectionValue; // look for if header exists already - let existingHeader = sectionHeaders.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.sectionFilter.toUpperCase()} VALUE`)); + const existingHeader = sectionHeaders.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.sectionFilter.toUpperCase()} VALUE`)); if (existingHeader) { fields.get(existingHeader)!.push(d); } else { - let newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `NO ${this.sectionFilter.toUpperCase()} VALUE`); + const newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `NO ${this.sectionFilter.toUpperCase()} VALUE`); fields.set(newSchemaHeader, [d]); sectionHeaders.push(newSchemaHeader); } @@ -108,26 +108,26 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { super.componentDidMount(); this._heightDisposer = reaction(() => { if (this.props.Document.autoHeight) { - let sectionsList = Array.from(this.Sections.size ? this.Sections.values() : [this.filteredChildren]); + const sectionsList = Array.from(this.Sections.size ? this.Sections.values() : [this.filteredChildren]); if (this.isStackingView) { - let res = this.props.ContentScaling() * sectionsList.reduce((maxHght, s) => { - let r1 = Math.max(maxHght, + const res = this.props.ContentScaling() * sectionsList.reduce((maxHght, s) => { + const r1 = Math.max(maxHght, (this.Sections.size ? 50 : 0) + s.reduce((height, d, i) => { - let val = height + this.childDocHeight(d) + (i === s.length - 1 ? this.yMargin : this.gridGap); + const val = height + this.childDocHeight(d) + (i === s.length - 1 ? this.yMargin : this.gridGap); return val; }, this.yMargin)); return r1; }, 0); return res; } else { - let sum = Array.from(this._heightMap.values()).reduce((acc: number, curr: number) => acc += curr, 0); + const sum = Array.from(this._heightMap.values()).reduce((acc: number, curr: number) => acc += curr, 0); return this.props.ContentScaling() * (sum + (this.Sections.size ? (this.props.Document.miniHeaders ? 20 : 85) : -15)); } } return -1; }, (hgt: number) => { - let doc = hgt === -1 ? undefined : this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc; + const doc = hgt === -1 ? undefined : this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc; doc && hgt > 0 && (Doc.Layout(doc).height = hgt); }, { fireImmediately: true } @@ -162,9 +162,9 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @computed get onClickHandler() { return ScriptCast(this.Document.onChildClick); } getDisplayDoc(doc: Doc, dataDoc: Doc | undefined, dxf: () => Transform, width: () => number) { - let layoutDoc = Doc.Layout(doc); - let height = () => this.getDocHeight(doc); - let finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]()); + const layoutDoc = Doc.Layout(doc); + const height = () => this.getDocHeight(doc); + const finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]()); return <ContentFittingDocumentView Document={doc} DataDocument={dataDoc} @@ -192,12 +192,12 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } getDocHeight(d?: Doc) { if (!d) return 0; - let layoutDoc = Doc.Layout(d); - let nw = NumCast(layoutDoc.nativeWidth); - let nh = NumCast(layoutDoc.nativeHeight); + const layoutDoc = Doc.Layout(d); + const nw = NumCast(layoutDoc.nativeWidth); + const nh = NumCast(layoutDoc.nativeHeight); let wid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1); if (!layoutDoc.ignoreAspect && !layoutDoc.fitWidth && nw && nh) { - let aspect = nw && nh ? nh / nw : 1; + const aspect = nw && nh ? nh / nw : 1; if (!(d.nativeWidth && !layoutDoc.ignoreAspect && this.props.Document.fillColumn)) wid = Math.min(layoutDoc[WidthSym](), wid); return wid * aspect; } @@ -215,8 +215,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } @action onDividerMove = (e: PointerEvent): void => { - let dragPos = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0]; - let delta = dragPos - this._columnStart; + const dragPos = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0]; + const delta = dragPos - this._columnStart; this._columnStart = dragPos; this.layoutDoc.columnWidth = Math.max(10, this.columnWidth + delta); } @@ -238,13 +238,13 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @undoBatch @action drop = (e: Event, de: DragManager.DropEvent) => { - let where = [de.x, de.y]; + const where = [de.x, de.y]; let targInd = -1; let plusOne = false; if (de.data instanceof DragManager.DocumentDragData) { this._docXfs.map((cd, i) => { - let pos = cd.dxf().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap); - let pos1 = cd.dxf().inverse().transformPoint(cd.width(), cd.height()); + const pos = cd.dxf().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap); + const pos1 = cd.dxf().inverse().transformPoint(cd.width(), cd.height()); if (where[0] > pos[0] && where[0] < pos1[0] && where[1] > pos[1] && where[1] < pos1[1]) { targInd = i; plusOne = (where[1] > (pos[1] + pos1[1]) / 2 ? 1 : 0) ? true : false; @@ -252,12 +252,12 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { }); } if (super.drop(e, de)) { - let newDoc = de.data.droppedDocuments[0]; - let docs = this.childDocList; + const newDoc = de.data.droppedDocuments[0]; + const docs = this.childDocList; if (docs) { if (targInd === -1) targInd = docs.length; else targInd = docs.indexOf(this.filteredChildren[targInd]); - let srcInd = docs.indexOf(newDoc); + const srcInd = docs.indexOf(newDoc); docs.splice(srcInd, 1); docs.splice((targInd > srcInd ? targInd - 1 : targInd) + (plusOne ? 1 : 0), 0, newDoc); } @@ -267,19 +267,19 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @undoBatch @action onDrop = async (e: React.DragEvent): Promise<void> => { - let where = [e.clientX, e.clientY]; + const where = [e.clientX, e.clientY]; let targInd = -1; this._docXfs.map((cd, i) => { - let pos = cd.dxf().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap); - let pos1 = cd.dxf().inverse().transformPoint(cd.width(), cd.height()); + const pos = cd.dxf().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap); + const pos1 = cd.dxf().inverse().transformPoint(cd.width(), cd.height()); if (where[0] > pos[0] && where[0] < pos1[0] && where[1] > pos[1] && where[1] < pos1[1]) { targInd = i; } }); super.onDrop(e, {}, () => { if (targInd !== -1) { - let newDoc = this.childDocs[this.childDocs.length - 1]; - let docs = this.childDocList; + const newDoc = this.childDocs[this.childDocs.length - 1]; + const docs = this.childDocList; if (docs) { docs.splice(docs.length - 1, 1); docs.splice(targInd, 0, newDoc); @@ -289,13 +289,13 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } headings = () => Array.from(this.Sections.keys()); sectionStacking = (heading: SchemaHeaderField | undefined, docList: Doc[]) => { - let key = this.sectionFilter; + const key = this.sectionFilter; let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined; - let types = docList.length ? docList.map(d => typeof d[key]) : this.childDocs.map(d => typeof d[key]); + const types = docList.length ? docList.map(d => typeof d[key]) : this.childDocs.map(d => typeof d[key]); if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) { type = types[0]; } - let cols = () => this.isStackingView ? 1 : Math.max(1, Math.min(this.filteredChildren.length, + const cols = () => this.isStackingView ? 1 : Math.max(1, Math.min(this.filteredChildren.length, Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap)))); return <CollectionStackingViewFieldColumn key={heading ? heading.heading : ""} @@ -313,23 +313,23 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { getDocTransform(doc: Doc, dref: HTMLDivElement) { if (!dref) return Transform.Identity(); - let y = this._scroll; // required for document decorations to update when the text box container is scrolled - let { scale, translateX, translateY } = Utils.GetScreenTransform(dref); - let outerXf = Utils.GetScreenTransform(this._masonryGridRef!); - let offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); + const y = this._scroll; // required for document decorations to update when the text box container is scrolled + const { scale, translateX, translateY } = Utils.GetScreenTransform(dref); + const outerXf = Utils.GetScreenTransform(this._masonryGridRef!); + const offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); return this.props.ScreenToLocalTransform(). translate(offset[0], offset[1] + (this.props.ChromeHeight && this.props.ChromeHeight() < 0 ? this.props.ChromeHeight() : 0)). scale(NumCast(doc.width, 1) / this.columnWidth); } sectionMasonry = (heading: SchemaHeaderField | undefined, docList: Doc[]) => { - let key = this.sectionFilter; + const key = this.sectionFilter; let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined; - let types = docList.length ? docList.map(d => typeof d[key]) : this.childDocs.map(d => typeof d[key]); + const types = docList.length ? docList.map(d => typeof d[key]) : this.childDocs.map(d => typeof d[key]); if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) { type = types[0]; } - let rows = () => !this.isStackingView ? 1 : Math.max(1, Math.min(docList.length, + const rows = () => !this.isStackingView ? 1 : Math.max(1, Math.min(docList.length, Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap)))); return <CollectionMasonryViewFieldRow key={heading ? heading.heading : ""} @@ -356,9 +356,9 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } sortFunc = (a: [SchemaHeaderField, Doc[]], b: [SchemaHeaderField, Doc[]]): 1 | -1 => { - let descending = BoolCast(this.props.Document.stackingHeadersSortDescending); - let firstEntry = descending ? b : a; - let secondEntry = descending ? a : b; + const descending = BoolCast(this.props.Document.stackingHeadersSortDescending); + const firstEntry = descending ? b : a; + const secondEntry = descending ? a : b; return firstEntry[0].heading > secondEntry[0].heading ? 1 : -1; } @@ -369,28 +369,28 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { onContextMenu = (e: React.MouseEvent): void => { // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout if (!e.isPropagationStopped()) { - let subItems: ContextMenuProps[] = []; + const subItems: ContextMenuProps[] = []; subItems.push({ description: `${this.props.Document.fillColumn ? "Variable Size" : "Autosize"} Column`, event: () => this.props.Document.fillColumn = !this.props.Document.fillColumn, icon: "plus" }); subItems.push({ description: `${this.props.Document.showTitles ? "Hide Titles" : "Show Titles"}`, event: () => this.props.Document.showTitles = !this.props.Document.showTitles ? "title" : "", icon: "plus" }); subItems.push({ description: `${this.props.Document.showCaptions ? "Hide Captions" : "Show Captions"}`, event: () => this.props.Document.showCaptions = !this.props.Document.showCaptions ? "caption" : "", icon: "plus" }); ContextMenu.Instance.addItem({ description: "Stacking Options ...", subitems: subItems, icon: "eye" }); - let existingOnClick = ContextMenu.Instance.findByDescription("OnClick..."); - let onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; + const existingOnClick = ContextMenu.Instance.findByDescription("OnClick..."); + const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; onClicks.push({ description: "Edit onChildClick script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript("On Child Clicked...", this.props.Document, "onChildClick", obj.x, obj.y) }); !existingOnClick && ContextMenu.Instance.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" }); } } render() { - let editableViewProps = { + const editableViewProps = { GetValue: () => "", SetValue: this.addGroup, contents: "+ ADD A GROUP" }; let sections = [[undefined, this.filteredChildren] as [SchemaHeaderField | undefined, Doc[]]]; if (this.sectionFilter) { - let entries = Array.from(this.Sections.entries()); + const entries = Array.from(this.Sections.entries()); sections = entries.sort(this.sortFunc); } return ( diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index b9d334b10..80dc482af 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -2,17 +2,14 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; import { faPalette } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, observable, trace, runInAction } from "mobx"; +import { action, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc, WidthSym } from "../../../new_fields/Doc"; -import { Id } from "../../../new_fields/FieldSymbols"; +import { Doc } from "../../../new_fields/Doc"; import { PastelSchemaPalette, SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { ScriptField } from "../../../new_fields/ScriptField"; import { NumCast, StrCast } from "../../../new_fields/Types"; -import { Utils } from "../../../Utils"; import { Docs } from "../../documents/Documents"; import { DragManager } from "../../util/DragManager"; -import { CompileScript } from "../../util/Scripting"; import { SelectionManager } from "../../util/SelectionManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; @@ -61,8 +58,8 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC columnDrop = action((e: Event, de: DragManager.DropEvent) => { this._createAliasSelected = false; if (de.data instanceof DragManager.DocumentDragData) { - let key = StrCast(this.props.parent.props.Document.sectionFilter); - let castedValue = this.getValue(this._heading); + const key = StrCast(this.props.parent.props.Document.sectionFilter); + const castedValue = this.getValue(this._heading); if (castedValue) { de.data.droppedDocuments.forEach(d => d[key] = castedValue); } @@ -74,7 +71,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC } }); getValue = (value: string): any => { - let parsed = parseInt(value); + const parsed = parseInt(value); if (!isNaN(parsed)) { return parsed; } @@ -90,8 +87,8 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC @action headingChanged = (value: string, shiftDown?: boolean) => { this._createAliasSelected = false; - let key = StrCast(this.props.parent.props.Document.sectionFilter); - let castedValue = this.getValue(value); + const key = StrCast(this.props.parent.props.Document.sectionFilter); + const castedValue = this.getValue(value); if (castedValue) { if (this.props.parent.sectionHeaders) { if (this.props.parent.sectionHeaders.map(i => i.heading).indexOf(castedValue.toString()) > -1) { @@ -135,11 +132,11 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC @action addDocument = (value: string, shiftDown?: boolean) => { this._createAliasSelected = false; - let key = StrCast(this.props.parent.props.Document.sectionFilter); - let newDoc = Docs.Create.TextDocument({ height: 18, width: 200, documentText: "@@@" + value, title: value, autoHeight: true }); + const key = StrCast(this.props.parent.props.Document.sectionFilter); + const newDoc = Docs.Create.TextDocument({ height: 18, width: 200, documentText: "@@@" + value, title: value, autoHeight: true }); newDoc[key] = this.getValue(this.props.heading); - let maxHeading = this.props.docList.reduce((maxHeading, doc) => NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading, 0); - let heading = maxHeading === 0 || this.props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3; + const maxHeading = this.props.docList.reduce((maxHeading, doc) => NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading, 0); + const heading = maxHeading === 0 || this.props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3; newDoc.heading = heading; return this.props.parent.props.addDocument(newDoc); } @@ -147,10 +144,10 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC @action deleteColumn = () => { this._createAliasSelected = false; - let key = StrCast(this.props.parent.props.Document.sectionFilter); + const key = StrCast(this.props.parent.props.Document.sectionFilter); this.props.docList.forEach(d => d[key] = undefined); if (this.props.parent.sectionHeaders && this.props.headingObject) { - let index = this.props.parent.sectionHeaders.indexOf(this.props.headingObject); + const index = this.props.parent.sectionHeaders.indexOf(this.props.headingObject); this.props.parent.sectionHeaders.splice(index, 1); } } @@ -166,10 +163,10 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC } startDrag = (e: PointerEvent) => { - let [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y); + const [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y); if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) { - let alias = Doc.MakeAlias(this.props.parent.props.Document); - let key = StrCast(this.props.parent.props.Document.sectionFilter); + const alias = Doc.MakeAlias(this.props.parent.props.Document); + const key = StrCast(this.props.parent.props.Document.sectionFilter); let value = this.getValue(this._heading); value = typeof value === "string" ? `"${value}"` : value; alias.viewSpecScript = ScriptField.MakeFunction(`doc.${key} === ${value}`, { doc: Doc.name }); @@ -195,7 +192,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC e.stopPropagation(); e.preventDefault(); - let [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX, e.clientY); + const [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX, e.clientY); this._startDragPosition = { x: dx, y: dy }; if (this._createAliasSelected) { @@ -208,17 +205,17 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC } renderColorPicker = () => { - let selected = this.props.headingObject ? this.props.headingObject.color : "#f1efeb"; + const selected = this.props.headingObject ? this.props.headingObject.color : "#f1efeb"; - let pink = PastelSchemaPalette.get("pink2"); - let purple = PastelSchemaPalette.get("purple4"); - let blue = PastelSchemaPalette.get("bluegreen1"); - let yellow = PastelSchemaPalette.get("yellow4"); - let red = PastelSchemaPalette.get("red2"); - let green = PastelSchemaPalette.get("bluegreen7"); - let cyan = PastelSchemaPalette.get("bluegreen5"); - let orange = PastelSchemaPalette.get("orange1"); - let gray = "#f1efeb"; + const pink = PastelSchemaPalette.get("pink2"); + const purple = PastelSchemaPalette.get("purple4"); + const blue = PastelSchemaPalette.get("bluegreen1"); + const yellow = PastelSchemaPalette.get("yellow4"); + const red = PastelSchemaPalette.get("red2"); + const green = PastelSchemaPalette.get("bluegreen7"); + const cyan = PastelSchemaPalette.get("bluegreen5"); + const orange = PastelSchemaPalette.get("orange1"); + const gray = "#f1efeb"; return ( <div className="collectionStackingView-colorPicker"> @@ -243,7 +240,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC } renderMenu = () => { - let selected = this._createAliasSelected; + const selected = this._createAliasSelected; return ( <div className="collectionStackingView-optionPicker"> <div className="optionOptions"> @@ -262,16 +259,16 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC @observable _headingsHack: number = 1; render() { - let cols = this.props.cols(); - let key = StrCast(this.props.parent.props.Document.sectionFilter); + const cols = this.props.cols(); + const key = StrCast(this.props.parent.props.Document.sectionFilter); let templatecols = ""; - let headings = this.props.headings(); - let heading = this._heading; - let style = this.props.parent; - let singleColumn = style.isStackingView; - let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); - let evContents = heading ? heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`; - let headerEditableViewProps = { + const headings = this.props.headings(); + const heading = this._heading; + const style = this.props.parent; + const singleColumn = style.isStackingView; + const uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); + const evContents = heading ? heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`; + const headerEditableViewProps = { GetValue: () => evContents, SetValue: this.headingChanged, contents: evContents, @@ -281,7 +278,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC toggle: this.toggleVisibility, color: this._color }; - let newEditableViewProps = { + const newEditableViewProps = { GetValue: () => "", SetValue: this.addDocument, contents: "+ NEW", @@ -290,7 +287,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC toggle: this.toggleVisibility, color: this._color }; - let headingView = this.props.headingObject ? + const headingView = this.props.headingObject ? <div key={heading} className="collectionStackingView-sectionHeader" ref={this._headerRef} style={{ width: (style.columnWidth) / @@ -335,7 +332,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC </div> </div> : (null); for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth / style.numGroupColumns}px `; - let chromeStatus = this.props.parent.props.Document.chromeStatus; + const chromeStatus = this.props.parent.props.Document.chromeStatus; return ( <div className="collectionStackingViewFieldColumn" key={heading} style={{ width: `${100 / ((uniqueHeadings.length + ((chromeStatus !== 'view-mode' && chromeStatus !== 'disabled') ? 1 : 0)) || 1)}%`, background: this._background }} ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}> diff --git a/src/client/views/collections/CollectionStaffView.tsx b/src/client/views/collections/CollectionStaffView.tsx index 40e860b12..105061f46 100644 --- a/src/client/views/collections/CollectionStaffView.tsx +++ b/src/client/views/collections/CollectionStaffView.tsx @@ -2,7 +2,7 @@ import { CollectionSubView } from "./CollectionSubView"; import { Transform } from "../../util/Transform"; import React = require("react"); import { computed, action, IReactionDisposer, reaction, runInAction, observable } from "mobx"; -import { Doc, HeightSym } from "../../../new_fields/Doc"; +import { Doc } from "../../../new_fields/Doc"; import { NumCast } from "../../../new_fields/Types"; import "./CollectionStaffView.scss"; import { observer } from "mobx-react"; @@ -32,9 +32,9 @@ export class CollectionStaffView extends CollectionSubView(doc => doc) { } @computed get staves() { - let staves = []; + const staves = []; for (let i = 0; i < this._staves; i++) { - let rows = []; + const rows = []; for (let j = 0; j < 5; j++) { rows.push(<div key={`staff-${i}-${j}`} className="collectionStaffView-line"></div>); } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index e80825825..0a2e27165 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -19,7 +19,7 @@ import { FieldViewProps } from "../nodes/FieldView"; import { FormattedTextBox, GoogleRef } from "../nodes/FormattedTextBox"; import { CollectionView } from "./CollectionView"; import React = require("react"); -var path = require('path'); +import { basename } from 'path'; import { GooglePhotos } from "../../apis/google_docs/GooglePhotosClientUtils"; import { ImageUtils } from "../../util/Import & Export/ImageUtils"; import { Networking } from "../../Network"; @@ -92,7 +92,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { return Cast(this.dataField, listSpec(Doc)); } get childDocs() { - let docs = DocListCast(this.dataField); + const docs = DocListCast(this.dataField); const viewSpecScript = Cast(this.props.Document.viewSpecScript, ScriptField); return viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs; } @@ -100,10 +100,10 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { @action protected async setCursorPosition(position: [number, number]) { let ind; - let doc = this.props.Document; - let id = CurrentUserUtils.id; - let email = Doc.CurrentUserEmail; - let pos = { x: position[0], y: position[1] }; + const doc = this.props.Document; + const id = CurrentUserUtils.id; + const email = Doc.CurrentUserEmail; + const pos = { x: position[0], y: position[1] }; if (id && email) { const proto = Doc.GetProto(doc); if (!proto) { @@ -123,7 +123,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { if (cursors.length > 0 && (ind = cursors.findIndex(entry => entry.data.metadata.id === id)) > -1) { cursors[ind].setPosition(pos); } else { - let entry = new CursorField({ metadata: { id: id, identifier: email, timestamp: Date.now() }, position: pos }); + const entry = new CursorField({ metadata: { id: id, identifier: email, timestamp: Date.now() }, position: pos }); cursors.push(entry); } } @@ -145,7 +145,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { if (de.data.dropAction || de.data.userDropAction) { added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false); } else if (de.data.moveDocument) { - let movedDocs = de.data.draggedDocuments; + const movedDocs = de.data.draggedDocuments; added = movedDocs.reduce((added: boolean, d, i) => de.data.droppedDocuments[i] !== d ? this.props.addDocument(de.data.droppedDocuments[i]) : de.data.moveDocument(d, this.props.Document, this.props.addDocument) || added, false); @@ -169,8 +169,8 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { e.stopPropagation(); // bcz: this is a hack to stop propagation when dropping an image on a text document with shift+ctrl return; } - let html = e.dataTransfer.getData("text/html"); - let text = e.dataTransfer.getData("text/plain"); + const html = e.dataTransfer.getData("text/html"); + const text = e.dataTransfer.getData("text/plain"); if (text && text.startsWith("<div")) { return; @@ -179,9 +179,9 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { e.preventDefault(); if (html && FormattedTextBox.IsFragment(html)) { - let href = FormattedTextBox.GetHref(html); + const href = FormattedTextBox.GetHref(html); if (href) { - let docid = FormattedTextBox.GetDocFromUrl(href); + const docid = FormattedTextBox.GetDocFromUrl(href); if (docid) { // prosemirror text containing link to dash document DocServer.GetRefField(docid).then(f => { if (f instanceof Doc) { @@ -198,19 +198,19 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { return; } if (html && !html.startsWith("<a")) { - let tags = html.split("<"); + const tags = html.split("<"); if (tags[0] === "") tags.splice(0, 1); - let img = tags[0].startsWith("img") ? tags[0] : tags.length > 1 && tags[1].startsWith("img") ? tags[1] : ""; + const img = tags[0].startsWith("img") ? tags[0] : tags.length > 1 && tags[1].startsWith("img") ? tags[1] : ""; if (img) { - let split = img.split("src=\"")[1].split("\"")[0]; - let doc = Docs.Create.ImageDocument(split, { ...options, width: 300 }); + const split = img.split("src=\"")[1].split("\"")[0]; + const doc = Docs.Create.ImageDocument(split, { ...options, width: 300 }); ImageUtils.ExtractExif(doc); this.props.addDocument(doc); return; } else { - let path = window.location.origin + "/doc/"; + const path = window.location.origin + "/doc/"; if (text.startsWith(path)) { - let docid = text.replace(Utils.prepend("/doc/"), "").split("?")[0]; + const docid = text.replace(Utils.prepend("/doc/"), "").split("?")[0]; DocServer.GetRefField(docid).then(f => { if (f instanceof Doc) { if (options.x || options.y) { f.x = options.x; f.y = options.y; } // should be in CollectionFreeFormView @@ -218,7 +218,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { } }); } else { - let htmlDoc = Docs.Create.HtmlDocument(html, { ...options, title: "-web page-", width: 300, height: 300, documentText: text }); + const htmlDoc = Docs.Create.HtmlDocument(html, { ...options, title: "-web page-", width: 300, height: 300, documentText: text }); this.props.addDocument(htmlDoc); } return; @@ -231,8 +231,8 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { } let matches: RegExpExecArray | null; if ((matches = /(https:\/\/)?docs\.google\.com\/document\/d\/([^\\]+)\/edit/g.exec(text)) !== null) { - let newBox = Docs.Create.TextDocument({ ...options, width: 400, height: 200, title: "Awaiting title from Google Docs..." }); - let proto = newBox.proto!; + const newBox = Docs.Create.TextDocument({ ...options, width: 400, height: 200, title: "Awaiting title from Google Docs..." }); + const proto = newBox.proto!; const documentId = matches[2]; proto[GoogleRef] = documentId; proto.data = "Please select this document and then click on its pull button to load its contents from from Google Docs..."; @@ -249,17 +249,17 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { const mediaItems = await GooglePhotos.Query.AlbumSearch(albumId); console.log(mediaItems); } - let batch = UndoManager.StartBatch("collection view drop"); - let promises: Promise<void>[] = []; + const batch = UndoManager.StartBatch("collection view drop"); + const promises: Promise<void>[] = []; // tslint:disable-next-line:prefer-for-of for (let i = 0; i < e.dataTransfer.items.length; i++) { - let item = e.dataTransfer.items[i]; + const item = e.dataTransfer.items[i]; if (item.kind === "string" && item.type.indexOf("uri") !== -1) { let str: string; - let prom = new Promise<string>(resolve => e.dataTransfer.items[i].getAsString(resolve)) + const prom = new Promise<string>(resolve => e.dataTransfer.items[i].getAsString(resolve)) .then(action((s: string) => rp.head(Utils.CorsProxy(str = s)))) .then(result => { - let type = result["content-type"]; + const type = result["content-type"]; if (type) { Docs.Get.DocumentFromType(type, str, { ...options, width: 300, nativeWidth: type.indexOf("video") !== -1 ? 600 : 300 }) .then(doc => doc && this.props.addDocument(doc)); @@ -267,23 +267,23 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { }); promises.push(prom); } - let type = item.type; + const type = item.type; if (item.kind === "file") { - let file = item.getAsFile(); - let formData = new FormData(); + const file = item.getAsFile(); + const formData = new FormData(); if (!file || !file.type) { continue; } formData.append('file', file); - let dropFileName = file ? file.name : "-empty-"; + const dropFileName = file ? file.name : "-empty-"; promises.push(Networking.PostFormDataToServer("/upload", formData).then(results => { results.map(action(({ clientAccessPath }: any) => { - let full = { ...options, nativeWidth: type.indexOf("video") !== -1 ? 600 : 300, width: 300, title: dropFileName }; - let pathname = Utils.prepend(clientAccessPath); + const full = { ...options, nativeWidth: type.indexOf("video") !== -1 ? 600 : 300, width: 300, title: dropFileName }; + const pathname = Utils.prepend(clientAccessPath); Docs.Get.DocumentFromType(type, pathname, full).then(doc => { - doc && (Doc.GetProto(doc).fileUpload = path.basename(pathname).replace("upload_", "").replace(/\.[a-z0-9]*$/, "")); + doc && (Doc.GetProto(doc).fileUpload = basename(pathname).replace("upload_", "").replace(/\.[a-z0-9]*$/, "")); doc && this.props.addDocument(doc); }); })); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index c4b7e2d31..48ea35c6b 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -3,7 +3,7 @@ import { faAngleRight, faArrowsAltH, faBell, faCamera, faCaretDown, faCaretRight import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast, Field, HeightSym, Opt, WidthSym } from '../../../new_fields/Doc'; +import { Doc, DocListCast, Field, HeightSym, WidthSym } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; import { List } from '../../../new_fields/List'; import { Document, listSpec } from '../../../new_fields/Schema'; @@ -95,11 +95,11 @@ class TreeView extends React.Component<TreeViewProps> { @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.document.maxEmbedHeight, 300); } @computed get dataDoc() { return this.templateDataDoc ? this.templateDataDoc : this.props.document; } @computed get fieldKey() { - let splits = StrCast(Doc.LayoutField(this.props.document)).split("fieldKey={\""); + const splits = StrCast(Doc.LayoutField(this.props.document)).split("fieldKey={\""); return splits.length > 1 ? splits[1].split("\"")[0] : "data"; } childDocList(field: string) { - let layout = Doc.LayoutField(this.props.document) instanceof Doc ? Doc.LayoutField(this.props.document) as Doc : undefined; + const layout = Doc.LayoutField(this.props.document) instanceof Doc ? Doc.LayoutField(this.props.document) as Doc : undefined; return ((this.props.dataDoc ? Cast(this.props.dataDoc[field], listSpec(Doc)) : undefined) || (layout ? Cast(layout[field], listSpec(Doc)) : undefined) || Cast(this.props.document[field], listSpec(Doc))) as Doc[]; @@ -149,10 +149,10 @@ class TreeView extends React.Component<TreeViewProps> { } onDragMove = (e: PointerEvent): void => { Doc.UnBrushDoc(this.dataDoc); - let pt = [e.clientX, e.clientY] - let rect = this._header!.current!.getBoundingClientRect(); - let before = pt[1] < rect.top + rect.height / 2; - let inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && DocListCast(this.dataDoc[this.fieldKey]).length); + const pt = [e.clientX, e.clientY]; + const rect = this._header!.current!.getBoundingClientRect(); + const before = pt[1] < rect.top + rect.height / 2; + const inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && DocListCast(this.dataDoc[this.fieldKey]).length); this._header!.current!.className = "treeViewItem-header"; if (inside) this._header!.current!.className += " treeViewItem-header-inside"; else if (before) this._header!.current!.className += " treeViewItem-header-above"; @@ -172,8 +172,8 @@ class TreeView extends React.Component<TreeViewProps> { SetValue={undoBatch((value: string) => Doc.SetInPlace(this.props.document, key, value, false) || true)} OnFillDown={undoBatch((value: string) => { Doc.SetInPlace(this.props.document, key, value, false); - let layoutDoc = this.props.document.layoutCustom instanceof Doc ? Doc.ApplyTemplate(Doc.GetProto(this.props.document.layoutCustom)) : undefined; - let doc = layoutDoc || Docs.Create.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List<string>([Templates.Title.Layout]) }); + const layoutDoc = this.props.document.layoutCustom instanceof Doc ? Doc.ApplyTemplate(Doc.GetProto(this.props.document.layoutCustom)) : undefined; + const doc = layoutDoc || Docs.Create.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List<string>([Templates.Title.Layout]) }); TreeView.loadId = doc[Id]; return this.props.addDocument(doc); })} @@ -205,7 +205,7 @@ class TreeView extends React.Component<TreeViewProps> { ContextMenu.Instance.addItem({ description: "Delete Workspace", event: () => this.props.deleteDoc(this.props.document), icon: "trash-alt" }); ContextMenu.Instance.addItem({ description: "Create New Workspace", event: () => MainView.Instance.createNewWorkspace(), icon: "plus" }); } - ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { let kvp = Docs.Create.KVPDocument(this.props.document, { width: 300, height: 300 }); this.props.addDocTab(kvp, this.props.dataDoc ? this.props.dataDoc : kvp, "onRight"); }, icon: "layer-group" }); + ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { const kvp = Docs.Create.KVPDocument(this.props.document, { width: 300, height: 300 }); this.props.addDocTab(kvp, this.props.dataDoc ? this.props.dataDoc : kvp, "onRight"); }, icon: "layer-group" }); ContextMenu.Instance.addItem({ description: "Publish", event: () => DocUtils.Publish(this.props.document, StrCast(this.props.document.title), () => { }, () => { }), icon: "file" }); ContextMenu.Instance.displayMenu(e.pageX > 156 ? e.pageX - 156 : 0, e.pageY - 15); e.stopPropagation(); @@ -215,13 +215,13 @@ class TreeView extends React.Component<TreeViewProps> { @undoBatch treeDrop = (e: Event, de: DragManager.DropEvent) => { - let pt = [de.x, de.y]; - let rect = this._header!.current!.getBoundingClientRect(); - let before = pt[1] < rect.top + rect.height / 2; - let inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && DocListCast(this.dataDoc[this.fieldKey]).length); + const pt = [de.x, de.y]; + const rect = this._header!.current!.getBoundingClientRect(); + const before = pt[1] < rect.top + rect.height / 2; + const inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && DocListCast(this.dataDoc[this.fieldKey]).length); if (de.data instanceof DragManager.LinkDragData) { - let sourceDoc = de.data.linkSourceDocument; - let destDoc = this.props.document; + const sourceDoc = de.data.linkSourceDocument; + const destDoc = this.props.document; DocUtils.MakeLink({ doc: sourceDoc }, { doc: destDoc }); e.stopPropagation(); } @@ -232,7 +232,7 @@ class TreeView extends React.Component<TreeViewProps> { if (inside) { addDoc = (doc: Doc) => Doc.AddDocToList(this.dataDoc, this.fieldKey, doc) || addDoc(doc); } - let movedDocs = (de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments); + const movedDocs = (de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments); return ((de.data.dropAction && (de.data.options !== this.props.treeViewId)) || de.data.userDropAction) ? de.data.droppedDocuments.reduce((added, d) => addDoc(d) || added, false) : de.data.moveDocument ? @@ -243,23 +243,23 @@ class TreeView extends React.Component<TreeViewProps> { } docTransform = () => { - let { scale, translateX, translateY } = Utils.GetScreenTransform(this._dref.current!); - let outerXf = this.props.outerXf(); - let offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); - let finalXf = this.props.ScreenToLocalTransform().translate(offset[0], offset[1] + (this.props.ChromeHeight && this.props.ChromeHeight() < 0 ? this.props.ChromeHeight() : 0)); + const { scale, translateX, translateY } = Utils.GetScreenTransform(this._dref.current!); + const outerXf = this.props.outerXf(); + const offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); + const finalXf = this.props.ScreenToLocalTransform().translate(offset[0], offset[1] + (this.props.ChromeHeight && this.props.ChromeHeight() < 0 ? this.props.ChromeHeight() : 0)); return finalXf; } docWidth = () => { - let layoutDoc = Doc.Layout(this.props.document); - let aspect = NumCast(layoutDoc.nativeHeight) / NumCast(layoutDoc.nativeWidth); + const layoutDoc = Doc.Layout(this.props.document); + const aspect = NumCast(layoutDoc.nativeHeight) / NumCast(layoutDoc.nativeWidth); if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.panelWidth() - 20)); return NumCast(layoutDoc.nativeWidth) ? Math.min(layoutDoc[WidthSym](), this.props.panelWidth() - 20) : this.props.panelWidth() - 20; } docHeight = () => { - let layoutDoc = Doc.Layout(this.props.document); - let bounds = this.boundsOfCollectionDocument; + const layoutDoc = Doc.Layout(this.props.document); + const bounds = this.boundsOfCollectionDocument; return Math.min(this.MAX_EMBED_HEIGHT, (() => { - let aspect = NumCast(layoutDoc.nativeHeight) / NumCast(layoutDoc.nativeWidth, 1); + const aspect = NumCast(layoutDoc.nativeHeight) / NumCast(layoutDoc.nativeWidth, 1); if (aspect) return this.docWidth() * aspect; if (bounds) return this.docWidth() * (bounds.b - bounds.y) / (bounds.r - bounds.x); return layoutDoc.fitWidth ? (!this.props.document.nativeHeight ? NumCast(this.props.containingCollection.height) : @@ -270,18 +270,18 @@ class TreeView extends React.Component<TreeViewProps> { } @computed get expandedField() { - let ids: { [key: string]: string } = {}; - let doc = this.props.document; + const ids: { [key: string]: string } = {}; + const doc = this.props.document; doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)); - let rows: JSX.Element[] = []; - for (let key of Object.keys(ids).slice().sort()) { - let contents = doc[key]; + const rows: JSX.Element[] = []; + for (const key of Object.keys(ids).slice().sort()) { + const contents = doc[key]; let contentElement: (JSX.Element | null)[] | JSX.Element = []; if (contents instanceof Doc || Cast(contents, listSpec(Doc))) { - let remDoc = (doc: Doc) => this.remove(doc, key); - let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true); + const remDoc = (doc: Doc) => this.remove(doc, key); + const addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true); contentElement = TreeView.GetChildElements(contents instanceof Doc ? [contents] : DocListCast(contents), this.props.treeViewId, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, @@ -310,9 +310,9 @@ class TreeView extends React.Component<TreeViewProps> { @computed get renderContent() { const expandKey = this.treeViewExpandedView === this.fieldKey ? this.fieldKey : this.treeViewExpandedView === "links" ? "links" : undefined; if (expandKey !== undefined) { - let remDoc = (doc: Doc) => this.remove(doc, expandKey); - let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, expandKey, doc, addBefore, before, false, true); - let docs = expandKey === "links" ? this.childLinks : this.childDocs; + const remDoc = (doc: Doc) => this.remove(doc, expandKey); + const addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, expandKey, doc, addBefore, before, false, true); + const docs = expandKey === "links" ? this.childLinks : this.childDocs; return <ul key={expandKey + "more"}> {!docs ? (null) : TreeView.GetChildElements(docs, this.props.treeViewId, Doc.Layout(this.props.document), @@ -326,7 +326,7 @@ class TreeView extends React.Component<TreeViewProps> { {this.expandedField} </div></ul>; } else { - let layoutDoc = Doc.Layout(this.props.document); + const layoutDoc = Doc.Layout(this.props.document); return <div ref={this._dref} style={{ display: "inline-block", height: this.docHeight() }} key={this.props.document[Id] + this.props.document.title}> <ContentFittingDocumentView Document={layoutDoc} @@ -363,10 +363,10 @@ class TreeView extends React.Component<TreeViewProps> { */ @computed get renderTitle() { - let reference = React.createRef<HTMLDivElement>(); - let onItemDown = SetupDrag(reference, () => this.dataDoc, this.move, this.props.dropAction, this.props.treeViewId, true); + const reference = React.createRef<HTMLDivElement>(); + const onItemDown = SetupDrag(reference, () => this.dataDoc, this.move, this.props.dropAction, this.props.treeViewId, true); - let headerElements = ( + const headerElements = ( <span className="collectionTreeView-keyHeader" key={this.treeViewExpandedView} onPointerDown={action(() => { if (this.treeViewOpen) { @@ -379,7 +379,7 @@ class TreeView extends React.Component<TreeViewProps> { })}> {this.treeViewExpandedView} </span>); - let openRight = (<div className="treeViewItem-openRight" onPointerDown={this.onPointerDown} onClick={this.openRight}> + const openRight = (<div className="treeViewItem-openRight" onPointerDown={this.onPointerDown} onClick={this.openRight}> <FontAwesomeIcon title="open in pane on right" icon="angle-right" size="lg" /> </div>); return <> @@ -440,28 +440,28 @@ class TreeView extends React.Component<TreeViewProps> { childDocs = childDocs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result); } - let docs = childDocs.slice(); - let dataExtension = containingCollection[key + "_ext"] as Doc; - let ascending = dataExtension && BoolCast(dataExtension.sortAscending, null); + const docs = childDocs.slice(); + const dataExtension = containingCollection[key + "_ext"] as Doc; + const ascending = dataExtension && BoolCast(dataExtension.sortAscending, null); if (ascending !== undefined) { - let sortAlphaNum = (a: string, b: string): 0 | 1 | -1 => { - var reN = /[0-9]*$/; - var aA = a.replace(reN, ""); // get rid of trailing numbers - var bA = b.replace(reN, ""); + const sortAlphaNum = (a: string, b: string): 0 | 1 | -1 => { + const reN = /[0-9]*$/; + const aA = a.replace(reN, ""); // get rid of trailing numbers + const bA = b.replace(reN, ""); if (aA === bA) { // if header string matches, then compare numbers numerically - var aN = parseInt(a.match(reN)![0], 10); - var bN = parseInt(b.match(reN)![0], 10); + const aN = parseInt(a.match(reN)![0], 10); + const bN = parseInt(b.match(reN)![0], 10); return aN === bN ? 0 : aN > bN ? 1 : -1; } else { return aA > bA ? 1 : -1; } - } + }; docs.sort(function (a, b): 0 | 1 | -1 { - let descA = ascending ? b : a; - let descB = ascending ? a : b; - let first = descA.title; - let second = descB.title; + const descA = ascending ? b : a; + const descB = ascending ? a : b; + const first = descA.title; + const second = descB.title; // TODO find better way to sort how to sort.................. if (typeof first === 'number' && typeof second === 'number') { return (first - second) > 0 ? 1 : -1; @@ -479,17 +479,17 @@ class TreeView extends React.Component<TreeViewProps> { }); } - let rowWidth = () => panelWidth() - 20; + const rowWidth = () => panelWidth() - 20; return docs.map((child, i) => { const pair = Doc.GetLayoutDataDocPair(containingCollection, dataDoc, key, child); if (!pair.layout || pair.data instanceof Promise) { return (null); } - let indent = i === 0 ? undefined : () => { + const indent = i === 0 ? undefined : () => { if (StrCast(docs[i - 1].layout).indexOf("fieldKey") !== -1) { - let fieldKeysub = StrCast(docs[i - 1].layout).split("fieldKey")[1]; - let fieldKey = fieldKeysub.split("\"")[1]; + const fieldKeysub = StrCast(docs[i - 1].layout).split("fieldKey")[1]; + const fieldKey = fieldKeysub.split("\"")[1]; if (fieldKey && Cast(docs[i - 1][fieldKey], listSpec(Doc)) !== undefined) { Doc.AddDocToList(docs[i - 1], fieldKey, child); docs[i - 1].treeViewOpen = true; @@ -497,21 +497,21 @@ class TreeView extends React.Component<TreeViewProps> { } } }; - let outdent = !parentCollectionDoc ? undefined : () => { + const outdent = !parentCollectionDoc ? undefined : () => { if (StrCast(parentCollectionDoc.layout).indexOf("fieldKey") !== -1) { - let fieldKeysub = StrCast(parentCollectionDoc.layout).split("fieldKey")[1]; - let fieldKey = fieldKeysub.split("\"")[1]; + const fieldKeysub = StrCast(parentCollectionDoc.layout).split("fieldKey")[1]; + const fieldKey = fieldKeysub.split("\"")[1]; Doc.AddDocToList(parentCollectionDoc, fieldKey, child, parentPrevSibling, false); parentCollectionDoc.treeViewOpen = true; remove(child); } }; - let addDocument = (doc: Doc, relativeTo?: Doc, before?: boolean) => { + const addDocument = (doc: Doc, relativeTo?: Doc, before?: boolean) => { return add(doc, relativeTo ? relativeTo : docs[i], before !== undefined ? before : false); }; const childLayout = Doc.Layout(pair.layout); - let rowHeight = () => { - let aspect = NumCast(childLayout.nativeWidth, 0) / NumCast(childLayout.nativeHeight, 0); + const rowHeight = () => { + const aspect = NumCast(childLayout.nativeWidth, 0) / NumCast(childLayout.nativeHeight, 0); return aspect ? Math.min(childLayout[WidthSym](), rowWidth()) / aspect : childLayout[HeightSym](); }; return !(child instanceof Doc) ? (null) : <TreeView @@ -566,7 +566,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { @action remove = (document: Document): boolean => { - let children = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []); + const children = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []); if (children.indexOf(document) !== -1) { children.splice(children.indexOf(document), 1); return true; @@ -587,7 +587,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { e.preventDefault(); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); } else { - let layoutItems: ContextMenuProps[] = []; + const layoutItems: ContextMenuProps[] = []; layoutItems.push({ description: (this.props.Document.preventTreeViewOpen ? "Persist" : "Abandon") + "Treeview State", event: () => this.props.Document.preventTreeViewOpen = !this.props.Document.preventTreeViewOpen, icon: "paint-brush" }); layoutItems.push({ description: (this.props.Document.hideHeaderFields ? "Show" : "Hide") + " Header Fields", event: () => this.props.Document.hideHeaderFields = !this.props.Document.hideHeaderFields, icon: "paint-brush" }); ContextMenu.Instance.addItem({ description: "Treeview Options ...", subitems: layoutItems, icon: "eye" }); @@ -606,9 +606,9 @@ export class CollectionTreeView extends CollectionSubView(Document) { } render() { - let dropAction = StrCast(this.props.Document.dropAction) as dropActionType; - let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before, false, false, false); - let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); + const dropAction = StrCast(this.props.Document.dropAction) as dropActionType; + const addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before, false, false, false); + const moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); return !this.childDocs ? (null) : ( <div id="body" className="collectionTreeView-dropTarget" style={{ overflow: "auto", background: StrCast(this.props.Document.backgroundColor, "lightgray"), paddingTop: `${NumCast(this.props.Document.yMargin, 20)}px` }} @@ -625,8 +625,8 @@ export class CollectionTreeView extends CollectionSubView(Document) { SetValue={undoBatch((value: string) => Doc.SetInPlace(this.dataDoc, "title", value, false) || true)} OnFillDown={undoBatch((value: string) => { Doc.SetInPlace(this.dataDoc, "title", value, false); - let layoutDoc = this.props.Document.layoutCustom instanceof Doc ? Doc.ApplyTemplate(Doc.GetProto(this.props.Document.layoutCustom)) : undefined; - let doc = layoutDoc || Docs.Create.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List<string>([Templates.Title.Layout]) }); + const layoutDoc = this.props.Document.layoutCustom instanceof Doc ? Doc.ApplyTemplate(Doc.GetProto(this.props.Document.layoutCustom)) : undefined; + const doc = layoutDoc || Docs.Create.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List<string>([Templates.Title.Layout]) }); TreeView.loadId = doc[Id]; Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, this.childDocs.length ? this.childDocs[0] : undefined, true, false, false, false); })} /> diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 4c49054d2..54f5a2c42 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -84,7 +84,7 @@ export class CollectionView extends Touchable<FieldViewProps> { public static SetSafeMode(safeMode: boolean) { this._safeMode = safeMode; } get collectionViewType(): CollectionViewType | undefined { - let viewField = Cast(this.props.Document.viewType, "number"); + const viewField = Cast(this.props.Document.viewType, "number"); if (CollectionView._safeMode) { if (viewField === CollectionViewType.Freeform) { return CollectionViewType.Tree; @@ -101,7 +101,7 @@ export class CollectionView extends Touchable<FieldViewProps> { () => { // chrome status is one of disabled, collapsed, or visible. this determines initial state from document // chrome status may also be view-mode, in reference to stacking view's toggle mode. it is essentially disabled mode, but prevents the toggle button from showing up on the left sidebar. - let chromeStatus = this.props.Document.chromeStatus; + const chromeStatus = this.props.Document.chromeStatus; if (chromeStatus && (chromeStatus === "disabled" || chromeStatus === "collapsed")) { runInAction(() => this._collapsed = true); } @@ -119,9 +119,9 @@ export class CollectionView extends Touchable<FieldViewProps> { @action.bound addDocument(doc: Doc): boolean { - let targetDataDoc = Doc.GetProto(this.props.Document); + const targetDataDoc = Doc.GetProto(this.props.Document); Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc); - let extension = Doc.fieldExtensionDoc(targetDataDoc, this.props.fieldKey); // set metadata about the field being rendered (ie, the set of documents) on an extension field for that field + const extension = Doc.fieldExtensionDoc(targetDataDoc, this.props.fieldKey); // set metadata about the field being rendered (ie, the set of documents) on an extension field for that field extension && (extension.lastModified = new DateField(new Date(Date.now()))); Doc.GetProto(doc).lastOpened = new DateField; return true; @@ -129,9 +129,9 @@ export class CollectionView extends Touchable<FieldViewProps> { @action.bound removeDocument(doc: Doc): boolean { - let docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView); + const docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView); docView && SelectionManager.DeselectDoc(docView); - let value = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []); + const value = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []); let index = value.reduce((p, v, i) => (v instanceof Doc && v === doc) ? i : p, -1); index = index !== -1 ? index : value.reduce((p, v, i) => (v instanceof Doc && Doc.AreProtosEqual(v, doc)) ? i : p, -1); @@ -163,7 +163,7 @@ export class CollectionView extends Touchable<FieldViewProps> { } private SubViewHelper = (type: CollectionViewType, renderProps: CollectionRenderProps) => { - let props = { ...this.props, ...renderProps, chromeCollapsed: this._collapsed, ChromeHeight: this.chromeHeight, CollectionView: this, annotationsKey: "" }; + const props = { ...this.props, ...renderProps, chromeCollapsed: this._collapsed, ChromeHeight: this.chromeHeight, CollectionView: this, annotationsKey: "" }; switch (type) { case CollectionViewType.Schema: return (<CollectionSchemaView key="collview" {...props} />); case CollectionViewType.Docking: return (<CollectionDockingView key="collview" {...props} />); @@ -186,7 +186,7 @@ export class CollectionView extends Touchable<FieldViewProps> { private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => { // currently cant think of a reason for collection docking view to have a chrome. mind may change if we ever have nested docking views -syip - let chrome = this.props.Document.chromeStatus === "disabled" || type === CollectionViewType.Docking ? (null) : + const chrome = this.props.Document.chromeStatus === "disabled" || type === CollectionViewType.Docking ? (null) : <CollectionViewBaseChrome CollectionView={this} key="chrome" type={type} collapse={this.collapse} />; return [chrome, this.SubViewHelper(type, renderProps)]; } @@ -194,8 +194,8 @@ export class CollectionView extends Touchable<FieldViewProps> { onContextMenu = (e: React.MouseEvent): void => { if (!e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 - let existingVm = ContextMenu.Instance.findByDescription("View Modes..."); - let subItems = existingVm && "subitems" in existingVm ? existingVm.subitems : []; + const existingVm = ContextMenu.Instance.findByDescription("View Modes..."); + const subItems = existingVm && "subitems" in existingVm ? existingVm.subitems : []; subItems.push({ description: "Freeform", event: () => { this.props.Document.viewType = CollectionViewType.Freeform; }, icon: "signature" }); if (CollectionView._safeMode) { ContextMenu.Instance.addItem({ description: "Test Freeform", event: () => this.props.Document.viewType = CollectionViewType.Invalid, icon: "project-diagram" }); @@ -221,13 +221,13 @@ export class CollectionView extends Touchable<FieldViewProps> { subItems.push({ description: "lightbox", event: action(() => this._isLightboxOpen = true), icon: "eye" }); !existingVm && ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems, icon: "eye" }); - let existing = ContextMenu.Instance.findByDescription("Layout..."); - let layoutItems = existing && "subitems" in existing ? existing.subitems : []; + const existing = ContextMenu.Instance.findByDescription("Layout..."); + const layoutItems = existing && "subitems" in existing ? existing.subitems : []; layoutItems.push({ description: `${this.props.Document.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.props.Document.forceActive = !this.props.Document.forceActive, icon: "project-diagram" }); !existing && ContextMenu.Instance.addItem({ description: "Layout...", subitems: layoutItems, icon: "hand-point-right" }); - let more = ContextMenu.Instance.findByDescription("More..."); - let moreItems = more && "subitems" in more ? more.subitems : []; + const more = ContextMenu.Instance.findByDescription("More..."); + const moreItems = more && "subitems" in more ? more.subitems : []; moreItems.push({ description: "Export Image Hierarchy", icon: "columns", event: () => ImageUtils.ExportHierarchyToFileSystem(this.props.Document) }); !more && ContextMenu.Instance.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" }); } diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 06fca7c38..4161e5d6e 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -13,7 +13,6 @@ import { DragManager } from "../../util/DragManager"; import { undoBatch } from "../../util/UndoManager"; import { EditableView } from "../EditableView"; import { COLLECTION_BORDER_WIDTH } from "../globalCssVariables.scss"; -import { DocLike } from "../MetadataEntryMenu"; import { CollectionViewType } from "./CollectionView"; import { CollectionView } from "./CollectionView"; import "./CollectionViewChromes.scss"; @@ -33,7 +32,7 @@ interface Filter { contains: boolean; } -let stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation(); +const stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation(); @observer export class CollectionViewBaseChrome extends React.Component<CollectionViewChromeProps> { @@ -80,11 +79,11 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro @computed private get filterValue() { return Cast(this.props.CollectionView.props.Document.viewSpecScript, ScriptField); } getFilters = (script: string) => { - let re: any = /(!)?\(\(\(doc\.(\w+)\s+&&\s+\(doc\.\w+\s+as\s+\w+\)\.includes\(\"(\w+)\"\)/g; - let arr: any[] = re.exec(script); - let toReturn: Filter[] = []; + const re: any = /(!)?\(\(\(doc\.(\w+)\s+&&\s+\(doc\.\w+\s+as\s+\w+\)\.includes\(\"(\w+)\"\)/g; + const arr: any[] = re.exec(script); + const toReturn: Filter[] = []; if (arr !== null) { - let filter: Filter = { + const filter: Filter = { key: arr[2], value: arr[3], contains: (arr[1] === "!") ? false : true, @@ -120,14 +119,14 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro let fields: Filter[] = []; if (this.filterValue) { - let string = this.filterValue.script.originalScript; + const string = this.filterValue.script.originalScript; fields = this.getFilters(string); } runInAction(() => { this.addKeyRestrictions(fields); // chrome status is one of disabled, collapsed, or visible. this determines initial state from document - let chromeStatus = this.props.CollectionView.props.Document.chromeStatus; + const chromeStatus = this.props.CollectionView.props.Document.chromeStatus; if (chromeStatus) { if (chromeStatus === "disabled") { throw new Error("how did you get here, if chrome status is 'disabled' on a collection, a chrome shouldn't even be instantiated!"); @@ -183,7 +182,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro @action addKeyRestriction = (e: React.MouseEvent) => { - let index = this._keyRestrictions.length; + const index = this._keyRestrictions.length; this._keyRestrictions.push([<KeyRestrictionRow field="" value="" key={Utils.GenerateGuid()} contains={true} script={(value: string) => runInAction(() => this._keyRestrictions[index][1] = value)} />, ""]); this.openViewSpecs(e); @@ -194,26 +193,26 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro this.openViewSpecs(e); - let keyRestrictionScript = "(" + this._keyRestrictions.map(i => i[1]).filter(i => i.length > 0).join(" && ") + ")"; - let yearOffset = this._dateWithinValue[1] === 'y' ? 1 : 0; - let monthOffset = this._dateWithinValue[1] === 'm' ? parseInt(this._dateWithinValue[0]) : 0; - let weekOffset = this._dateWithinValue[1] === 'w' ? parseInt(this._dateWithinValue[0]) : 0; - let dayOffset = (this._dateWithinValue[1] === 'd' ? parseInt(this._dateWithinValue[0]) : 0) + weekOffset * 7; + const keyRestrictionScript = "(" + this._keyRestrictions.map(i => i[1]).filter(i => i.length > 0).join(" && ") + ")"; + const yearOffset = this._dateWithinValue[1] === 'y' ? 1 : 0; + const monthOffset = this._dateWithinValue[1] === 'm' ? parseInt(this._dateWithinValue[0]) : 0; + const weekOffset = this._dateWithinValue[1] === 'w' ? parseInt(this._dateWithinValue[0]) : 0; + const dayOffset = (this._dateWithinValue[1] === 'd' ? parseInt(this._dateWithinValue[0]) : 0) + weekOffset * 7; let dateRestrictionScript = ""; if (this._dateValue instanceof Date) { - let lowerBound = new Date(this._dateValue.getFullYear() - yearOffset, this._dateValue.getMonth() - monthOffset, this._dateValue.getDate() - dayOffset); - let upperBound = new Date(this._dateValue.getFullYear() + yearOffset, this._dateValue.getMonth() + monthOffset, this._dateValue.getDate() + dayOffset + 1); + const lowerBound = new Date(this._dateValue.getFullYear() - yearOffset, this._dateValue.getMonth() - monthOffset, this._dateValue.getDate() - dayOffset); + const upperBound = new Date(this._dateValue.getFullYear() + yearOffset, this._dateValue.getMonth() + monthOffset, this._dateValue.getDate() + dayOffset + 1); dateRestrictionScript = `((doc.creationDate as any).date >= ${lowerBound.valueOf()} && (doc.creationDate as any).date <= ${upperBound.valueOf()})`; } else { - let createdDate = new Date(this._dateValue); + const createdDate = new Date(this._dateValue); if (!isNaN(createdDate.getTime())) { - let lowerBound = new Date(createdDate.getFullYear() - yearOffset, createdDate.getMonth() - monthOffset, createdDate.getDate() - dayOffset); - let upperBound = new Date(createdDate.getFullYear() + yearOffset, createdDate.getMonth() + monthOffset, createdDate.getDate() + dayOffset + 1); + const lowerBound = new Date(createdDate.getFullYear() - yearOffset, createdDate.getMonth() - monthOffset, createdDate.getDate() - dayOffset); + const upperBound = new Date(createdDate.getFullYear() + yearOffset, createdDate.getMonth() + monthOffset, createdDate.getDate() + dayOffset + 1); dateRestrictionScript = `((doc.creationDate as any).date >= ${lowerBound.valueOf()} && (doc.creationDate as any).date <= ${upperBound.valueOf()})`; } } - let fullScript = dateRestrictionScript.length || keyRestrictionScript.length ? dateRestrictionScript.length ? + const fullScript = dateRestrictionScript.length || keyRestrictionScript.length ? dateRestrictionScript.length ? `${dateRestrictionScript} ${keyRestrictionScript.length ? "&&" : ""} (${keyRestrictionScript})` : `(${keyRestrictionScript}) ${dateRestrictionScript.length ? "&&" : ""} ${dateRestrictionScript}` : "true"; @@ -270,7 +269,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro value={this.pivotKeyDisplay} onChange={action((e: React.ChangeEvent<HTMLInputElement>) => this.pivotKeyDisplay = e.currentTarget.value)} onKeyPress={action((e: React.KeyboardEvent<HTMLInputElement>) => { - let value = e.currentTarget.value; + const value = e.currentTarget.value; if (e.which === 13) { this.pivotKey = value; this.pivotKeyDisplay = ""; @@ -357,7 +356,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro dragPointerMove = (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); - let [dx, dy] = [e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y]; + const [dx, dy] = [e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y]; if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) { this._buttonizableCommands.filter(c => c.title === this._currentKey).map(c => DragManager.StartButtonDrag([this._commandRef.current!], c.script, c.title, @@ -373,7 +372,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro } render() { - let collapsed = this.props.CollectionView.props.Document.chromeStatus !== "enabled"; + const collapsed = this.props.CollectionView.props.Document.chromeStatus !== "enabled"; return ( <div className="collectionViewChrome-cont" style={{ top: collapsed ? -70 : 0, height: collapsed ? 0 : undefined }}> <div className="collectionViewChrome"> @@ -480,7 +479,7 @@ export class CollectionStackingViewChrome extends React.Component<CollectionView getKeySuggestions = async (value: string): Promise<string[]> => { value = value.toLowerCase(); - let docs = DocListCast(this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey]); + const docs = DocListCast(this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey]); if (docs instanceof Doc) { return Object.keys(docs).filter(key => key.toLowerCase().startsWith(value)); } else { @@ -571,31 +570,31 @@ export class CollectionSchemaViewChrome extends React.Component<CollectionViewCh @undoBatch togglePreview = () => { - let dividerWidth = 4; - let borderWidth = Number(COLLECTION_BORDER_WIDTH); - let panelWidth = this.props.CollectionView.props.PanelWidth(); - let previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth); - let tableWidth = panelWidth - 2 * borderWidth - dividerWidth - previewWidth; + const dividerWidth = 4; + const borderWidth = Number(COLLECTION_BORDER_WIDTH); + const panelWidth = this.props.CollectionView.props.PanelWidth(); + const previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth); + const tableWidth = panelWidth - 2 * borderWidth - dividerWidth - previewWidth; this.props.CollectionView.props.Document.schemaPreviewWidth = previewWidth === 0 ? Math.min(tableWidth / 3, 200) : 0; } @undoBatch @action toggleTextwrap = async () => { - let textwrappedRows = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []); + const textwrappedRows = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []); if (textwrappedRows.length) { this.props.CollectionView.props.Document.textwrappedSchemaRows = new List<string>([]); } else { - let docs = DocListCast(this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey]); - let allRows = docs instanceof Doc ? [docs[Id]] : docs.map(doc => doc[Id]); + const docs = DocListCast(this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey]); + const allRows = docs instanceof Doc ? [docs[Id]] : docs.map(doc => doc[Id]); this.props.CollectionView.props.Document.textwrappedSchemaRows = new List<string>(allRows); } } render() { - let previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth); - let textWrapped = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0; + const previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth); + const textWrapped = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0; return ( <div className="collectionSchemaViewChrome-cont"> diff --git a/src/client/views/collections/KeyRestrictionRow.tsx b/src/client/views/collections/KeyRestrictionRow.tsx index e35b7d7d3..f3071b316 100644 --- a/src/client/views/collections/KeyRestrictionRow.tsx +++ b/src/client/views/collections/KeyRestrictionRow.tsx @@ -1,8 +1,6 @@ import * as React from "react"; import { observable, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { PastelSchemaPalette } from "../../../new_fields/SchemaHeaderField"; -import { Doc } from "../../../new_fields/Doc"; interface IKeyRestrictionProps { contains: boolean; @@ -20,13 +18,13 @@ export default class KeyRestrictionRow extends React.Component<IKeyRestrictionPr render() { if (this._key && this._value) { let parsedValue: string | number = `"${this._value}"`; - let parsed = parseInt(this._value); + const parsed = parseInt(this._value); let type = "string"; if (!isNaN(parsed)) { parsedValue = parsed; type = "number"; } - let scriptText = `${this._contains ? "" : "!"}(((doc.${this._key} && (doc.${this._key} as ${type})${type === "string" ? ".includes" : "<="}(${parsedValue}))) || + const scriptText = `${this._contains ? "" : "!"}(((doc.${this._key} && (doc.${this._key} as ${type})${type === "string" ? ".includes" : "<="}(${parsedValue}))) || ((doc.data_ext && doc.data_ext.${this._key}) && (doc.data_ext.${this._key} as ${type})${type === "string" ? ".includes" : "<="}(${parsedValue}))))`; // let doc = new Doc(); // ((doc.data_ext && doc.data_ext!.text) && (doc.data_ext!.text as string).includes("hello")); diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx index 4eb9e9d1e..75ee8de32 100644 --- a/src/client/views/collections/ParentDocumentSelector.tsx +++ b/src/client/views/collections/ParentDocumentSelector.tsx @@ -34,7 +34,7 @@ export class SelectorContextMenu extends React.Component<SelectorProps> { } async fetchDocuments() { - let aliases = (await SearchUtil.GetAliasesOfDocument(this.props.Document)).filter(doc => doc !== this.props.Document); + const aliases = (await SearchUtil.GetAliasesOfDocument(this.props.Document)).filter(doc => doc !== this.props.Document); const { docs } = await SearchUtil.Search("", true, { fq: `data_l:"${this.props.Document[Id]}"` }); const map: Map<Doc, Doc> = new Map; const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", true, { fq: `data_l:"${doc[Id]}"` }).then(result => result.docs))); @@ -129,7 +129,7 @@ export class ButtonSelector extends React.Component<{ Document: Doc, Stack: any render() { let flyout; if (this.hover) { - let view = DocumentManager.Instance.getDocumentView(this.props.Document); + const view = DocumentManager.Instance.getDocumentView(this.props.Document); flyout = !view ? (null) : ( <div className="PDS-flyout" title=" " onMouseLeave={this.onMouseLeave}> <DocumentButtonBar views={[view]} stack={this.props.Stack} /> diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index 4a32c1647..012115b1f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -77,7 +77,7 @@ export function computePivotLayout(poolData: ObservableMap<string, any>, pivotDo fontSize: NumCast(pivotDoc.pivotFontSize, 10) }); for (const doc of val) { - let layoutDoc = Doc.Layout(doc); + const layoutDoc = Doc.Layout(doc); let wid = pivotAxisWidth; let hgt = layoutDoc.nativeWidth ? (NumCast(layoutDoc.nativeHeight) / NumCast(layoutDoc.nativeWidth)) * pivotAxisWidth : pivotAxisWidth; if (hgt > pivotAxisWidth) { @@ -100,7 +100,7 @@ export function computePivotLayout(poolData: ObservableMap<string, any>, pivotDo }); childPairs.map(pair => { - let defaultPosition = { + const defaultPosition = { x: NumCast(pair.layout.x), y: NumCast(pair.layout.y), z: NumCast(pair.layout.z), @@ -108,7 +108,7 @@ export function computePivotLayout(poolData: ObservableMap<string, any>, pivotDo height: NumCast(pair.layout.height) }; const pos = docMap.get(pair.layout) || defaultPosition; - let data = poolData.get(pair.layout[Id]); + const data = poolData.get(pair.layout[Id]); if (!data || pos.x !== data.x || pos.y !== data.y || pos.z !== data.z || pos.width !== data.width || pos.height !== data.height) { runInAction(() => poolData.set(pair.layout[Id], { transition: "transform 1s", ...pos })); } @@ -118,10 +118,10 @@ export function computePivotLayout(poolData: ObservableMap<string, any>, pivotDo export function AddCustomFreeFormLayout(doc: Doc, dataKey: string): () => void { return () => { - let addOverlay = (key: "arrangeScript" | "arrangeInit", options: OverlayElementOptions, params?: Record<string, string>, requiredType?: string) => { + const addOverlay = (key: "arrangeScript" | "arrangeInit", options: OverlayElementOptions, params?: Record<string, string>, requiredType?: string) => { let overlayDisposer: () => void = emptyFunction; // filled in below after we have a reference to the scriptingBox const scriptField = Cast(doc[key], ScriptField); - let scriptingBox = <ScriptBox initialText={scriptField && scriptField.script.originalScript} + const scriptingBox = <ScriptBox initialText={scriptField && scriptField.script.originalScript} // tslint:disable-next-line: no-unnecessary-callback-wrapper onCancel={() => overlayDisposer()} // don't get rid of the function wrapper-- we don't want to use the current value of overlayDiposer, but the one set below onSave={(text, onError) => { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index b00728079..5e4b4fd27 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -6,9 +6,8 @@ import "./CollectionFreeFormLinkView.scss"; import React = require("react"); import v5 = require("uuid/v5"); import { DocumentType } from "../../../documents/DocumentTypes"; -import { observable, action, reaction, IReactionDisposer, trace } from "mobx"; -import { StrCast, Cast } from "../../../../new_fields/Types"; -import { TraceMobx } from "../../../../new_fields/util"; +import { observable, action, reaction, IReactionDisposer } from "mobx"; +import { StrCast } from "../../../../new_fields/Types"; export interface CollectionFreeFormLinkViewProps { A: DocumentView; @@ -26,22 +25,22 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo action(() => { setTimeout(action(() => this._opacity = 1), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render() setTimeout(action(() => this._opacity = 0.05), 750); // this will unhighlight the link line. - let acont = this.props.A.props.Document.type === DocumentType.LINK ? this.props.A.ContentDiv!.getElementsByClassName("docuLinkBox-cont") : []; - let bcont = this.props.B.props.Document.type === DocumentType.LINK ? this.props.B.ContentDiv!.getElementsByClassName("docuLinkBox-cont") : []; - let adiv = (acont.length ? acont[0] : this.props.A.ContentDiv!); - let bdiv = (bcont.length ? bcont[0] : this.props.B.ContentDiv!); - let a = adiv.getBoundingClientRect(); - let b = bdiv.getBoundingClientRect(); - let abounds = adiv.parentElement!.getBoundingClientRect(); - let bbounds = bdiv.parentElement!.getBoundingClientRect(); - let apt = Utils.closestPtBetweenRectangles(abounds.left, abounds.top, abounds.width, abounds.height, + const acont = this.props.A.props.Document.type === DocumentType.LINK ? this.props.A.ContentDiv!.getElementsByClassName("docuLinkBox-cont") : []; + const bcont = this.props.B.props.Document.type === DocumentType.LINK ? this.props.B.ContentDiv!.getElementsByClassName("docuLinkBox-cont") : []; + const adiv = (acont.length ? acont[0] : this.props.A.ContentDiv!); + const bdiv = (bcont.length ? bcont[0] : this.props.B.ContentDiv!); + const a = adiv.getBoundingClientRect(); + const b = bdiv.getBoundingClientRect(); + const abounds = adiv.parentElement!.getBoundingClientRect(); + const bbounds = bdiv.parentElement!.getBoundingClientRect(); + const apt = Utils.closestPtBetweenRectangles(abounds.left, abounds.top, abounds.width, abounds.height, bbounds.left, bbounds.top, bbounds.width, bbounds.height, a.left + a.width / 2, a.top + a.height / 2); - let bpt = Utils.closestPtBetweenRectangles(bbounds.left, bbounds.top, bbounds.width, bbounds.height, + const bpt = Utils.closestPtBetweenRectangles(bbounds.left, bbounds.top, bbounds.width, bbounds.height, abounds.left, abounds.top, abounds.width, abounds.height, apt.point.x, apt.point.y); - let afield = StrCast(this.props.A.props.Document[StrCast(this.props.A.props.layoutKey, "layout")]).indexOf("anchor1") === -1 ? "anchor2" : "anchor1"; - let bfield = afield === "anchor1" ? "anchor2" : "anchor1"; + const afield = StrCast(this.props.A.props.Document[StrCast(this.props.A.props.layoutKey, "layout")]).indexOf("anchor1") === -1 ? "anchor2" : "anchor1"; + const bfield = afield === "anchor1" ? "anchor2" : "anchor1"; this.props.A.props.Document[afield + "_x"] = (apt.point.x - abounds.left) / abounds.width * 100; this.props.A.props.Document[afield + "_y"] = (apt.point.y - abounds.top) / abounds.height * 100; this.props.A.props.Document[bfield + "_x"] = (bpt.point.x - bbounds.left) / bbounds.width * 100; @@ -55,18 +54,18 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo } render() { - let acont = this.props.A.props.Document.type === DocumentType.LINK ? this.props.A.ContentDiv!.getElementsByClassName("docuLinkBox-cont") : []; - let bcont = this.props.B.props.Document.type === DocumentType.LINK ? this.props.B.ContentDiv!.getElementsByClassName("docuLinkBox-cont") : []; - let a = (acont.length ? acont[0] : this.props.A.ContentDiv!).getBoundingClientRect(); - let b = (bcont.length ? bcont[0] : this.props.B.ContentDiv!).getBoundingClientRect(); - let apt = Utils.closestPtBetweenRectangles(a.left, a.top, a.width, a.height, + const acont = this.props.A.props.Document.type === DocumentType.LINK ? this.props.A.ContentDiv!.getElementsByClassName("docuLinkBox-cont") : []; + const bcont = this.props.B.props.Document.type === DocumentType.LINK ? this.props.B.ContentDiv!.getElementsByClassName("docuLinkBox-cont") : []; + const a = (acont.length ? acont[0] : this.props.A.ContentDiv!).getBoundingClientRect(); + const b = (bcont.length ? bcont[0] : this.props.B.ContentDiv!).getBoundingClientRect(); + const apt = Utils.closestPtBetweenRectangles(a.left, a.top, a.width, a.height, b.left, b.top, b.width, b.height, a.left + a.width / 2, a.top + a.height / 2); - let bpt = Utils.closestPtBetweenRectangles(b.left, b.top, b.width, b.height, + const bpt = Utils.closestPtBetweenRectangles(b.left, b.top, b.width, b.height, a.left, a.top, a.width, a.height, apt.point.x, apt.point.y); - let pt1 = [apt.point.x, apt.point.y]; - let pt2 = [bpt.point.x, bpt.point.y]; + const pt1 = [apt.point.x, apt.point.y]; + const pt2 = [bpt.point.x, bpt.point.y]; return (<line key="linkLine" className="collectionfreeformlinkview-linkLine" style={{ opacity: this._opacity }} x1={`${pt1[0]}`} y1={`${pt1[1]}`} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index e9191c176..218012fe1 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -72,11 +72,11 @@ export class CollectionFreeFormLinksView extends React.Component { } @computed get uniqueConnections() { - let connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => { + const connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => { if (!drawnPairs.reduce((found, drawnPair) => { - let match1 = (connection.a === drawnPair.a && connection.b === drawnPair.b); - let match2 = (connection.a === drawnPair.b && connection.b === drawnPair.a); - let match = match1 || match2; + const match1 = (connection.a === drawnPair.a && connection.b === drawnPair.b); + const match2 = (connection.a === drawnPair.b && connection.b === drawnPair.a); + const match = match1 || match2; if (match && !drawnPair.l.reduce((found, link) => found || link[Id] === connection.l[Id], false)) { drawnPair.l.push(connection.l); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx index b8148852d..bb9ae4326 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx @@ -13,14 +13,14 @@ import v5 = require("uuid/v5"); export class CollectionFreeFormRemoteCursors extends React.Component<CollectionViewProps> { protected getCursors(): CursorField[] { - let doc = this.props.Document; + const doc = this.props.Document; - let id = CurrentUserUtils.id; + const id = CurrentUserUtils.id; if (!id) { return []; } - let cursors = Cast(doc.cursors, listSpec(CursorField)); + const cursors = Cast(doc.cursors, listSpec(CursorField)); const now = mobxUtils.now(); // const now = Date.now(); @@ -30,7 +30,7 @@ export class CollectionFreeFormRemoteCursors extends React.Component<CollectionV private crosshairs?: HTMLCanvasElement; drawCrosshairs = (backgroundColor: string) => { if (this.crosshairs) { - let ctx = this.crosshairs.getContext('2d'); + const ctx = this.crosshairs.getContext('2d'); if (ctx) { ctx.fillStyle = backgroundColor; ctx.fillRect(0, 0, 20, 20); @@ -62,8 +62,8 @@ export class CollectionFreeFormRemoteCursors extends React.Component<CollectionV get sharedCursors() { return this.getCursors().map(c => { - let m = c.data.metadata; - let l = c.data.position; + const m = c.data.metadata; + const l = c.data.position; this.drawCrosshairs("#" + v5(m.id, v5.URL).substring(0, 6).toUpperCase() + "22"); return ( <div key={m.id} className="collectionFreeFormRemoteCursors-cont" diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 9506ce084..c69b264c4 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,12 +1,12 @@ import { library } from "@fortawesome/fontawesome-svg-core"; import { faEye } from "@fortawesome/free-regular-svg-icons"; import { faBraille, faChalkboard, faCompass, faCompressArrowsAlt, faExpandArrowsAlt, faFileUpload, faPaintBrush, faTable, faUpload } from "@fortawesome/free-solid-svg-icons"; -import { action, computed, observable, trace, ObservableMap, untracked, reaction, runInAction, IReactionDisposer } from "mobx"; +import { action, computed, observable, ObservableMap, reaction, runInAction, IReactionDisposer } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../../new_fields/Doc"; +import { Doc, DocListCast, HeightSym, Opt, WidthSym, DocListCastAsync } from "../../../../new_fields/Doc"; import { documentSchema, positionSchema } from "../../../../new_fields/documentSchemas"; import { Id } from "../../../../new_fields/FieldSymbols"; -import { InkTool } from "../../../../new_fields/InkField"; +import { InkTool, InkField, InkData } from "../../../../new_fields/InkField"; import { createSchema, makeInterface } from "../../../../new_fields/Schema"; import { ScriptField } from "../../../../new_fields/ScriptField"; import { BoolCast, Cast, DateCast, NumCast, StrCast } from "../../../../new_fields/Types"; @@ -26,7 +26,7 @@ import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss" import { ContextMenu } from "../../ContextMenu"; import { ContextMenuProps } from "../../ContextMenuItem"; import { InkingControl } from "../../InkingControl"; -import { CreatePolyline, InkingStroke } from "../../InkingStroke"; +import { CreatePolyline } from "../../InkingStroke"; import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView"; import { DocumentViewProps } from "../../nodes/DocumentView"; import { FormattedTextBox } from "../../nodes/FormattedTextBox"; @@ -39,8 +39,9 @@ import "./CollectionFreeFormView.scss"; import MarqueeOptionsMenu from "./MarqueeOptionsMenu"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); -import { computedFn, keepAlive } from "mobx-utils"; +import { computedFn } from "mobx-utils"; import { TraceMobx } from "../../../../new_fields/util"; +import { CognitiveServices } from "../../../cognitive_services/CognitiveServices"; library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload); @@ -98,10 +99,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { private getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.zoomScaling()).translate(this.panX(), this.panY()); private addLiveTextBox = (newBox: Doc) => { FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed - let maxHeading = this.childDocs.reduce((maxHeading, doc) => NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading, 0); + const maxHeading = this.childDocs.reduce((maxHeading, doc) => NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading, 0); let heading = maxHeading === 0 || this.childDocs.length === 0 ? 1 : maxHeading === 1 ? 2 : 0; if (heading === 0) { - let sorted = this.childDocs.filter(d => d.type === DocumentType.TEXT && d.data_ext instanceof Doc && d.data_ext.lastModified).sort((a, b) => DateCast((Cast(a.data_ext, Doc) as Doc).lastModified).date > DateCast((Cast(b.data_ext, Doc) as Doc).lastModified).date ? 1 : + const sorted = this.childDocs.filter(d => d.type === DocumentType.TEXT && d.data_ext instanceof Doc && d.data_ext.lastModified).sort((a, b) => DateCast((Cast(a.data_ext, Doc) as Doc).lastModified).date > DateCast((Cast(b.data_ext, Doc) as Doc).lastModified).date ? 1 : DateCast((Cast(a.data_ext, Doc) as Doc).lastModified).date < DateCast((Cast(b.data_ext, Doc) as Doc).lastModified).date ? -1 : 0); heading = !sorted.length ? Math.max(1, maxHeading) : NumCast(sorted[sorted.length - 1].heading) === 1 ? 2 : NumCast(sorted[sorted.length - 1].heading); } @@ -109,7 +110,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { this.addDocument(newBox); } private addDocument = (newBox: Doc) => { - let added = this.props.addDocument(newBox); + const added = this.props.addDocument(newBox); added && this.bringToFront(newBox); added && this.updateCluster(newBox); return added; @@ -126,36 +127,36 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @action onDrop = (e: React.DragEvent): Promise<void> => { - var pt = this.getTransform().transformPoint(e.pageX, e.pageY); + const pt = this.getTransform().transformPoint(e.pageX, e.pageY); return super.onDrop(e, { x: pt[0], y: pt[1] }); } @undoBatch @action drop = (e: Event, de: DragManager.DropEvent) => { - let xf = this.getTransform(); - let xfo = this.getTransformOverlay(); - let [xp, yp] = xf.transformPoint(de.x, de.y); - let [xpo, ypo] = xfo.transformPoint(de.x, de.y); + const xf = this.getTransform(); + const xfo = this.getTransformOverlay(); + const [xp, yp] = xf.transformPoint(de.x, de.y); + const [xpo, ypo] = xfo.transformPoint(de.x, de.y); if (super.drop(e, de)) { if (de.data instanceof DragManager.DocumentDragData) { if (de.data.droppedDocuments.length) { - let firstDoc = de.data.droppedDocuments[0]; - let z = NumCast(firstDoc.z); - let x = (z ? xpo : xp) - de.data.offset[0]; - let y = (z ? ypo : yp) - de.data.offset[1]; - let dropX = NumCast(firstDoc.x); - let dropY = NumCast(firstDoc.y); + const firstDoc = de.data.droppedDocuments[0]; + const z = NumCast(firstDoc.z); + const x = (z ? xpo : xp) - de.data.offset[0]; + const y = (z ? ypo : yp) - de.data.offset[1]; + const dropX = NumCast(firstDoc.x); + const dropY = NumCast(firstDoc.y); de.data.droppedDocuments.forEach(action((d: Doc) => { - let layoutDoc = Doc.Layout(d); + const layoutDoc = Doc.Layout(d); d.x = x + NumCast(d.x) - dropX; d.y = y + NumCast(d.y) - dropY; if (!NumCast(layoutDoc.width)) { layoutDoc.width = 300; } if (!NumCast(layoutDoc.height)) { - let nw = NumCast(layoutDoc.nativeWidth); - let nh = NumCast(layoutDoc.nativeHeight); + const nw = NumCast(layoutDoc.nativeWidth); + const nh = NumCast(layoutDoc.nativeHeight); layoutDoc.height = nw && nh ? nh / nw * NumCast(layoutDoc.width) : 300; } this.bringToFront(d); @@ -166,11 +167,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } else if (de.data instanceof DragManager.AnnotationDragData) { if (de.data.dropDocument) { - let dragDoc = de.data.dropDocument; - let x = xp - de.data.offset[0]; - let y = yp - de.data.offset[1]; - let dropX = NumCast(dragDoc.x); - let dropY = NumCast(dragDoc.y); + const dragDoc = de.data.dropDocument; + const x = xp - de.data.offset[0]; + const y = yp - de.data.offset[1]; + const dropX = NumCast(dragDoc.x); + const dropY = NumCast(dragDoc.y); dragDoc.x = x + NumCast(dragDoc.x) - dropX; dragDoc.y = y + NumCast(dragDoc.y) - dropY; de.data.targetContext = this.props.Document; // dropped a PDF annotation, so we need to set the targetContext on the dragData which the PDF view uses at the end of the drop operation @@ -183,23 +184,23 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { pickCluster(probe: number[]) { return this.childLayoutPairs.map(pair => pair.layout).reduce((cluster, cd) => { - let layoutDoc = Doc.Layout(cd); - let cx = NumCast(cd.x) - this._clusterDistance; - let cy = NumCast(cd.y) - this._clusterDistance; - let cw = NumCast(layoutDoc.width) + 2 * this._clusterDistance; - let ch = NumCast(layoutDoc.height) + 2 * this._clusterDistance; + const layoutDoc = Doc.Layout(cd); + const cx = NumCast(cd.x) - this._clusterDistance; + const cy = NumCast(cd.y) - this._clusterDistance; + const cw = NumCast(layoutDoc.width) + 2 * this._clusterDistance; + const ch = NumCast(layoutDoc.height) + 2 * this._clusterDistance; return !layoutDoc.z && intersectRect({ left: cx, top: cy, width: cw, height: ch }, { left: probe[0], top: probe[1], width: 1, height: 1 }) ? NumCast(cd.cluster) : cluster; }, -1); } tryDragCluster(e: PointerEvent | TouchEvent) { - let ptsParent = e instanceof PointerEvent ? e : e.targetTouches.item(0); + const ptsParent = e instanceof PointerEvent ? e : e.targetTouches.item(0); if (ptsParent) { - let cluster = this.pickCluster(this.getTransform().transformPoint(ptsParent.clientX, ptsParent.clientY)); + const cluster = this.pickCluster(this.getTransform().transformPoint(ptsParent.clientX, ptsParent.clientY)); if (cluster !== -1) { - let eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => NumCast(cd.cluster) === cluster); - let clusterDocs = eles.map(ele => DocumentManager.Instance.getDocumentView(ele, this.props.CollectionView)!); - let de = new DragManager.DocumentDragData(eles); + const eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => NumCast(cd.cluster) === cluster); + const clusterDocs = eles.map(ele => DocumentManager.Instance.getDocumentView(ele, this.props.CollectionView)!); + const de = new DragManager.DocumentDragData(eles); de.moveDocument = this.props.moveDocument; const [left, top] = clusterDocs[0].props.ScreenToLocalTransform().scale(clusterDocs[0].props.ContentScaling()).inverse().transformPoint(0, 0); de.offset = this.getTransform().transformDirection(ptsParent.clientX - left, ptsParent.clientY - top); @@ -225,10 +226,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @undoBatch @action updateCluster(doc: Doc) { - let childLayouts = this.childLayoutPairs.map(pair => pair.layout); + const childLayouts = this.childLayoutPairs.map(pair => pair.layout); if (this.props.Document.useClusters) { this._clusterSets.map(set => Doc.IndexOf(doc, set) !== -1 && set.splice(Doc.IndexOf(doc, set), 1)); - let preferredInd = NumCast(doc.cluster); + const preferredInd = NumCast(doc.cluster); doc.cluster = -1; this._clusterSets.map((set, i) => set.map(member => { if (doc.cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && Doc.overlapping(doc, member, this._clusterDistance)) { @@ -255,15 +256,15 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { getClusterColor = (doc: Doc) => { let clusterColor = ""; - let cluster = NumCast(doc.cluster); + const cluster = NumCast(doc.cluster); if (this.Document.useClusters) { if (this._clusterSets.length <= cluster) { setTimeout(() => this.updateCluster(doc), 0); } else { // choose a cluster color from a palette - let colors = ["#da42429e", "#31ea318c", "#8c4000", "#4a7ae2c4", "#d809ff", "#ff7601", "#1dffff", "yellow", "#1b8231f2", "#000000ad"]; + const colors = ["#da42429e", "#31ea318c", "#8c4000", "#4a7ae2c4", "#d809ff", "#ff7601", "#1dffff", "yellow", "#1b8231f2", "#000000ad"]; clusterColor = colors[cluster % colors.length]; - let set = this._clusterSets[cluster] && this._clusterSets[cluster].filter(s => s.backgroundColor && (s.backgroundColor !== s.defaultBackgroundColor)); + const set = this._clusterSets[cluster] && this._clusterSets[cluster].filter(s => s.backgroundColor && (s.backgroundColor !== s.defaultBackgroundColor)); // override the cluster color with an explicitly set color on a non-background document. then override that with an explicitly set color on a background document set && set.filter(s => !s.isBackground).map(s => clusterColor = StrCast(s.backgroundColor)); set && set.filter(s => s.isBackground).map(s => clusterColor = StrCast(s.backgroundColor)); @@ -287,7 +288,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { if (InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || (InkingControl.Instance.selectedTool === InkTool.Highlighter || InkingControl.Instance.selectedTool === InkTool.Pen)) { e.stopPropagation(); e.preventDefault(); - let point = this.getTransform().transformPoint(e.pageX, e.pageY); + const point = this.getTransform().transformPoint(e.pageX, e.pageY); this._points.push({ x: point[0], y: point[1] }); } // if not using a pen and in no ink mode @@ -324,7 +325,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @action handle1PointerDown = (e: React.TouchEvent) => { - let pt = e.targetTouches.item(0); + const pt = e.targetTouches.item(0); if (pt) { this._hitCluster = this.props.Document.useCluster ? this.pickCluster(this.getTransform().transformPoint(pt.clientX, pt.clientY)) !== -1 : false; } @@ -335,9 +336,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { if (InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) && this._points.length <= 1) return; if (this._points.length > 1) { - let B = this.svgBounds; - let points = this._points.map(p => ({ x: p.x - B.left, y: p.y - B.top })); - let inkDoc = Docs.Create.InkDocument(InkingControl.Instance.selectedColor, InkingControl.Instance.selectedTool, parseInt(InkingControl.Instance.selectedWidth), points, { width: B.width, height: B.height, x: B.left, y: B.top }); + const B = this.svgBounds; + const points = this._points.map(p => ({ x: p.x - B.left, y: p.y - B.top })); + const inkDoc = Docs.Create.InkDocument(InkingControl.Instance.selectedColor, InkingControl.Instance.selectedTool, parseInt(InkingControl.Instance.selectedWidth), points, { width: B.width, height: B.height, x: B.left, y: B.top }); this.addDocument(inkDoc); this._points = []; } @@ -355,26 +356,26 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { let x = this.Document.panX || 0; let y = this.Document.panY || 0; - let docs = this.childLayoutPairs.map(pair => pair.layout); - let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); + const docs = this.childLayoutPairs.map(pair => pair.layout); + const [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); if (!this.isAnnotationOverlay) { PDFMenu.Instance.fadeOut(true); - let minx = docs.length ? NumCast(docs[0].x) : 0; - let maxx = docs.length ? NumCast(docs[0].width) + minx : minx; - let miny = docs.length ? NumCast(docs[0].y) : 0; - let maxy = docs.length ? NumCast(docs[0].height) + miny : miny; - let ranges = docs.filter(doc => doc).reduce((range, doc) => { - let layoutDoc = Doc.Layout(doc); - let x = NumCast(doc.x); - let xe = x + NumCast(layoutDoc.width); - let y = NumCast(doc.y); - let ye = y + NumCast(layoutDoc.height); + const minx = docs.length ? NumCast(docs[0].x) : 0; + const maxx = docs.length ? NumCast(docs[0].width) + minx : minx; + const miny = docs.length ? NumCast(docs[0].y) : 0; + const maxy = docs.length ? NumCast(docs[0].height) + miny : miny; + const ranges = docs.filter(doc => doc).reduce((range, doc) => { + const layoutDoc = Doc.Layout(doc); + const x = NumCast(doc.x); + const xe = x + NumCast(layoutDoc.width); + const y = NumCast(doc.y); + const ye = y + NumCast(layoutDoc.height); return [[range[0][0] > x ? x : range[0][0], range[0][1] < xe ? xe : range[0][1]], [range[1][0] > y ? y : range[1][0], range[1][1] < ye ? ye : range[1][1]]]; }, [[minx, maxx], [miny, maxy]]); - let cscale = this.props.ContainingCollectionDoc ? NumCast(this.props.ContainingCollectionDoc.scale) : 1; - let panelDim = this.props.ScreenToLocalTransform().transformDirection(this.props.PanelWidth() / this.zoomScaling() * cscale, + const cscale = this.props.ContainingCollectionDoc ? NumCast(this.props.ContainingCollectionDoc.scale) : 1; + const panelDim = this.props.ScreenToLocalTransform().transformDirection(this.props.PanelWidth() / this.zoomScaling() * cscale, this.props.PanelHeight() / this.zoomScaling() * cscale); if (ranges[0][0] - dx > (this.panX() + panelDim[0] / 2)) x = ranges[0][1] + panelDim[0] / 2; if (ranges[0][1] - dx < (this.panX() - panelDim[0] / 2)) x = ranges[0][0] - panelDim[0] / 2; @@ -397,7 +398,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { if (!e.cancelBubble) { const selectedTool = InkingControl.Instance.selectedTool; if (selectedTool === InkTool.Highlighter || selectedTool === InkTool.Pen || InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) { - let point = this.getTransform().transformPoint(e.clientX, e.clientY); + const point = this.getTransform().transformPoint(e.clientX, e.clientY); this._points.push({ x: point[0], y: point[1] }); } else if (selectedTool === InkTool.None) { @@ -418,7 +419,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { handle1PointerMove = (e: TouchEvent) => { // panning a workspace if (!e.cancelBubble) { - let pt = e.targetTouches.item(0); + const pt = e.targetTouches.item(0); if (pt) { if (InkingControl.Instance.selectedTool === InkTool.None) { if (this._hitCluster && this.tryDragCluster(e)) { @@ -431,7 +432,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { this.pan(pt); } else if (InkingControl.Instance.selectedTool !== InkTool.Eraser && InkingControl.Instance.selectedTool !== InkTool.Scrubber) { - let point = this.getTransform().transformPoint(pt.clientX, pt.clientY); + const point = this.getTransform().transformPoint(pt.clientX, pt.clientY); this._points.push({ x: point[0], y: point[1] }); } } @@ -443,28 +444,28 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { handle2PointersMove = (e: TouchEvent) => { // pinch zooming if (!e.cancelBubble) { - let pt1: Touch | null = e.targetTouches.item(0); - let pt2: Touch | null = e.targetTouches.item(1); + const pt1: Touch | null = e.targetTouches.item(0); + const pt2: Touch | null = e.targetTouches.item(1); if (!pt1 || !pt2) return; if (this.prevPoints.size === 2) { - let oldPoint1 = this.prevPoints.get(pt1.identifier); - let oldPoint2 = this.prevPoints.get(pt2.identifier); + const oldPoint1 = this.prevPoints.get(pt1.identifier); + const oldPoint2 = this.prevPoints.get(pt2.identifier); if (oldPoint1 && oldPoint2) { - let dir = InteractionUtils.Pinching(pt1, pt2, oldPoint1, oldPoint2); + const dir = InteractionUtils.Pinching(pt1, pt2, oldPoint1, oldPoint2); // if zooming, zoom if (dir !== 0) { - let d1 = Math.sqrt(Math.pow(pt1.clientX - oldPoint1.clientX, 2) + Math.pow(pt1.clientY - oldPoint1.clientY, 2)); - let d2 = Math.sqrt(Math.pow(pt2.clientX - oldPoint2.clientX, 2) + Math.pow(pt2.clientY - oldPoint2.clientY, 2)); - let centerX = Math.min(pt1.clientX, pt2.clientX) + Math.abs(pt2.clientX - pt1.clientX) / 2; - let centerY = Math.min(pt1.clientY, pt2.clientY) + Math.abs(pt2.clientY - pt1.clientY) / 2; + const d1 = Math.sqrt(Math.pow(pt1.clientX - oldPoint1.clientX, 2) + Math.pow(pt1.clientY - oldPoint1.clientY, 2)); + const d2 = Math.sqrt(Math.pow(pt2.clientX - oldPoint2.clientX, 2) + Math.pow(pt2.clientY - oldPoint2.clientY, 2)); + const centerX = Math.min(pt1.clientX, pt2.clientX) + Math.abs(pt2.clientX - pt1.clientX) / 2; + const centerY = Math.min(pt1.clientY, pt2.clientY) + Math.abs(pt2.clientY - pt1.clientY) / 2; // calculate the raw delta value - let rawDelta = (dir * (d1 + d2)); + const rawDelta = (dir * (d1 + d2)); // this floors and ceils the delta value to prevent jitteriness - let delta = Math.sign(rawDelta) * Math.min(Math.abs(rawDelta), 16); + const delta = Math.sign(rawDelta) * Math.min(Math.abs(rawDelta), 16); this.zoom(centerX, centerY, delta); this.prevPoints.set(pt1.identifier, pt1); this.prevPoints.set(pt2.identifier, pt2); @@ -472,8 +473,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { // this is not zooming. derive some form of panning from it. else { // use the centerx and centery as the "new mouse position" - let centerX = Math.min(pt1.clientX, pt2.clientX) + Math.abs(pt2.clientX - pt1.clientX) / 2; - let centerY = Math.min(pt1.clientY, pt2.clientY) + Math.abs(pt2.clientY - pt1.clientY) / 2; + const centerX = Math.min(pt1.clientX, pt2.clientX) + Math.abs(pt2.clientX - pt1.clientX) / 2; + const centerY = Math.min(pt1.clientY, pt2.clientY) + Math.abs(pt2.clientY - pt1.clientY) / 2; this.pan({ clientX: centerX, clientY: centerY }); this._lastX = centerX; this._lastY = centerY; @@ -486,12 +487,12 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } handle2PointersDown = (e: React.TouchEvent) => { - let pt1: React.Touch | null = e.targetTouches.item(0); - let pt2: React.Touch | null = e.targetTouches.item(1); + const pt1: React.Touch | null = e.targetTouches.item(0); + const pt2: React.Touch | null = e.targetTouches.item(1); if (!pt1 || !pt2) return; - let centerX = Math.min(pt1.clientX, pt2.clientX) + Math.abs(pt2.clientX - pt1.clientX) / 2; - let centerY = Math.min(pt1.clientY, pt2.clientY) + Math.abs(pt2.clientY - pt1.clientY) / 2; + const centerX = Math.min(pt1.clientX, pt2.clientX) + Math.abs(pt2.clientX - pt1.clientX) / 2; + const centerY = Math.min(pt1.clientY, pt2.clientY) + Math.abs(pt2.clientY - pt1.clientY) / 2; this._lastX = centerX; this._lastY = centerY; } @@ -510,11 +511,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { deltaScale = 1 / this.zoomScaling(); } if (deltaScale < 0) deltaScale = -deltaScale; - let [x, y] = this.getTransform().transformPoint(pointX, pointY); - let localTransform = this.getLocalTransform().inverse().scaleAbout(deltaScale, x, y); + const [x, y] = this.getTransform().transformPoint(pointX, pointY); + const localTransform = this.getLocalTransform().inverse().scaleAbout(deltaScale, x, y); if (localTransform.Scale >= 0.15) { - let safeScale = Math.min(Math.max(0.15, localTransform.Scale), 40); + const safeScale = Math.min(Math.max(0.15, localTransform.Scale), 40); this.props.Document.scale = Math.abs(safeScale); this.setPan(-localTransform.TranslateX / safeScale, -localTransform.TranslateY / safeScale); } @@ -536,7 +537,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { setPan(panX: number, panY: number, panType: string = "None") { if (!this.Document.lockedTransform || this.Document.inOverlay) { this.Document.panTransformType = panType; - var scale = this.getLocalTransform().inverse().Scale; + const scale = this.getLocalTransform().inverse().Scale; const newPanX = Math.min((1 - 1 / scale) * this.nativeWidth, Math.max(0, panX)); const newPanY = Math.min((this.props.Document.scrollHeight !== undefined ? NumCast(this.Document.scrollHeight) : (1 - 1 / scale) * this.nativeHeight), Math.max(0, panY)); this.Document.panX = this.isAnnotationOverlay ? newPanX : panX; @@ -576,23 +577,23 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } SelectionManager.DeselectAll(); if (this.props.Document.scrollHeight) { - let annotOn = Cast(doc.annotationOn, Doc) as Doc; + const annotOn = Cast(doc.annotationOn, Doc) as Doc; if (!annotOn) { this.props.focus(doc); } else { - let contextHgt = Doc.AreProtosEqual(annotOn, this.props.Document) && this.props.VisibleHeight ? this.props.VisibleHeight() : NumCast(annotOn.height); - let offset = annotOn && (contextHgt / 2 * 96 / 72); + const contextHgt = Doc.AreProtosEqual(annotOn, this.props.Document) && this.props.VisibleHeight ? this.props.VisibleHeight() : NumCast(annotOn.height); + const offset = annotOn && (contextHgt / 2 * 96 / 72); this.props.Document.scrollY = NumCast(doc.y) - offset; } } else { - let layoutdoc = Doc.Layout(doc); + const layoutdoc = Doc.Layout(doc); const newPanX = NumCast(doc.x) + NumCast(layoutdoc.width) / 2; const newPanY = NumCast(doc.y) + NumCast(layoutdoc.height) / 2; const newState = HistoryUtil.getState(); newState.initializers![this.Document[Id]] = { panX: newPanX, panY: newPanY }; HistoryUtil.pushState(newState); - let savedState = { px: this.Document.panX, py: this.Document.panY, s: this.Document.scale, pt: this.Document.panTransformType }; + const savedState = { px: this.Document.panX, py: this.Document.panY, s: this.Document.scale, pt: this.Document.panTransformType }; this.setPan(newPanX, newPanY, "Ease"); Doc.BrushDoc(this.props.Document); @@ -677,7 +678,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } } - childDataProvider = computedFn(function childDataProvider(doc: Doc) { return (this as any)._layoutPoolData.get(doc[Id]); }.bind(this)); + childDataProvider = computedFn(function childDataProvider(this: any, doc: Doc) { return this._layoutPoolData.get(doc[Id]); }.bind(this)); doPivotLayout(poolData: ObservableMap<string, any>) { return computePivotLayout(poolData, this.props.Document, this.childDocs, @@ -685,10 +686,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } doFreeformLayout(poolData: ObservableMap<string, any>) { - let layoutDocs = this.childLayoutPairs.map(pair => pair.layout); + const layoutDocs = this.childLayoutPairs.map(pair => pair.layout); const initResult = this.Document.arrangeInit && this.Document.arrangeInit.script.run({ docs: layoutDocs, collection: this.Document }, console.log); let state = initResult && initResult.success ? initResult.result.scriptState : undefined; - let elements = initResult && initResult.success ? this.viewDefsToJSX(initResult.result.views) : []; + const elements = initResult && initResult.success ? this.viewDefsToJSX(initResult.result.views) : []; this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map((pair, i) => { const data = poolData.get(pair.layout[Id]); @@ -737,7 +738,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { layoutDocsInGrid = () => { UndoManager.RunInBatch(() => { const docs = DocListCast(this.Document[this.props.fieldKey]); - let startX = this.Document.panX || 0; + const startX = this.Document.panX || 0; let x = startX; let y = this.Document.panY || 0; let i = 0; @@ -762,8 +763,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { this.Document.isRuleProvider && this.childLayoutPairs.map(pair => // iterate over the children of a displayed document (or if the displayed document is a template, iterate over the children of that template) DocListCast(Doc.Layout(pair.layout).data).map(heading => { - let headingPair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, heading); - let headingLayout = headingPair.layout && (pair.layout.data_ext instanceof Doc) && (pair.layout.data_ext[`Layout[${headingPair.layout[Id]}]`] as Doc) || headingPair.layout; + const headingPair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, heading); + const headingLayout = headingPair.layout && (pair.layout.data_ext instanceof Doc) && (pair.layout.data_ext[`Layout[${headingPair.layout[Id]}]`] as Doc) || headingPair.layout; if (headingLayout && NumCast(headingLayout.heading) > 0 && headingLayout.backgroundColor !== headingLayout.defaultBackgroundColor) { Doc.GetProto(this.props.Document)["ruleColor_" + NumCast(headingLayout.heading)] = headingLayout.backgroundColor; } @@ -772,11 +773,23 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } analyzeStrokes = async () => { - // CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.dataDoc, ["inkAnalysis", "handwriting"], data.inkData); + const children = await DocListCastAsync(this.dataDoc.data); + if (!children) { + return; + } + const inkData: InkData[] = []; + for (const doc of children) { + const data = Cast(doc.data, InkField)?.inkData; + data && inkData.push(data); + } + if (!inkData.length) { + return; + } + CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.dataDoc, ["inkAnalysis", "handwriting"], inkData); } onContextMenu = (e: React.MouseEvent) => { - let layoutItems: ContextMenuProps[] = []; + const layoutItems: ContextMenuProps[] = []; if (this.childDocs.some(d => BoolCast(d.isTemplateDoc))) { layoutItems.push({ description: "Template Layout Instance", event: () => this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" }); @@ -795,7 +808,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { input.accept = ".zip"; input.onchange = async _e => { const upload = Utils.prepend("/uploadDoc"); - let formData = new FormData(); + const formData = new FormData(); const file = input.files && input.files[0]; if (file) { formData.append('file', file); @@ -830,7 +843,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { private childViews = () => { - let children = typeof this.props.children === "function" ? (this.props.children as any)() as JSX.Element[] : []; + const children = typeof this.props.children === "function" ? (this.props.children as any)() as JSX.Element[] : []; return [ ...children, ...this.views, @@ -838,12 +851,12 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } @computed get svgBounds() { - let xs = this._points.map(p => p.x); - let ys = this._points.map(p => p.y); - let right = Math.max(...xs); - let left = Math.min(...xs); - let bottom = Math.max(...ys); - let top = Math.min(...ys); + const xs = this._points.map(p => p.x); + const ys = this._points.map(p => p.y); + const right = Math.max(...xs); + const left = Math.min(...xs); + const bottom = Math.max(...ys); + const top = Math.min(...ys); return { right: right, left: left, bottom: bottom, top: top, width: right - left, height: bottom - top }; } @@ -852,7 +865,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return (null); } - let B = this.svgBounds; + const B = this.svgBounds; return ( <svg width={B.width} height={B.height} style={{ transform: `translate(${B.left}px, ${B.top}px)` }}> @@ -862,7 +875,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } children = () => { - let eles: JSX.Element[] = []; + const eles: JSX.Element[] = []; this.extensionDoc && (eles.push(...this.childViews())); this.currentStroke && (eles.push(this.currentStroke)); eles.push(<CollectionFreeFormRemoteCursors {...this.props} key="remoteCursors" />); @@ -917,7 +930,7 @@ interface CollectionFreeFormViewPannableContentsProps { @observer class CollectionFreeFormViewPannableContents extends React.Component<CollectionFreeFormViewPannableContentsProps>{ render() { - let freeformclass = "collectionfreeformview" + (this.props.easing() ? "-ease" : "-none"); + const freeformclass = "collectionfreeformview" + (this.props.easing() ? "-ease" : "-none"); const cenx = this.props.centeringShiftX(); const ceny = this.props.centeringShiftY(); const panx = -this.props.panX(); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx index 28ddc19d7..32e39d25e 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx @@ -21,7 +21,7 @@ export default class MarqueeOptionsMenu extends AntimodeMenu { } render() { - let buttons = [ + const buttons = [ <button className="antimodeMenu-button" title="Create a Collection" diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 5ed3fecb5..dc68ae81c 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -1,7 +1,7 @@ import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast } from "../../../../new_fields/Doc"; -import { InkField, PointData } from "../../../../new_fields/InkField"; +import { InkField } from "../../../../new_fields/InkField"; import { List } from "../../../../new_fields/List"; import { listSpec } from "../../../../new_fields/Schema"; import { SchemaHeaderField } from "../../../../new_fields/SchemaHeaderField"; @@ -15,11 +15,9 @@ import { Transform } from "../../../util/Transform"; import { undoBatch } from "../../../util/UndoManager"; import { PreviewCursor } from "../../PreviewCursor"; import { CollectionViewType } from "../CollectionView"; -import { CollectionFreeFormView } from "./CollectionFreeFormView"; import "./MarqueeView.scss"; import React = require("react"); import MarqueeOptionsMenu from "./MarqueeOptionsMenu"; -import InkSelectDecorations from "../../InkSelectDecorations"; import { SubCollectionViewProps } from "../CollectionSubView"; interface MarqueeViewProps { @@ -67,26 +65,27 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque @action onKeyPress = (e: KeyboardEvent) => { //make textbox and add it to this collection + // tslint:disable-next-line:prefer-const let [x, y] = this.props.getTransform().transformPoint(this._downX, this._downY); if (e.key === "q" && e.ctrlKey) { e.preventDefault(); (async () => { - let text: string = await navigator.clipboard.readText(); - let ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); + const text: string = await navigator.clipboard.readText(); + const ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); for (let i = 0; i < ns.length - 1; i++) { while (!(ns[i].trim() === "" || ns[i].endsWith("-\r") || ns[i].endsWith("-") || ns[i].endsWith(";\r") || ns[i].endsWith(";") || ns[i].endsWith(".\r") || ns[i].endsWith(".") || ns[i].endsWith(":\r") || ns[i].endsWith(":")) && i < ns.length - 1) { - let sub = ns[i].endsWith("\r") ? 1 : 0; - let br = ns[i + 1].trim() === ""; + const sub = ns[i].endsWith("\r") ? 1 : 0; + const br = ns[i + 1].trim() === ""; ns.splice(i, 2, ns[i].substr(0, ns[i].length - sub) + ns[i + 1].trimLeft()); if (br) break; } } ns.map(line => { - let indent = line.search(/\S|$/); - let newBox = Docs.Create.TextDocument({ width: 200, height: 35, x: x + indent / 3 * 10, y: y, documentText: "@@@" + line, title: line }); + const indent = line.search(/\S|$/); + const newBox = Docs.Create.TextDocument({ width: 200, height: 35, x: x + indent / 3 * 10, y: y, documentText: "@@@" + line, title: line }); this.props.addDocument(newBox); y += 40 * this.props.getTransform().Scale; }); @@ -94,7 +93,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque } else if (e.key === "b" && e.ctrlKey) { e.preventDefault(); navigator.clipboard.readText().then(text => { - let ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); + const ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); if (ns.length === 1 && text.startsWith("http")) { this.props.addDocument(Docs.Create.ImageDocument(text, { nativeWidth: 300, width: 300, x: x, y: y }));// paste an image from its URL in the paste buffer } else { @@ -105,8 +104,8 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque this.props.addLiveTextDocument( Docs.Create.TextDocument({ width: 200, height: 100, x: x, y: y, autoHeight: true, title: "-typed text-" })); } else if (e.keyCode > 48 && e.keyCode <= 57) { - let notes = DocListCast((CurrentUserUtils.UserDocument.noteTypes as Doc).data); - let text = Docs.Create.TextDocument({ width: 200, height: 100, x: x, y: y, autoHeight: true, title: "-typed text-" }); + const notes = DocListCast((CurrentUserUtils.UserDocument.noteTypes as Doc).data); + const text = Docs.Create.TextDocument({ width: 200, height: 100, x: x, y: y, autoHeight: true, title: "-typed text-" }); text.layout = notes[(e.keyCode - 49) % notes.length]; this.props.addLiveTextDocument(text); } @@ -124,31 +123,31 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque ns.splice(0, 1); } if (ns.length > 0) { - let columns = ns[0].split("\t"); - let docList: Doc[] = []; + const columns = ns[0].split("\t"); + const docList: Doc[] = []; let groupAttr: string | number = ""; - let rowProto = new Doc(); + const rowProto = new Doc(); rowProto.title = rowProto.Id; rowProto.width = 200; rowProto.isPrototype = true; for (let i = 1; i < ns.length - 1; i++) { - let values = ns[i].split("\t"); + const values = ns[i].split("\t"); if (values.length === 1 && columns.length > 1) { groupAttr = values[0]; continue; } - let docDataProto = Doc.MakeDelegate(rowProto); + const docDataProto = Doc.MakeDelegate(rowProto); docDataProto.isPrototype = true; columns.forEach((col, i) => docDataProto[columns[i]] = (values.length > i ? ((values[i].indexOf(Number(values[i]).toString()) !== -1) ? Number(values[i]) : values[i]) : undefined)); if (groupAttr) { docDataProto._group = groupAttr; } docDataProto.title = i.toString(); - let doc = Doc.MakeDelegate(docDataProto); + const doc = Doc.MakeDelegate(docDataProto); doc.width = 200; docList.push(doc); } - let newCol = Docs.Create.SchemaDocument([...(groupAttr ? [new SchemaHeaderField("_group", "#f1efeb")] : []), ...columns.filter(c => c).map(c => new SchemaHeaderField(c, "#f1efeb"))], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 }); + const newCol = Docs.Create.SchemaDocument([...(groupAttr ? [new SchemaHeaderField("_group", "#f1efeb")] : []), ...columns.filter(c => c).map(c => new SchemaHeaderField(c, "#f1efeb"))], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 }); this.props.addDocument(newCol); } @@ -193,13 +192,13 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque onPointerUp = (e: PointerEvent): void => { if (!this.props.active(true)) this.props.selectDocuments([this.props.Document], []); if (this._visible) { - let mselect = this.marqueeSelect(); + const mselect = this.marqueeSelect(); if (!e.shiftKey) { SelectionManager.DeselectAll(mselect.length ? undefined : this.props.Document); } // let inkselect = this.ink ? this.marqueeInkSelect(this.ink.inkData) : new Map(); // let inks = inkselect.size ? [{ Document: this.inkDoc, Ink: inkselect }] : []; - let docs = mselect.length ? mselect : [this.props.Document]; + const docs = mselect.length ? mselect : [this.props.Document]; this.props.selectDocuments(docs, []); } if (!this._commandExecuted && (Math.abs(this.Bounds.height * this.Bounds.width) > 100)) { @@ -212,7 +211,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque } this.cleanupInteractions(true, this._commandExecuted); - let hideMarquee = () => { + const hideMarquee = () => { this.hideMarquee(); MarqueeOptionsMenu.Instance.fadeOut(true); document.removeEventListener("pointerdown", hideMarquee); @@ -260,10 +259,10 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque @computed get Bounds() { - let left = this._downX < this._lastX ? this._downX : this._lastX; - let top = this._downY < this._lastY ? this._downY : this._lastY; - let topLeft = this.props.getTransform().transformPoint(left, top); - let size = this.props.getTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY); + const left = this._downX < this._lastX ? this._downX : this._lastX; + const top = this._downY < this._lastY ? this._downY : this._lastY; + const topLeft = this.props.getTransform().transformPoint(left, top); + const size = this.props.getTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY); return { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) }; } @@ -302,15 +301,15 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque } getCollection = (selected: Doc[]) => { - let bounds = this.Bounds; - let defaultPalette = ["rgb(114,229,239)", "rgb(255,246,209)", "rgb(255,188,156)", "rgb(247,220,96)", "rgb(122,176,238)", + const bounds = this.Bounds; + const defaultPalette = ["rgb(114,229,239)", "rgb(255,246,209)", "rgb(255,188,156)", "rgb(247,220,96)", "rgb(122,176,238)", "rgb(209,150,226)", "rgb(127,235,144)", "rgb(252,188,189)", "rgb(247,175,81)",]; - let colorPalette = Cast(this.props.Document.colorPalette, listSpec("string")); + const colorPalette = Cast(this.props.Document.colorPalette, listSpec("string")); if (!colorPalette) this.props.Document.colorPalette = new List<string>(defaultPalette); - let palette = Array.from(Cast(this.props.Document.colorPalette, listSpec("string")) as string[]); - let usedPaletted = new Map<string, number>(); + const palette = Array.from(Cast(this.props.Document.colorPalette, listSpec("string")) as string[]); + const usedPaletted = new Map<string, number>(); [...this.props.activeDocuments(), this.props.Document].map(child => { - let bg = StrCast(Doc.Layout(child).backgroundColor); + const bg = StrCast(Doc.Layout(child).backgroundColor); if (palette.indexOf(bg) !== -1) { palette.splice(palette.indexOf(bg), 1); if (usedPaletted.get(bg)) usedPaletted.set(bg, usedPaletted.get(bg)! + 1); @@ -320,10 +319,10 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque usedPaletted.delete("#f1efeb"); usedPaletted.delete("white"); usedPaletted.delete("rgba(255,255,255,1)"); - let usedSequnce = Array.from(usedPaletted.keys()).sort((a, b) => usedPaletted.get(a)! < usedPaletted.get(b)! ? -1 : usedPaletted.get(a)! > usedPaletted.get(b)! ? 1 : 0); - let chosenColor = (usedPaletted.size === 0) ? "white" : palette.length ? palette[0] : usedSequnce[0]; - let inkData = this.ink ? this.ink.inkData : undefined; - let newCollection = Docs.Create.FreeformDocument(selected, { + const usedSequnce = Array.from(usedPaletted.keys()).sort((a, b) => usedPaletted.get(a)! < usedPaletted.get(b)! ? -1 : usedPaletted.get(a)! > usedPaletted.get(b)! ? 1 : 0); + const chosenColor = (usedPaletted.size === 0) ? "white" : palette.length ? palette[0] : usedSequnce[0]; + // const inkData = this.ink ? this.ink.inkData : undefined; + const newCollection = Docs.Create.FreeformDocument(selected, { x: bounds.left, y: bounds.top, panX: 0, @@ -334,7 +333,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque height: bounds.height, title: "a nested collection", }); - let dataExtensionField = Doc.CreateDocumentExtensionForField(newCollection, "data"); + // const dataExtensionField = Doc.CreateDocumentExtensionForField(newCollection, "data"); // dataExtensionField.ink = inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined; // this.marqueeInkDelete(inkData); this.hideMarquee(); @@ -343,8 +342,8 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque @action collection = (e: KeyboardEvent | React.PointerEvent | undefined) => { - let bounds = this.Bounds; - let selected = this.marqueeSelect(false); + const bounds = this.Bounds; + const selected = this.marqueeSelect(false); if (e instanceof KeyboardEvent ? e.key === "c" : true) { selected.map(d => { this.props.removeDocument(d); @@ -354,7 +353,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque return d; }); } - let newCollection = this.getCollection(selected); + const newCollection = this.getCollection(selected); this.props.addDocument(newCollection); this.props.selectDocuments([newCollection], []); MarqueeOptionsMenu.Instance.fadeOut(true); @@ -363,9 +362,9 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque @action summary = (e: KeyboardEvent | React.PointerEvent | undefined) => { - let bounds = this.Bounds; - let selected = this.marqueeSelect(false); - let newCollection = this.getCollection(selected); + const bounds = this.Bounds; + const selected = this.marqueeSelect(false); + const newCollection = this.getCollection(selected); selected.map(d => { this.props.removeDocument(d); @@ -375,13 +374,13 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque return d; }); newCollection.chromeStatus = "disabled"; - let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, autoHeight: true, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" }); + const summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, autoHeight: true, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" }); Doc.GetProto(summary).summarizedDocs = new List<Doc>([newCollection]); newCollection.x = bounds.left + bounds.width; Doc.GetProto(newCollection).summaryDoc = summary; Doc.GetProto(newCollection).title = ComputedField.MakeFunction(`summaryTitle(this);`); if (e instanceof KeyboardEvent ? e.key === "s" : true) { // summary is wrapped in an expand/collapse container that also contains the summarized documents in a free form view. - let container = Docs.Create.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, chromeStatus: "disabled", title: "-summary-" }); + const container = Docs.Create.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, chromeStatus: "disabled", title: "-summary-" }); container.viewType = CollectionViewType.Stacking; container.autoHeight = true; Doc.GetProto(summary).maximizeLocation = "inPlace"; // or "onRight" @@ -462,42 +461,42 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque // } marqueeSelect(selectBackgrounds: boolean = true) { - let selRect = this.Bounds; - let selection: Doc[] = []; + const selRect = this.Bounds; + const selection: Doc[] = []; this.props.activeDocuments().filter(doc => !doc.isBackground && doc.z === undefined).map(doc => { - let layoutDoc = Doc.Layout(doc); - var x = NumCast(doc.x); - var y = NumCast(doc.y); - var w = NumCast(layoutDoc.width); - var h = NumCast(layoutDoc.height); + const layoutDoc = Doc.Layout(doc); + const x = NumCast(doc.x); + const y = NumCast(doc.y); + const w = NumCast(layoutDoc.width); + const h = NumCast(layoutDoc.height); if (this.intersectRect({ left: x, top: y, width: w, height: h }, selRect)) { selection.push(doc); } }); if (!selection.length && selectBackgrounds) { this.props.activeDocuments().filter(doc => doc.z === undefined).map(doc => { - let layoutDoc = Doc.Layout(doc); - var x = NumCast(doc.x); - var y = NumCast(doc.y); - var w = NumCast(layoutDoc.width); - var h = NumCast(layoutDoc.height); + const layoutDoc = Doc.Layout(doc); + const x = NumCast(doc.x); + const y = NumCast(doc.y); + const w = NumCast(layoutDoc.width); + const h = NumCast(layoutDoc.height); if (this.intersectRect({ left: x, top: y, width: w, height: h }, selRect)) { selection.push(doc); } }); } if (!selection.length) { - let left = this._downX < this._lastX ? this._downX : this._lastX; - let top = this._downY < this._lastY ? this._downY : this._lastY; - let topLeft = this.props.getContainerTransform().transformPoint(left, top); - let size = this.props.getContainerTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY); - let otherBounds = { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) }; + const left = this._downX < this._lastX ? this._downX : this._lastX; + const top = this._downY < this._lastY ? this._downY : this._lastY; + const topLeft = this.props.getContainerTransform().transformPoint(left, top); + const size = this.props.getContainerTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY); + const otherBounds = { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) }; this.props.activeDocuments().filter(doc => doc.z !== undefined).map(doc => { - let layoutDoc = Doc.Layout(doc); - var x = NumCast(doc.x); - var y = NumCast(doc.y); - var w = NumCast(layoutDoc.width); - var h = NumCast(layoutDoc.height); + const layoutDoc = Doc.Layout(doc); + const x = NumCast(doc.x); + const y = NumCast(doc.y); + const w = NumCast(layoutDoc.width); + const h = NumCast(layoutDoc.height); if (this.intersectRect({ left: x, top: y, width: w, height: h }, otherBounds)) { selection.push(doc); } @@ -508,8 +507,8 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque @computed get marqueeDiv() { - let p: [number, number] = this._visible ? this.props.getContainerTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY) : [0, 0]; - let v = this.props.getContainerTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY); + const p: [number, number] = this._visible ? this.props.getContainerTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY) : [0, 0]; + const v = this.props.getContainerTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY); /** * @RE - The commented out span below * This contains the "C for collection, ..." text on marquees. diff --git a/src/client/views/document_templates/caption_toggle/DetailedCaptionToggle.tsx b/src/client/views/document_templates/caption_toggle/DetailedCaptionToggle.tsx index f8104cef3..3aaf4120c 100644 --- a/src/client/views/document_templates/caption_toggle/DetailedCaptionToggle.tsx +++ b/src/client/views/document_templates/caption_toggle/DetailedCaptionToggle.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; -import { FontWeightProperty, FontStyleProperty, FontSizeProperty, ColorProperty } from 'csstype'; +import { FontStyleProperty, ColorProperty } from 'csstype'; import { observer } from 'mobx-react'; import { observable, action, runInAction } from 'mobx'; -import { FormattedTextBox, FormattedTextBoxProps } from '../../nodes/FormattedTextBox'; +import { FormattedTextBox } from '../../nodes/FormattedTextBox'; import { FieldViewProps } from '../../nodes/FieldView'; interface DetailedCaptionDataProps { @@ -33,7 +33,7 @@ export default class DetailedCaptionToggle extends React.Component<DetailedCapti } render() { - let size = this.props.toggleSize || 20; + const size = this.props.toggleSize || 20; return ( <div style={{ transition: "0.5s opacity ease", diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index ecb3e9db4..bb8a8b47b 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -43,12 +43,12 @@ class GroupTypesDropdown extends React.Component<GroupTypesDropdownProps> { @action onKeyDown = (e: React.KeyboardEvent): void => { if (e.key === "Enter") { - let allGroupTypes = Array.from(LinkManager.Instance.getAllGroupTypes()); - let groupOptions = allGroupTypes.filter(groupType => groupType.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1); - let exactFound = groupOptions.findIndex(groupType => groupType.toUpperCase() === this._searchTerm.toUpperCase()); + const allGroupTypes = Array.from(LinkManager.Instance.getAllGroupTypes()); + const groupOptions = allGroupTypes.filter(groupType => groupType.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1); + const exactFound = groupOptions.findIndex(groupType => groupType.toUpperCase() === this._searchTerm.toUpperCase()); if (exactFound > -1) { - let groupType = groupOptions[exactFound]; + const groupType = groupOptions[exactFound]; this.props.setGroupType(groupType); this._groupType = groupType; } else { @@ -84,19 +84,19 @@ class GroupTypesDropdown extends React.Component<GroupTypesDropdownProps> { renderOptions = (): JSX.Element[] | JSX.Element => { if (this._searchTerm === "") return <></>; - let allGroupTypes = Array.from(LinkManager.Instance.getAllGroupTypes()); - let groupOptions = allGroupTypes.filter(groupType => groupType.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1); - let exactFound = groupOptions.findIndex(groupType => groupType.toUpperCase() === this._searchTerm.toUpperCase()) > -1; + const allGroupTypes = Array.from(LinkManager.Instance.getAllGroupTypes()); + const groupOptions = allGroupTypes.filter(groupType => groupType.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1); + const exactFound = groupOptions.findIndex(groupType => groupType.toUpperCase() === this._searchTerm.toUpperCase()) > -1; - let options = groupOptions.map(groupType => { - let ref = React.createRef<HTMLDivElement>(); + const options = groupOptions.map(groupType => { + const ref = React.createRef<HTMLDivElement>(); return <div key={groupType} ref={ref} className="linkEditor-option" onClick={() => this.onOptionClick(groupType, false)}>{groupType}</div>; }); // if search term does not already exist as a group type, give option to create new group type if (!exactFound && this._searchTerm !== "") { - let ref = React.createRef<HTMLDivElement>(); + const ref = React.createRef<HTMLDivElement>(); options.push(<div key={""} ref={ref} className="linkEditor-option" onClick={() => this.onOptionClick(this._searchTerm, true)}>Define new "{this._searchTerm}" relationship</div>); } @@ -138,10 +138,10 @@ class LinkMetadataEditor extends React.Component<LinkMetadataEditorProps> { @action setMetadataKey = (value: string): void => { - let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType); + const groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType); // don't allow user to create existing key - let newIndex = groupMdKeys.findIndex(key => key.toUpperCase() === value.toUpperCase()); + const newIndex = groupMdKeys.findIndex(key => key.toUpperCase() === value.toUpperCase()); if (newIndex > -1) { this._keyError = true; this._key = value; @@ -151,7 +151,7 @@ class LinkMetadataEditor extends React.Component<LinkMetadataEditorProps> { } // set new value for key - let currIndex = groupMdKeys.findIndex(key => { + const currIndex = groupMdKeys.findIndex(key => { return StrCast(key).toUpperCase() === this._key.toUpperCase(); }); if (currIndex === -1) console.error("LinkMetadataEditor: key was not found"); @@ -172,9 +172,9 @@ class LinkMetadataEditor extends React.Component<LinkMetadataEditorProps> { @action removeMetadata = (): void => { - let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType); + const groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType); - let index = groupMdKeys.findIndex(key => key.toUpperCase() === this._key.toUpperCase()); + const index = groupMdKeys.findIndex(key => key.toUpperCase() === this._key.toUpperCase()); if (index === -1) console.error("LinkMetadataEditor: key was not found"); groupMdKeys.splice(index, 1); @@ -206,7 +206,7 @@ export class LinkGroupEditor extends React.Component<LinkGroupEditorProps> { constructor(props: LinkGroupEditorProps) { super(props); - let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(StrCast(props.groupDoc.type)); + const groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(StrCast(props.groupDoc.type)); groupMdKeys.forEach(key => { this._metadataIds.set(key, Utils.GenerateGuid()); }); @@ -226,25 +226,25 @@ export class LinkGroupEditor extends React.Component<LinkGroupEditorProps> { } copyGroup = async (groupType: string): Promise<void> => { - let sourceGroupDoc = this.props.groupDoc; + const sourceGroupDoc = this.props.groupDoc; const sourceMdDoc = await Cast(sourceGroupDoc.metadata, Doc); if (!sourceMdDoc) return; - let destDoc = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); + const destDoc = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); // let destGroupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, destDoc); - let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); + const keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); // create new metadata doc with copied kvp - let destMdDoc = new Doc(); + const destMdDoc = new Doc(); destMdDoc.anchor1 = StrCast(sourceMdDoc.anchor2); destMdDoc.anchor2 = StrCast(sourceMdDoc.anchor1); keys.forEach(key => { - let val = sourceMdDoc[key] === undefined ? "" : StrCast(sourceMdDoc[key]); + const val = sourceMdDoc[key] === undefined ? "" : StrCast(sourceMdDoc[key]); destMdDoc[key] = val; }); // create new group doc with new metadata doc - let destGroupDoc = new Doc(); + const destGroupDoc = new Doc(); destGroupDoc.type = groupType; destGroupDoc.metadata = destMdDoc; @@ -256,7 +256,7 @@ export class LinkGroupEditor extends React.Component<LinkGroupEditorProps> { @action addMetadata = (groupType: string): void => { this._metadataIds.set("new key", Utils.GenerateGuid()); - let mdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType); + const mdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType); // only add "new key" if there is no other key with value "new key"; prevents spamming if (mdKeys.indexOf("new key") === -1) mdKeys.push("new key"); LinkManager.Instance.setMetadataKeysForGroup(groupType, mdKeys); @@ -268,17 +268,17 @@ export class LinkGroupEditor extends React.Component<LinkGroupEditorProps> { } renderMetadata = (): JSX.Element[] => { - let metadata: Array<JSX.Element> = []; - let groupDoc = this.props.groupDoc; + const metadata: Array<JSX.Element> = []; + const groupDoc = this.props.groupDoc; const mdDoc = FieldValue(Cast(groupDoc.metadata, Doc)); if (!mdDoc) { return []; } - let groupType = StrCast(groupDoc.type); - let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType); + const groupType = StrCast(groupDoc.type); + const groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType); groupMdKeys.forEach((key) => { - let val = StrCast(mdDoc[key]); + const val = StrCast(mdDoc[key]); metadata.push( <LinkMetadataEditor key={"mded-" + this._metadataIds.get(key)} id={this._metadataIds.get(key)!} groupType={groupType} mdDoc={mdDoc} mdKey={key} mdValue={val} changeMdIdKey={this.changeMdIdKey} /> ); @@ -287,18 +287,18 @@ export class LinkGroupEditor extends React.Component<LinkGroupEditorProps> { } viewGroupAsTable = (groupType: string): JSX.Element => { - let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); - let index = keys.indexOf(""); + const keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); + const index = keys.indexOf(""); if (index > -1) keys.splice(index, 1); - let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb")); - let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType); - let createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" })); - let ref = React.createRef<HTMLDivElement>(); + const cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb")); + const docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType); + const createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" })); + const ref = React.createRef<HTMLDivElement>(); return <div ref={ref}><button className="linkEditor-button" onPointerDown={SetupDrag(ref, createTable)} title="Drag to view relationship table"><FontAwesomeIcon icon="table" size="sm" /></button></div>; } render() { - let groupType = StrCast(this.props.groupDoc.type); + const groupType = StrCast(this.props.groupDoc.type); // if ((groupType && LinkManager.Instance.getMetadataKeysInGroup(groupType).length > 0) || groupType === "") { let buttons; if (groupType === "") { @@ -356,15 +356,15 @@ export class LinkEditor extends React.Component<LinkEditorProps> { @action addGroup = (): void => { // create new metadata document for group - let mdDoc = new Doc(); + const mdDoc = new Doc(); mdDoc.anchor1 = this.props.sourceDoc.title; - let opp = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); + const opp = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); if (opp) { mdDoc.anchor2 = opp.title; } // create new group document - let groupDoc = new Doc(); + const groupDoc = new Doc(); groupDoc.type = ""; groupDoc.metadata = mdDoc; @@ -372,10 +372,10 @@ export class LinkEditor extends React.Component<LinkEditorProps> { } render() { - let destination = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); + const destination = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); - let groupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc); - let groups = groupList.map(groupDoc => { + const groupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc); + const groups = groupList.map(groupDoc => { return <LinkGroupEditor key={"gred-" + StrCast(groupDoc.type)} linkDoc={this.props.linkDoc} sourceDoc={this.props.sourceDoc} groupDoc={groupDoc} />; }); diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index efe2c7f2a..29e167ff7 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -68,14 +68,14 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { this._contextDisposer = reaction( () => this.selectedContextString, async () => { - let ref = await DocServer.GetRefField(this.selectedContextString); + const ref = await DocServer.GetRefField(this.selectedContextString); runInAction(() => { if (ref instanceof Doc) { this.selectedContext = ref; } }); if (this.selectedContext instanceof Doc) { - let aliases = await SearchUtil.GetViewsOfDocument(this.selectedContext); + const aliases = await SearchUtil.GetViewsOfDocument(this.selectedContext); runInAction(() => { this.selectedContextAliases = aliases; }); } } @@ -90,8 +90,8 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { if (LinkFollowBox.destinationDoc && this.sourceView && this.sourceView.props.ContainingCollectionDoc) { runInAction(() => this.canPan = false); if (this.sourceView.props.ContainingCollectionDoc.viewType === CollectionViewType.Freeform) { - let docs = Cast(this.sourceView.props.ContainingCollectionDoc.data, listSpec(Doc), []); - let aliases = await SearchUtil.GetViewsOfDocument(Doc.GetProto(LinkFollowBox.destinationDoc)); + const docs = Cast(this.sourceView.props.ContainingCollectionDoc.data, listSpec(Doc), []); + const aliases = await SearchUtil.GetViewsOfDocument(Doc.GetProto(LinkFollowBox.destinationDoc)); aliases.forEach(alias => { if (docs.filter(doc => doc === alias).length > 0) { @@ -118,8 +118,8 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { async fetchDocuments() { if (LinkFollowBox.destinationDoc) { - let dest: Doc = LinkFollowBox.destinationDoc; - let aliases = await SearchUtil.GetViewsOfDocument(Doc.GetProto(dest)); + const dest: Doc = LinkFollowBox.destinationDoc; + const aliases = await SearchUtil.GetViewsOfDocument(Doc.GetProto(dest)); const { docs } = await SearchUtil.Search("", true, { fq: `data_l:"${dest[Id]}"` }); const map: Map<Doc, Doc> = new Map; const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", true, { fq: `data_l:"${doc[Id]}"` }).then(result => result.docs))); @@ -128,7 +128,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { runInAction(async () => { this._docs = docs.filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)).map(doc => ({ col: doc, target: dest })); this._otherDocs = Array.from(map.entries()).filter(entry => !Doc.AreProtosEqual(entry[0], CollectionDockingView.Instance.props.Document)).map(([col, target]) => ({ col, target })); - let tcontext = LinkFollowBox.linkDoc && (await Cast(LinkFollowBox.linkDoc.anchor2Context, Doc)) as Doc; + const tcontext = LinkFollowBox.linkDoc && (await Cast(LinkFollowBox.linkDoc.anchor2Context, Doc)) as Doc; runInAction(() => tcontext && this._docs.splice(0, 0, { col: tcontext, target: dest })); }); } @@ -157,7 +157,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { @undoBatch openFullScreen = () => { if (LinkFollowBox.destinationDoc) { - let view = DocumentManager.Instance.getDocumentView(LinkFollowBox.destinationDoc); + const view = DocumentManager.Instance.getDocumentView(LinkFollowBox.destinationDoc); view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view); } } @@ -171,7 +171,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { options.context.panX = newPanX; options.context.panY = newPanY; } - let view = DocumentManager.Instance.getDocumentView(options.context); + const view = DocumentManager.Instance.getDocumentView(options.context); view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view); this.highlightDoc(); } @@ -211,7 +211,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { @undoBatch openLinkRight = () => { if (LinkFollowBox.destinationDoc) { - let alias = Doc.MakeAlias(LinkFollowBox.destinationDoc); + const alias = Doc.MakeAlias(LinkFollowBox.destinationDoc); (LinkFollowBox._addDocTab || this.props.addDocTab)(alias, undefined, "onRight"); this.highlightDoc(); SelectionManager.DeselectAll(); @@ -222,7 +222,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { @undoBatch jumpToLink = async (options: { shouldZoom: boolean }) => { if (LinkFollowBox.sourceDoc && LinkFollowBox.linkDoc) { - let focus = (document: Doc) => { (LinkFollowBox._addDocTab || this.props.addDocTab)(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; + const focus = (document: Doc) => { (LinkFollowBox._addDocTab || this.props.addDocTab)(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; //let focus = (doc: Doc, maxLocation: string) => this.props.focus(docthis.props.focus(LinkFollowBox.destinationDoc, true, 1, () => this.props.addDocTab(doc, undefined, maxLocation)); DocumentManager.Instance.FollowLink(LinkFollowBox.linkDoc, LinkFollowBox.sourceDoc, focus, options && options.shouldZoom, false, undefined); @@ -232,7 +232,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { @undoBatch openLinkTab = () => { if (LinkFollowBox.destinationDoc) { - let fullScreenAlias = Doc.MakeAlias(LinkFollowBox.destinationDoc); + const fullScreenAlias = Doc.MakeAlias(LinkFollowBox.destinationDoc); // this.prosp.addDocTab is empty -- use the link source's addDocTab (LinkFollowBox._addDocTab || this.props.addDocTab)(fullScreenAlias, undefined, "inTab"); @@ -264,14 +264,14 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { if (LinkFollowBox.destinationDoc && LinkFollowBox.sourceDoc) { if (this.sourceView && this.sourceView.props.addDocument) { - let destViews = DocumentManager.Instance.getDocumentViews(LinkFollowBox.destinationDoc); + const destViews = DocumentManager.Instance.getDocumentViews(LinkFollowBox.destinationDoc); if (!destViews.find(dv => dv.props.ContainingCollectionView === this.sourceView!.props.ContainingCollectionView)) { - let alias = Doc.MakeAlias(LinkFollowBox.destinationDoc); - let y = NumCast(LinkFollowBox.sourceDoc.y); - let x = NumCast(LinkFollowBox.sourceDoc.x); + const alias = Doc.MakeAlias(LinkFollowBox.destinationDoc); + const y = NumCast(LinkFollowBox.sourceDoc.y); + const x = NumCast(LinkFollowBox.sourceDoc.x); - let width = NumCast(LinkFollowBox.sourceDoc.width); - let height = NumCast(LinkFollowBox.sourceDoc.height); + const width = NumCast(LinkFollowBox.sourceDoc.width); + const height = NumCast(LinkFollowBox.sourceDoc.height); alias.x = x + width + 30; alias.y = y; @@ -301,8 +301,8 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { this.selectedContext = LinkFollowBox.destinationDoc; } if (this.selectedOption === "") this.selectedOption = FollowOptions.NOZOOM; - let shouldZoom: boolean = this.selectedOption === FollowOptions.NOZOOM ? false : true; - let notOpenInContext: boolean = this.selectedContextString === "self" || this.selectedContextString === LinkFollowBox.destinationDoc[Id]; + const shouldZoom: boolean = this.selectedOption === FollowOptions.NOZOOM ? false : true; + const notOpenInContext: boolean = this.selectedContextString === "self" || this.selectedContextString === LinkFollowBox.destinationDoc[Id]; if (this.selectedMode === FollowModes.INPLACE) { if (shouldZoom !== undefined) this.openLinkInPlace({ shouldZoom: shouldZoom }); @@ -328,7 +328,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { @action handleModeChange = (e: React.ChangeEvent) => { - let target = e.target as HTMLInputElement; + const target = e.target as HTMLInputElement; this.selectedMode = target.value; this.selectedContext = undefined; this.selectedContextString = ""; @@ -345,13 +345,13 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { @action handleOptionChange = (e: React.ChangeEvent) => { - let target = e.target as HTMLInputElement; + const target = e.target as HTMLInputElement; this.selectedOption = target.value; } @action handleContextChange = (e: React.ChangeEvent) => { - let target = e.target as HTMLInputElement; + const target = e.target as HTMLInputElement; this.selectedContextString = target.value; // selectedContext is updated in reaction this.selectedOption = ""; @@ -360,7 +360,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { @computed get canOpenInPlace() { if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) { - let colDoc = this.sourceView.props.ContainingCollectionDoc; + const colDoc = this.sourceView.props.ContainingCollectionDoc; if (colDoc.viewType && colDoc.viewType === CollectionViewType.Freeform) return true; } return false; diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index 27af873b5..52628ba4c 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -34,7 +34,7 @@ export class LinkMenu extends React.Component<Props> { } renderAllGroups = (groups: Map<string, Array<Doc>>): Array<JSX.Element> => { - let linkItems: Array<JSX.Element> = []; + const linkItems: Array<JSX.Element> = []; groups.forEach((group, groupType) => { linkItems.push( <LinkMenuGroup @@ -55,8 +55,8 @@ export class LinkMenu extends React.Component<Props> { } render() { - let sourceDoc = this.props.docView.props.Document; - let groups: Map<string, Doc[]> = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc); + const sourceDoc = this.props.docView.props.Document; + const groups: Map<string, Doc[]> = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc); if (this._editingLink === undefined) { return ( <div className="linkMenu"> diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index 1891919ce..15aacbbc9 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -51,11 +51,11 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> { document.removeEventListener("pointermove", this.onLinkButtonMoved); document.removeEventListener("pointerup", this.onLinkButtonUp); - let draggedDocs = this.props.group.map(linkDoc => { - let opp = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc); + const draggedDocs = this.props.group.map(linkDoc => { + const opp = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc); if (opp) return opp; }) as Doc[]; - let dragData = new DragManager.DocumentDragData(draggedDocs); + const dragData = new DragManager.DocumentDragData(draggedDocs); DragManager.StartLinkedDocumentDrag([this._drag.current], dragData, e.x, e.y, { handlers: { @@ -69,19 +69,19 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> { } viewGroupAsTable = (groupType: string): JSX.Element => { - let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); - let index = keys.indexOf(""); + const keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); + const index = keys.indexOf(""); if (index > -1) keys.splice(index, 1); - let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb")); - let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType); - let createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" })); - let ref = React.createRef<HTMLDivElement>(); + const cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb")); + const docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType); + const createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" })); + const ref = React.createRef<HTMLDivElement>(); return <div ref={ref}><button className="linkEditor-button linkEditor-tableButton" onPointerDown={SetupDrag(ref, createTable)} title="Drag to view relationship table"><FontAwesomeIcon icon="table" size="sm" /></button></div>; } render() { - let groupItems = this.props.group.map(linkDoc => { - let destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc); + const groupItems = this.props.group.map(linkDoc => { + const destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc); if (destination && this.props.sourceDoc) { return <LinkMenuItem key={destination[Id] + this.props.sourceDoc[Id]} groupType={this.props.groupType} diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 238660de3..edf5e9c26 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -36,15 +36,15 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { } renderMetadata = (): JSX.Element => { - let groups = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc); - let index = groups.findIndex(groupDoc => StrCast(groupDoc.type).toUpperCase() === this.props.groupType.toUpperCase()); - let groupDoc = index > -1 ? groups[index] : undefined; + const groups = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc); + const index = groups.findIndex(groupDoc => StrCast(groupDoc.type).toUpperCase() === this.props.groupType.toUpperCase()); + const groupDoc = index > -1 ? groups[index] : undefined; let mdRows: Array<JSX.Element> = []; if (groupDoc) { - let mdDoc = Cast(groupDoc.metadata, Doc, null); + const mdDoc = Cast(groupDoc.metadata, Doc, null); if (mdDoc) { - let keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType); + const keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType); mdRows = keys.map(key => { return (<div key={key} className="link-metadata-row"><b>{key}</b>: {StrCast(mdDoc[key])}</div>); }); @@ -110,8 +110,8 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { render() { - let keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType); - let canExpand = keys ? keys.length > 0 : false; + const keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType); + const canExpand = keys ? keys.length > 0 : false; return ( <div className="linkMenu-item"> diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 77b10e395..95c765e8a 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -56,19 +56,19 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume this._linkPlayDisposer = reaction(() => this.layoutDoc.scrollToLinkID, scrollLinkId => { scrollLinkId && DocListCast(this.dataDoc.links).filter(l => l[Id] === scrollLinkId).map(l => { - let la1 = l.anchor1 as Doc; - let linkTime = Doc.AreProtosEqual(la1, this.dataDoc) ? NumCast(l.anchor1Timecode) : NumCast(l.anchor2Timecode); + const la1 = l.anchor1 as Doc; + const linkTime = Doc.AreProtosEqual(la1, this.dataDoc) ? NumCast(l.anchor1Timecode) : NumCast(l.anchor2Timecode); setTimeout(() => { this.playFrom(linkTime); Doc.linkFollowHighlight(l); }, 250); }); scrollLinkId && Doc.SetInPlace(this.layoutDoc, "scrollToLinkID", undefined, false); }, { fireImmediately: true }); this._reactionDisposer = reaction(() => SelectionManager.SelectedDocuments(), selected => { - let sel = selected.length ? selected[0].props.Document : undefined; + const sel = selected.length ? selected[0].props.Document : undefined; this.Document.playOnSelect && sel && !Doc.AreProtosEqual(sel, this.props.Document) && this.playFrom(DateCast(sel.creationTime).date.getTime()); }); this._scrubbingDisposer = reaction(() => AudioBox._scrubTime, timeInMillisecondsFrom1970 => { - let start = this.extensionDoc && DateCast(this.extensionDoc.recordingStart); + const start = this.extensionDoc && DateCast(this.extensionDoc.recordingStart); start && this.playFrom((timeInMillisecondsFrom1970 - start.date.getTime()) / 1000); }); } @@ -127,7 +127,7 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume recordAudioAnnotation = () => { let gumStream: any; - let self = this; + const self = this; const extensionDoc = this.extensionDoc; extensionDoc && navigator.mediaDevices.getUserMedia({ audio: true @@ -160,7 +160,7 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume } specificContextMenu = (e: React.MouseEvent): void => { - let funcs: ContextMenuProps[] = []; + const funcs: ContextMenuProps[] = []; funcs.push({ description: (this.Document.playOnSelect ? "Don't play" : "Play") + " when document selected", event: () => this.Document.playOnSelect = !this.Document.playOnSelect, icon: "expand-arrows-alt" }); ContextMenu.Instance.addItem({ description: "Audio Funcs...", subitems: funcs, icon: "asterisk" }); @@ -170,7 +170,7 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume this._recorder.stop(); this.dataDoc.duration = (new Date().getTime() - this._recordStart) / 1000; this._audioState = "recorded"; - let ind = AudioBox.ActiveRecordings.indexOf(this.props.Document); + const ind = AudioBox.ActiveRecordings.indexOf(this.props.Document); ind !== -1 && (AudioBox.ActiveRecordings.splice(ind, 1)); }); @@ -198,13 +198,13 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume } @computed get path() { - let field = Cast(this.props.Document[this.props.fieldKey], AudioField); - let path = (field instanceof AudioField) ? field.url.href : ""; + const field = Cast(this.props.Document[this.props.fieldKey], AudioField); + const path = (field instanceof AudioField) ? field.url.href : ""; return path === nullAudio ? "" : path; } @computed get audio() { - let interactive = this.active() ? "-interactive" : ""; + const interactive = this.active() ? "-interactive" : ""; return <audio ref={this.setRef} className={`audiobox-control${interactive}`}> <source src={this.path} type="audio/mpeg" /> Not supported. @@ -212,7 +212,7 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume } render() { - let interactive = this.active() ? "-interactive" : ""; + const interactive = this.active() ? "-interactive" : ""; return (!this.extensionDoc ? (null) : <div className={`audiobox-container`} onContextMenu={this.specificContextMenu} onClick={!this.path ? this.recordClick : undefined}> @@ -228,7 +228,7 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume <div className="audiobox-timeline" onClick={e => e.stopPropagation()} onPointerDown={e => { if (e.button === 0 && !e.ctrlKey) { - let rect = (e.target as any).getBoundingClientRect(); + const rect = (e.target as any).getBoundingClientRect(); this._ele!.currentTime = this.Document.currentTimecode = (e.clientX - rect.x) / rect.width * NumCast(this.dataDoc.duration); this.pause(); e.stopPropagation(); diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx index 659ba154a..34151a311 100644 --- a/src/client/views/nodes/ButtonBox.tsx +++ b/src/client/views/nodes/ButtonBox.tsx @@ -51,10 +51,10 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt } specificContextMenu = (e: React.MouseEvent): void => { - let funcs: ContextMenuProps[] = []; + const funcs: ContextMenuProps[] = []; funcs.push({ description: "Clear Script Params", event: () => { - let params = FieldValue(this.Document.buttonParams); + const params = FieldValue(this.Document.buttonParams); params && params.map(p => this.props.Document[p] = undefined); }, icon: "trash" }); @@ -73,8 +73,8 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt } // (!missingParams || !missingParams.length ? "" : "(" + missingParams.map(m => m + ":").join(" ") + ")") render() { - let params = this.Document.buttonParams; - let missingParams = params && params.filter(p => this.props.Document[p] === undefined); + const params = this.Document.buttonParams; + const missingParams = params && params.filter(p => this.props.Document[p] === undefined); params && params.map(p => DocListCast(this.props.Document[p])); // bcz: really hacky form of prefetching ... return ( <div className="buttonBox-outerDiv" ref={this.createDropTarget} onContextMenu={this.specificContextMenu} diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 2b079fe50..d599de56e 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -31,7 +31,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF get Y() { return this._animPos !== undefined ? this._animPos[1] : this.renderScriptDim ? this.renderScriptDim.y : this.props.y !== undefined ? this.props.y : this.dataProvider ? this.dataProvider.y : (this.Document.y || 0); } get width() { return this.renderScriptDim ? this.renderScriptDim.width : this.props.width !== undefined ? this.props.width : this.props.dataProvider && this.dataProvider ? this.dataProvider.width : this.layoutDoc[WidthSym](); } get height() { - let hgt = this.renderScriptDim ? this.renderScriptDim.height : this.props.height !== undefined ? this.props.height : this.props.dataProvider && this.dataProvider ? this.dataProvider.height : this.layoutDoc[HeightSym](); + const hgt = this.renderScriptDim ? this.renderScriptDim.height : this.props.height !== undefined ? this.props.height : this.props.dataProvider && this.dataProvider ? this.dataProvider.height : this.layoutDoc[HeightSym](); return (hgt === undefined && this.nativeWidth && this.nativeHeight) ? this.width * this.nativeHeight / this.nativeWidth : hgt; } @computed get dataProvider() { return this.props.dataProvider && this.props.dataProvider(this.props.Document) ? this.props.dataProvider(this.props.Document) : undefined; } @@ -40,13 +40,13 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF @computed get renderScriptDim() { if (this.Document.renderScript) { - let someView = Cast(this.props.Document.someView, Doc); - let minimap = Cast(this.props.Document.minimap, Doc); + const someView = Cast(this.props.Document.someView, Doc); + const minimap = Cast(this.props.Document.minimap, Doc); if (someView instanceof Doc && minimap instanceof Doc) { - let x = (NumCast(someView.panX) - NumCast(someView.width) / 2 / NumCast(someView.scale) - (NumCast(minimap.fitX) - NumCast(minimap.fitW) / 2)) / NumCast(minimap.fitW) * NumCast(minimap.width) - NumCast(minimap.width) / 2; - let y = (NumCast(someView.panY) - NumCast(someView.height) / 2 / NumCast(someView.scale) - (NumCast(minimap.fitY) - NumCast(minimap.fitH) / 2)) / NumCast(minimap.fitH) * NumCast(minimap.height) - NumCast(minimap.height) / 2; - let w = NumCast(someView.width) / NumCast(someView.scale) / NumCast(minimap.fitW) * NumCast(minimap.width); - let h = NumCast(someView.height) / NumCast(someView.scale) / NumCast(minimap.fitH) * NumCast(minimap.height); + const x = (NumCast(someView.panX) - NumCast(someView.width) / 2 / NumCast(someView.scale) - (NumCast(minimap.fitX) - NumCast(minimap.fitW) / 2)) / NumCast(minimap.fitW) * NumCast(minimap.width) - NumCast(minimap.width) / 2; + const y = (NumCast(someView.panY) - NumCast(someView.height) / 2 / NumCast(someView.scale) - (NumCast(minimap.fitY) - NumCast(minimap.fitH) / 2)) / NumCast(minimap.fitH) * NumCast(minimap.height) - NumCast(minimap.height) / 2; + const w = NumCast(someView.width) / NumCast(someView.scale) / NumCast(minimap.fitW) * NumCast(minimap.width); + const h = NumCast(someView.height) / NumCast(someView.scale) / NumCast(minimap.fitH) * NumCast(minimap.height); return { x: x, y: y, width: w, height: h }; } } @@ -70,9 +70,9 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF .scale(1 / this.contentScaling()) borderRounding = () => { - let ruleRounding = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleRounding_" + this.Document.heading]) : undefined; - let ld = this.layoutDoc[StrCast(this.layoutDoc.layoutKey, "layout")] instanceof Doc ? this.layoutDoc[StrCast(this.layoutDoc.layoutKey, "layout")] as Doc : undefined; - let br = StrCast((ld || this.props.Document).borderRounding); + const ruleRounding = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleRounding_" + this.Document.heading]) : undefined; + const ld = this.layoutDoc[StrCast(this.layoutDoc.layoutKey, "layout")] instanceof Doc ? this.layoutDoc[StrCast(this.layoutDoc.layoutKey, "layout")] as Doc : undefined; + const br = StrCast((ld || this.props.Document).borderRounding); return !br && ruleRounding ? ruleRounding : br; } diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index a5f96d2de..efc907f9b 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -47,7 +47,7 @@ export class ContentFittingDocumentView extends React.Component<ContentFittingDo private get nativeWidth() { return NumCast(this.layoutDoc!.nativeWidth, this.props.PanelWidth()); } private get nativeHeight() { return NumCast(this.layoutDoc!.nativeHeight, this.props.PanelHeight()); } private contentScaling = () => { - let wscale = this.props.PanelWidth() / (this.nativeWidth ? this.nativeWidth : this.props.PanelWidth()); + const wscale = this.props.PanelWidth() / (this.nativeWidth ? this.nativeWidth : this.props.PanelWidth()); if (wscale * this.nativeHeight > this.props.PanelHeight()) { return this.props.PanelHeight() / (this.nativeHeight ? this.nativeHeight : this.props.PanelHeight()); } @@ -59,7 +59,7 @@ export class ContentFittingDocumentView extends React.Component<ContentFittingDo drop = (e: Event, de: DragManager.DropEvent) => { if (de.data instanceof DragManager.DocumentDragData) { this.props.childDocs && this.props.childDocs.map(otherdoc => { - let target = Doc.GetProto(otherdoc); + const target = Doc.GetProto(otherdoc); target.layout = ComputedField.MakeFunction("this.image_data[0]"); target.layoutCustom = Doc.MakeDelegate(de.data.draggedDocuments[0]); }); diff --git a/src/client/views/nodes/DocuLinkBox.tsx b/src/client/views/nodes/DocuLinkBox.tsx index d73407903..a22472e9e 100644 --- a/src/client/views/nodes/DocuLinkBox.tsx +++ b/src/client/views/nodes/DocuLinkBox.tsx @@ -36,12 +36,12 @@ export class DocuLinkBox extends DocComponent<FieldViewProps, DocLinkSchema>(Doc (e.button === 0 && !e.ctrlKey) && e.stopPropagation(); } onPointerMove = action((e: PointerEvent) => { - let cdiv = this._ref && this._ref.current && this._ref.current.parentElement; + const cdiv = this._ref && this._ref.current && this._ref.current.parentElement; if (cdiv && (Math.abs(e.clientX - this._downx) > 5 || Math.abs(e.clientY - this._downy) > 5)) { - let bounds = cdiv.getBoundingClientRect(); - let pt = Utils.getNearestPointInPerimeter(bounds.left, bounds.top, bounds.width, bounds.height, e.clientX, e.clientY); - let separation = Math.sqrt((pt[0] - e.clientX) * (pt[0] - e.clientX) + (pt[1] - e.clientY) * (pt[1] - e.clientY)); - let dragdist = Math.sqrt((pt[0] - this._downx) * (pt[0] - this._downx) + (pt[1] - this._downy) * (pt[1] - this._downy)); + const bounds = cdiv.getBoundingClientRect(); + const pt = Utils.getNearestPointInPerimeter(bounds.left, bounds.top, bounds.width, bounds.height, e.clientX, e.clientY); + const separation = Math.sqrt((pt[0] - e.clientX) * (pt[0] - e.clientX) + (pt[1] - e.clientY) * (pt[1] - e.clientY)); + const dragdist = Math.sqrt((pt[0] - this._downx) * (pt[0] - this._downx) + (pt[1] - this._downy) * (pt[1] - this._downy)); if (separation > 100) { DragLinksAsDocuments(this._ref.current!, pt[0], pt[1], Cast(this.props.Document[this.props.fieldKey], Doc) as Doc, this.props.Document); // Containging collection is the document, not a collection... hack. document.removeEventListener("pointermove", this.onPointerMove); @@ -67,14 +67,14 @@ export class DocuLinkBox extends DocComponent<FieldViewProps, DocLinkSchema>(Doc } render() { - let anchorDoc = Cast(this.props.Document[this.props.fieldKey], Doc); - let hasAnchor = anchorDoc instanceof Doc && anchorDoc.type === DocumentType.PDFANNO; - let y = NumCast(this.props.Document[this.props.fieldKey + "_y"], 100); - let x = NumCast(this.props.Document[this.props.fieldKey + "_x"], 100); - let c = StrCast(this.props.Document.backgroundColor, "lightblue"); - let anchor = this.props.fieldKey === "anchor1" ? "anchor2" : "anchor1"; - let timecode = this.props.Document[anchor + "Timecode"]; - let targetTitle = StrCast((this.props.Document[anchor]! as Doc).title) + (timecode !== undefined ? ":" + timecode : ""); + const anchorDoc = Cast(this.props.Document[this.props.fieldKey], Doc); + const hasAnchor = anchorDoc instanceof Doc && anchorDoc.type === DocumentType.PDFANNO; + const y = NumCast(this.props.Document[this.props.fieldKey + "_y"], 100); + const x = NumCast(this.props.Document[this.props.fieldKey + "_x"], 100); + const c = StrCast(this.props.Document.backgroundColor, "lightblue"); + const anchor = this.props.fieldKey === "anchor1" ? "anchor2" : "anchor1"; + const timecode = this.props.Document[anchor + "Timecode"]; + const targetTitle = StrCast((this.props.Document[anchor]! as Doc).title) + (timecode !== undefined ? ":" + timecode : ""); return <div className="docuLinkBox-cont" onPointerDown={this.onPointerDown} onClick={this.onClick} title={targetTitle} ref={this._ref} style={{ background: c, left: `calc(${x}% - 12.5px)`, top: `calc(${y}% - 12.5px)`, diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index b9b84d5ce..13fd3cde1 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -83,7 +83,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & { } CreateBindings(): JsxBindings { - let list = { + const list = { ...OmitKeys(this.props, ['parentActive'], (obj: any) => obj.active = this.props.parentActive).omit, Document: this.layoutDoc, DataDoc: this.dataDoc, diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 057b4eecd..63ce6233c 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -122,7 +122,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu startDragging(x: number, y: number, dropAction: dropActionType, applyAsTemplate?: boolean) { if (this._mainCont.current) { - let dragData = new DragManager.DocumentDragData([this.props.Document]); + const dragData = new DragManager.DocumentDragData([this.props.Document]); const [left, top] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(0, 0); dragData.offset = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top); dragData.dropAction = dropAction; @@ -143,7 +143,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu e.stopPropagation(); let preventDefault = true; if (this._doubleTap && this.props.renderDepth && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click - let fullScreenAlias = Doc.MakeAlias(this.props.Document); + const fullScreenAlias = Doc.MakeAlias(this.props.Document); if (StrCast(fullScreenAlias.layoutKey) !== "layoutCustom" && fullScreenAlias.layoutCustom !== undefined) { fullScreenAlias.layoutKey = "layoutCustom"; } @@ -166,9 +166,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu } buttonClick = async (altKey: boolean, ctrlKey: boolean) => { - let maximizedDocs = await DocListCastAsync(this.Document.maximizedDocs); - let summarizedDocs = await DocListCastAsync(this.Document.summarizedDocs); - let linkDocs = LinkManager.Instance.getAllRelatedLinks(this.props.Document); + const maximizedDocs = await DocListCastAsync(this.Document.maximizedDocs); + const summarizedDocs = await DocListCastAsync(this.Document.summarizedDocs); + const linkDocs = LinkManager.Instance.getAllRelatedLinks(this.props.Document); let expandedDocs: Doc[] = []; expandedDocs = maximizedDocs ? [...maximizedDocs, ...expandedDocs] : expandedDocs; expandedDocs = summarizedDocs ? [...summarizedDocs, ...expandedDocs] : expandedDocs; @@ -179,7 +179,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu maxLocation = this.Document.maximizeLocation = (!ctrlKey ? !altKey ? maxLocation : (maxLocation !== "inPlace" ? "inPlace" : "onRight") : (maxLocation !== "inPlace" ? "inPlace" : "inTab")); if (maxLocation === "inPlace") { expandedDocs.forEach(maxDoc => this.props.addDocument && this.props.addDocument(maxDoc)); - let scrpt = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(NumCast(this.layoutDoc.width) / 2, NumCast(this.layoutDoc.height) / 2); + const scrpt = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(NumCast(this.layoutDoc.width) / 2, NumCast(this.layoutDoc.height) / 2); DocumentManager.Instance.animateBetweenPoint(scrpt, expandedDocs); } else { expandedDocs.forEach(maxDoc => (!this.props.addDocTab(maxDoc, undefined, "close") && this.props.addDocTab(maxDoc, undefined, maxLocation))); @@ -278,7 +278,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu fieldTemplate.heading = 1; fieldTemplate.autoHeight = true; - let docTemplate = Docs.Create.FreeformDocument([fieldTemplate], { title: doc.title + "_layout", width: width + 20, height: Math.max(100, height + 45) }); + const docTemplate = Docs.Create.FreeformDocument([fieldTemplate], { title: doc.title + "_layout", width: width + 20, height: Math.max(100, height + 45) }); Doc.MakeMetadataFieldTemplate(fieldTemplate, Doc.GetProto(docTemplate), true); Doc.ApplyTemplateTo(docTemplate, dataDoc || doc, "layoutCustom", undefined); @@ -324,10 +324,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu @action onDrop = (e: React.DragEvent) => { - let text = e.dataTransfer.getData("text/plain"); + const text = e.dataTransfer.getData("text/plain"); if (!e.isDefaultPrevented() && text && text.startsWith("<div")) { - let oldLayout = this.Document.layout || ""; - let layout = text.replace("{layout}", oldLayout); + const oldLayout = this.Document.layout || ""; + const layout = text.replace("{layout}", oldLayout); this.Document.layout = layout; e.stopPropagation(); e.preventDefault(); @@ -348,11 +348,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu @undoBatch @action makeIntoPortal = async () => { - let anchors = await Promise.all(DocListCast(this.Document.links).map(async (d: Doc) => Cast(d.anchor2, Doc))); + const anchors = await Promise.all(DocListCast(this.Document.links).map(async (d: Doc) => Cast(d.anchor2, Doc))); if (!anchors.find(anchor2 => anchor2 && anchor2.title === this.Document.title + ".portal" ? true : false)) { - let portalID = (this.Document.title + ".portal").replace(/^-/, "").replace(/\([0-9]*\)$/, ""); + const portalID = (this.Document.title + ".portal").replace(/^-/, "").replace(/\([0-9]*\)$/, ""); DocServer.GetRefField(portalID).then(existingPortal => { - let portal = existingPortal instanceof Doc ? existingPortal : Docs.Create.FreeformDocument([], { width: (this.layoutDoc.width || 0) + 10, height: this.layoutDoc.height || 0, title: portalID }); + const portal = existingPortal instanceof Doc ? existingPortal : Docs.Create.FreeformDocument([], { width: (this.layoutDoc.width || 0) + 10, height: this.layoutDoc.height || 0, title: portalID }); DocUtils.MakeLink({ doc: this.props.Document, ctx: this.props.ContainingCollectionDoc }, { doc: portal }, portalID, "portal link"); this.Document.isButton = true; }); @@ -400,7 +400,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu e.preventDefault(); const cm = ContextMenu.Instance; - let subitems: ContextMenuProps[] = []; + const subitems: ContextMenuProps[] = []; subitems.push({ description: "Open Full Screen", event: () => CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(this), icon: "desktop" }); subitems.push({ description: "Open Tab ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "inTab"), icon: "folder" }); subitems.push({ description: "Open Right ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "onRight"), icon: "caret-square-right" }); @@ -410,8 +410,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu cm.addItem({ description: "Open...", subitems: subitems, icon: "external-link-alt" }); - let existingOnClick = ContextMenu.Instance.findByDescription("OnClick..."); - let onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; + const existingOnClick = ContextMenu.Instance.findByDescription("OnClick..."); + const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" }); onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript("toggleDetail(this)"), icon: "window-restore" }); onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" }); @@ -425,7 +425,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu }); !existingOnClick && cm.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" }); - let funcs: ContextMenuProps[] = []; + const funcs: ContextMenuProps[] = []; if (this.Document.onDragStart) { funcs.push({ description: "Drag an Alias", icon: "edit", event: () => this.Document.dragFactory && (this.Document.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) }); funcs.push({ description: "Drag a Copy", icon: "edit", event: () => this.Document.dragFactory && (this.Document.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) }); @@ -433,8 +433,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu ContextMenu.Instance.addItem({ description: "OnDrag...", subitems: funcs, icon: "asterisk" }); } - let existing = ContextMenu.Instance.findByDescription("Layout..."); - let layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : []; + const existing = ContextMenu.Instance.findByDescription("Layout..."); + const layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : []; layoutItems.push({ description: this.Document.isBackground ? "As Foreground" : "As Background", event: this.makeBackground, icon: this.Document.lockedPosition ? "unlock" : "lock" }); if (this.props.DataDoc) { layoutItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc!), icon: "concierge-bell" }); @@ -453,8 +453,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu } !existing && cm.addItem({ description: "Layout...", subitems: layoutItems, icon: "compass" }); - let more = ContextMenu.Instance.findByDescription("More..."); - let moreItems: ContextMenuProps[] = more && "subitems" in more ? more.subitems : []; + const more = ContextMenu.Instance.findByDescription("More..."); + const moreItems: ContextMenuProps[] = more && "subitems" in more ? more.subitems : []; if (!ClientUtils.RELEASE) { // let copies: ContextMenuProps[] = []; @@ -489,7 +489,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" }); runInAction(() => { if (!ClientUtils.RELEASE) { - let setWriteMode = (mode: DocServer.WriteMode) => { + const setWriteMode = (mode: DocServer.WriteMode) => { DocServer.AclsMode = mode; const mode1 = mode; const mode2 = mode === DocServer.WriteMode.Default ? mode : DocServer.WriteMode.Playground; @@ -503,7 +503,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu DocServer.setFieldWriteMode("scale", mode2); DocServer.setFieldWriteMode("viewType", mode2); }; - let aclsMenu: ContextMenuProps[] = []; + const aclsMenu: ContextMenuProps[] = []; aclsMenu.push({ description: "Default (write/read all)", event: () => setWriteMode(DocServer.WriteMode.Default), icon: DocServer.AclsMode === DocServer.WriteMode.Default ? "check" : "exclamation" }); aclsMenu.push({ description: "Playground (write own/no read)", event: () => setWriteMode(DocServer.WriteMode.Playground), icon: DocServer.AclsMode === DocServer.WriteMode.Playground ? "check" : "exclamation" }); aclsMenu.push({ description: "Live Playground (write own/read others)", event: () => setWriteMode(DocServer.WriteMode.LivePlayground), icon: DocServer.AclsMode === DocServer.WriteMode.LivePlayground ? "check" : "exclamation" }); @@ -539,8 +539,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); }; chromeHeight = () => { - let showOverlays = this.props.showOverlays ? this.props.showOverlays(this.Document) : undefined; - let showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : StrCast(this.Document.showTitle); + const showOverlays = this.props.showOverlays ? this.props.showOverlays(this.Document) : undefined; + const showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : StrCast(this.Document.showTitle); return (showTitle ? 25 : 0) + 1; } @@ -585,8 +585,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu // if it's a tempoarl link (currently just for Audio), then the audioBox will display the anchor and we don't want to display it here. // would be good to generalize this some way. isNonTemporalLink = (linkDoc: Doc) => { - let anchor = Cast(Doc.AreProtosEqual(this.props.Document, Cast(linkDoc.anchor1, Doc) as Doc) ? linkDoc.anchor1 : linkDoc.anchor2, Doc) as Doc; - let ept = Doc.AreProtosEqual(this.props.Document, Cast(linkDoc.anchor1, Doc) as Doc) ? linkDoc.anchor1Timecode : linkDoc.anchor2Timecode; + const anchor = Cast(Doc.AreProtosEqual(this.props.Document, Cast(linkDoc.anchor1, Doc) as Doc) ? linkDoc.anchor1 : linkDoc.anchor2, Doc) as Doc; + const ept = Doc.AreProtosEqual(this.props.Document, Cast(linkDoc.anchor1, Doc) as Doc) ? linkDoc.anchor1Timecode : linkDoc.anchor2Timecode; return anchor.type === DocumentType.AUDIO && NumCast(ept) ? false : true; } @@ -651,14 +651,14 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu @action handle2PointersMove = (e: TouchEvent) => { - let pt1 = e.targetTouches.item(0); - let pt2 = e.targetTouches.item(1); + const pt1 = e.targetTouches.item(0); + const pt2 = e.targetTouches.item(1); if (pt1 && pt2 && this.prevPoints.has(pt1.identifier) && this.prevPoints.has(pt2.identifier)) { - let oldPoint1 = this.prevPoints.get(pt1.identifier); - let oldPoint2 = this.prevPoints.get(pt2.identifier); - let pinching = InteractionUtils.Pinning(pt1, pt2, oldPoint1!, oldPoint2!); + const oldPoint1 = this.prevPoints.get(pt1.identifier); + const oldPoint2 = this.prevPoints.get(pt2.identifier); + const pinching = InteractionUtils.Pinning(pt1, pt2, oldPoint1!, oldPoint2!); if (pinching !== 0) { - let newWidth = Math.max(Math.abs(oldPoint1!.clientX - oldPoint2!.clientX), Math.abs(pt1.clientX - pt2.clientX)); + const newWidth = Math.max(Math.abs(oldPoint1!.clientX - oldPoint2!.clientX), Math.abs(pt1.clientX - pt2.clientX)); this.props.Document.width = newWidth; } } @@ -679,12 +679,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu const localScale = fullDegree; const animDims = this.Document.animateToDimensions ? Array.from(this.Document.animateToDimensions) : undefined; - let animheight = animDims ? animDims[1] : "100%"; - let animwidth = animDims ? animDims[0] : "100%"; + const animheight = animDims ? animDims[1] : "100%"; + const animwidth = animDims ? animDims[0] : "100%"; const highlightColors = ["transparent", "maroon", "maroon", "yellow", "magenta", "cyan", "orange"]; const highlightStyles = ["solid", "dashed", "solid", "solid", "solid", "solid", "solid"]; - let highlighting = fullDegree && this.layoutDoc.type !== DocumentType.FONTICON && this.layoutDoc.viewType !== CollectionViewType.Linear; + const highlighting = fullDegree && this.layoutDoc.type !== DocumentType.FONTICON && this.layoutDoc.viewType !== CollectionViewType.Linear; return <div className={`documentView-node${this.topMost ? "-topmost" : ""}`} ref={this._mainCont} onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick} onPointerEnter={e => Doc.BrushDoc(this.props.Document)} onPointerLeave={e => Doc.UnBrushDoc(this.props.Document)} diff --git a/src/client/views/nodes/FaceRectangle.tsx b/src/client/views/nodes/FaceRectangle.tsx index 887efc0d5..20afa4565 100644 --- a/src/client/views/nodes/FaceRectangle.tsx +++ b/src/client/views/nodes/FaceRectangle.tsx @@ -12,7 +12,7 @@ export default class FaceRectangle extends React.Component<{ rectangle: Rectangl } render() { - let rectangle = this.props.rectangle; + const rectangle = this.props.rectangle; return ( <div style={{ diff --git a/src/client/views/nodes/FaceRectangles.tsx b/src/client/views/nodes/FaceRectangles.tsx index acf1aced3..3c7f1f206 100644 --- a/src/client/views/nodes/FaceRectangles.tsx +++ b/src/client/views/nodes/FaceRectangles.tsx @@ -20,10 +20,10 @@ export interface RectangleTemplate { export default class FaceRectangles extends React.Component<FaceRectanglesProps> { render() { - let faces = DocListCast(this.props.document.faces); - let templates: RectangleTemplate[] = faces.map(faceDoc => { - let rectangle = Cast(faceDoc.faceRectangle, Doc) as Doc; - let style = { + const faces = DocListCast(this.props.document.faces); + const templates: RectangleTemplate[] = faces.map(faceDoc => { + const rectangle = Cast(faceDoc.faceRectangle, Doc) as Doc; + const style = { top: NumCast(rectangle.top), left: NumCast(rectangle.left), width: NumCast(rectangle.width), diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index 960b55e3e..2433251b3 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -25,8 +25,8 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>( this._backgroundReaction = reaction(() => this.props.Document.backgroundColor, () => { if (this._ref && this._ref.current) { - let col = Utils.fromRGBAstr(getComputedStyle(this._ref.current).backgroundColor); - let colsum = (col.r + col.g + col.b); + const col = Utils.fromRGBAstr(getComputedStyle(this._ref.current).backgroundColor); + const colsum = (col.r + col.g + col.b); if (colsum / col.a > 600 || col.a < 0.25) runInAction(() => this._foregroundColor = "black"); else if (colsum / col.a <= 600 || col.a >= .25) runInAction(() => this._foregroundColor = "white"); } @@ -36,8 +36,8 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>( this._backgroundReaction && this._backgroundReaction(); } render() { - let referenceDoc = (this.props.Document.dragFactory instanceof Doc ? this.props.Document.dragFactory : this.props.Document); - let referenceLayout = Doc.Layout(referenceDoc); + const referenceDoc = (this.props.Document.dragFactory instanceof Doc ? this.props.Document.dragFactory : this.props.Document); + const referenceLayout = Doc.Layout(referenceDoc); return <button className="fontIconBox-outerDiv" title={StrCast(this.props.Document.title)} ref={this._ref} style={{ background: StrCast(referenceLayout.backgroundColor), diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index a5530f32d..57321de49 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -1,6 +1,6 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faEdit, faSmile, faTextHeight, faUpload } from '@fortawesome/free-solid-svg-icons'; -import _ from "lodash"; +import { isEqual } from "lodash"; import { action, computed, IReactionDisposer, Lambda, observable, reaction, runInAction, trace } from "mobx"; import { observer } from "mobx-react"; import { baseKeymap } from "prosemirror-commands"; @@ -103,8 +103,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & return html.indexOf("data-pm-slice") !== -1; } public static GetHref(html: string): string { - let parser = new DOMParser(); - let parsedHtml = parser.parseFromString(html, 'text/html'); + const parser = new DOMParser(); + const parsedHtml = parser.parseFromString(html, 'text/html'); if (parsedHtml.body.childNodes.length === 1 && parsedHtml.body.childNodes[0].childNodes.length === 1 && (parsedHtml.body.childNodes[0].childNodes[0] as any).href) { return (parsedHtml.body.childNodes[0].childNodes[0] as any).href; @@ -126,12 +126,12 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & @undoBatch public setFontColor(color: string) { - let view = this._editorView!; + const view = this._editorView!; if (view.state.selection.from === view.state.selection.to) return false; if (view.state.selection.to - view.state.selection.from > view.state.doc.nodeSize - 3) { this.layoutDoc.color = color; } - let colorMark = view.state.schema.mark(view.state.schema.marks.pFontColor, { color: color }); + const colorMark = view.state.schema.mark(view.state.schema.marks.pFontColor, { color: color }); view.dispatch(view.state.tr.addMark(view.state.selection.from, view.state.selection.to, colorMark)); return true; } @@ -147,9 +147,9 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & doLinkOnDeselect() { Array.from(this.linkOnDeselect.entries()).map(entry => { - let key = entry[0]; - let value = entry[1]; - let id = Utils.GenerateDeterministicGuid(this.dataDoc[Id] + key); + const key = entry[0]; + const value = entry[1]; + const id = Utils.GenerateDeterministicGuid(this.dataDoc[Id] + key); DocServer.GetRefField(value).then(doc => { DocServer.GetRefField(id).then(linkDoc => { this.dataDoc[key] = doc || Docs.Create.FreeformDocument([], { title: value, width: 500, height: 500 }, value); @@ -164,24 +164,24 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & dispatchTransaction = (tx: Transaction) => { if (this._editorView) { - let metadata = tx.selection.$from.marks().find((m: Mark) => m.type === schema.marks.metadata); + const metadata = tx.selection.$from.marks().find((m: Mark) => m.type === schema.marks.metadata); if (metadata) { - let range = tx.selection.$from.blockRange(tx.selection.$to); + const range = tx.selection.$from.blockRange(tx.selection.$to); let text = range ? tx.doc.textBetween(range.start, range.end) : ""; let textEndSelection = tx.selection.to; for (; textEndSelection < range!.end && text[textEndSelection - range!.start] !== " "; textEndSelection++) { } text = text.substr(0, textEndSelection - range!.start); text = text.split(" ")[text.split(" ").length - 1]; - let split = text.split("::"); + const split = text.split("::"); if (split.length > 1 && split[1]) { - let key = split[0]; - let value = split[split.length - 1]; + const key = split[0]; + const value = split[split.length - 1]; this.linkOnDeselect.set(key, value); - let id = Utils.GenerateDeterministicGuid(this.dataDoc[Id] + key); + const id = Utils.GenerateDeterministicGuid(this.dataDoc[Id] + key); const link = this._editorView.state.schema.marks.link.create({ href: `http://localhost:1050/doc/${id}`, location: "onRight", title: value }); const mval = this._editorView.state.schema.marks.metadataVal.create(); - let offset = (tx.selection.to === range!.end - 1 ? -1 : 0); + const offset = (tx.selection.to === range!.end - 1 ? -1 : 0); tx = tx.addMark(textEndSelection - value.length + offset, textEndSelection, link).addMark(textEndSelection - value.length + offset, textEndSelection, mval); this.dataDoc[key] = value; } @@ -189,7 +189,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & const state = this._editorView.state.apply(tx); this._editorView.updateState(state); - let tsel = this._editorView.state.selection.$from; + const tsel = this._editorView.state.selection.$from; tsel.marks().filter(m => m.type === this._editorView!.state.schema.marks.user_mark).map(m => AudioBox.SetScrubTime(Math.max(0, m.attrs.modified * 5000 - 1000))); this._applyingChange = true; this.extensionDoc && (this.extensionDoc.lastModified = new DateField(new Date(Date.now()))); @@ -202,8 +202,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & updateTitle = () => { if (StrCast(this.dataDoc.title).startsWith("-") && this._editorView && !this.Document.customTitle) { - let str = this._editorView.state.doc.textContent; - let titlestr = str.substr(0, Math.min(40, str.length)); + const str = this._editorView.state.doc.textContent; + const titlestr = str.substr(0, Math.min(40, str.length)); this.dataDoc.title = "-" + titlestr + (str.length > 40 ? "..." : ""); } } @@ -212,11 +212,11 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & if (this._editorView && (this._editorView as any).docView) { const mark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight); const activeMark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight, { selected: true }); - let res = terms.map(term => this.findInNode(this._editorView!, this._editorView!.state.doc, term)); + const res = terms.map(term => this.findInNode(this._editorView!, this._editorView!.state.doc, term)); let tr = this._editorView.state.tr; - let flattened: TextSelection[] = []; + const flattened: TextSelection[] = []; res.map(r => r.map(h => flattened.push(h))); - let lastSel = Math.min(flattened.length - 1, this._searchIndex); + const lastSel = Math.min(flattened.length - 1, this._searchIndex); flattened.forEach((h: TextSelection, ind: number) => tr = tr.addMark(h.from, h.to, ind === lastSel ? activeMark : mark)); this._searchIndex = ++this._searchIndex > flattened.length - 1 ? 0 : this._searchIndex; this._editorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(flattened[lastSel].from), tr.doc.resolve(flattened[lastSel].to))).scrollIntoView()); @@ -227,13 +227,13 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & if (this._editorView && (this._editorView as any).docView) { const mark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight); const activeMark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight, { selected: true }); - let end = this._editorView.state.doc.nodeSize - 2; + const end = this._editorView.state.doc.nodeSize - 2; this._editorView.dispatch(this._editorView.state.tr.removeMark(0, end, mark).removeMark(0, end, activeMark)); } } setAnnotation = (start: number, end: number, mark: Mark, opened: boolean, keep: boolean = false) => { - let view = this._editorView!; - let nmark = view.state.schema.marks.user_mark.create({ ...mark.attrs, userid: keep ? Doc.CurrentUserEmail : mark.attrs.userid, opened: opened }); + const view = this._editorView!; + const nmark = view.state.schema.marks.user_mark.create({ ...mark.attrs, userid: keep ? Doc.CurrentUserEmail : mark.attrs.userid, opened: opened }); view.dispatch(view.state.tr.removeMark(start, end, nmark).addMark(start, end, nmark)); } protected createDropTarget = (ele: HTMLDivElement) => { @@ -266,16 +266,16 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & e.stopPropagation(); // embed document when dragging with a userDropAction or an embedDoc flag set } else if (de.data.userDropAction || de.data.embedDoc) { - let target = de.data.droppedDocuments[0]; + const target = de.data.droppedDocuments[0]; // const link = DocUtils.MakeLink({ doc: this.dataDoc, ctx: this.props.ContainingCollectionDoc }, { doc: target }, "Embedded Doc:" + target.title); // if (link) { target.fitToBox = true; - let node = schema.nodes.dashDoc.create({ + const node = schema.nodes.dashDoc.create({ width: target[WidthSym](), height: target[HeightSym](), title: "dashDoc", docid: target[Id], float: "right" }); - let view = this._editorView!; + const view = this._editorView!; view.dispatch(view.state.tr.insert(view.posAtCoords({ left: de.x, top: de.y })!.pos, node)); this.tryUpdateHeight(); e.stopPropagation(); @@ -292,7 +292,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & if (node.isBlock) { // tslint:disable-next-line: prefer-for-of for (let i = 0; i < (context.content as any).content.length; i++) { - let result = this.getNodeEndpoints((context.content as any).content[i], node); + const result = this.getNodeEndpoints((context.content as any).content[i], node); if (result) { return { from: result.from + offset + (context.type.name === "doc" ? 0 : 1), @@ -313,9 +313,10 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & let ret: TextSelection[] = []; if (node.isTextblock) { - let index = 0, foundAt, ep = this.getNodeEndpoints(pm.state.doc, node); + let index = 0, foundAt; + const ep = this.getNodeEndpoints(pm.state.doc, node); while (ep && (foundAt = node.textContent.slice(index).search(RegExp(find, "i"))) > -1) { - let sel = new TextSelection(pm.state.doc.resolve(ep.from + index + foundAt + 1), pm.state.doc.resolve(ep.from + index + foundAt + find.length + 1)); + const sel = new TextSelection(pm.state.doc.resolve(ep.from + index + foundAt + 1), pm.state.doc.resolve(ep.from + index + foundAt + find.length + 1)); ret.push(sel); index = index + foundAt + find.length; } @@ -348,13 +349,13 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } if (FormattedTextBox._highlights.indexOf("By Recent Minute") !== -1) { addStyleSheetRule(FormattedTextBox._userStyleSheet, "userMark-" + Doc.CurrentUserEmail.replace(".", "").replace("@", ""), { opacity: "0.1" }); - let min = Math.round(Date.now() / 1000 / 60); + const min = Math.round(Date.now() / 1000 / 60); numberRange(10).map(i => addStyleSheetRule(FormattedTextBox._userStyleSheet, "userMark-min-" + (min - i), { opacity: ((10 - i - 1) / 10).toString() })); setTimeout(() => this.updateHighlights()); } if (FormattedTextBox._highlights.indexOf("By Recent Hour") !== -1) { addStyleSheetRule(FormattedTextBox._userStyleSheet, "userMark-" + Doc.CurrentUserEmail.replace(".", "").replace("@", ""), { opacity: "0.1" }); - let hr = Math.round(Date.now() / 1000 / 60 / 60); + const hr = Math.round(Date.now() / 1000 / 60 / 60); numberRange(10).map(i => addStyleSheetRule(FormattedTextBox._userStyleSheet, "userMark-hr-" + (hr - i), { opacity: ((10 - i - 1) / 10).toString() })); } } @@ -362,7 +363,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & toggleSidebar = () => this.props.Document.sidebarWidthPercent = StrCast(this.props.Document.sidebarWidthPercent, "0%") === "0%" ? "25%" : "0%"; specificContextMenu = (e: React.MouseEvent): void => { - let funcs: ContextMenuProps[] = []; + const funcs: ContextMenuProps[] = []; funcs.push({ description: "Toggle Sidebar", event: () => { e.stopPropagation(); this.toggleSidebar(); }, icon: "expand-arrows-alt" }); funcs.push({ description: "Record Bullet", event: () => { e.stopPropagation(); this.recordBullet(); }, icon: "expand-arrows-alt" }); ["My Text", "Text from Others", "Todo Items", "Important Items", "Ignore Items", "Disagree Items", "By Recent Minute", "By Recent Hour"].forEach(option => @@ -403,8 +404,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } recordBullet = async () => { - let completedCue = "end session"; - let results = await DictationManager.Controls.listen({ + const completedCue = "end session"; + const results = await DictationManager.Controls.listen({ interimHandler: this.setCurrentBulletContent, continuous: { indefinite: false }, terminators: [completedCue, "bullet", "next"] @@ -420,20 +421,20 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & setCurrentBulletContent = (value: string) => { if (this._editorView) { let state = this._editorView.state; - let from = state.selection.from; - let to = state.selection.to; + const from = state.selection.from; + const to = state.selection.to; this._editorView.dispatch(state.tr.insertText(value, from, to)); state = this._editorView.state; - let updated = TextSelection.create(state.doc, from, from + value.length); + const updated = TextSelection.create(state.doc, from, from + value.length); this._editorView.dispatch(state.tr.setSelection(updated)); } } nextBullet = (pos: number) => { if (this._editorView) { - let frag = Fragment.fromArray(this.newListItems(2)); + const frag = Fragment.fromArray(this.newListItems(2)); if (this._editorView.state.doc.resolve(pos).depth >= 2) { - let slice = new Slice(frag, 2, 2); + const slice = new Slice(frag, 2, 2); let state = this._editorView.state; this._editorView.dispatch(state.tr.step(new ReplaceStep(pos, pos, slice))); pos += 4; @@ -471,8 +472,10 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } componentDidMount() { - this.pullFromGoogleDoc(this.checkState); - this.dataDoc[GoogleRef] && this.dataDoc.unchanged && runInAction(() => DocumentDecorations.Instance.isAnimatingFetch = true); + if (DocumentButtonBar.Instance) { + this.pullFromGoogleDoc(this.checkState); + this.dataDoc[GoogleRef] && this.dataDoc.unchanged && runInAction(() => DocumentButtonBar.Instance.isAnimatingFetch = true); + } this._reactionDisposer = reaction( () => { @@ -481,7 +484,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & }, incomingValue => { if (this._editorView && !this._applyingChange) { - let updatedState = JSON.parse(incomingValue); + const updatedState = JSON.parse(incomingValue); this._editorView.updateState(EditorState.fromJSON(this.config, updatedState)); this.tryUpdateHeight(); } @@ -493,7 +496,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & () => { if (!DocumentButtonBar.hasPulledHack) { DocumentButtonBar.hasPulledHack = true; - let unchanged = this.dataDoc.unchanged; + const unchanged = this.dataDoc.unchanged; this.pullFromGoogleDoc(unchanged ? this.checkState : this.updateState); } } @@ -514,7 +517,6 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & () => this.tryUpdateHeight() ); - this.setupEditor(this.config, this.dataDoc, this.props.fieldKey); this._searchReactionDisposer = reaction(() => { @@ -528,10 +530,9 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } }, { fireImmediately: true }); - this._rulesReactionDisposer = reaction(() => { - let ruleProvider = this.props.ruleProvider; - let heading = NumCast(this.layoutDoc.heading); + const ruleProvider = this.props.ruleProvider; + const heading = NumCast(this.layoutDoc.heading); if (ruleProvider instanceof Doc) { return { align: StrCast(ruleProvider["ruleAlign_" + heading], ""), @@ -547,7 +548,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & rules && setTimeout(() => { const view = this._editorView!; if (this._proseRef) { - let n = new NodeSelection(view.state.doc.resolve(0)); + const n = new NodeSelection(view.state.doc.resolve(0)); if (this._editorView!.state.doc.textContent === "") { view.dispatch(view.state.tr.setSelection(new TextSelection(view.state.doc.resolve(0), view.state.doc.resolve(2))). replaceSelectionWith(this._editorView!.state.schema.nodes.paragraph.create({ align: rules.align }), true)); @@ -562,10 +563,10 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this._scrollToRegionReactionDisposer = reaction( () => StrCast(this.layoutDoc.scrollToLinkID), async (scrollToLinkID) => { - let findLinkFrag = (frag: Fragment, editor: EditorView) => { + const findLinkFrag = (frag: Fragment, editor: EditorView) => { const nodes: Node[] = []; frag.forEach((node, index) => { - let examinedNode = findLinkNode(node, editor); + const examinedNode = findLinkNode(node, editor); if (examinedNode && examinedNode.textContent) { nodes.push(examinedNode); start += index; @@ -573,7 +574,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & }); return { frag: Fragment.fromArray(nodes), start: start }; }; - let findLinkNode = (node: Node, editor: EditorView) => { + const findLinkNode = (node: Node, editor: EditorView) => { if (!node.isText) { const content = findLinkFrag(node.content, editor); return node.copy(content.frag); @@ -585,8 +586,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & let start = -1; if (this._editorView && scrollToLinkID) { - let editor = this._editorView; - let ret = findLinkFrag(editor.state.doc.content, editor); + const editor = this._editorView; + const ret = findLinkFrag(editor.state.doc.content, editor); if (ret.frag.size > 2 && ret.start >= 0) { let selection = TextSelection.near(editor.state.doc.resolve(ret.start)); // default to near the start @@ -610,28 +611,28 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & pushToGoogleDoc = async () => { this.pullFromGoogleDoc(async (exportState: Opt<GoogleApiClientUtils.Docs.ImportResult>, dataDoc: Doc) => { - let modes = GoogleApiClientUtils.Docs.WriteMode; + const modes = GoogleApiClientUtils.Docs.WriteMode; let mode = modes.Replace; let reference: Opt<GoogleApiClientUtils.Docs.Reference> = Cast(this.dataDoc[GoogleRef], "string"); if (!reference) { mode = modes.Insert; reference = { title: StrCast(this.dataDoc.title) }; } - let redo = async () => { + const redo = async () => { if (this._editorView && reference) { - let content = await RichTextUtils.GoogleDocs.Export(this._editorView.state); - let response = await GoogleApiClientUtils.Docs.write({ reference, content, mode }); + const content = await RichTextUtils.GoogleDocs.Export(this._editorView.state); + const response = await GoogleApiClientUtils.Docs.write({ reference, content, mode }); response && (this.dataDoc[GoogleRef] = response.documentId); - let pushSuccess = response !== undefined && !("errors" in response); + const pushSuccess = response !== undefined && !("errors" in response); dataDoc.unchanged = pushSuccess; DocumentButtonBar.Instance.startPushOutcome(pushSuccess); } }; - let undo = () => { + const undo = () => { if (!exportState) { return; } - let content: GoogleApiClientUtils.Docs.Content = { + const content: GoogleApiClientUtils.Docs.Content = { text: exportState.text, requests: [] }; @@ -645,8 +646,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } pullFromGoogleDoc = async (handler: PullHandler) => { - let dataDoc = this.dataDoc; - let documentId = StrCast(dataDoc[GoogleRef]); + const dataDoc = this.dataDoc; + const documentId = StrCast(dataDoc[GoogleRef]); let exportState: Opt<GoogleApiClientUtils.Docs.ImportResult>; if (documentId) { exportState = await RichTextUtils.GoogleDocs.Import(documentId, dataDoc); @@ -661,8 +662,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & dataDoc.data = new RichTextField(JSON.stringify(exportState.state.toJSON())); setTimeout(() => { if (this._editorView) { - let state = this._editorView.state; - let end = state.doc.content.size - 1; + const state = this._editorView.state; + const end = state.doc.content.size - 1; this._editorView.dispatch(state.tr.setSelection(TextSelection.create(state.doc, end, end))); } }, 0); @@ -677,9 +678,9 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & checkState = (exportState: Opt<GoogleApiClientUtils.Docs.ImportResult>, dataDoc: Doc) => { if (exportState && this._editorView) { - let equalContent = _.isEqual(this._editorView.state.doc, exportState.state.doc); - let equalTitles = dataDoc.title === exportState.title; - let unchanged = equalContent && equalTitles; + const equalContent = isEqual(this._editorView.state.doc, exportState.state.doc); + const equalTitles = dataDoc.title === exportState.title; + const unchanged = equalContent && equalTitles; dataDoc.unchanged = unchanged; DocumentButtonBar.Instance.setPullState(unchanged); } @@ -707,7 +708,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } handlePaste = (view: EditorView, event: Event, slice: Slice): boolean => { - let cbe = event as ClipboardEvent; + const cbe = event as ClipboardEvent; const pdfDocId = cbe.clipboardData && cbe.clipboardData.getData("dash/pdfOrigin"); const pdfRegionId = cbe.clipboardData && cbe.clipboardData.getData("dash/pdfRegion"); if (pdfDocId && pdfRegionId) { @@ -717,18 +718,18 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & setTimeout(async () => { const extension = Doc.fieldExtensionDoc(pdfDoc, "data"); if (extension) { - let targetAnnotations = await DocListCastAsync(extension.annotations);// bcz: NO... this assumes the pdf is using its 'data' field. need to have the PDF's view handle updating its own annotations + const targetAnnotations = await DocListCastAsync(extension.annotations);// bcz: NO... this assumes the pdf is using its 'data' field. need to have the PDF's view handle updating its own annotations targetAnnotations && targetAnnotations.push(pdfRegion); } }); - let link = DocUtils.MakeLink({ doc: this.props.Document, ctx: this.props.ContainingCollectionDoc }, { doc: pdfRegion, ctx: pdfDoc }, "note on " + pdfDoc.title, "pasted PDF link"); + const link = DocUtils.MakeLink({ doc: this.props.Document, ctx: this.props.ContainingCollectionDoc }, { doc: pdfRegion, ctx: pdfDoc }, "note on " + pdfDoc.title, "pasted PDF link"); if (link) { cbe.clipboardData!.setData("dash/linkDoc", link[Id]); - let linkId = link[Id]; - let frag = addMarkToFrag(slice.content, (node: Node) => addLinkMark(node, StrCast(pdfDoc.title), linkId)); + const linkId = link[Id]; + const frag = addMarkToFrag(slice.content, (node: Node) => addLinkMark(node, StrCast(pdfDoc.title), linkId)); slice = new Slice(frag, slice.openStart, slice.openEnd); - var tr = view.state.tr.replaceSelection(slice); + const tr = view.state.tr.replaceSelection(slice); view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste")); } } @@ -758,11 +759,11 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } private setupEditor(config: any, doc: Doc, fieldKey: string) { - let field = doc ? Cast(doc[fieldKey], RichTextField) : undefined; + const field = doc ? Cast(doc[fieldKey], RichTextField) : undefined; let startup = StrCast(doc.documentText); startup = startup.startsWith("@@@") ? startup.replace("@@@", "") : ""; if (!field && doc) { - let text = StrCast(doc[fieldKey]); + const text = StrCast(doc[fieldKey]); if (text) { startup = text; } else if (Cast(doc[fieldKey], "number")) { @@ -770,16 +771,16 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } } if (this._proseRef) { - let self = this; + const self = this; this._editorView && this._editorView.destroy(); this._editorView = new EditorView(this._proseRef, { state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config), handleScrollToSelection: (editorView) => { - let ref = editorView.domAtPos(editorView.state.selection.from); + const ref = editorView.domAtPos(editorView.state.selection.from); let refNode = ref.node as any; while (refNode && !("getBoundingClientRect" in refNode)) refNode = refNode.parentElement; - let r1 = refNode && refNode.getBoundingClientRect(); - let r3 = self._ref.current!.getBoundingClientRect(); + const r1 = refNode && refNode.getBoundingClientRect(); + const r3 = self._ref.current!.getBoundingClientRect(); if (r1.top < r3.top || r1.top > r3.bottom) { r1 && (self._ref.current!.scrollTop += (r1.top - r3.top) * self.props.ScreenToLocalTransform().Scale); } @@ -803,7 +804,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } } - let selectOnLoad = this.props.Document[Id] === FormattedTextBox.SelectOnLoad; + const selectOnLoad = this.props.Document[Id] === FormattedTextBox.SelectOnLoad; if (selectOnLoad) { FormattedTextBox.SelectOnLoad = ""; this.props.select(false); @@ -838,7 +839,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } onPointerDown = (e: React.PointerEvent): void => { FormattedTextBoxComment.textBox = this; - let pos = this._editorView!.posAtCoords({ left: e.clientX, top: e.clientY }); + const pos = this._editorView!.posAtCoords({ left: e.clientX, top: e.clientY }); pos && (this._nodeClicked = this._editorView!.state.doc.nodeAt(pos.pos)); if (this.props.onClick && e.button === 0) { e.preventDefault(); @@ -923,16 +924,16 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & hitBulletTargets(x: number, y: number, offsetX: number, select: boolean, highlightOnly = false) { clearStyleSheetRules(FormattedTextBox._bulletStyleSheet); if (this.props.isSelected(true) && offsetX < 40) { - let pos = this._editorView!.posAtCoords({ left: x, top: y }); + const pos = this._editorView!.posAtCoords({ left: x, top: y }); if (pos && pos.pos > 0) { - let node = this._editorView!.state.doc.nodeAt(pos.pos); - let node2 = node?.type === schema.nodes.paragraph ? this._editorView!.state.doc.nodeAt(pos.pos - 1) : undefined; + const node = this._editorView!.state.doc.nodeAt(pos.pos); + const node2 = node?.type === schema.nodes.paragraph ? this._editorView!.state.doc.nodeAt(pos.pos - 1) : undefined; if ((node === this._nodeClicked || highlightOnly) && (node2?.type === schema.nodes.ordered_list || node2?.type === schema.nodes.list_item)) { - let hit = this._editorView!.domAtPos(pos.pos).node as any; // let beforeEle = document.querySelector("." + hit.className) as Element; - let before = hit ? window.getComputedStyle(hit, ':before') : undefined; - let beforeWidth = before ? Number(before.getPropertyValue('width').replace("px", "")) : undefined; + const hit = this._editorView!.domAtPos(pos.pos).node as any; // let beforeEle = document.querySelector("." + hit.className) as Element; + const before = hit ? window.getComputedStyle(hit, ':before') : undefined; + const beforeWidth = before ? Number(before.getPropertyValue('width').replace("px", "")) : undefined; if (beforeWidth && offsetX < beforeWidth * .9) { - let ol = this._editorView!.state.doc.nodeAt(pos.pos - 2) ? this._editorView!.state.doc.nodeAt(pos.pos - 2) : undefined; + const ol = this._editorView!.state.doc.nodeAt(pos.pos - 2) ? this._editorView!.state.doc.nodeAt(pos.pos - 2) : undefined; if (ol?.type === schema.nodes.ordered_list && select) { if (!highlightOnly) { this._editorView!.dispatch(this._editorView!.state.tr.setSelection(new NodeSelection(this._editorView!.state.doc.resolve(pos.pos - 2)))); @@ -953,11 +954,11 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & onMouseUp = (e: React.MouseEvent): void => { e.stopPropagation(); - let view = this._editorView as any; + const view = this._editorView as any; // this interposes on prosemirror's upHandler to prevent prosemirror's up from invoked multiple times when there // are nested prosemirrors. We only want the lowest level prosemirror to be invoked. if (view.mouseDown) { - let originalUpHandler = view.mouseDown.up; + const originalUpHandler = view.mouseDown.up; view.root.removeEventListener("mouseup", originalUpHandler); view.mouseDown.up = (e: MouseEvent) => { !(e as any).formattedHandled && originalUpHandler(e); @@ -969,7 +970,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } tooltipTextMenuPlugin() { - let self = FormattedTextBox; + const self = FormattedTextBox; return new Plugin({ view(newView) { return self.ToolTipTextMenu = FormattedTextBox.getToolTip(newView); @@ -978,7 +979,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } tooltipLinkingMenuPlugin() { - let myprops = this.props; + const myprops = this.props; return new Plugin({ view(_editorView) { return new TooltipLinkingMenu(_editorView, myprops); @@ -1001,7 +1002,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & if (e.key === "Tab" || e.key === "Enter") { e.preventDefault(); } - let mark = schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.round(Date.now() / 1000 / 5) }); + const mark = schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.round(Date.now() / 1000 / 5) }); this._editorView!.dispatch(this._editorView!.state.tr.removeStoredMark(schema.marks.user_mark.create({})).addStoredMark(mark)); if (!this._undoTyping) { @@ -1018,8 +1019,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & const scrollHeight = this._ref.current?.scrollHeight; if (!this.layoutDoc.animateToPos && this.layoutDoc.autoHeight && scrollHeight && getComputedStyle(this._ref.current!.parentElement!).top === "0px") { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation - let nh = this.Document.isTemplateField ? 0 : NumCast(this.dataDoc.nativeHeight, 0); - let dh = NumCast(this.layoutDoc.height, 0); + const nh = this.Document.isTemplateField ? 0 : NumCast(this.dataDoc.nativeHeight, 0); + const dh = NumCast(this.layoutDoc.height, 0); this.layoutDoc.height = Math.max(10, (nh ? dh / nh * scrollHeight : scrollHeight) + (this.props.ChromeHeight ? this.props.ChromeHeight() : 0)); this.dataDoc.nativeHeight = nh ? scrollHeight : undefined; } @@ -1030,8 +1031,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & @computed get annotationsKey() { return "annotations"; } render() { TraceMobx(); - let rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : ""; - let interactive = InkingControl.Instance.selectedTool || this.layoutDoc.isBackground; + const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : ""; + const interactive = InkingControl.Instance.selectedTool || this.layoutDoc.isBackground; if (this.props.isSelected()) { FormattedTextBox.ToolTipTextMenu!.updateFromDash(this._editorView!, undefined, this.props); } else if (FormattedTextBoxComment.textBox === this) { diff --git a/src/client/views/nodes/FormattedTextBoxComment.tsx b/src/client/views/nodes/FormattedTextBoxComment.tsx index c076fd34a..2ec30e3b3 100644 --- a/src/client/views/nodes/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/FormattedTextBoxComment.tsx @@ -81,7 +81,7 @@ export class FormattedTextBoxComment { FormattedTextBoxComment.tooltip.style.display = "none"; FormattedTextBoxComment.tooltip.appendChild(FormattedTextBoxComment.tooltipInput); FormattedTextBoxComment.tooltip.onpointerdown = (e: PointerEvent) => { - let keep = e.target && (e.target as any).type === "checkbox" ? true : false; + const keep = e.target && (e.target as any).type === "checkbox" ? true : false; const textBox = FormattedTextBoxComment.textBox; if (FormattedTextBoxComment.linkDoc && !keep && textBox) { DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document, @@ -113,7 +113,7 @@ export class FormattedTextBoxComment { } static update(view: EditorView, lastState?: EditorState) { - let state = view.state; + const state = view.state; // Don't do anything if the document/selection didn't change if (lastState && lastState.doc.eq(state.doc) && lastState.selection.eq(state.selection)) { @@ -136,11 +136,11 @@ export class FormattedTextBoxComment { // this section checks to see if the insertion point is over text entered by a different user. If so, it sets ths comment text to indicate the user and the modification date if (state.selection.$from) { nbef = findStartOfMark(state.selection.$from, view, findOtherUserMark); - let naft = findEndOfMark(state.selection.$from, view, findOtherUserMark); - let noselection = view.state.selection.$from === view.state.selection.$to; + const naft = findEndOfMark(state.selection.$from, view, findOtherUserMark); + const noselection = view.state.selection.$from === view.state.selection.$to; let child: any = null; state.doc.nodesBetween(state.selection.from, state.selection.to, (node: any, pos: number, parent: any) => !child && node.marks.length && (child = node)); - let mark = child && findOtherUserMark(child.marks); + const mark = child && findOtherUserMark(child.marks); if (mark && child && (nbef || naft) && (!mark.attrs.opened || noselection)) { FormattedTextBoxComment.SetState(FormattedTextBoxComment.textBox, mark.attrs.opened, state.selection.$from.pos - nbef, state.selection.$from.pos + naft, mark); } @@ -153,10 +153,10 @@ export class FormattedTextBoxComment { // this checks if the selection is a hyperlink. If so, it displays the target doc's text for internal links, and the url of the target for external links. if (set === "none" && state.selection.$from) { nbef = findStartOfMark(state.selection.$from, view, findLinkMark); - let naft = findEndOfMark(state.selection.$from, view, findLinkMark); + const naft = findEndOfMark(state.selection.$from, view, findLinkMark); let child: any = null; state.doc.nodesBetween(state.selection.from, state.selection.to, (node: any, pos: number, parent: any) => !child && node.marks.length && (child = node)); - let mark = child && findLinkMark(child.marks); + const mark = child && findLinkMark(child.marks); if (mark && child && nbef && naft) { FormattedTextBoxComment.tooltipText.textContent = "external => " + mark.attrs.href; if (mark.attrs.href.startsWith("https://en.wikipedia.org/wiki/")) { @@ -167,7 +167,7 @@ export class FormattedTextBoxComment { } (FormattedTextBoxComment.tooltipText as any).href = mark.attrs.href; if (mark.attrs.href.indexOf(Utils.prepend("/doc/")) === 0) { - let docTarget = mark.attrs.href.replace(Utils.prepend("/doc/"), "").split("?")[0]; + const docTarget = mark.attrs.href.replace(Utils.prepend("/doc/"), "").split("?")[0]; docTarget && DocServer.GetRefField(docTarget).then(linkDoc => { if (linkDoc instanceof Doc) { FormattedTextBoxComment.linkDoc = linkDoc; @@ -210,12 +210,12 @@ export class FormattedTextBoxComment { if (set !== "none") { // These are in screen coordinates // let start = view.coordsAtPos(state.selection.from), end = view.coordsAtPos(state.selection.to); - let start = view.coordsAtPos(state.selection.from - nbef), end = view.coordsAtPos(state.selection.from - nbef); + const start = view.coordsAtPos(state.selection.from - nbef), end = view.coordsAtPos(state.selection.from - nbef); // The box in which the tooltip is positioned, to use as base - let box = (document.getElementById("mainView-container") as any).getBoundingClientRect(); + const box = (document.getElementById("mainView-container") as any).getBoundingClientRect(); // Find a center-ish x position from the selection endpoints (when // crossing lines, end may be more to the left) - let left = Math.max((start.left + end.left) / 2, start.left + 3); + const left = Math.max((start.left + end.left) / 2, start.left + 3); FormattedTextBoxComment.tooltip.style.left = (left - box.left) + "px"; FormattedTextBoxComment.tooltip.style.bottom = (box.bottom - start.top) + "px"; } diff --git a/src/client/views/nodes/IconBox.tsx b/src/client/views/nodes/IconBox.tsx index 60f547b1e..9462ff024 100644 --- a/src/client/views/nodes/IconBox.tsx +++ b/src/client/views/nodes/IconBox.tsx @@ -51,7 +51,7 @@ export class IconBox extends React.Component<FieldViewProps> { } public static DocumentIcon(layout: string) { - let button = layout.indexOf("PDFBox") !== -1 ? faFilePdf : + const button = layout.indexOf("PDFBox") !== -1 ? faFilePdf : layout.indexOf("ImageBox") !== -1 ? faImage : layout.indexOf("Formatted") !== -1 ? faStickyNote : layout.indexOf("Video") !== -1 ? faFilm : @@ -65,14 +65,14 @@ export class IconBox extends React.Component<FieldViewProps> { } specificContextMenu = (): void => { - let cm = ContextMenu.Instance; + const cm = ContextMenu.Instance; cm.addItem({ description: this.props.Document.hideLabel ? "Show label with icon" : "Remove label from icon", event: this.setLabelField, icon: "tag" }); if (!this.props.Document.hideLabel) { cm.addItem({ description: "Use Target Title", event: () => IconBox.AutomaticTitle(this.props.Document), icon: "text-height" }); } } render() { - let label = this.props.Document.hideLabel ? "" : this.props.Document.title; + const label = this.props.Document.hideLabel ? "" : this.props.Document.title; return ( <div className="iconBox-container" onContextMenu={this.specificContextMenu}> {this.minimizedIcon} diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index c283e4f21..b4a51657f 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -28,8 +28,8 @@ import { documentSchema } from '../../../new_fields/documentSchemas'; import { Id } from '../../../new_fields/FieldSymbols'; import { TraceMobx } from '../../../new_fields/util'; import { SelectionManager } from '../../util/SelectionManager'; -var requestImageSize = require('../../util/request-image-size'); -var path = require('path'); +const requestImageSize = require('../../util/request-image-size'); +const path = require('path'); const { Howl } = require('howler'); @@ -88,7 +88,7 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum recordAudioAnnotation = () => { let gumStream: any; let recorder: any; - let self = this; + const self = this; const extensionDoc = this.extensionDoc; extensionDoc && navigator.mediaDevices.getUserMedia({ audio: true @@ -105,9 +105,9 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum const files = await res.json(); const url = Utils.prepend(files[0].path); // upload to server with known URL - let audioDoc = Docs.Create.AudioDocument(url, { title: "audio test", width: 200, height: 32 }); + const audioDoc = Docs.Create.AudioDocument(url, { title: "audio test", width: 200, height: 32 }); audioDoc.treeViewExpandedView = "layout"; - let audioAnnos = Cast(extensionDoc.audioAnnotations, listSpec(Doc)); + const audioAnnos = Cast(extensionDoc.audioAnnotations, listSpec(Doc)); if (audioAnnos === undefined) { extensionDoc.audioAnnotations = new List([audioDoc]); } else { @@ -126,10 +126,10 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum @undoBatch rotate = action(() => { - let nw = this.Document.nativeWidth; - let nh = this.Document.nativeHeight; - let w = this.Document.width; - let h = this.Document.height; + const nw = this.Document.nativeWidth; + const nh = this.Document.nativeHeight; + const w = this.Document.width; + const h = this.Document.height; this.Document.rotation = ((this.Document.rotation || 0) + 90) % 360; this.Document.nativeWidth = nh; this.Document.nativeHeight = nw; @@ -140,12 +140,12 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum specificContextMenu = (e: React.MouseEvent): void => { const field = Cast(this.Document[this.props.fieldKey], ImageField); if (field) { - let funcs: ContextMenuProps[] = []; + const funcs: ContextMenuProps[] = []; funcs.push({ description: "Copy path", event: () => Utils.CopyText(field.url.href), icon: "expand-arrows-alt" }); funcs.push({ description: "Rotate", event: this.rotate, icon: "expand-arrows-alt" }); - let existingAnalyze = ContextMenu.Instance.findByDescription("Analyzers..."); - let modes: ContextMenuProps[] = existingAnalyze && "subitems" in existingAnalyze ? existingAnalyze.subitems : []; + const existingAnalyze = ContextMenu.Instance.findByDescription("Analyzers..."); + const modes: ContextMenuProps[] = existingAnalyze && "subitems" in existingAnalyze ? existingAnalyze.subitems : []; modes.push({ description: "Generate Tags", event: this.generateMetadata, icon: "tag" }); modes.push({ description: "Find Faces", event: this.extractFaces, icon: "camera" }); !existingAnalyze && ContextMenu.Instance.addItem({ description: "Analyzers...", subitems: modes, icon: "hand-point-right" }); @@ -155,8 +155,8 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum } extractFaces = () => { - let converter = (results: any) => { - let faceDocs = new List<Doc>(); + const converter = (results: any) => { + const faceDocs = new List<Doc>(); results.reduce((face: CognitiveServices.Image.Face, faceDocs: List<Doc>) => faceDocs.push(Docs.Get.DocumentHierarchyFromJson(face, `Face: ${face.faceId}`)!), new List<Doc>()); return faceDocs; }; @@ -164,12 +164,12 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum } generateMetadata = (threshold: Confidence = Confidence.Excellent) => { - let converter = (results: any) => { - let tagDoc = new Doc; - let tagsList = new List(); + const converter = (results: any) => { + const tagDoc = new Doc; + const tagsList = new List(); results.tags.map((tag: Tag) => { tagsList.push(tag.name); - let sanitized = tag.name.replace(" ", "_"); + const sanitized = tag.name.replace(" ", "_"); tagDoc[sanitized] = ComputedField.MakeFunction(`(${tag.confidence} >= this.confidence) ? ${tag.confidence} : "${ComputedField.undefined}"`); }); this.extensionDoc && (this.extensionDoc.generatedTags = tagsList); @@ -181,7 +181,7 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum } @computed private get url() { - let data = Cast(this.dataDoc[this.props.fieldKey], ImageField); + const data = Cast(this.dataDoc[this.props.fieldKey], ImageField); return data ? data.url.href : undefined; } @@ -194,7 +194,7 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum } else if (!(lower.endsWith(".png") || lower.endsWith(".jpg") || lower.endsWith(".jpeg"))) { return url.href;//Why is this here } - let ext = path.extname(url.href); + const ext = path.extname(url.href); const suffix = this.props.renderDepth < 1 ? "_o" : this._curSuffix; return url.href.replace(ext, suffix + ext); } @@ -208,7 +208,7 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum if (this._curSuffix === "_l") this._largeRetryCount++; } @action onError = () => { - let timeout = this._curSuffix === "_s" ? this._smallRetryCount : this._curSuffix === "_m" ? this._mediumRetryCount : this._largeRetryCount; + const timeout = this._curSuffix === "_s" ? this._smallRetryCount : this._curSuffix === "_m" ? this._mediumRetryCount : this._largeRetryCount; if (timeout < 10) { setTimeout(this.retryPath, Math.min(10000, timeout * 5)); } @@ -218,9 +218,9 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum resize = (srcpath: string) => { requestImageSize(srcpath) .then((size: any) => { - let rotation = NumCast(this.dataDoc.rotation) % 180; - let realsize = rotation === 90 || rotation === 270 ? { height: size.width, width: size.height } : size; - let aspect = realsize.height / realsize.width; + const rotation = NumCast(this.dataDoc.rotation) % 180; + const realsize = rotation === 90 || rotation === 270 ? { height: size.width, width: size.height } : size; + const aspect = realsize.height / realsize.width; if (this.Document.width && (Math.abs(1 - NumCast(this.Document.height) / NumCast(this.Document.width) / (realsize.height / realsize.width)) > 0.1)) { setTimeout(action(() => { this.Document.height = this.Document[WidthSym]() * aspect; @@ -234,9 +234,9 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum fadesize = (srcpath: string) => { requestImageSize(srcpath) .then((size: any) => { - let rotation = NumCast(this.dataDoc.rotation) % 180; - let realsize = rotation === 90 || rotation === 270 ? { height: size.width, width: size.height } : size; - let aspect = realsize.height / realsize.width; + const rotation = NumCast(this.dataDoc.rotation) % 180; + const realsize = rotation === 90 || rotation === 270 ? { height: size.width, width: size.height } : size; + const aspect = realsize.height / realsize.width; if (this.Document.width && (Math.abs(1 - NumCast(this.Document.height) / NumCast(this.Document.width) / (realsize.height / realsize.width)) > 0.1)) { setTimeout(action(() => { this.Document.height = this.Document[WidthSym]() * aspect; @@ -250,10 +250,10 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum @action onPointerEnter = () => { - let self = this; - let audioAnnos = this.extensionDoc && DocListCast(this.extensionDoc.audioAnnotations); + const self = this; + const audioAnnos = this.extensionDoc && DocListCast(this.extensionDoc.audioAnnotations); if (audioAnnos && audioAnnos.length && this._audioState === 0) { - let anno = audioAnnos[Math.floor(Math.random() * audioAnnos.length)]; + const anno = audioAnnos[Math.floor(Math.random() * audioAnnos.length)]; anno.data instanceof AudioField && new Howl({ src: [anno.data.url.href], format: ["mp3"], @@ -289,32 +289,32 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum const extensionDoc = this.extensionDoc; if (!extensionDoc) return (null); // let transform = this.props.ScreenToLocalTransform().inverse(); - let pw = typeof this.props.PanelWidth === "function" ? this.props.PanelWidth() : typeof this.props.PanelWidth === "number" ? (this.props.PanelWidth as any) as number : 50; + const pw = typeof this.props.PanelWidth === "function" ? this.props.PanelWidth() : typeof this.props.PanelWidth === "number" ? (this.props.PanelWidth as any) as number : 50; // var [sptX, sptY] = transform.transformPoint(0, 0); // let [bptX, bptY] = transform.transformPoint(pw, this.props.PanelHeight()); // let w = bptX - sptX; - let nativeWidth = (this.Document.nativeWidth || pw); - let nativeHeight = (this.Document.nativeHeight || 1); + const nativeWidth = (this.Document.nativeWidth || pw); + const nativeHeight = (this.Document.nativeHeight || 1); let paths = [[Utils.CorsProxy("http://www.cs.brown.edu/~bcz/noImage.png"), nativeWidth / nativeHeight]]; // this._curSuffix = ""; // if (w > 20) { - let alts = DocListCast(extensionDoc.Alternates); - let altpaths = alts.filter(doc => doc.data instanceof ImageField).map(doc => [this.choosePath((doc.data as ImageField).url), doc[WidthSym]() / doc[HeightSym]()]); - let field = this.dataDoc[this.props.fieldKey]; + const alts = DocListCast(extensionDoc.Alternates); + const altpaths = alts.filter(doc => doc.data instanceof ImageField).map(doc => [this.choosePath((doc.data as ImageField).url), doc[WidthSym]() / doc[HeightSym]()]); + const field = this.dataDoc[this.props.fieldKey]; // if (w < 100 && this._smallRetryCount < 10) this._curSuffix = "_s"; // else if (w < 600 && this._mediumRetryCount < 10) this._curSuffix = "_m"; // else if (this._largeRetryCount < 10) this._curSuffix = "_l"; if (field instanceof ImageField) paths = [[this.choosePath(field.url), nativeWidth / nativeHeight]]; paths.push(...altpaths); // } - let dragging = !SelectionManager.GetIsDragging() ? "" : "-dragging"; - let rotation = NumCast(this.Document.rotation, 0); - let aspect = (rotation % 180) ? this.Document[HeightSym]() / this.Document[WidthSym]() : 1; - let shift = (rotation % 180) ? (nativeHeight - nativeWidth / aspect) / 2 : 0; - let srcpath = paths[Math.min(paths.length - 1, (this.Document.curPage || 0))][0] as string; - let srcaspect = paths[Math.min(paths.length - 1, (this.Document.curPage || 0))][1] as number; - let fadepath = paths[Math.min(paths.length - 1, 1)][0] as string; + const dragging = !SelectionManager.GetIsDragging() ? "" : "-dragging"; + const rotation = NumCast(this.Document.rotation, 0); + const aspect = (rotation % 180) ? this.Document[HeightSym]() / this.Document[WidthSym]() : 1; + const shift = (rotation % 180) ? (nativeHeight - nativeWidth / aspect) / 2 : 0; + const srcpath = paths[Math.min(paths.length - 1, (this.Document.curPage || 0))][0] as string; + const srcaspect = paths[Math.min(paths.length - 1, (this.Document.curPage || 0))][1] as number; + const fadepath = paths[Math.min(paths.length - 1, 1)][0] as string; !this.Document.ignoreAspect && this.resize(srcpath); diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index aa6e135fe..fba29e4cd 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -53,13 +53,13 @@ export class KeyValueBox extends React.Component<FieldViewProps> { } } public static CompileKVPScript(value: string): KVPScript | undefined { - let eq = value.startsWith("="); + const eq = value.startsWith("="); value = eq ? value.substr(1) : value; const dubEq = value.startsWith(":=") ? "computed" : value.startsWith(";=") ? "script" : false; value = dubEq ? value.substr(2) : value; - let options: ScriptOptions = { addReturn: true, params: { this: "Doc" } }; + const options: ScriptOptions = { addReturn: true, params: { this: "Doc" } }; if (dubEq) options.typecheck = false; - let script = CompileScript(value, options); + const script = CompileScript(value, options); if (!script.compiled) { return undefined; } @@ -76,7 +76,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> { } else if (type === "script") { field = new ScriptField(script); } else { - let res = script.run({ this: target }, console.log); + const res = script.run({ this: target }, console.log); if (!res.success) return false; field = res.result; } @@ -106,14 +106,14 @@ export class KeyValueBox extends React.Component<FieldViewProps> { rowHeight = () => 30; createTable = () => { - let doc = this.fieldDocToLayout; + const doc = this.fieldDocToLayout; if (!doc) { return <tr><td>Loading...</td></tr>; } - let realDoc = doc; + const realDoc = doc; - let ids: { [key: string]: string } = {}; - let protos = Doc.GetAllPrototypes(doc); + const ids: { [key: string]: string } = {}; + const protos = Doc.GetAllPrototypes(doc); for (const proto of protos) { Object.keys(proto).forEach(key => { if (!(key in ids) && realDoc[key] !== ComputedField.undefined) { @@ -122,10 +122,10 @@ export class KeyValueBox extends React.Component<FieldViewProps> { }); } - let rows: JSX.Element[] = []; + const rows: JSX.Element[] = []; let i = 0; const self = this; - for (let key of Object.keys(ids).slice().sort()) { + for (const key of Object.keys(ids).slice().sort()) { rows.push(<KeyValuePair doc={realDoc} addDocTab={this.props.addDocTab} PanelWidth={this.props.PanelWidth} PanelHeight={this.rowHeight} ref={(function () { let oldEl: KeyValuePair | undefined; @@ -163,7 +163,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> { @action onDividerMove = (e: PointerEvent): void => { - let nativeWidth = this._mainCont.current!.getBoundingClientRect(); + const nativeWidth = this._mainCont.current!.getBoundingClientRect(); this.props.Document.schemaSplitPercentage = Math.max(0, 100 - Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100)); } @action @@ -179,10 +179,10 @@ export class KeyValueBox extends React.Component<FieldViewProps> { } getTemplate = async () => { - let parent = Docs.Create.StackingDocument([], { width: 800, height: 800, title: "Template" }); + const parent = Docs.Create.StackingDocument([], { width: 800, height: 800, title: "Template" }); parent.singleColumn = false; parent.columnWidth = 100; - for (let row of this.rows.filter(row => row.isChecked)) { + for (const row of this.rows.filter(row => row.isChecked)) { await this.createTemplateField(parent, row); row.uncheck(); } @@ -190,17 +190,17 @@ export class KeyValueBox extends React.Component<FieldViewProps> { } createTemplateField = async (parentStackingDoc: Doc, row: KeyValuePair) => { - let metaKey = row.props.keyName; - let sourceDoc = await Cast(this.props.Document.data, Doc); + const metaKey = row.props.keyName; + const sourceDoc = await Cast(this.props.Document.data, Doc); if (!sourceDoc) { return; } - let fieldTemplate = await this.inferType(sourceDoc[metaKey], metaKey); + const fieldTemplate = await this.inferType(sourceDoc[metaKey], metaKey); if (!fieldTemplate) { return; } - let previousViewType = fieldTemplate.viewType; + const previousViewType = fieldTemplate.viewType; Doc.MakeMetadataFieldTemplate(fieldTemplate, Doc.GetProto(parentStackingDoc)); previousViewType && (fieldTemplate.viewType = previousViewType); @@ -208,14 +208,14 @@ export class KeyValueBox extends React.Component<FieldViewProps> { } inferType = async (data: FieldResult, metaKey: string) => { - let options = { width: 300, height: 300, title: metaKey }; + const options = { width: 300, height: 300, title: metaKey }; if (data instanceof RichTextField || typeof data === "string" || typeof data === "number") { return Docs.Create.TextDocument(options); } else if (data instanceof List) { if (data.length === 0) { return Docs.Create.StackingDocument([], options); } - let first = await Cast(data[0], Doc); + const first = await Cast(data[0], Doc); if (!first || !first.data) { return Docs.Create.StackingDocument([], options); } @@ -235,7 +235,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> { } render() { - let dividerDragger = this.splitPercentage === 0 ? (null) : + const dividerDragger = this.splitPercentage === 0 ? (null) : <div className="keyValueBox-dividerDragger" style={{ transform: `translate(calc(${100 - this.splitPercentage}% - 5px), 0px)` }}> <div className="keyValueBox-dividerDraggerThumb" onPointerDown={this.onDividerDown} /> </div>; diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 225565964..bca68cdd9 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -53,7 +53,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> { } render() { - let props: FieldViewProps = { + const props: FieldViewProps = { Document: this.props.doc, DataDoc: this.props.doc, ContainingCollectionView: undefined, @@ -73,7 +73,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> { pinToPres: returnZero, ContentScaling: returnOne }; - let contents = <FieldView {...props} />; + const contents = <FieldView {...props} />; // let fieldKey = Object.keys(props.Document).indexOf(props.fieldKey) !== -1 ? props.fieldKey : "(" + props.fieldKey + ")"; let protoCount = 0; let doc: Doc | undefined = props.Document; @@ -85,9 +85,9 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> { doc = doc.proto; } const parenCount = Math.max(0, protoCount - 1); - let keyStyle = protoCount === 0 ? "black" : "blue"; + const keyStyle = protoCount === 0 ? "black" : "blue"; - let hover = { transition: "0.3s ease opacity", opacity: this.isPointerOver || this.isChecked ? 1 : 0 }; + const hover = { transition: "0.3s ease opacity", opacity: this.isPointerOver || this.isChecked ? 1 : 0 }; return ( <tr className={this.props.rowStyle} onPointerEnter={action(() => this.isPointerOver = true)} onPointerLeave={action(() => this.isPointerOver = false)}> diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 87be1f4e9..0f5cc0fa9 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -95,7 +95,7 @@ export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument> @undoBatch @action private applyFilter = () => { - let scriptText = this._scriptValue ? this._scriptValue : + const scriptText = this._scriptValue ? this._scriptValue : this._keyValue && this._valueValue ? `this.${this._keyValue} === ${this._valueValue}` : "true"; this.props.Document.filterScript = ScriptField.MakeFunction(scriptText); } @@ -116,7 +116,7 @@ export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument> searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => this._searchString = e.currentTarget.value; settingsPanel() { - let pageBtns = <> + const pageBtns = <> <button className="pdfBox-overlayButton-iconCont" key="back" title="Page Back" onPointerDown={e => e.stopPropagation()} onClick={e => this.backPage()} style={{ left: 45, top: 5 }}> <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-left"} size="sm" /> @@ -186,7 +186,7 @@ export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument> specificContextMenu = (e: React.MouseEvent): void => { const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField); - let funcs: ContextMenuProps[] = []; + const funcs: ContextMenuProps[] = []; pdfUrl && funcs.push({ description: "Copy path", event: () => Utils.CopyText(pdfUrl.url.pathname), icon: "expand-arrows-alt" }); funcs.push({ description: "Toggle Fit Width " + (this.Document.fitWidth ? "Off" : "On"), event: () => this.Document.fitWidth = !this.Document.fitWidth, icon: "expand-arrows-alt" }); @@ -195,7 +195,7 @@ export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument> @computed get contentScaling() { return this.props.ContentScaling(); } @computed get renderTitleBox() { - let classname = "pdfBox" + (this.active() ? "-interactive" : ""); + const classname = "pdfBox" + (this.active() ? "-interactive" : ""); return <div className={classname} style={{ width: !this.props.Document.fitWidth ? NumCast(this.props.Document.nativeWidth) : `${100 / this.contentScaling}%`, height: !this.props.Document.fitWidth ? NumCast(this.props.Document.nativeHeight) : `${100 / this.contentScaling}%`, diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index cbb83b511..1e6894f37 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -42,7 +42,7 @@ export class PresBox extends React.Component<FieldViewProps> { if (value) { value.forEach((item, i) => { if (item instanceof Doc && item.type !== DocumentType.PRESELEMENT) { - let pinDoc = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent" }); + const pinDoc = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent" }); Doc.GetProto(pinDoc).presentationTargetDoc = item; Doc.GetProto(pinDoc).title = ComputedField.MakeFunction('(this.presentationTargetDoc instanceof Doc) && this.presentationTargetDoc.title.toString()'); value.splice(i, 1, pinDoc); @@ -61,9 +61,9 @@ export class PresBox extends React.Component<FieldViewProps> { next = async () => { const current = NumCast(this.props.Document.selectedDoc); //asking to get document at current index - let docAtCurrentNext = await this.getDocAtIndex(current + 1); + const docAtCurrentNext = await this.getDocAtIndex(current + 1); if (docAtCurrentNext !== undefined) { - let presDocs = DocListCast(this.props.Document[this.props.fieldKey]); + const presDocs = DocListCast(this.props.Document[this.props.fieldKey]); let nextSelected = current + 1; for (; nextSelected < presDocs.length - 1; nextSelected++) { @@ -78,15 +78,15 @@ export class PresBox extends React.Component<FieldViewProps> { back = async () => { const current = NumCast(this.props.Document.selectedDoc); //requesting for the doc at current index - let docAtCurrent = await this.getDocAtIndex(current); + const docAtCurrent = await this.getDocAtIndex(current); if (docAtCurrent !== undefined) { //asking for its presentation id. let prevSelected = current; let zoomOut: boolean = false; - let presDocs = await DocListCastAsync(this.props.Document[this.props.fieldKey]); - let currentsArray: Doc[] = []; + const presDocs = await DocListCastAsync(this.props.Document[this.props.fieldKey]); + const currentsArray: Doc[] = []; for (; presDocs && prevSelected > 0 && presDocs[prevSelected].groupButton; prevSelected--) { currentsArray.push(presDocs[prevSelected]); } @@ -104,8 +104,8 @@ export class PresBox extends React.Component<FieldViewProps> { //If so making sure to zoom out, which goes back to state before zooming action if (current > 0) { if (zoomOut || docAtCurrent.showButton) { - let prevScale = NumCast(this.childDocs[prevSelected].viewScale, null); - let curScale = DocumentManager.Instance.getScaleOfDocView(this.childDocs[current]); + const prevScale = NumCast(this.childDocs[prevSelected].viewScale, null); + const curScale = DocumentManager.Instance.getScaleOfDocView(this.childDocs[current]); if (prevScale !== undefined && prevScale !== curScale) { DocumentManager.Instance.zoomIntoScale(docAtCurrent, prevScale); } @@ -162,13 +162,13 @@ export class PresBox extends React.Component<FieldViewProps> { * te option open, navigates to that element. */ navigateToElement = async (curDoc: Doc, fromDocIndex: number) => { - let fromDoc = this.childDocs[fromDocIndex].presentationTargetDoc as Doc; + const fromDoc = this.childDocs[fromDocIndex].presentationTargetDoc as Doc; let docToJump = curDoc; let willZoom = false; - let presDocs = DocListCast(this.props.Document[this.props.fieldKey]); + const presDocs = DocListCast(this.props.Document[this.props.fieldKey]); let nextSelected = presDocs.indexOf(curDoc); - let currentDocGroups: Doc[] = []; + const currentDocGroups: Doc[] = []; for (; nextSelected < presDocs.length - 1; nextSelected++) { if (!presDocs[nextSelected + 1].groupButton) { break; @@ -190,11 +190,11 @@ export class PresBox extends React.Component<FieldViewProps> { //docToJump stayed same meaning, it was not in the group or was the last element in the group if (docToJump === curDoc) { //checking if curDoc has navigation open - let target = await curDoc.presentationTargetDoc as Doc; + const target = await curDoc.presentationTargetDoc as Doc; if (curDoc.navButton) { DocumentManager.Instance.jumpToDocument(target, false); } else if (curDoc.showButton) { - let curScale = DocumentManager.Instance.getScaleOfDocView(fromDoc); + const curScale = DocumentManager.Instance.getScaleOfDocView(fromDoc); //awaiting jump so that new scale can be found, since jumping is async await DocumentManager.Instance.jumpToDocument(target, true); curDoc.viewScale = DocumentManager.Instance.getScaleOfDocView(target); @@ -207,11 +207,11 @@ export class PresBox extends React.Component<FieldViewProps> { } return; } - let curScale = DocumentManager.Instance.getScaleOfDocView(fromDoc); + const curScale = DocumentManager.Instance.getScaleOfDocView(fromDoc); //awaiting jump so that new scale can be found, since jumping is async await DocumentManager.Instance.jumpToDocument(await docToJump.presentationTargetDoc as Doc, willZoom); - let newScale = DocumentManager.Instance.getScaleOfDocView(await curDoc.presentationTargetDoc as Doc); + const newScale = DocumentManager.Instance.getScaleOfDocView(await curDoc.presentationTargetDoc as Doc); curDoc.viewScale = newScale; //saving the scale that user was on if (curScale !== 1) { @@ -238,7 +238,7 @@ export class PresBox extends React.Component<FieldViewProps> { public removeDocument = (doc: Doc) => { const value = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc))); if (value) { - let indexOfDoc = value.indexOf(doc); + const indexOfDoc = value.indexOf(doc); if (indexOfDoc !== - 1) { value.splice(indexOfDoc, 1)[0]; return true; @@ -337,13 +337,13 @@ export class PresBox extends React.Component<FieldViewProps> { @action initializeScaleViews = (docList: Doc[], viewtype: number) => { this.props.Document.chromeStatus = "disabled"; - let hgt = (viewtype === CollectionViewType.Tree) ? 50 : 72; + const hgt = (viewtype === CollectionViewType.Tree) ? 50 : 72; docList.forEach((doc: Doc) => { doc.presBox = this.props.Document; doc.presBoxKey = this.props.fieldKey; doc.collapsedHeight = hgt; doc.height = ComputedField.MakeFunction("this.collapsedHeight + Number(this.embedOpen ? 100:0)"); - let curScale = NumCast(doc.viewScale, null); + const curScale = NumCast(doc.viewScale, null); if (curScale === undefined) { doc.viewScale = 1; } @@ -352,7 +352,7 @@ export class PresBox extends React.Component<FieldViewProps> { selectElement = (doc: Doc) => { - let index = DocListCast(this.props.Document[this.props.fieldKey]).indexOf(doc); + const index = DocListCast(this.props.Document[this.props.fieldKey]).indexOf(doc); index !== -1 && this.gotoDocument(index, NumCast(this.props.Document.selectedDoc)); } diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 741dcada0..376d27380 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -22,7 +22,7 @@ import { InkingControl } from "../InkingControl"; import { FieldView, FieldViewProps } from './FieldView'; import "./VideoBox.scss"; import { documentSchema, positionSchema } from "../../../new_fields/documentSchemas"; -var path = require('path'); +const path = require('path'); export const timeSchema = createSchema({ currentTimecode: "number", // the current time of a video or other linear, time-based document. Note, should really get set on an extension field, but that's more complicated when it needs to be set since the extension doc needs to be found first @@ -54,9 +54,9 @@ export class VideoBox extends DocAnnotatableComponent<FieldViewProps, VideoDocum } videoLoad = () => { - let aspect = this.player!.videoWidth / this.player!.videoHeight; - var nativeWidth = (this.Document.nativeWidth || 0); - var nativeHeight = (this.Document.nativeHeight || 0); + const aspect = this.player!.videoWidth / this.player!.videoHeight; + const nativeWidth = (this.Document.nativeWidth || 0); + const nativeHeight = (this.Document.nativeHeight || 0); if (!nativeWidth || !nativeHeight) { if (!this.Document.nativeWidth) this.Document.nativeWidth = this.player!.videoWidth; this.Document.nativeHeight = (this.Document.nativeWidth || 0) / aspect; @@ -101,12 +101,12 @@ export class VideoBox extends DocAnnotatableComponent<FieldViewProps, VideoDocum } @action public Snapshot() { - let width = this.Document.width || 0; - let height = this.Document.height || 0; - var canvas = document.createElement('canvas'); + const width = this.Document.width || 0; + const height = this.Document.height || 0; + const canvas = document.createElement('canvas'); canvas.width = 640; canvas.height = 640 * (this.Document.nativeHeight || 0) / (this.Document.nativeWidth || 1); - var ctx = canvas.getContext('2d');//draw image to canvas. scale to target dimensions + const ctx = canvas.getContext('2d');//draw image to canvas. scale to target dimensions if (ctx) { ctx.rect(0, 0, canvas.width, canvas.height); ctx.fillStyle = "blue"; @@ -115,20 +115,20 @@ export class VideoBox extends DocAnnotatableComponent<FieldViewProps, VideoDocum } if (!this._videoRef) { // can't find a way to take snapshots of videos - let b = Docs.Create.ButtonDocument({ + const b = Docs.Create.ButtonDocument({ x: (this.Document.x || 0) + width, y: (this.Document.y || 0), width: 150, height: 50, title: (this.Document.currentTimecode || 0).toString() }); b.onClick = ScriptField.MakeScript(`this.currentTimecode = ${(this.Document.currentTimecode || 0)}`); } else { //convert to desired file format - var dataUrl = canvas.toDataURL('image/png'); // can also use 'image/png' + const dataUrl = canvas.toDataURL('image/png'); // can also use 'image/png' // if you want to preview the captured image, - let filename = path.basename(encodeURIComponent("snapshot" + StrCast(this.Document.title).replace(/\..*$/, "") + "_" + (this.Document.currentTimecode || 0).toString().replace(/\./, "_"))); + const filename = path.basename(encodeURIComponent("snapshot" + StrCast(this.Document.title).replace(/\..*$/, "") + "_" + (this.Document.currentTimecode || 0).toString().replace(/\./, "_"))); VideoBox.convertDataUri(dataUrl, filename).then(returnedFilename => { if (returnedFilename) { - let url = this.choosePath(Utils.prepend(returnedFilename)); - let imageSummary = Docs.Create.ImageDocument(url, { + const url = this.choosePath(Utils.prepend(returnedFilename)); + const imageSummary = Docs.Create.ImageDocument(url, { x: (this.Document.x || 0) + width, y: (this.Document.y || 0), width: 150, height: height / width * 150, title: "--snapshot" + (this.Document.currentTimecode || 0) + " image-" }); @@ -150,9 +150,9 @@ export class VideoBox extends DocAnnotatableComponent<FieldViewProps, VideoDocum if (this.props.setVideoBox) this.props.setVideoBox(this); if (this.youtubeVideoId) { - let youtubeaspect = 400 / 315; - var nativeWidth = (this.Document.nativeWidth || 0); - var nativeHeight = (this.Document.nativeHeight || 0); + const youtubeaspect = 400 / 315; + const nativeWidth = (this.Document.nativeWidth || 0); + const nativeHeight = (this.Document.nativeHeight || 0); if (!nativeWidth || !nativeHeight) { if (!this.Document.nativeWidth) this.Document.nativeWidth = 600; this.Document.nativeHeight = (this.Document.nativeWidth || 0) / youtubeaspect; @@ -181,7 +181,7 @@ export class VideoBox extends DocAnnotatableComponent<FieldViewProps, VideoDocum public static async convertDataUri(imageUri: string, returnedFilename: string) { try { - let posting = Utils.prepend("/uploadURI"); + const posting = Utils.prepend("/uploadURI"); const returnedUri = await rp.post(posting, { body: { uri: imageUri, @@ -196,10 +196,10 @@ export class VideoBox extends DocAnnotatableComponent<FieldViewProps, VideoDocum } } specificContextMenu = (e: React.MouseEvent): void => { - let field = Cast(this.dataDoc[this.props.fieldKey], VideoField); + const field = Cast(this.dataDoc[this.props.fieldKey], VideoField); if (field) { - let url = field.url.href; - let subitems: ContextMenuProps[] = []; + const url = field.url.href; + const subitems: ContextMenuProps[] = []; subitems.push({ description: "Copy path", event: () => { Utils.CopyText(url); }, icon: "expand-arrows-alt" }); subitems.push({ description: "Toggle Show Controls", event: action(() => VideoBox._showControls = !VideoBox._showControls), icon: "expand-arrows-alt" }); subitems.push({ description: "Take Snapshot", event: () => this.Snapshot(), icon: "expand-arrows-alt" }); @@ -208,9 +208,9 @@ export class VideoBox extends DocAnnotatableComponent<FieldViewProps, VideoDocum } @computed get content() { - let field = Cast(this.dataDoc[this.props.fieldKey], VideoField); - let interactive = InkingControl.Instance.selectedTool || !this.props.isSelected() ? "" : "-interactive"; - let style = "videoBox-content" + (this._fullScreen ? "-fullScreen" : "") + interactive; + const field = Cast(this.dataDoc[this.props.fieldKey], VideoField); + const interactive = InkingControl.Instance.selectedTool || !this.props.isSelected() ? "" : "-interactive"; + const style = "videoBox-content" + (this._fullScreen ? "-fullScreen" : "") + interactive; return !field ? <div>Loading</div> : <video className={`${style}`} key="video" ref={this.setVideoRef} onCanPlay={this.videoLoad} controls={VideoBox._showControls} onPlay={() => this.Play()} onSeeked={this.updateTimecode} onPause={() => this.Pause()} onClick={e => e.preventDefault()}> @@ -220,7 +220,7 @@ export class VideoBox extends DocAnnotatableComponent<FieldViewProps, VideoDocum } @computed get youtubeVideoId() { - let field = Cast(this.dataDoc[this.props.fieldKey], VideoField); + const field = Cast(this.dataDoc[this.props.fieldKey], VideoField); return field && field.url.href.indexOf("youtube") !== -1 ? ((arr: string[]) => arr[arr.length - 1])(field.url.href.split("/")) : ""; } @@ -231,9 +231,9 @@ export class VideoBox extends DocAnnotatableComponent<FieldViewProps, VideoDocum } else this._youtubeContentCreated = false; - let iframe = e.target; + const iframe = e.target; let started = true; - let onYoutubePlayerStateChange = (event: any) => runInAction(() => { + const onYoutubePlayerStateChange = (event: any) => runInAction(() => { if (started && event.data === YT.PlayerState.PLAYING) { started = false; this._youtubePlayer && this._youtubePlayer.unMute(); @@ -243,12 +243,12 @@ export class VideoBox extends DocAnnotatableComponent<FieldViewProps, VideoDocum if (event.data === YT.PlayerState.PLAYING && !this._playing) this.Play(false); if (event.data === YT.PlayerState.PAUSED && this._playing) this.Pause(false); }); - let onYoutubePlayerReady = (event: any) => { + const onYoutubePlayerReady = (event: any) => { this._reactionDisposer && this._reactionDisposer(); this._youtubeReactionDisposer && this._youtubeReactionDisposer(); this._reactionDisposer = reaction(() => this.Document.currentTimecode, () => !this._playing && this.Seek(this.Document.currentTimecode || 0)); this._youtubeReactionDisposer = reaction(() => [this.props.isSelected(), DocumentDecorations.Instance.Interacting, InkingControl.Instance.selectedTool], () => { - let interactive = InkingControl.Instance.selectedTool === InkTool.None && this.props.isSelected(true) && !DocumentDecorations.Instance.Interacting; + const interactive = InkingControl.Instance.selectedTool === InkTool.None && this.props.isSelected(true) && !DocumentDecorations.Instance.Interacting; iframe.style.pointerEvents = interactive ? "all" : "none"; }, { fireImmediately: true }); }; @@ -261,8 +261,8 @@ export class VideoBox extends DocAnnotatableComponent<FieldViewProps, VideoDocum } private get uIButtons() { - let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().Scale); - let curTime = (this.Document.currentTimecode || 0); + const scaling = Math.min(1.8, this.props.ScreenToLocalTransform().Scale); + const curTime = (this.Document.currentTimecode || 0); return ([<div className="videoBox-time" key="time" onPointerDown={this.onResetDown} > <span>{"" + Math.round(curTime)}</span> <span style={{ fontSize: 8 }}>{" " + Math.round((curTime - Math.trunc(curTime)) * 100)}</span> @@ -318,8 +318,8 @@ export class VideoBox extends DocAnnotatableComponent<FieldViewProps, VideoDocum @computed get youtubeContent() { this._youtubeIframeId = VideoBox._youtubeIframeCounter++; this._youtubeContentCreated = this._forceCreateYouTubeIFrame ? true : true; - let style = "videoBox-content-YouTube" + (this._fullScreen ? "-fullScreen" : ""); - let start = untracked(() => Math.round(this.Document.currentTimecode || 0)); + const style = "videoBox-content-YouTube" + (this._fullScreen ? "-fullScreen" : ""); + const start = untracked(() => Math.round(this.Document.currentTimecode || 0)); return <iframe key={this._youtubeIframeId} id={`${this.youtubeVideoId + this._youtubeIframeId}-player`} onLoad={this.youtubeIframeLoaded} className={`${style}`} width={(this.Document.nativeWidth || 640)} height={(this.Document.nativeHeight || 390)} src={`https://www.youtube.com/embed/${this.youtubeVideoId}?enablejsapi=1&rel=0&showinfo=1&autoplay=1&mute=1&start=${start}&modestbranding=1&controls=${VideoBox._showControls ? 1 : 0}`} />; @@ -327,7 +327,7 @@ export class VideoBox extends DocAnnotatableComponent<FieldViewProps, VideoDocum @action.bound addDocumentWithTimestamp(doc: Doc): boolean { - var curTime = (this.Document.currentTimecode || -1); + const curTime = (this.Document.currentTimecode || -1); curTime !== -1 && (doc.displayTimecode = curTime); return this.addDocument(doc); } diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 5af743859..b0a93224d 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -36,11 +36,11 @@ export class WebBox extends DocAnnotatableComponent<FieldViewProps, WebDocument> componentWillMount() { - let field = Cast(this.props.Document[this.props.fieldKey], WebField); + const field = Cast(this.props.Document[this.props.fieldKey], WebField); if (field && field.url.href.indexOf("youtube") !== -1) { - let youtubeaspect = 400 / 315; - var nativeWidth = NumCast(this.layoutDoc.nativeWidth); - var nativeHeight = NumCast(this.layoutDoc.nativeHeight); + const youtubeaspect = 400 / 315; + const nativeWidth = NumCast(this.layoutDoc.nativeWidth); + const nativeHeight = NumCast(this.layoutDoc.nativeHeight); if (!nativeWidth || !nativeHeight || Math.abs(nativeWidth / nativeHeight - youtubeaspect) > 0.05) { if (!nativeWidth) this.layoutDoc.nativeWidth = 600; this.layoutDoc.nativeHeight = NumCast(this.layoutDoc.nativeWidth) / youtubeaspect; @@ -65,7 +65,7 @@ export class WebBox extends DocAnnotatableComponent<FieldViewProps, WebDocument> @action setURL() { - let urlField: FieldResult<WebField> = Cast(this.props.Document.data, WebField); + const urlField: FieldResult<WebField> = Cast(this.props.Document.data, WebField); if (urlField) this.url = urlField.url.toString(); else this.url = ""; } @@ -80,10 +80,10 @@ export class WebBox extends DocAnnotatableComponent<FieldViewProps, WebDocument> switchToText = () => { let url: string = ""; - let field = Cast(this.props.Document[this.props.fieldKey], WebField); + const field = Cast(this.props.Document[this.props.fieldKey], WebField); if (field) url = field.url.href; - let newBox = Docs.Create.TextDocument({ + const newBox = Docs.Create.TextDocument({ x: NumCast(this.props.Document.x), y: NumCast(this.props.Document.y), title: url, @@ -167,7 +167,7 @@ export class WebBox extends DocAnnotatableComponent<FieldViewProps, WebDocument> @computed get content() { - let field = this.dataDoc[this.props.fieldKey]; + const field = this.dataDoc[this.props.fieldKey]; let view; if (field instanceof HtmlField) { view = <span id="webBox-htmlSpan" dangerouslySetInnerHTML={{ __html: field.html }} />; @@ -176,15 +176,15 @@ export class WebBox extends DocAnnotatableComponent<FieldViewProps, WebDocument> } else { view = <iframe src={"https://crossorigin.me/https://cs.brown.edu"} style={{ position: "absolute", width: "100%", height: "100%", top: 0 }} />; } - let content = + const content = <div style={{ width: "100%", height: "100%", position: "absolute" }} onWheel={this.onPostWheel} onPointerDown={this.onPostPointer} onPointerMove={this.onPostPointer} onPointerUp={this.onPostPointer}> {this.urlEditor()} {view} </div>; - let frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting; + const frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting; - let classname = "webBox-cont" + (this.props.isSelected() && InkingControl.Instance.selectedTool === InkTool.None && !DocumentDecorations.Instance.Interacting ? "-interactive" : ""); + const classname = "webBox-cont" + (this.props.isSelected() && InkingControl.Instance.selectedTool === InkTool.None && !DocumentDecorations.Instance.Interacting ? "-interactive" : ""); return ( <> <div className={classname} > diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index 936af9ab8..6599c0e3c 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -62,11 +62,11 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> { } deleteAnnotation = () => { - let annotation = DocListCast(this.props.extensionDoc.annotations); - let group = FieldValue(Cast(this.props.document.group, Doc)); + const annotation = DocListCast(this.props.extensionDoc.annotations); + const group = FieldValue(Cast(this.props.document.group, Doc)); if (group) { if (annotation.indexOf(group) !== -1) { - let newAnnotations = annotation.filter(a => a !== FieldValue(Cast(this.props.document.group, Doc))); + const newAnnotations = annotation.filter(a => a !== FieldValue(Cast(this.props.document.group, Doc))); this.props.extensionDoc.annotations = new List<Doc>(newAnnotations); } @@ -77,7 +77,7 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> { } pinToPres = () => { - let group = FieldValue(Cast(this.props.document.group, Doc)); + const group = FieldValue(Cast(this.props.document.group, Doc)); group && this.props.pinToPres(group); } @@ -93,7 +93,7 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> { e.stopPropagation(); } else if (e.button === 0) { - let annoGroup = await Cast(this.props.document.group, Doc); + const annoGroup = await Cast(this.props.document.group, Doc); if (annoGroup) { DocumentManager.Instance.FollowLink(undefined, annoGroup, (doc: Doc, maxLocation: string) => this.props.addDocTab(doc, undefined, e.ctrlKey ? "inTab" : "onRight"), @@ -105,9 +105,9 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> { addTag = (key: string, value: string): boolean => { - let group = FieldValue(Cast(this.props.document.group, Doc)); + const group = FieldValue(Cast(this.props.document.group, Doc)); if (group) { - let valNum = parseInt(value); + const valNum = parseInt(value); group[key] = isNaN(valNum) ? value : valNum; return true; } diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index c64741769..38e10e99a 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -128,7 +128,7 @@ export default class PDFMenu extends AntimodeMenu { } render() { - let buttons = this.Status === "pdf" || this.Status === "snippet" ? + const buttons = this.Status === "pdf" || this.Status === "snippet" ? [ <button key="1" className="antimodeMenu-button" title="Click to Highlight" onClick={this.highlightClicked} style={this.Highlighting ? { backgroundColor: "#121212" } : {}}> <FontAwesomeIcon icon="highlighter" size="lg" style={{ transition: "transform 0.1s", transform: this.Highlighting ? "" : "rotate(-45deg)" }} /></button>, diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index c075a4f99..69aacc902 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -169,7 +169,7 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument copy = (e: ClipboardEvent) => { if (this.props.active(true) && e.clipboardData) { - let annoDoc = this.makeAnnotationDocument("rgba(3,144,152,0.3)"); // copied text markup color (blueish) + const annoDoc = this.makeAnnotationDocument("rgba(3,144,152,0.3)"); // copied text markup color (blueish) if (annoDoc) { e.clipboardData.setData("text/plain", this._selectionText); e.clipboardData.setData("dash/pdfOrigin", this.props.Document[Id]); @@ -212,7 +212,7 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument this._filterReactionDisposer = reaction( () => ({ scriptField: Cast(this.Document.filterScript, ScriptField), annos: this._annotations.slice() }), action(({ scriptField, annos }: { scriptField: FieldResult<ScriptField>, annos: Doc[] }) => { - let oldScript = this._script.originalScript; + const oldScript = this._script.originalScript; this._script = scriptField && scriptField.script.compiled ? scriptField.script : CompileScript("return true") as CompiledScript; if (this._script.originalScript !== oldScript) { this.Index = -1; @@ -240,8 +240,8 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument this.gotoPage(this.Document.curPage || 1); })); document.addEventListener("pagerendered", action(() => this._showCover = this._showWaiting = false)); - var pdfLinkService = new PDFJSViewer.PDFLinkService(); - let pdfFindController = new PDFJSViewer.PDFFindController({ linkService: pdfLinkService }); + const pdfLinkService = new PDFJSViewer.PDFLinkService(); + const pdfFindController = new PDFJSViewer.PDFFindController({ linkService: pdfLinkService }); this._pdfViewer = new PDFJSViewer.PDFViewer({ container: this._mainCont.current, viewer: this._viewer.current, @@ -260,12 +260,12 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument if (this._savedAnnotations.size() === 0) return undefined; let mainAnnoDoc = Docs.Create.InstanceFromProto(new Doc(), "", {}); let mainAnnoDocProto = Doc.GetProto(mainAnnoDoc); - let annoDocs: Doc[] = []; + const annoDocs: Doc[] = []; let maxX = -Number.MAX_VALUE; let minY = Number.MAX_VALUE; if ((this._savedAnnotations.values()[0][0] as any).marqueeing) { - let anno = this._savedAnnotations.values()[0][0]; - let annoDoc = Docs.Create.FreeformDocument([], { backgroundColor: color, title: "Annotation on " + this.Document.title }); + const anno = this._savedAnnotations.values()[0][0]; + const annoDoc = Docs.Create.FreeformDocument([], { backgroundColor: color, title: "Annotation on " + this.Document.title }); if (anno.style.left) annoDoc.x = parseInt(anno.style.left); if (anno.style.top) annoDoc.y = parseInt(anno.style.top); if (anno.style.height) annoDoc.height = parseInt(anno.style.height); @@ -280,7 +280,7 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument mainAnnoDocProto.y = annoDoc.y; } else { this._savedAnnotations.forEach((key: number, value: HTMLDivElement[]) => value.map(anno => { - let annoDoc = new Doc(); + const annoDoc = new Doc(); if (anno.style.left) annoDoc.x = parseInt(anno.style.left); if (anno.style.top) annoDoc.y = parseInt(anno.style.top); if (anno.style.height) annoDoc.height = parseInt(anno.style.height); @@ -324,7 +324,7 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument @action scrollToAnnotation = (scrollToAnnotation: Doc) => { if (scrollToAnnotation) { - let offset = this.visibleHeight() / 2 * 96 / 72; + const offset = this.visibleHeight() / 2 * 96 / 72; this._mainCont.current && smoothScroll(500, this._mainCont.current, NumCast(scrollToAnnotation.y) - offset); Doc.linkFollowHighlight(scrollToAnnotation); } @@ -356,7 +356,7 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument this._annotationLayer.current.append(div); div.style.backgroundColor = "yellow"; div.style.opacity = "0.5"; - let savedPage = this._savedAnnotations.getValue(page); + const savedPage = this._savedAnnotations.getValue(page); if (savedPage) { savedPage.push(div); this._savedAnnotations.setValue(page, savedPage); @@ -382,7 +382,7 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument }); } else if (this._mainCont.current) { - let executeFind = () => { + const executeFind = () => { this._pdfViewer.findController.executeCommand('find', { caseSensitive: false, findPrevious: !fwd, @@ -398,7 +398,7 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument @action onPointerDown = (e: React.PointerEvent): void => { - let hit = document.elementFromPoint(e.clientX, e.clientY); + const hit = document.elementFromPoint(e.clientX, e.clientY); if (hit && hit.localName === "span" && this.props.isSelected(true)) { // drag selecting text stops propagation e.button === 0 && e.stopPropagation(); } @@ -425,7 +425,7 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument } else if (this._mainCont.current) { // set marquee x and y positions to the spatially transformed position - let boundingRect = this._mainCont.current.getBoundingClientRect(); + const boundingRect = this._mainCont.current.getBoundingClientRect(); this._startX = this._marqueeX = (e.clientX - boundingRect.left) * (this._mainCont.current.offsetWidth / boundingRect.width); this._startY = this._marqueeY = (e.clientY - boundingRect.top) * (this._mainCont.current.offsetHeight / boundingRect.height) + this._mainCont.current.scrollTop; this._marqueeHeight = this._marqueeWidth = 0; @@ -442,7 +442,7 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument onSelectMove = (e: PointerEvent): void => { if (this._marqueeing && this._mainCont.current) { // transform positions and find the width and height to set the marquee to - let boundingRect = this._mainCont.current.getBoundingClientRect(); + const boundingRect = this._mainCont.current.getBoundingClientRect(); this._marqueeWidth = ((e.clientX - boundingRect.left) * (this._mainCont.current.offsetWidth / boundingRect.width)) - this._startX; this._marqueeHeight = ((e.clientY - boundingRect.top) * (this._mainCont.current.offsetHeight / boundingRect.height)) - this._startY + this._mainCont.current.scrollTop; this._marqueeX = Math.min(this._startX, this._startX + this._marqueeWidth); @@ -460,16 +460,16 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument @action createTextAnnotation = (sel: Selection, selRange: Range) => { if (this._mainCont.current) { - let boundingRect = this._mainCont.current.getBoundingClientRect(); - let clientRects = selRange.getClientRects(); + const boundingRect = this._mainCont.current.getBoundingClientRect(); + const clientRects = selRange.getClientRects(); for (let i = 0; i < clientRects.length; i++) { - let rect = clientRects.item(i); + const rect = clientRects.item(i); if (rect) { - let scaleY = this._mainCont.current.offsetHeight / boundingRect.height; - let scaleX = this._mainCont.current.offsetWidth / boundingRect.width; + const scaleY = this._mainCont.current.offsetHeight / boundingRect.height; + const scaleX = this._mainCont.current.offsetWidth / boundingRect.width; if (rect.width !== this._mainCont.current.clientWidth && (i === 0 || !intersectRect(clientRects[i], clientRects[i - 1]))) { - let annoBox = document.createElement("div"); + const annoBox = document.createElement("div"); annoBox.className = "pdfViewer-annotationBox"; // transforms the positions from screen onto the pdf div annoBox.style.top = ((rect.top - boundingRect.top) * scaleY / this._zoomed + this._mainCont.current.scrollTop).toString(); @@ -497,10 +497,10 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument this._savedAnnotations.clear(); if (this._marqueeing) { if (this._marqueeWidth > 10 || this._marqueeHeight > 10) { - let marquees = this._mainCont.current!.getElementsByClassName("pdfViewer-dragAnnotationBox"); + const marquees = this._mainCont.current!.getElementsByClassName("pdfViewer-dragAnnotationBox"); if (marquees && marquees.length) { // copy the marquee and convert it to a permanent annotation. - let style = (marquees[0] as HTMLDivElement).style; - let copy = document.createElement("div"); + const style = (marquees[0] as HTMLDivElement).style; + const copy = document.createElement("div"); copy.style.left = style.left; copy.style.top = style.top; copy.style.width = style.width; @@ -521,9 +521,9 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument this._marqueeing = false; } else { - let sel = window.getSelection(); + const sel = window.getSelection(); if (sel && sel.type === "Range") { - let selRange = sel.getRangeAt(0); + const selRange = sel.getRangeAt(0); this.createTextAnnotation(sel, selRange); PDFMenu.Instance.jumpTo(e.clientX, e.clientY); } @@ -543,7 +543,7 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument @action highlight = (color: string) => { // creates annotation documents for current highlights - let annotationDoc = this.makeAnnotationDocument(color); + const annotationDoc = this.makeAnnotationDocument(color); annotationDoc && this.props.addDocument && this.props.addDocument(annotationDoc); return annotationDoc; } @@ -556,10 +556,10 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument startDrag = (e: PointerEvent, ele: HTMLElement): void => { e.preventDefault(); e.stopPropagation(); - let targetDoc = Docs.Create.TextDocument({ width: 200, height: 200, title: "Note linked to " + this.props.Document.title }); + const targetDoc = Docs.Create.TextDocument({ width: 200, height: 200, title: "Note linked to " + this.props.Document.title }); const annotationDoc = this.highlight("rgba(146, 245, 95, 0.467)"); // yellowish highlight color when dragging out a text selection if (annotationDoc) { - let dragData = new DragManager.AnnotationDragData(this.props.Document, annotationDoc, targetDoc); + const dragData = new DragManager.AnnotationDragData(this.props.Document, annotationDoc, targetDoc); DragManager.StartAnnotationDrag([ele], dragData, e.pageX, e.pageY, { handlers: { dragComplete: () => !(dragData as any).linkedToDoc && @@ -572,8 +572,8 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument } createSnippet = (marquee: { left: number, top: number, width: number, height: number }): void => { - let view = Doc.MakeAlias(this.props.Document); - let data = Doc.MakeDelegate(Doc.GetProto(this.props.Document)); + const view = Doc.MakeAlias(this.props.Document); + const data = Doc.MakeDelegate(Doc.GetProto(this.props.Document)); data.title = StrCast(data.title) + "_snippet"; view.proto = data; view.nativeHeight = marquee.height; @@ -605,8 +605,8 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument this.Document.nativeHeight = nativeWidth * this._coverPath.height / this._coverPath.width; }).bind(this), 0); } - let nativeWidth = (this.Document.nativeWidth || 0); - let nativeHeight = (this.Document.nativeHeight || 0); + const nativeWidth = (this.Document.nativeWidth || 0); + const nativeHeight = (this.Document.nativeHeight || 0); return <img key={this._coverPath.path} src={this._coverPath.path} onError={action(() => this._coverPath.path = "http://www.cs.brown.edu/~bcz/face.gif")} onLoad={action(() => this._showWaiting = false)} style={{ position: "absolute", display: "inline-block", top: 0, left: 0, width: `${nativeWidth}px`, height: `${nativeHeight}px` }} />; } @@ -615,7 +615,7 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument onZoomWheel = (e: React.WheelEvent) => { e.stopPropagation(); if (e.ctrlKey) { - let curScale = Number(this._pdfViewer.currentScaleValue); + const curScale = Number(this._pdfViewer.currentScaleValue); this._pdfViewer.currentScaleValue = Math.max(1, Math.min(10, curScale - curScale * e.deltaY / 1000)); this._zoomed = Number(this._pdfViewer.currentScaleValue); } diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index f50a3a0ef..47f876ac2 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -161,9 +161,9 @@ export class PresElementBox extends DocComponent<FieldViewProps, PresDocument>(P return (null); } - let propDocWidth = NumCast(this.layoutDoc.nativeWidth); - let propDocHeight = NumCast(this.layoutDoc.nativeHeight); - let scale = () => 175 / NumCast(this.layoutDoc.nativeWidth, 175); + const propDocWidth = NumCast(this.layoutDoc.nativeWidth); + const propDocHeight = NumCast(this.layoutDoc.nativeHeight); + const scale = () => 175 / NumCast(this.layoutDoc.nativeWidth, 175); return ( <div className="presElementBox-embedded" style={{ height: propDocHeight === 0 ? NumCast(this.layoutDoc.height) - NumCast(this.layoutDoc.collapsedHeight) : propDocHeight * scale(), @@ -193,9 +193,9 @@ export class PresElementBox extends DocComponent<FieldViewProps, PresDocument>(P } render() { - let treecontainer = this.props.ContainingCollectionDoc && this.props.ContainingCollectionDoc.viewType === CollectionViewType.Tree; - let className = "presElementBox-item" + (this.currentIndex === this.indexInPres ? " presElementBox-selected" : ""); - let pbi = "presElementBox-interaction"; + const treecontainer = this.props.ContainingCollectionDoc && this.props.ContainingCollectionDoc.viewType === CollectionViewType.Tree; + const className = "presElementBox-item" + (this.currentIndex === this.indexInPres ? " presElementBox-selected" : ""); + const pbi = "presElementBox-interaction"; return ( <div className={className} key={this.props.Document[Id] + this.indexInPres} style={{ outlineWidth: Doc.IsBrushed(this.targetDoc) ? `1px` : "0px", }} diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index 7812c9d97..12e1bc265 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -79,7 +79,7 @@ export class FilterBox extends React.Component { acc[i].addEventListener("click", function (this: HTMLElement) { this.classList.toggle("active"); - var panel = this.nextElementSibling as HTMLElement; + const panel = this.nextElementSibling as HTMLElement; if (panel.style.maxHeight) { panel.style.overflow = "hidden"; panel.style.maxHeight = ""; @@ -96,7 +96,7 @@ export class FilterBox extends React.Component { } }); - let el = acc[i] as HTMLElement; + const el = acc[i] as HTMLElement; el.click(); } }); @@ -105,14 +105,14 @@ export class FilterBox extends React.Component { @action.bound minimizeAll() { $('document').ready(function () { - var acc = document.getElementsByClassName('filter-header'); + const acc = document.getElementsByClassName('filter-header'); // tslint:disable-next-line: prefer-for-of for (var i = 0; i < acc.length; i++) { - let classList = acc[i].classList; + const classList = acc[i].classList; if (classList.contains("active")) { acc[i].classList.toggle("active"); - var panel = acc[i].nextElementSibling as HTMLElement; + const panel = acc[i].nextElementSibling as HTMLElement; panel.style.overflow = "hidden"; panel.style.maxHeight = ""; } @@ -128,10 +128,10 @@ export class FilterBox extends React.Component { } basicRequireWords(query: string): string { - let oldWords = query.split(" "); - let newWords: string[] = []; + const oldWords = query.split(" "); + const newWords: string[] = []; oldWords.forEach(word => { - let newWrd = "+" + word; + const newWrd = "+" + word; newWords.push(newWrd); }); query = newWords.join(" "); @@ -140,7 +140,7 @@ export class FilterBox extends React.Component { } basicFieldFilters(query: string, type: string): string { - let oldWords = query.split(" "); + const oldWords = query.split(" "); let mod = ""; if (type === Keys.AUTHOR) { @@ -151,9 +151,9 @@ export class FilterBox extends React.Component { mod = " title_t:"; } - let newWords: string[] = []; + const newWords: string[] = []; oldWords.forEach(word => { - let newWrd = mod + word; + const newWrd = mod + word; newWords.push(newWrd); }); @@ -183,11 +183,11 @@ export class FilterBox extends React.Component { //gets all of the collections of all the docviews that are selected //if a collection is the only thing selected, search only in that collection (not its container) getCurCollections(): Doc[] { - let selectedDocs: DocumentView[] = SelectionManager.SelectedDocuments(); - let collections: Doc[] = []; + const selectedDocs: DocumentView[] = SelectionManager.SelectedDocuments(); + const collections: Doc[] = []; selectedDocs.forEach(async element => { - let layout: string = StrCast(element.props.Document.layout); + const layout: string = StrCast(element.props.Document.layout); //checks if selected view (element) is a collection. if it is, adds to list to search through if (layout.indexOf("Collection") > -1) { //makes sure collections aren't added more than once @@ -229,14 +229,14 @@ export class FilterBox extends React.Component { } addCollectionFilter(query: string): string { - let collections: Doc[] = this.getCurCollections(); - let oldWords = query.split(" "); + const collections: Doc[] = this.getCurCollections(); + const oldWords = query.split(" "); - let collectionString: string[] = []; + const collectionString: string[] = []; collections.forEach(doc => { - let proto = doc.proto; - let protoId = (proto || doc)[Id]; - let colString: string = "{!join from=data_l to=id}id:" + protoId + " "; + const proto = doc.proto; + const protoId = (proto || doc)[Id]; + const colString: string = "{!join from=data_l to=id}id:" + protoId + " "; collectionString.push(colString); }); @@ -254,9 +254,9 @@ export class FilterBox extends React.Component { if (this._icons.length === 9) { return docs; } - let finalDocs: Doc[] = []; + const finalDocs: Doc[] = []; docs.forEach(doc => { - let layoutresult = Cast(doc.type, "string"); + const layoutresult = Cast(doc.type, "string"); if (layoutresult && this._icons.includes(layoutresult)) { finalDocs.push(doc); } diff --git a/src/client/views/search/IconButton.tsx b/src/client/views/search/IconButton.tsx index d2cfe7fad..f01508141 100644 --- a/src/client/views/search/IconButton.tsx +++ b/src/client/views/search/IconButton.tsx @@ -108,7 +108,7 @@ export class IconButton extends React.Component<IconButtonProps>{ @action.bound onClick = () => { - let newList: string[] = FilterBox.Instance.getIcons(); + const newList: string[] = FilterBox.Instance.getIcons(); if (!this._isSelected) { this._isSelected = true; diff --git a/src/client/views/search/NaviconButton.tsx b/src/client/views/search/NaviconButton.tsx index 3fa36b163..0fa4a0fca 100644 --- a/src/client/views/search/NaviconButton.tsx +++ b/src/client/views/search/NaviconButton.tsx @@ -4,7 +4,7 @@ import "./NaviconButton.scss"; import * as $ from 'jquery'; import { observable } from 'mobx'; -export interface NaviconProps{ +export interface NaviconProps { onClick(): void; } @@ -13,19 +13,21 @@ export class NaviconButton extends React.Component<NaviconProps> { @observable private _ref: React.RefObject<HTMLAnchorElement> = React.createRef(); componentDidMount = () => { - let that = this; - if(this._ref.current){this._ref.current.addEventListener("click", function(e) { - e.preventDefault(); - if(that._ref.current){ - that._ref.current.classList.toggle('active'); - return false; - } - });} + const that = this; + if (this._ref.current) { + this._ref.current.addEventListener("click", function (e) { + e.preventDefault(); + if (that._ref.current) { + that._ref.current.classList.toggle('active'); + return false; + } + }); + } } render() { return ( - <a id="hamburger-icon" href="#" ref = {this._ref} title="Menu"> + <a id="hamburger-icon" href="#" ref={this._ref} title="Menu"> <span className="line line-1"></span> <span className="line line-2"></span> <span className="line line-3"></span> diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index ff35542ed..c45fbe210 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -89,7 +89,7 @@ export class SearchBox extends React.Component { public static async convertDataUri(imageUri: string, returnedFilename: string) { try { - let posting = Utils.prepend("/uploadURI"); + const posting = Utils.prepend("/uploadURI"); const returnedUri = await rp.post(posting, { body: { uri: imageUri, @@ -166,7 +166,7 @@ export class SearchBox extends React.Component { const docs = await Promise.all(res.docs.map(async doc => (await Cast(doc.extendsDoc, Doc)) || doc)); const highlights: typeof res.highlighting = {}; docs.forEach((doc, index) => highlights[doc[Id]] = highlightList[index]); - let filteredDocs = FilterBox.Instance.filterDocsByType(docs); + const filteredDocs = FilterBox.Instance.filterDocsByType(docs); runInAction(() => { // this._results.push(...filteredDocs); filteredDocs.forEach(doc => { @@ -198,8 +198,8 @@ export class SearchBox extends React.Component { collectionRef = React.createRef<HTMLSpanElement>(); startDragCollection = async () => { - let res = await this.getAllResults(FilterBox.Instance.getFinalQuery(this._searchString)); - let filtered = FilterBox.Instance.filterDocsByType(res.docs); + const res = await this.getAllResults(FilterBox.Instance.getFinalQuery(this._searchString)); + const filtered = FilterBox.Instance.filterDocsByType(res.docs); // console.log(this._results) const docs = filtered.map(doc => { const isProto = Doc.GetT(doc, "isPrototype", "boolean", true); @@ -266,10 +266,10 @@ export class SearchBox extends React.Component { @action resultsScrolled = (e?: React.UIEvent<HTMLDivElement>) => { - let scrollY = e ? e.currentTarget.scrollTop : this.resultsRef.current ? this.resultsRef.current.scrollTop : 0; - let itemHght = 53; - let startIndex = Math.floor(Math.max(0, scrollY / itemHght)); - let endIndex = Math.ceil(Math.min(this._numTotalResults - 1, startIndex + (this.resultsRef.current!.getBoundingClientRect().height / itemHght))); + const scrollY = e ? e.currentTarget.scrollTop : this.resultsRef.current ? this.resultsRef.current.scrollTop : 0; + const itemHght = 53; + const startIndex = Math.floor(Math.max(0, scrollY / itemHght)); + const endIndex = Math.ceil(Math.min(this._numTotalResults - 1, startIndex + (this.resultsRef.current!.getBoundingClientRect().height / itemHght))); this._endIndex = endIndex === -1 ? 12 : endIndex; @@ -307,7 +307,7 @@ export class SearchBox extends React.Component { this.getResults(this._searchString); if (i < this._results.length) result = this._results[i]; if (result) { - let highlights = Array.from([...Array.from(new Set(result[1]).values())]).filter(v => v !== "search_string"); + const highlights = Array.from([...Array.from(new Set(result[1]).values())]).filter(v => v !== "search_string"); this._visibleElements[i] = <SearchItem doc={result[0]} query={this._searchString} key={result[0][Id]} lines={result[2]} highlighting={highlights} />; this._isSearch[i] = "search"; } @@ -315,7 +315,7 @@ export class SearchBox extends React.Component { else { result = this._results[i]; if (result) { - let highlights = Array.from([...Array.from(new Set(result[1]).values())]).filter(v => v !== "search_string"); + const highlights = Array.from([...Array.from(new Set(result[1]).values())]).filter(v => v !== "search_string"); this._visibleElements[i] = <SearchItem doc={result[0]} query={this._searchString} key={result[0][Id]} lines={result[2]} highlighting={highlights} />; this._isSearch[i] = "search"; } diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index f1d825aa0..6ffff0562 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -52,7 +52,7 @@ export class SelectorContextMenu extends React.Component<SearchItemProps> { } async fetchDocuments() { - let aliases = (await SearchUtil.GetViewsOfDocument(this.props.doc)).filter(doc => doc !== this.props.doc); + const aliases = (await SearchUtil.GetViewsOfDocument(this.props.doc)).filter(doc => doc !== this.props.doc); const { docs } = await SearchUtil.Search("", true, { fq: `data_l:"${this.props.doc[Id]}"` }); const map: Map<Doc, Doc> = new Map; const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", true, { fq: `data_l:"${doc[Id]}"` }).then(result => result.docs))); @@ -82,7 +82,7 @@ export class SelectorContextMenu extends React.Component<SearchItemProps> { <div className="parents"> <p className="contexts">Contexts:</p> {[...this._docs, ...this._otherDocs].map(doc => { - let item = React.createRef<HTMLDivElement>(); + const item = React.createRef<HTMLDivElement>(); return <div className="collection" key={doc.col[Id] + doc.target[Id]} ref={item}> <div className="collection-item" onPointerDown={ SetupDrag(item, () => doc.col, undefined, undefined, undefined, undefined, () => SearchBox.Instance.closeSearch())}> @@ -146,11 +146,11 @@ export class SearchItem extends React.Component<SearchItemProps> { //@computed @action public DocumentIcon() { - let layoutresult = StrCast(this.props.doc.type); + const layoutresult = StrCast(this.props.doc.type); if (!this._useIcons) { - let returnXDimension = () => this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE); - let returnYDimension = () => this._displayDim; - let scale = () => returnXDimension() / NumCast(Doc.Layout(this.props.doc).nativeWidth, returnXDimension()); + const returnXDimension = () => this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE); + const returnYDimension = () => this._displayDim; + const scale = () => returnXDimension() / NumCast(Doc.Layout(this.props.doc).nativeWidth, returnXDimension()); const docview = <div onPointerDown={action(() => { this._useIcons = !this._useIcons; @@ -184,7 +184,7 @@ export class SearchItem extends React.Component<SearchItemProps> { </div>; return docview; } - let button = layoutresult.indexOf(DocumentType.PDF) !== -1 ? faFilePdf : + const button = layoutresult.indexOf(DocumentType.PDF) !== -1 ? faFilePdf : layoutresult.indexOf(DocumentType.IMG) !== -1 ? faImage : layoutresult.indexOf(DocumentType.TEXT) !== -1 ? faStickyNote : layoutresult.indexOf(DocumentType.VID) !== -1 ? faFilm : @@ -201,7 +201,7 @@ export class SearchItem extends React.Component<SearchItemProps> { collectionRef = React.createRef<HTMLDivElement>(); startDocDrag = () => { - let doc = this.props.doc; + const doc = this.props.doc; const isProto = Doc.GetT(doc, "isPrototype", "boolean", true); if (isProto) { return Doc.MakeDelegate(doc); @@ -218,7 +218,7 @@ export class SearchItem extends React.Component<SearchItemProps> { nextHighlight = (e: React.PointerEvent) => { e.preventDefault(); e.button === 0 && SearchBox.Instance.openSearch(e); - let sstring = StrCast(this.props.doc.search_string); + const sstring = StrCast(this.props.doc.search_string); this.props.doc.search_string = ""; setTimeout(() => this.props.doc.search_string = sstring, 0); } @@ -226,8 +226,8 @@ export class SearchItem extends React.Component<SearchItemProps> { if (this.props.doc.type === DocumentType.LINK) { if (this.props.doc.anchor1 && this.props.doc.anchor2) { - let doc1 = Cast(this.props.doc.anchor1, Doc, null); - let doc2 = Cast(this.props.doc.anchor2, Doc, null); + const doc1 = Cast(this.props.doc.anchor1, Doc, null); + const doc2 = Cast(this.props.doc.anchor2, Doc, null); Doc.BrushDoc(doc1); Doc.BrushDoc(doc2); } @@ -241,8 +241,8 @@ export class SearchItem extends React.Component<SearchItemProps> { if (this.props.doc.type === DocumentType.LINK) { if (this.props.doc.anchor1 && this.props.doc.anchor2) { - let doc1 = Cast(this.props.doc.anchor1, Doc, null); - let doc2 = Cast(this.props.doc.anchor2, Doc, null); + const doc1 = Cast(this.props.doc.anchor1, Doc, null); + const doc2 = Cast(this.props.doc.anchor2, Doc, null); Doc.UnBrushDoc(doc1); Doc.UnBrushDoc(doc2); } diff --git a/src/client/views/search/ToggleBar.tsx b/src/client/views/search/ToggleBar.tsx index ed5ecd3ba..e4d7f2fd5 100644 --- a/src/client/views/search/ToggleBar.tsx +++ b/src/client/views/search/ToggleBar.tsx @@ -33,8 +33,7 @@ export class ToggleBar extends React.Component<ToggleBarProps>{ } componentDidMount = () => { - - let totalWidth = 265; + const totalWidth = 265; if (this._originalStatus) { this._forwardTimeline.add({ diff --git a/src/debug/Viewer.tsx b/src/debug/Viewer.tsx index 24db3f934..a26d2e06a 100644 --- a/src/debug/Viewer.tsx +++ b/src/debug/Viewer.tsx @@ -24,7 +24,7 @@ CursorField; function applyToDoc(doc: { [index: string]: FieldResult }, key: string, scriptString: string): boolean; function applyToDoc(doc: { [index: number]: FieldResult }, key: number, scriptString: string): boolean; function applyToDoc(doc: any, key: string | number, scriptString: string): boolean { - let script = CompileScript(scriptString, { addReturn: true, params: { this: doc instanceof Doc ? Doc.name : List.name } }); + const script = CompileScript(scriptString, { addReturn: true, params: { this: doc instanceof Doc ? Doc.name : List.name } }); if (!script.compiled) { return false; } @@ -85,7 +85,7 @@ class DocumentViewer extends React.Component<{ field: Doc }> { let content; if (this.expanded) { const keys = Object.keys(this.props.field); - let fields = keys.map(key => { + const fields = keys.map(key => { return ( <div key={key}> <b>({key}): </b> diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index 9fdaac66e..ec698b151 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -34,13 +34,13 @@ class Uploader extends React.Component { try { this.status = "initializing protos"; await Docs.Prototypes.initialize(); - let imgPrev = document.getElementById("img_preview"); + const imgPrev = document.getElementById("img_preview"); if (imgPrev) { - let files: FileList | null = inputRef.current!.files; + const files: FileList | null = inputRef.current!.files; if (files && files.length !== 0) { console.log(files[0]); const name = files[0].name; - let formData = new FormData(); + const formData = new FormData(); formData.append("file", files[0]); const upload = window.location.origin + "/upload"; @@ -52,8 +52,8 @@ class Uploader extends React.Component { this.status = "upload image, getting json"; const json = await res.json(); json.map(async (file: any) => { - let path = window.location.origin + file; - var doc = Docs.Create.ImageDocument(path, { nativeWidth: 200, width: 200, title: name }); + const path = window.location.origin + file; + const doc = Docs.Create.ImageDocument(path, { nativeWidth: 200, width: 200, title: name }); this.status = "getting user document"; diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index a811322d7..cf32fa74a 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -21,7 +21,7 @@ export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { const onDelegate = Object.keys(doc).includes(key); - let field = ComputedField.WithoutComputed(() => FieldValue(doc[key])); + const field = ComputedField.WithoutComputed(() => FieldValue(doc[key])); if (Field.IsField(field)) { return (onDelegate ? "=" : "") + (field instanceof ComputedField ? `:=${field.script.originalScript}` : Field.toScriptString(field)); } @@ -255,9 +255,9 @@ export namespace Doc { return GetT(doc, "isPrototype", "boolean", true); } export async function SetInPlace(doc: Doc, key: string, value: Field | undefined, defaultProto: boolean) { - let hasProto = doc.proto instanceof Doc; - let onDeleg = Object.getOwnPropertyNames(doc).indexOf(key) !== -1; - let onProto = hasProto && Object.getOwnPropertyNames(doc.proto).indexOf(key) !== -1; + const hasProto = doc.proto instanceof Doc; + const onDeleg = Object.getOwnPropertyNames(doc).indexOf(key) !== -1; + const onProto = hasProto && Object.getOwnPropertyNames(doc.proto).indexOf(key) !== -1; if (onDeleg || !hasProto || (!onProto && !defaultProto)) { doc[key] = value; } else doc.proto![key] = value; @@ -306,10 +306,10 @@ export namespace Doc { // compare whether documents or their protos match export function AreProtosEqual(doc?: Doc, other?: Doc) { if (!doc || !other) return false; - let r = (doc === other); - let r2 = (Doc.GetProto(doc) === other); - let r3 = (Doc.GetProto(other) === doc); - let r4 = (Doc.GetProto(doc) === Doc.GetProto(other) && Doc.GetProto(other) !== undefined); + const r = (doc === other); + const r2 = (Doc.GetProto(doc) === other); + const r3 = (Doc.GetProto(other) === doc); + const r4 = (Doc.GetProto(doc) === Doc.GetProto(other) && Doc.GetProto(other) !== undefined); return r || r2 || r3 || r4; } @@ -318,7 +318,7 @@ export namespace Doc { return doc && (Doc.GetT(doc, "isPrototype", "boolean", true) ? doc : (doc.proto || doc)); } export function GetDataDoc(doc: Doc): Doc { - let proto = Doc.GetProto(doc); + const proto = Doc.GetProto(doc); return proto === doc ? proto : Doc.GetDataDoc(proto); } @@ -343,9 +343,9 @@ export namespace Doc { if (listDoc[key] === undefined) { Doc.GetProto(listDoc)[key] = new List<Doc>(); } - let list = Cast(listDoc[key], listSpec(Doc)); + const list = Cast(listDoc[key], listSpec(Doc)); if (list) { - let ind = list.indexOf(doc); + const ind = list.indexOf(doc); if (ind !== -1) { list.splice(ind, 1); return true; @@ -357,10 +357,10 @@ export namespace Doc { if (listDoc[key] === undefined) { Doc.GetProto(listDoc)[key] = new List<Doc>(); } - let list = Cast(listDoc[key], listSpec(Doc)); + const list = Cast(listDoc[key], listSpec(Doc)); if (list) { if (allowDuplicates !== true) { - let pind = list.reduce((l, d, i) => d instanceof Doc && d[Id] === doc[Id] ? i : l, -1); + const pind = list.reduce((l, d, i) => d instanceof Doc && d[Id] === doc[Id] ? i : l, -1); if (pind !== -1) { list.splice(pind, 1); } @@ -369,7 +369,7 @@ export namespace Doc { list.splice(0, 0, doc); } else { - let ind = relativeTo ? list.indexOf(relativeTo) : -1; + const ind = relativeTo ? list.indexOf(relativeTo) : -1; if (ind === -1) { if (reversed) list.splice(0, 0, doc); else list.push(doc); @@ -388,9 +388,9 @@ export namespace Doc { // Computes the bounds of the contents of a set of documents. // export function ComputeContentBounds(docList: Doc[]) { - let bounds = docList.reduce((bounds, doc) => { - var [sptX, sptY] = [NumCast(doc.x), NumCast(doc.y)]; - let [bptX, bptY] = [sptX + doc[WidthSym](), sptY + doc[HeightSym]()]; + const bounds = docList.reduce((bounds, doc) => { + const [sptX, sptY] = [NumCast(doc.x), NumCast(doc.y)]; + const [bptX, bptY] = [sptX + doc[WidthSym](), sptY + doc[HeightSym]()]; return { x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y), r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b) @@ -400,16 +400,16 @@ export namespace Doc { } export function MakeTitled(title: string) { - let doc = new Doc(); + const doc = new Doc(); doc.title = title; return doc; } export function MakeAlias(doc: Doc) { - let alias = !GetT(doc, "isPrototype", "boolean", true) ? Doc.MakeCopy(doc) : Doc.MakeDelegate(doc); + const alias = !GetT(doc, "isPrototype", "boolean", true) ? Doc.MakeCopy(doc) : Doc.MakeDelegate(doc); if (alias.layout instanceof Doc) { alias.layout = Doc.MakeAlias(alias.layout); } - let aliasNumber = Doc.GetProto(doc).aliasNumber = NumCast(Doc.GetProto(doc).aliasNumber) + 1; + const aliasNumber = Doc.GetProto(doc).aliasNumber = NumCast(Doc.GetProto(doc).aliasNumber) + 1; alias.title = ComputedField.MakeFunction(`renameAlias(this, ${aliasNumber})`); return alias; } @@ -437,8 +437,8 @@ export namespace Doc { // ... which means we change the layout to be an expanded view of the template layout. // This allows the view override the template's properties and be referenceable as its own document. - let expandedLayoutFieldKey = "Layout[" + templateLayoutDoc[Id] + "]"; - let expandedTemplateLayout = dataDoc[expandedLayoutFieldKey]; + const expandedLayoutFieldKey = "Layout[" + templateLayoutDoc[Id] + "]"; + const expandedTemplateLayout = dataDoc[expandedLayoutFieldKey]; if (expandedTemplateLayout instanceof Doc) { return expandedTemplateLayout; } @@ -451,9 +451,9 @@ export namespace Doc { export function GetLayoutDataDocPair(doc: Doc, dataDoc: Doc | undefined, fieldKey: string, childDocLayout: Doc) { let layoutDoc: Doc | undefined = childDocLayout; - let resolvedDataDoc = !doc.isTemplateField && dataDoc !== doc && dataDoc ? Doc.GetDataDoc(dataDoc) : undefined; + const resolvedDataDoc = !doc.isTemplateField && dataDoc !== doc && dataDoc ? Doc.GetDataDoc(dataDoc) : undefined; if (resolvedDataDoc && Doc.WillExpandTemplateLayout(childDocLayout, resolvedDataDoc)) { - let extensionDoc = fieldExtensionDoc(resolvedDataDoc, StrCast(childDocLayout.templateField, StrCast(childDocLayout.title))); + const extensionDoc = fieldExtensionDoc(resolvedDataDoc, StrCast(childDocLayout.templateField, StrCast(childDocLayout.title))); layoutDoc = Doc.expandTemplateLayout(childDocLayout, extensionDoc !== resolvedDataDoc ? extensionDoc : undefined); } else layoutDoc = childDocLayout; return { layout: layoutDoc, data: resolvedDataDoc }; @@ -467,13 +467,13 @@ export namespace Doc { // to store annotations, ink, and other data. // export function fieldExtensionDoc(doc: Doc, fieldKey: string) { - let extension = doc[fieldKey + "_ext"] as Doc; + const extension = doc[fieldKey + "_ext"] as Doc; (extension === undefined) && setTimeout(() => CreateDocumentExtensionForField(doc, fieldKey), 0); return extension ? extension : undefined; } export function CreateDocumentExtensionForField(doc: Doc, fieldKey: string) { - let docExtensionForField = new Doc(doc[Id] + fieldKey, true); + const docExtensionForField = new Doc(doc[Id] + fieldKey, true); docExtensionForField.title = fieldKey + ".ext"; // courtesy field--- shouldn't be needed except maybe for debugging docExtensionForField.extendsDoc = doc; // this is used by search to map field matches on the extension doc back to the document it extends. docExtensionForField.extendsField = fieldKey; // this can be used by search to map matches on the extension doc back to the field that was extended. @@ -512,7 +512,7 @@ export namespace Doc { export function MakeCopy(doc: Doc, copyProto: boolean = false, copyProtoId?: string): Doc { const copy = new Doc(copyProtoId, true); Object.keys(doc).forEach(key => { - let cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key])); + const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key])); const field = ProxyField.WithoutProxy(() => doc[key]); if (key === "proto" && copyProto) { if (doc[key] instanceof Doc) { @@ -551,7 +551,7 @@ export namespace Doc { let _applyCount: number = 0; export function ApplyTemplate(templateDoc: Doc) { if (templateDoc) { - let applied = ApplyTemplateTo(templateDoc, Doc.MakeDelegate(new Doc()), "layoutCustom", templateDoc.title + "(..." + _applyCount++ + ")"); + const applied = ApplyTemplateTo(templateDoc, Doc.MakeDelegate(new Doc()), "layoutCustom", templateDoc.title + "(..." + _applyCount++ + ")"); applied && (Doc.GetProto(applied).layout = applied.layout); return applied; } @@ -567,7 +567,7 @@ export namespace Doc { return; } - let layoutCustomLayout = Doc.MakeDelegate(templateDoc); + const layoutCustomLayout = Doc.MakeDelegate(templateDoc); titleTarget && (Doc.GetProto(target).title = titleTarget); Doc.GetProto(target).type = DocumentType.TEMPLATE; @@ -580,7 +580,7 @@ export namespace Doc { export function MakeMetadataFieldTemplate(fieldTemplate: Doc, templateDataDoc: Doc, suppressTitle: boolean = false): boolean { // move data doc fields to layout doc as needed (nativeWidth/nativeHeight, data, ??) - let metadataFieldName = StrCast(fieldTemplate.title).replace(/^-/, ""); + const metadataFieldName = StrCast(fieldTemplate.title).replace(/^-/, ""); let fieldLayoutDoc = fieldTemplate; if (fieldTemplate.layout instanceof Doc) { fieldLayoutDoc = Doc.MakeDelegate(fieldTemplate.layout); @@ -601,11 +601,11 @@ export namespace Doc { fieldTemplate.panY = 0; fieldTemplate.scale = 1; fieldTemplate.showTitle = suppressTitle ? undefined : "title"; - let data = fieldTemplate.data; + const data = fieldTemplate.data; // setTimeout(action(() => { !templateDataDoc[metadataFieldName] && data instanceof ObjectField && (Doc.GetProto(templateDataDoc)[metadataFieldName] = ObjectField.MakeCopy(data)); - let layout = StrCast(fieldLayoutDoc.layout).replace(/fieldKey={"[^"]*"}/, `fieldKey={"${metadataFieldName}"}`); - let layoutDelegate = Doc.Layout(fieldTemplate); + const layout = StrCast(fieldLayoutDoc.layout).replace(/fieldKey={"[^"]*"}/, `fieldKey={"${metadataFieldName}"}`); + const layoutDelegate = Doc.Layout(fieldTemplate); layoutDelegate.layout = layout; fieldTemplate.layout = layoutDelegate !== fieldTemplate ? layoutDelegate : layout; if (fieldTemplate.backgroundColor !== templateDataDoc.defaultBackgroundColor) fieldTemplate.defaultBackgroundColor = fieldTemplate.backgroundColor; @@ -615,16 +615,16 @@ export namespace Doc { } export function overlapping(doc1: Doc, doc2: Doc, clusterDistance: number) { - let doc2Layout = Doc.Layout(doc2); - let doc1Layout = Doc.Layout(doc1); - var x2 = NumCast(doc2.x) - clusterDistance; - var y2 = NumCast(doc2.y) - clusterDistance; - var w2 = NumCast(doc2Layout.width) + clusterDistance; - var h2 = NumCast(doc2Layout.height) + clusterDistance; - var x = NumCast(doc1.x) - clusterDistance; - var y = NumCast(doc1.y) - clusterDistance; - var w = NumCast(doc1Layout.width) + clusterDistance; - var h = NumCast(doc1Layout.height) + clusterDistance; + const doc2Layout = Doc.Layout(doc2); + const doc1Layout = Doc.Layout(doc1); + const x2 = NumCast(doc2.x) - clusterDistance; + const y2 = NumCast(doc2.y) - clusterDistance; + const w2 = NumCast(doc2Layout.width) + clusterDistance; + const h2 = NumCast(doc2Layout.height) + clusterDistance; + const x = NumCast(doc1.x) - clusterDistance; + const y = NumCast(doc1.y) - clusterDistance; + const w = NumCast(doc1Layout.width) + clusterDistance; + const h = NumCast(doc1Layout.height) + clusterDistance; return doc1.z === doc2.z && intersectRect({ left: x, top: y, width: w, height: h }, { left: x2, top: y2, width: w2, height: h2 }); } @@ -691,7 +691,7 @@ export namespace Doc { Doc.HighlightDoc(destDoc); document.removeEventListener("pointerdown", linkFollowUnhighlight); document.addEventListener("pointerdown", linkFollowUnhighlight); - let x = dt = Date.now(); + const x = dt = Date.now(); window.setTimeout(() => dt === x && linkFollowUnhighlight(), 5000); } @@ -700,7 +700,7 @@ export namespace Doc { } const highlightManager = new HighlightBrush(); export function IsHighlighted(doc: Doc) { - let IsHighlighted = highlightManager.HighlightedDoc.get(doc) || highlightManager.HighlightedDoc.get(Doc.GetDataDoc(doc)); + const IsHighlighted = highlightManager.HighlightedDoc.get(doc) || highlightManager.HighlightedDoc.get(Doc.GetDataDoc(doc)); return IsHighlighted; } export function HighlightDoc(doc: Doc) { @@ -716,10 +716,10 @@ export namespace Doc { }); } export function UnhighlightAll() { - let mapEntries = highlightManager.HighlightedDoc.keys(); + const mapEntries = highlightManager.HighlightedDoc.keys(); let docEntry: IteratorResult<Doc>; while (!(docEntry = mapEntries.next()).done) { - let targetDoc = docEntry.value; + const targetDoc = docEntry.value; targetDoc && Doc.UnHighlightDoc(targetDoc); } diff --git a/src/new_fields/List.ts b/src/new_fields/List.ts index 0c7b77fa5..e9101158b 100644 --- a/src/new_fields/List.ts +++ b/src/new_fields/List.ts @@ -270,8 +270,8 @@ class ListImpl<T extends Field> extends ObjectField { } [Copy]() { - let copiedData = this[Self].__fields.map(f => f instanceof ObjectField ? f[Copy]() : f); - let deepCopy = new ListImpl<T>(copiedData as any); + const copiedData = this[Self].__fields.map(f => f instanceof ObjectField ? f[Copy]() : f); + const deepCopy = new ListImpl<T>(copiedData as any); return deepCopy; } diff --git a/src/new_fields/RichTextUtils.ts b/src/new_fields/RichTextUtils.ts index dc5574782..682206aa2 100644 --- a/src/new_fields/RichTextUtils.ts +++ b/src/new_fields/RichTextUtils.ts @@ -25,8 +25,8 @@ export namespace RichTextUtils { export const Initialize = (initial?: string) => { - let content: any[] = []; - let state = { + const content: any[] = []; + const state = { doc: { type: "doc", content, @@ -56,32 +56,32 @@ export namespace RichTextUtils { export const ToPlainText = (state: EditorState) => { // Because we're working with plain text, just concatenate all paragraphs - let content = state.doc.content; - let paragraphs: Node<any>[] = []; + const content = state.doc.content; + const paragraphs: Node<any>[] = []; content.forEach(node => node.type.name === "paragraph" && paragraphs.push(node)); // Functions to flatten ProseMirror paragraph objects (and their components) to plain text // Concatentate paragraphs and string the result together - let textParagraphs: string[] = paragraphs.map(paragraph => { - let text: string[] = []; + const textParagraphs: string[] = paragraphs.map(paragraph => { + const text: string[] = []; paragraph.content.forEach(node => node.text && text.push(node.text)); return text.join(joiner) + delimiter; }); - let plainText = textParagraphs.join(joiner); + const plainText = textParagraphs.join(joiner); return plainText.substring(0, plainText.length - 1); }; export const ToProsemirrorState = (plainText: string, oldState?: RichTextField) => { // Remap the text, creating blocks split on newlines - let elements = plainText.split(delimiter); + const elements = plainText.split(delimiter); // Google Docs adds in an extra carriage return automatically, so this counteracts it !elements[elements.length - 1].length && elements.pop(); // Preserve the current state, but re-write the content to be the blocks - let parsed = JSON.parse(oldState ? oldState.Data : Initialize()); + const parsed = JSON.parse(oldState ? oldState.Data : Initialize()); parsed.doc.content = elements.map(text => { - let paragraph: any = { type: "paragraph" }; + const paragraph: any = { type: "paragraph" }; text.length && (paragraph.content = [{ type: "text", marks: [], text }]); // An empty paragraph gets treated as a line break return paragraph; }); @@ -97,7 +97,7 @@ export namespace RichTextUtils { export const Export = async (state: EditorState): Promise<GoogleApiClientUtils.Docs.Content> => { const nodes: (Node<any> | null)[] = []; - let text = ToPlainText(state); + const text = ToPlainText(state); state.doc.content.forEach(node => { if (!node.childCount) { nodes.push(null); @@ -168,20 +168,20 @@ export namespace RichTextUtils { const title = document.title!; const { text, paragraphs } = GoogleApiClientUtils.Docs.Utils.extractText(document); let state = FormattedTextBox.blankState(); - let structured = parseLists(paragraphs); + const structured = parseLists(paragraphs); let position = 3; - let lists: ListGroup[] = []; + const lists: ListGroup[] = []; const indentMap = new Map<ListGroup, BulletPosition[]>(); let globalOffset = 0; const nodes: Node<any>[] = []; - for (let element of structured) { + for (const element of structured) { if (Array.isArray(element)) { lists.push(element); - let positions: BulletPosition[] = []; - let items = element.map(paragraph => { - let item = listItem(state.schema, paragraph.contents); - let sinks = paragraph.bullet!; + const positions: BulletPosition[] = []; + const items = element.map(paragraph => { + const item = listItem(state.schema, paragraph.contents); + const sinks = paragraph.bullet!; positions.push({ value: position + globalOffset, sinks @@ -208,7 +208,7 @@ export namespace RichTextUtils { } }); } else { - let paragraph = paragraphNode(state.schema, element.contents); + const paragraph = paragraphNode(state.schema, element.contents); nodes.push(paragraph); position += paragraph.nodeSize; } @@ -216,11 +216,11 @@ export namespace RichTextUtils { } state = state.apply(state.tr.replaceWith(0, 2, nodes)); - let sink = sinkListItem(state.schema.nodes.list_item); - let dispatcher = (tr: Transaction) => state = state.apply(tr); - for (let list of lists) { - for (let pos of indentMap.get(list)!) { - let resolved = state.doc.resolve(pos.value); + const sink = sinkListItem(state.schema.nodes.list_item); + const dispatcher = (tr: Transaction) => state = state.apply(tr); + for (const list of lists) { + for (const pos of indentMap.get(list)!) { + const resolved = state.doc.resolve(pos.value); state = state.apply(state.tr.setSelection(new TextSelection(resolved))); for (let i = 0; i < pos.sinks; i++) { sink(state, dispatcher); @@ -236,9 +236,9 @@ export namespace RichTextUtils { type PreparedParagraphs = (ListGroup | Paragraph)[]; const parseLists = (paragraphs: ListGroup) => { - let groups: PreparedParagraphs = []; + const groups: PreparedParagraphs = []; let group: ListGroup = []; - for (let paragraph of paragraphs) { + for (const paragraph of paragraphs) { if (paragraph.bullet !== undefined) { group.push(paragraph); } else { @@ -262,8 +262,8 @@ export namespace RichTextUtils { }; const paragraphNode = (schema: any, runs: docs_v1.Schema$TextRun[]): Node => { - let children = runs.map(run => textNode(schema, run)).filter(child => child !== undefined); - let fragment = children.length ? Fragment.from(children) : undefined; + const children = runs.map(run => textNode(schema, run)).filter(child => child !== undefined); + const fragment = children.length ? Fragment.from(children) : undefined; return schema.node("paragraph", null, fragment); }; @@ -284,7 +284,7 @@ export namespace RichTextUtils { }; const textNode = (schema: any, run: docs_v1.Schema$TextRun) => { - let text = run.content!.removeTrailingNewlines(); + const text = run.content!.removeTrailingNewlines(); return text.length ? schema.text(text, styleToMarks(schema, run.textStyle)) : undefined; }; @@ -299,17 +299,17 @@ export namespace RichTextUtils { if (!textStyle) { return undefined; } - let marks: Mark[] = []; + const marks: Mark[] = []; Object.keys(textStyle).forEach(key => { let value: any; - let targeted = key as keyof docs_v1.Schema$TextStyle; + const targeted = key as keyof docs_v1.Schema$TextStyle; if (value = textStyle[targeted]) { - let attributes: any = {}; + const attributes: any = {}; let converted = StyleToMark.get(targeted) || targeted; value.url && (attributes.href = value.url); if (value.color) { - let object = value.color.rgbColor; + const object = value.color.rgbColor; attributes.color = Color.rgb(["red", "green", "blue"].map(color => object[color] * 255 || 0)).hex(); } if (value.magnitude) { @@ -320,13 +320,13 @@ export namespace RichTextUtils { converted = ImportFontFamilyMapping.get(value.fontFamily) || "timesNewRoman"; } - let mapped = schema.marks[converted]; + const mapped = schema.marks[converted]; if (!mapped) { alert(`No mapping found for ${converted}!`); return; } - let mark = schema.mark(mapped, attributes); + const mark = schema.mark(mapped, attributes); mark && marks.push(mark); } }); @@ -366,9 +366,9 @@ export namespace RichTextUtils { const ignored = ["user_mark"]; const marksToStyle = async (nodes: (Node<any> | null)[]): Promise<docs_v1.Schema$Request[]> => { - let requests: docs_v1.Schema$Request[] = []; + const requests: docs_v1.Schema$Request[] = []; let position = 1; - for (let node of nodes) { + for (const node of nodes) { if (node === null) { position += 2; continue; @@ -382,7 +382,7 @@ export namespace RichTextUtils { }; let mark: Mark<any>; const markMap = BuildMarkMap(marks); - for (let markName of Object.keys(schema.marks)) { + for (const markName of Object.keys(schema.marks)) { if (ignored.includes(markName) || !(mark = markMap[markName])) { continue; } diff --git a/src/new_fields/Schema.ts b/src/new_fields/Schema.ts index b1a449e08..3f0ff4284 100644 --- a/src/new_fields/Schema.ts +++ b/src/new_fields/Schema.ts @@ -23,7 +23,7 @@ export type makeInterface<T extends Interface[]> = AllToInterface<T> & Doc & { p // export function makeInterface<T extends Interface[], U extends Doc>(schemas: T): (doc: U) => All<T, U>; // export function makeInterface<T extends Interface, U extends Doc>(schema: T): (doc: U) => makeInterface<T, U>; export function makeInterface<T extends Interface[]>(...schemas: T): InterfaceFunc<T> { - let schema: Interface = {}; + const schema: Interface = {}; for (const s of schemas) { for (const key in s) { schema[key] = s[key]; diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts index cdc9871a8..6b2723663 100644 --- a/src/new_fields/ScriptField.ts +++ b/src/new_fields/ScriptField.ts @@ -102,7 +102,7 @@ export class ScriptField extends ObjectField { return "script field"; } public static CompileScript(script: string, params: object = {}, addReturn = false) { - let compiled = CompileScript(script, { + const compiled = CompileScript(script, { params: { this: Doc.name, ...params }, typecheck: false, editable: true, @@ -111,12 +111,12 @@ export class ScriptField extends ObjectField { return compiled; } public static MakeFunction(script: string, params: object = {}) { - let compiled = ScriptField.CompileScript(script, params, true); + const compiled = ScriptField.CompileScript(script, params, true); return compiled.compiled ? new ScriptField(compiled) : undefined; } public static MakeScript(script: string, params: object = {}) { - let compiled = ScriptField.CompileScript(script, params, false); + const compiled = ScriptField.CompileScript(script, params, false); return compiled.compiled ? new ScriptField(compiled) : undefined; } } @@ -127,11 +127,11 @@ export class ComputedField extends ScriptField { //TODO maybe add an observable cache based on what is passed in for doc, considering there shouldn't really be that many possible values for doc value = computedFn((doc: Doc) => this.script.run({ this: doc }, console.log).result); public static MakeScript(script: string, params: object = {}, ) { - let compiled = ScriptField.CompileScript(script, params, false); + const compiled = ScriptField.CompileScript(script, params, false); return compiled.compiled ? new ComputedField(compiled) : undefined; } public static MakeFunction(script: string, params: object = {}) { - let compiled = ScriptField.CompileScript(script, params, true); + const compiled = ScriptField.CompileScript(script, params, true); return compiled.compiled ? new ComputedField(compiled) : undefined; } } diff --git a/src/server/ActionUtilities.ts b/src/server/ActionUtilities.ts index c9fc86fea..c155796a8 100644 --- a/src/server/ActionUtilities.ts +++ b/src/server/ActionUtilities.ts @@ -3,10 +3,11 @@ import { ExecOptions } from 'shelljs'; import { exec } from 'child_process'; import * as path from 'path'; import * as rimraf from "rimraf"; +import { yellow } from 'colors'; export const command_line = (command: string, fromDirectory?: string) => { return new Promise<string>((resolve, reject) => { - let options: ExecOptions = {}; + const options: ExecOptions = {}; if (fromDirectory) { options.cwd = path.join(__dirname, fromDirectory); } @@ -15,14 +16,14 @@ export const command_line = (command: string, fromDirectory?: string) => { }; export const read_text_file = (relativePath: string) => { - let target = path.join(__dirname, relativePath); + const target = path.join(__dirname, relativePath); return new Promise<string>((resolve, reject) => { fs.readFile(target, (err, data) => err ? reject(err) : resolve(data.toString())); }); }; export const write_text_file = (relativePath: string, contents: any) => { - let target = path.join(__dirname, relativePath); + const target = path.join(__dirname, relativePath); return new Promise<void>((resolve, reject) => { fs.writeFile(target, contents, (err) => err ? reject(err) : resolve()); }); @@ -42,31 +43,19 @@ export async function log_execution({ startMessage, endMessage, action }: LogDat console.log(color, endMessage); } -export enum ConsoleColors { - Black = `\x1b[30m%s\x1b[0m`, - Red = `\x1b[31m%s\x1b[0m`, - Green = `\x1b[32m%s\x1b[0m`, - Yellow = `\x1b[33m%s\x1b[0m`, - Blue = `\x1b[34m%s\x1b[0m`, - Magenta = `\x1b[35m%s\x1b[0m`, - Cyan = `\x1b[36m%s\x1b[0m`, - White = `\x1b[37m%s\x1b[0m` -} - export function logPort(listener: string, port: number) { - process.stdout.write(`${listener} listening on port `); - console.log(ConsoleColors.Yellow, port); + console.log(`${listener} listening on port ${yellow(String(port))}`); } export function msToTime(duration: number) { - let milliseconds = Math.floor((duration % 1000) / 100), + const milliseconds = Math.floor((duration % 1000) / 100), seconds = Math.floor((duration / 1000) % 60), minutes = Math.floor((duration / (1000 * 60)) % 60), hours = Math.floor((duration / (1000 * 60 * 60)) % 24); - let hoursS = (hours < 10) ? "0" + hours : hours; - let minutesS = (minutes < 10) ? "0" + minutes : minutes; - let secondsS = (seconds < 10) ? "0" + seconds : seconds; + const hoursS = (hours < 10) ? "0" + hours : hours; + const minutesS = (minutes < 10) ? "0" + minutes : minutes; + const secondsS = (seconds < 10) ? "0" + seconds : seconds; return hoursS + ":" + minutesS + ":" + secondsS + "." + milliseconds; } diff --git a/src/server/ApiManagers/DownloadManager.ts b/src/server/ApiManagers/DownloadManager.ts index 5bad46eda..2280739fc 100644 --- a/src/server/ApiManagers/DownloadManager.ts +++ b/src/server/ApiManagers/DownloadManager.ts @@ -57,14 +57,13 @@ export default class DownloadManager extends ApiManager { register({ method: Method.GET, - subscription: new RouteSubscriber("/serializeDoc").add("docId"), + subscription: new RouteSubscriber("serializeDoc").add("docId"), onValidation: async ({ req, res }) => { const { docs, files } = await getDocs(req.params.docId); res.send({ docs, files: Array.from(files) }); } }); - } } diff --git a/src/server/ApiManagers/GeneralGoogleManager.ts b/src/server/ApiManagers/GeneralGoogleManager.ts index 629684e0c..3617779d5 100644 --- a/src/server/ApiManagers/GeneralGoogleManager.ts +++ b/src/server/ApiManagers/GeneralGoogleManager.ts @@ -38,16 +38,19 @@ export default class GeneralGoogleManager extends ApiManager { register({ method: Method.POST, - subscription: new RouteSubscriber("/googleDocs").add("sector", "action"), + subscription: new RouteSubscriber("googleDocs").add("sector", "action"), onValidation: async ({ req, res, user }) => { - let sector: GoogleApiServerUtils.Service = req.params.sector as GoogleApiServerUtils.Service; - let action: GoogleApiServerUtils.Action = req.params.action as GoogleApiServerUtils.Action; + const sector: GoogleApiServerUtils.Service = req.params.sector as GoogleApiServerUtils.Service; + const action: GoogleApiServerUtils.Action = req.params.action as GoogleApiServerUtils.Action; const endpoint = await GoogleApiServerUtils.GetEndpoint(GoogleApiServerUtils.Service[sector], user.id); - let handler = EndpointHandlerMap.get(action); + const handler = EndpointHandlerMap.get(action); if (endpoint && handler) { - handler(endpoint, req.body) - .then(response => res.send(response.data)) - .catch(exception => res.send(exception)); + try { + const response = await handler(endpoint, req.body); + res.send(response.data); + } catch (e) { + res.send(e); + } return; } res.send(undefined); diff --git a/src/server/ApiManagers/GooglePhotosManager.ts b/src/server/ApiManagers/GooglePhotosManager.ts index 4a0c0b936..e2539f120 100644 --- a/src/server/ApiManagers/GooglePhotosManager.ts +++ b/src/server/ApiManagers/GooglePhotosManager.ts @@ -47,7 +47,7 @@ export default class GooglePhotosManager extends ApiManager { if (!token) { return _error(res, authenticationError); } - let failed: GooglePhotosUploadFailure[] = []; + const failed: GooglePhotosUploadFailure[] = []; const batched = BatchedArray.from<GooglePhotosUploadUtils.UploadSource>(media, { batchSize: 25 }); const newMediaItems = await batched.batchedMapPatientInterval<NewMediaItem>( { magnitude: 100, unit: TimeUnit.Milliseconds }, @@ -87,7 +87,7 @@ export default class GooglePhotosManager extends ApiManager { let failed = 0; if (contents) { const completed: Opt<DashUploadUtils.ImageUploadInformation>[] = []; - for (let item of contents.mediaItems) { + for (const item of contents.mediaItems) { const { contentSize, ...attributes } = await DashUploadUtils.InspectImage(item.baseUrl); const found: Opt<DashUploadUtils.ImageUploadInformation> = await Database.Auxiliary.QueryUploadHistory(contentSize!); if (!found) { diff --git a/src/server/ApiManagers/PDFManager.ts b/src/server/ApiManagers/PDFManager.ts index 151b48dd9..a190ab0cb 100644 --- a/src/server/ApiManagers/PDFManager.ts +++ b/src/server/ApiManagers/PDFManager.ts @@ -8,7 +8,7 @@ const imageSize = require("probe-image-size"); import * as express from "express"; import * as path from "path"; import { Directory, serverPathToFile, clientPathToFile } from "./UploadManager"; -import { ConsoleColors } from "../ActionUtilities"; +import { red } from "colors"; export default class PDFManager extends ApiManager { @@ -32,10 +32,10 @@ function getOrCreateThumbnail(thumbnailName: string, res: express.Response) { const path = serverPathToFile(Directory.pdf_thumbnails, thumbnailName); exists(path, (exists: boolean) => { if (exists) { - let existingThumbnail = createReadStream(path); + const existingThumbnail = createReadStream(path); imageSize(existingThumbnail, (err: any, { width, height }: any) => { if (err) { - console.log(ConsoleColors.Red, `In PDF thumbnail response, unable to determine dimensions of ${thumbnailName}:`); + console.log(red(`In PDF thumbnail response, unable to determine dimensions of ${thumbnailName}:`)); console.log(err); return; } @@ -81,7 +81,7 @@ async function CreateThumbnail(file: string, pageNumber: number, res: express.Re }); }); out.on("error", error => { - console.log(ConsoleColors.Red, `In PDF thumbnail creation, encountered the following error when piping ${pngFile}:`); + console.log(red(`In PDF thumbnail creation, encountered the following error when piping ${pngFile}:`)); console.log(error); }); } @@ -89,8 +89,8 @@ async function CreateThumbnail(file: string, pageNumber: number, res: express.Re class NodeCanvasFactory { create = (width: number, height: number) => { - var canvas = createCanvas(width, height); - var context = canvas.getContext('2d'); + const canvas = createCanvas(width, height); + const context = canvas.getContext('2d'); return { canvas, context diff --git a/src/server/ApiManagers/SearchManager.ts b/src/server/ApiManagers/SearchManager.ts index d3f8995b0..7afecbb18 100644 --- a/src/server/ApiManagers/SearchManager.ts +++ b/src/server/ApiManagers/SearchManager.ts @@ -1,7 +1,7 @@ import ApiManager, { Registration } from "./ApiManager"; import { Method } from "../RouteManager"; import { Search } from "../Search"; -var findInFiles = require('find-in-files'); +const findInFiles = require('find-in-files'); import * as path from 'path'; import { pathToDirectory, Directory } from "./UploadManager"; @@ -13,14 +13,14 @@ export default class SearchManager extends ApiManager { method: Method.GET, subscription: "/textsearch", onValidation: async ({ req, res }) => { - let q = req.query.q; + const q = req.query.q; if (q === undefined) { res.send([]); return; } - let results = await findInFiles.find({ 'term': q, 'flags': 'ig' }, pathToDirectory(Directory.text), ".txt$"); - let resObj: { ids: string[], numFound: number, lines: string[] } = { ids: [], numFound: 0, lines: [] }; - for (var result in results) { + const results = await findInFiles.find({ 'term': q, 'flags': 'ig' }, pathToDirectory(Directory.text), ".txt$"); + const resObj: { ids: string[], numFound: number, lines: string[] } = { ids: [], numFound: 0, lines: [] }; + for (const result in results) { resObj.ids.push(path.basename(result, ".txt").replace(/upload_/, "")); resObj.lines.push(results[result].line); resObj.numFound++; @@ -39,7 +39,7 @@ export default class SearchManager extends ApiManager { res.send([]); return; } - let results = await Search.Instance.search(solrQuery); + const results = await Search.Instance.search(solrQuery); res.send(results); } }); diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts index 80ae0ad61..da1f83b75 100644 --- a/src/server/ApiManagers/UploadManager.ts +++ b/src/server/ApiManagers/UploadManager.ts @@ -2,7 +2,7 @@ import ApiManager, { Registration } from "./ApiManager"; import { Method, _success } from "../RouteManager"; import * as formidable from 'formidable'; import v4 = require('uuid/v4'); -var AdmZip = require('adm-zip'); +const AdmZip = require('adm-zip'); import { extname, basename, dirname } from 'path'; import { createReadStream, createWriteStream, unlink, readFileSync } from "fs"; import { publicDirectory, filesDirectory } from ".."; @@ -42,12 +42,12 @@ export default class UploadManager extends ApiManager { method: Method.POST, subscription: "/upload", onValidation: async ({ req, res }) => { - let form = new formidable.IncomingForm(); + const form = new formidable.IncomingForm(); form.uploadDir = pathToDirectory(Directory.parsed_files); form.keepExtensions = true; return new Promise<void>(resolve => { form.parse(req, async (_err, _fields, files) => { - let results: any[] = []; + const results: any[] = []; for (const key in files) { const result = await DashUploadUtils.upload(files[key]); result && results.push(result); @@ -63,7 +63,7 @@ export default class UploadManager extends ApiManager { method: Method.POST, subscription: "/uploadDoc", onValidation: ({ req, res }) => { - let form = new formidable.IncomingForm(); + const form = new formidable.IncomingForm(); form.keepExtensions = true; // let path = req.body.path; const ids: { [id: string]: string } = {}; @@ -122,8 +122,8 @@ export default class UploadManager extends ApiManager { zip.getEntries().forEach((entry: any) => { if (!entry.entryName.startsWith("files/")) return; let directory = dirname(entry.entryName) + "/"; - let extension = extname(entry.entryName); - let base = basename(entry.entryName).split(".")[0]; + const extension = extname(entry.entryName); + const base = basename(entry.entryName).split(".")[0]; try { zip.extractEntryTo(entry.entryName, publicDirectory, true, false); directory = "/" + directory; @@ -139,7 +139,7 @@ export default class UploadManager extends ApiManager { const json = zip.getEntry("doc.json"); let docs: any; try { - let data = JSON.parse(json.getData().toString("utf8")); + const data = JSON.parse(json.getData().toString("utf8")); docs = data.docs; id = data.id; docs = Object.keys(docs).map(key => docs[key]); @@ -189,7 +189,7 @@ export default class UploadManager extends ApiManager { return imageDataUri.outputFile(uri, serverPathToFile(Directory.images, filename)).then((savedName: string) => { const ext = extname(savedName).toLowerCase(); const { pngs, jpgs } = AcceptibleMedia; - let resizers = [ + const resizers = [ { resizer: sharp().resize(100, undefined, { withoutEnlargement: true }), suffix: "_s" }, { resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: "_m" }, { resizer: sharp().resize(900, undefined, { withoutEnlargement: true }), suffix: "_l" }, diff --git a/src/server/ApiManagers/UtilManager.ts b/src/server/ApiManagers/UtilManager.ts index c1234be6c..601a7d0d0 100644 --- a/src/server/ApiManagers/UtilManager.ts +++ b/src/server/ApiManagers/UtilManager.ts @@ -35,11 +35,11 @@ export default class UtilManager extends ApiManager { method: Method.GET, subscription: "/buxton", onValidation: async ({ res }) => { - let cwd = '../scraping/buxton'; + const cwd = '../scraping/buxton'; - let onResolved = (stdout: string) => { console.log(stdout); res.redirect("/"); }; - let onRejected = (err: any) => { console.error(err.message); res.send(err); }; - let tryPython3 = () => command_line('python3 scraper.py', cwd).then(onResolved, onRejected); + const onResolved = (stdout: string) => { console.log(stdout); res.redirect("/"); }; + const onRejected = (err: any) => { console.error(err.message); res.send(err); }; + const tryPython3 = () => command_line('python3 scraper.py', cwd).then(onResolved, onRejected); return command_line('python scraper.py', cwd).then(onResolved, tryPython3); }, diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index 9ccc72e35..d9d985ca5 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -9,10 +9,11 @@ import { AcceptibleMedia } from './SharedMediaTypes'; import { filesDirectory } from '.'; import { File } from 'formidable'; import { basename } from "path"; -import { ConsoleColors, createIfNotExists } from './ActionUtilities'; +import { createIfNotExists } from './ActionUtilities'; import { ParsedPDF } from "../server/PdfTypes"; const parse = require('pdf-parse'); import { Directory, serverPathToFile, clientPathToFile } from './ApiManagers/UploadManager'; +import { red } from 'colors'; export enum SizeSuffix { Small = "_s", @@ -86,12 +87,12 @@ export namespace DashUploadUtils { } } - console.log(ConsoleColors.Red, `Ignoring unsupported file (${name}) with upload type (${type}).`); + console.log(red(`Ignoring unsupported file (${name}) with upload type (${type}).`)); return { clientAccessPath: undefined }; } async function UploadPdf(absolutePath: string) { - let dataBuffer = fs.readFileSync(absolutePath); + const dataBuffer = fs.readFileSync(absolutePath); const result: ParsedPDF = await parse(dataBuffer); const parsedName = basename(absolutePath); await new Promise<void>((resolve, reject) => { @@ -194,7 +195,7 @@ export namespace DashUploadUtils { const { isLocal, stream, normalizedUrl, contentSize, contentType, exifData } = metadata; const resolved = filename || generate(prefix, normalizedUrl); const extension = format || sanitizeExtension(normalizedUrl || resolved); - let information: ImageUploadInformation = { + const information: ImageUploadInformation = { clientAccessPath: clientPathToFile(Directory.images, resolved), serverAccessPaths: {}, exifData, @@ -215,8 +216,7 @@ export namespace DashUploadUtils { } else if (jpgs.includes(extension)) { resizers.forEach(element => element.resizer = element.resizer.jpeg()); } - for (let { resizer, suffix } of resizers) { - let mediaPath: string; + for (const { resizer, suffix } of resizers) { await new Promise<void>(resolve => { const filename = InjectSize(resolved, suffix); information.serverAccessPaths[suffix] = serverPathToFile(Directory.images, filename); diff --git a/src/server/Initialization.ts b/src/server/Initialization.ts index 8b633a7cd..74770153d 100644 --- a/src/server/Initialization.ts +++ b/src/server/Initialization.ts @@ -19,8 +19,9 @@ import * as fs from 'fs'; import * as request from 'request'; import RouteSubscriber from './RouteSubscriber'; import { publicDirectory } from '.'; -import { ConsoleColors, logPort } from './ActionUtilities'; +import { logPort } from './ActionUtilities'; import { timeMap } from './ApiManagers/UserManager'; +import { blue, yellow } from 'colors'; /* RouteSetter is a wrapper around the server that prevents the server from being exposed. */ @@ -53,10 +54,13 @@ export default async function InitializeServer(options: InitializationOptions) { registerAuthenticationRoutes(server); registerCorsProxy(server); - const isRelease = determineEnvironment(); //vs. dev mode + const isRelease = determineEnvironment(); routeSetter(new RouteManager(server, isRelease)); - server.listen(listenAtPort, () => logPort("server", listenAtPort)); + server.listen(listenAtPort, () => { + logPort("server", listenAtPort); + console.log(); + }); return isRelease; } @@ -92,8 +96,9 @@ function buildWithMiddleware(server: express.Express) { function determineEnvironment() { const isRelease = process.env.RELEASE === "true"; - console.log(`running server in ${isRelease ? 'release' : 'debug'} mode`); - console.log(process.env.PWD); + const color = isRelease ? blue : yellow; + const label = isRelease ? "release" : "development"; + console.log(`\nrunning server in ${color(label)} mode`); let clientUtils = fs.readFileSync("./src/client/util/ClientUtils.ts.temp", "utf8"); clientUtils = `//AUTO-GENERATED FILE: DO NOT EDIT\n${clientUtils.replace('"mode"', String(isRelease))}`; diff --git a/src/server/RouteManager.ts b/src/server/RouteManager.ts index 7c49485f1..3af36d879 100644 --- a/src/server/RouteManager.ts +++ b/src/server/RouteManager.ts @@ -1,7 +1,7 @@ import RouteSubscriber from "./RouteSubscriber"; import { DashUserModel } from "./authentication/models/user_model"; import * as express from 'express'; -import { ConsoleColors } from "./ActionUtilities"; +import { yellow, cyan, red } from 'colors'; export enum Method { GET, @@ -41,6 +41,12 @@ export default class RouteManager { this._isRelease = isRelease; } + log = () => { + console.log(yellow("\nthe following server routes have been registered:")); + Array.from(registered.keys()).sort().forEach(route => console.log(cyan(route))); + console.log(); + } + /** * * @param initializer @@ -48,14 +54,14 @@ export default class RouteManager { addSupervisedRoute = (initializer: RouteInitializer): void => { const { method, subscription, onValidation, onUnauthenticated, onError } = initializer; const isRelease = this._isRelease; - let supervised = async (req: express.Request, res: express.Response) => { + const supervised = async (req: express.Request, res: express.Response) => { const { user, originalUrl: target } = req; const core = { req, res, isRelease }; const tryExecute = async (toExecute: (args: any) => any | Promise<any>, args: any) => { try { await toExecute(args); } catch (e) { - console.log(ConsoleColors.Red, target, user?.email ?? "<user logged out>"); + console.log(red(target), user?.email ?? "<user logged out>"); if (onError) { onError({ ...core, error: e }); } else { @@ -78,7 +84,7 @@ export default class RouteManager { } setTimeout(() => { if (!res.headersSent) { - console.log("Initiating fallback for ", target); + console.log(`Initiating fallback for ${target}`); const warning = `request to ${target} fell through - this is a fallback response`; res.send({ warning }); } @@ -94,7 +100,7 @@ export default class RouteManager { const existing = registered.get(route); if (existing) { if (existing.has(method)) { - console.log(ConsoleColors.Red, `\nDuplicate registration error: already registered ${route} with Method[${method}]`); + console.log(red(`\nDuplicate registration error: already registered ${route} with Method[${method}]`)); console.log('Please remove duplicate registrations before continuing...\n'); process.exit(0); } diff --git a/src/server/Websocket/Websocket.ts b/src/server/Websocket/Websocket.ts index fbf71f707..2eb764945 100644 --- a/src/server/Websocket/Websocket.ts +++ b/src/server/Websocket/Websocket.ts @@ -7,12 +7,13 @@ import { Search } from "../Search"; import * as io from 'socket.io'; import YoutubeApi from "../apis/youtube/youtubeApiSample"; import { GoogleCredentialsLoader } from "../credentials/CredentialsLoader"; -import { ConsoleColors, logPort } from "../ActionUtilities"; +import { logPort } from "../ActionUtilities"; import { timeMap } from "../ApiManagers/UserManager"; +import { green } from "colors"; export namespace WebSocket { - let clients: { [key: string]: Client } = {}; + const clients: { [key: string]: Client } = {}; export const socketMap = new Map<SocketIO.Socket, string>(); export async function start(serverPort: number, isRelease: boolean) { @@ -27,7 +28,7 @@ export namespace WebSocket { const endpoint = io(); endpoint.on("connection", function (socket: Socket) { socket.use((_packet, next) => { - let userEmail = socketMap.get(socket); + const userEmail = socketMap.get(socket); if (userEmail) { timeMap[userEmail] = Date.now(); } @@ -85,7 +86,7 @@ export namespace WebSocket { function barReceived(socket: SocketIO.Socket, userEmail: string) { clients[userEmail] = new Client(userEmail.toString()); - console.log(ConsoleColors.Green, `user ${userEmail} has connected to the web socket`); + console.log(green(`user ${userEmail} has connected to the web socket`)); socketMap.set(socket, userEmail); } @@ -178,12 +179,12 @@ export namespace WebSocket { for (let key in docfield) { if (!key.startsWith("fields.")) continue; dynfield = true; - let val = docfield[key]; + const val = docfield[key]; key = key.substring(7); Object.values(suffixMap).forEach(suf => update[key + getSuffix(suf)] = { set: null }); - let term = ToSearchTerm(val); + const term = ToSearchTerm(val); if (term !== undefined) { - let { suffix, value } = term; + const { suffix, value } = term; update[key + suffix] = { set: value }; } } diff --git a/src/server/apis/google/GoogleApiServerUtils.ts b/src/server/apis/google/GoogleApiServerUtils.ts index b0f3ba993..329107a71 100644 --- a/src/server/apis/google/GoogleApiServerUtils.ts +++ b/src/server/apis/google/GoogleApiServerUtils.ts @@ -135,7 +135,7 @@ export namespace GoogleApiServerUtils { return resolve(); } let routed: Opt<Endpoint>; - let parameters: any = { auth, version: "v1" }; + const parameters: any = { auth, version: "v1" }; switch (sector) { case Service.Documents: routed = google.docs(parameters).documents; @@ -318,7 +318,7 @@ export namespace GoogleApiServerUtils { */ async function retrieveCredentials(userId: string): Promise<{ credentials: Opt<Credentials>, refreshed: boolean }> { let credentials: Opt<Credentials> = await Database.Auxiliary.GoogleAuthenticationToken.Fetch(userId); - let refreshed = false; + const refreshed = false; if (!credentials) { return { credentials: undefined, refreshed }; } @@ -340,9 +340,9 @@ export namespace GoogleApiServerUtils { * @returns the updated credentials */ async function refreshAccessToken(credentials: Credentials, userId: string): Promise<Credentials> { - let headerParameters = { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }; + const headerParameters = { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }; const { client_id, client_secret } = GoogleCredentialsLoader.ProjectCredentials; - let url = `https://oauth2.googleapis.com/token?${qs.stringify({ + const url = `https://oauth2.googleapis.com/token?${qs.stringify({ refreshToken: credentials.refresh_token, client_id, client_secret, diff --git a/src/server/authentication/config/passport.ts b/src/server/authentication/config/passport.ts index 726df7fd7..2271109a5 100644 --- a/src/server/authentication/config/passport.ts +++ b/src/server/authentication/config/passport.ts @@ -40,7 +40,7 @@ export let isAuthenticated = (req: Request, res: Response, next: NextFunction) = export let isAuthorized = (req: Request, res: Response, next: NextFunction) => { const provider = req.path.split("/").slice(-1)[0]; - if (_.find((req.user as any).tokens!, { kind: provider })) { + if (_.find(req.user?.tokens, { kind: provider })) { next(); } else { res.redirect(`/auth/${provider}`); diff --git a/src/server/authentication/controllers/user_controller.ts b/src/server/authentication/controllers/user_controller.ts index 517353479..f0086d4ea 100644 --- a/src/server/authentication/controllers/user_controller.ts +++ b/src/server/authentication/controllers/user_controller.ts @@ -68,9 +68,9 @@ export let postSignup = (req: Request, res: Response, next: NextFunction) => { }; -let tryRedirectToTarget = (req: Request, res: Response) => { +const tryRedirectToTarget = (req: Request, res: Response) => { if (req.session && req.session.target) { - let target = req.session.target; + const target = req.session.target; req.session.target = undefined; res.redirect(target); } else { @@ -148,7 +148,6 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio const email = req.body.email; async.waterfall([ function (done: any) { - let token: string; c.randomBytes(20, function (err: any, buffer: Buffer) { if (err) { done(null); diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index ac4462f78..50bfb4832 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -42,10 +42,10 @@ export class CurrentUserUtils { // setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools static setupCreatorButtons(doc: Doc) { - let notes = CurrentUserUtils.setupNoteTypes(doc); + const notes = CurrentUserUtils.setupNoteTypes(doc); doc.noteTypes = Docs.Create.TreeDocument(notes, { title: "Note Types", height: 75 }); doc.activePen = doc; - let docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, ischecked?: string, activePen?: Doc, backgroundColor?: string, dragFactory?: Doc }[] = [ + const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, ischecked?: string, activePen?: Doc, backgroundColor?: string, dragFactory?: Doc }[] = [ { title: "collection", icon: "folder", ignoreClick: true, drag: 'Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" })' }, { title: "todo item", icon: "check", ignoreClick: true, drag: 'getCopy(this.dragFactory, true)', dragFactory: notes[notes.length - 1] }, { title: "web page", icon: "globe-asia", ignoreClick: true, drag: 'Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })' }, @@ -278,7 +278,7 @@ export class CurrentUserUtils { if (this._northstarCatalog && CurrentUserUtils._northstarSchemas) { this._northstarCatalog.schemas!.push(schema); CurrentUserUtils._northstarSchemas.push(schemaDoc); - let schemas = Cast(CurrentUserUtils.UserDocument.DBSchemas, listSpec("string"), []); + const schemas = Cast(CurrentUserUtils.UserDocument.DBSchemas, listSpec("string"), []); schemas.push(schema.displayName!); CurrentUserUtils.UserDocument.DBSchemas = new List<string>(schemas); } diff --git a/src/server/database.ts b/src/server/database.ts index db81245c1..4039e6203 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -71,7 +71,7 @@ export namespace Database { public async update(id: string, value: any, callback: (err: mongodb.MongoError, res: mongodb.UpdateWriteOpResult) => void, upsert = true, collectionName = Database.DocumentsCollection) { if (this.db) { - let collection = this.db.collection(collectionName); + const collection = this.db.collection(collectionName); const prom = this.currentWrites[id]; let newProm: Promise<void>; const run = (): Promise<void> => { @@ -96,7 +96,7 @@ export namespace Database { public replace(id: string, value: any, callback: (err: mongodb.MongoError, res: mongodb.UpdateWriteOpResult) => void, upsert = true, collectionName = Database.DocumentsCollection) { if (this.db) { - let collection = this.db.collection(collectionName); + const collection = this.db.collection(collectionName); const prom = this.currentWrites[id]; let newProm: Promise<void>; const run = (): Promise<void> => { diff --git a/src/server/downsize.ts b/src/server/downsize.ts index ed68fbecc..cd0d83812 100644 --- a/src/server/downsize.ts +++ b/src/server/downsize.ts @@ -17,7 +17,7 @@ fs.readdir(folder, async (err, files) => { // }); for (const file of files) { const filesplit = file.split("."); - let resizers = [ + const resizers = [ { resizer: sharp().resize(100, undefined, { withoutEnlargement: true }), suffix: "_s" }, { resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: "_m" }, { resizer: sharp().resize(900, undefined, { withoutEnlargement: true }), suffix: "_l" }, diff --git a/src/server/index.ts b/src/server/index.ts index d77923710..0e0bd0bd6 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -51,7 +51,7 @@ async function preliminaryFunctions() { * that will manage the registration of new routes * with the server */ -function routeSetter({ isRelease, addSupervisedRoute }: RouteManager) { +function routeSetter({ isRelease, addSupervisedRoute, log }: RouteManager) { const managers = [ new UserManager(), new UploadManager(), @@ -67,6 +67,7 @@ function routeSetter({ isRelease, addSupervisedRoute }: RouteManager) { // initialize API Managers managers.forEach(manager => manager.register(addSupervisedRoute)); + log(); // initialize the web socket (bidirectional communication: if a user changes // a field on one client, that change must be broadcast to all other clients) @@ -82,8 +83,8 @@ function routeSetter({ isRelease, addSupervisedRoute }: RouteManager) { }); const serve: OnUnauthenticated = ({ req, res }) => { - let detector = new mobileDetect(req.headers['user-agent'] || ""); - let filename = detector.mobile() !== null ? 'mobile/image.html' : 'index.html'; + const detector = new mobileDetect(req.headers['user-agent'] || ""); + const filename = detector.mobile() !== null ? 'mobile/image.html' : 'index.html'; res.sendFile(path.join(__dirname, '../../deploy/' + filename)); }; @@ -104,8 +105,8 @@ function routeSetter({ isRelease, addSupervisedRoute }: RouteManager) { (async function start() { await log_execution({ - startMessage: "starting execution of preliminary functions", - endMessage: "completed preliminary functions", + startMessage: "\nstarting execution of preliminary functions", + endMessage: "completed preliminary functions\n", action: preliminaryFunctions }); await initializeServer({ listenAtPort: 1050, routeSetter }); diff --git a/src/typings/index.d.ts b/src/typings/index.d.ts index 36d828fdb..9e8ace962 100644 --- a/src/typings/index.d.ts +++ b/src/typings/index.d.ts @@ -1,6 +1,7 @@ /// <reference types="node" /> declare module 'googlephotos'; +declare module 'react-image-lightbox-with-rotate'; declare module '@react-pdf/renderer' { import * as React from 'react'; |