From 4574b7f03ccc85c4bebdbfd9475788456086704f Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 8 Aug 2024 12:27:40 -0400 Subject: many changes to add typing in place of 'any's etc --- src/server/websocket.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/server/websocket.ts') diff --git a/src/server/websocket.ts b/src/server/websocket.ts index cece8a1b7..821607df5 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -16,12 +16,11 @@ import YoutubeApi from './apis/youtube/youtubeApiSample'; import { initializeGuest } from './authentication/DashUserModel'; import { Database } from './database'; +// eslint-disable-next-line @typescript-eslint/no-namespace export namespace WebSocket { let CurUser: string | undefined; - // eslint-disable-next-line import/no-mutable-exports export let _socket: Socket; - // eslint-disable-next-line import/no-mutable-exports - export let _disconnect: Function; + export let _disconnect: () => void; export const clients: { [key: string]: Client } = {}; function processGesturePoints(socket: Socket, content: GestureContent) { -- cgit v1.2.3-70-g09d2 From 5c7964173d80752200727d8340825210c2704265 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 13 Aug 2024 10:42:24 -0400 Subject: removed youtube query calls --- src/server/websocket.ts | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'src/server/websocket.ts') diff --git a/src/server/websocket.ts b/src/server/websocket.ts index 821607df5..4a127f099 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -8,7 +8,7 @@ import { logPort } from './ActionUtilities'; import { Client } from './Client'; import { DashStats } from './DashStats'; import { DocumentsCollection } from './IDatabase'; -import { Diff, GestureContent, MessageStore, MobileDocumentUploadContent, MobileInkOverlayContent, Transferable, Types, UpdateMobileInkOverlayPositionContent, YoutubeQueryInput, YoutubeQueryTypes } from './Message'; +import { Diff, GestureContent, MessageStore, MobileDocumentUploadContent, MobileInkOverlayContent, Transferable, Types, UpdateMobileInkOverlayPositionContent } from './Message'; import { Search } from './Search'; import { resolvedPorts, socketMap, timeMap, userOperations } from './SocketData'; import { GoogleCredentialsLoader } from './apis/google/CredentialsLoader'; @@ -39,22 +39,6 @@ export namespace WebSocket { socket.broadcast.emit('receiveMobileDocumentUpload', content); } - function HandleYoutubeQuery([query, callback]: [YoutubeQueryInput, (result?: any[]) => void]) { - const { ProjectCredentials } = GoogleCredentialsLoader; - switch (query.type) { - case YoutubeQueryTypes.Channels: - YoutubeApi.authorizedGetChannel(ProjectCredentials); - break; - case YoutubeQueryTypes.SearchVideo: - YoutubeApi.authorizedGetVideos(ProjectCredentials, query.userInput, callback); - break; - case YoutubeQueryTypes.VideoDetails: - YoutubeApi.authorizedGetVideoDetails(ProjectCredentials, query.videoIds, callback); - break; - default: - } - } - export async function doDelete(onlyFields = true) { const target: string[] = []; onlyFields && target.push(DocumentsCollection); @@ -448,7 +432,6 @@ export namespace WebSocket { } ServerUtils.AddServerHandler(socket, MessageStore.CreateField, CreateField); - ServerUtils.AddServerHandlerCallback(socket, MessageStore.YoutubeApiQuery, HandleYoutubeQuery); ServerUtils.AddServerHandler(socket, MessageStore.UpdateField, diff => UpdateField(socket, diff)); ServerUtils.AddServerHandler(socket, MessageStore.DeleteField, id => DeleteField(socket, id)); ServerUtils.AddServerHandler(socket, MessageStore.DeleteFields, ids => DeleteFields(socket, ids)); -- cgit v1.2.3-70-g09d2 From ef79ab121c881d3e6a2982ce2e01da40294af656 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 13 Aug 2024 10:44:53 -0400 Subject: from last --- src/server/Message.ts | 18 +++--------------- src/server/Search.ts | 1 + src/server/websocket.ts | 4 +--- 3 files changed, 5 insertions(+), 18 deletions(-) (limited to 'src/server/websocket.ts') diff --git a/src/server/Message.ts b/src/server/Message.ts index 03150c841..8e30cd6df 100644 --- a/src/server/Message.ts +++ b/src/server/Message.ts @@ -47,19 +47,7 @@ export enum Types { export interface Transferable { readonly id: string; readonly type: Types; - readonly data?: any; -} - -export enum YoutubeQueryTypes { - Channels, - SearchVideo, - VideoDetails, -} - -export interface YoutubeQueryInput { - readonly type: YoutubeQueryTypes; - readonly userInput?: string; - readonly videoIds?: string; + readonly data?: unknown; } export interface Reference { @@ -99,6 +87,7 @@ export interface RoomMessage { readonly room: string; } +// eslint-disable-next-line @typescript-eslint/no-namespace export namespace MessageStore { export const Foo = new Message('Foo'); export const Bar = new Message('Bar'); @@ -106,7 +95,7 @@ export namespace MessageStore { export const GetField = new Message('Get Field'); // send string 'id' get Transferable back export const GetFields = new Message('Get Fields'); // send string[] of 'id' get Transferable[] back export const GetDocument = new Message('Get Document'); - export const DeleteAll = new Message('Delete All'); + export const DeleteAll = new Message('Delete All'); export const ConnectionTerminated = new Message('Connection Terminated'); export const GesturePoints = new Message('Gesture Points'); @@ -118,7 +107,6 @@ export namespace MessageStore { export const GetRefFields = new Message('Get Ref Fields'); export const UpdateField = new Message('Update Ref Field'); export const CreateField = new Message('Create Ref Field'); - export const YoutubeApiQuery = new Message('Youtube Api Query'); export const DeleteField = new Message('Delete field'); export const DeleteFields = new Message('Delete fields'); diff --git a/src/server/Search.ts b/src/server/Search.ts index b21ee853a..06af18776 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -3,6 +3,7 @@ import * as rp from 'request-promise'; const pathTo = (relative: string) => `http://localhost:8983/solr/dash/${relative}`; +// eslint-disable-next-line @typescript-eslint/no-namespace export namespace Search { export async function updateDocument(document: any) { try { diff --git a/src/server/websocket.ts b/src/server/websocket.ts index 4a127f099..905dbcf57 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -11,8 +11,6 @@ import { DocumentsCollection } from './IDatabase'; import { Diff, GestureContent, MessageStore, MobileDocumentUploadContent, MobileInkOverlayContent, Transferable, Types, UpdateMobileInkOverlayPositionContent } from './Message'; import { Search } from './Search'; import { resolvedPorts, socketMap, timeMap, userOperations } from './SocketData'; -import { GoogleCredentialsLoader } from './apis/google/CredentialsLoader'; -import YoutubeApi from './apis/youtube/youtubeApiSample'; import { initializeGuest } from './authentication/DashUserModel'; import { Database } from './database'; @@ -77,7 +75,7 @@ export namespace WebSocket { Database.Instance.update(newValue.id, newValue, () => socket.broadcast.emit(MessageStore.SetField.Message, newValue)); // broadcast set value to all other clients if (newValue.type === Types.Text) { // if the newValue has sring type, then it's suitable for searching -- pass it to SOLR - Search.updateDocument({ id: newValue.id, data: { set: (newValue as any).data } }); + Search.updateDocument({ id: newValue.id, data: { set: newValue.data } }); } } -- cgit v1.2.3-70-g09d2 From a0774ccdd2de7953b9822df2e106d7395cc0f216 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 13 Aug 2024 15:31:42 -0400 Subject: updated list ops on server --- src/server/websocket.ts | 244 ++++++++++++++++++------------------------------ 1 file changed, 89 insertions(+), 155 deletions(-) (limited to 'src/server/websocket.ts') diff --git a/src/server/websocket.ts b/src/server/websocket.ts index 905dbcf57..f10455680 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -3,13 +3,14 @@ import { createServer } from 'https'; import * as _ from 'lodash'; import { networkInterfaces } from 'os'; import { Server, Socket } from 'socket.io'; +import { SecureContextOptions } from 'tls'; import { ServerUtils } from '../ServerUtils'; +import { serializedDoctype, serializedFieldsType } from '../fields/ObjectField'; import { logPort } from './ActionUtilities'; import { Client } from './Client'; import { DashStats } from './DashStats'; import { DocumentsCollection } from './IDatabase'; -import { Diff, GestureContent, MessageStore, MobileDocumentUploadContent, MobileInkOverlayContent, Transferable, Types, UpdateMobileInkOverlayPositionContent } from './Message'; -import { Search } from './Search'; +import { Diff, GestureContent, MessageStore } from './Message'; import { resolvedPorts, socketMap, timeMap, userOperations } from './SocketData'; import { initializeGuest } from './authentication/DashUserModel'; import { Database } from './database'; @@ -25,25 +26,10 @@ export namespace WebSocket { socket.broadcast.emit('receiveGesturePoints', content); } - function processOverlayTrigger(socket: Socket, content: MobileInkOverlayContent) { - socket.broadcast.emit('receiveOverlayTrigger', content); - } - - function processUpdateOverlayPosition(socket: Socket, content: UpdateMobileInkOverlayPositionContent) { - socket.broadcast.emit('receiveUpdateOverlayPosition', content); - } - - function processMobileDocumentUpload(socket: Socket, content: MobileDocumentUploadContent) { - socket.broadcast.emit('receiveMobileDocumentUpload', content); - } - export async function doDelete(onlyFields = true) { const target: string[] = []; onlyFields && target.push(DocumentsCollection); await Database.Instance.dropSchema(...target); - if (process.env.DISABLE_SEARCH !== 'true') { - await Search.clear(); - } initializeGuest(); } @@ -63,31 +49,15 @@ export namespace WebSocket { DashStats.logUserLogin(userEmail); } - function getField([id, callback]: [string, (result?: Transferable) => void]) { - Database.Instance.getDocument(id, (result?: Transferable) => callback(result)); - } - - function getFields([ids, callback]: [string[], (result: Transferable[]) => void]) { - Database.Instance.getDocuments(ids, callback); - } - - function setField(socket: Socket, newValue: Transferable) { - Database.Instance.update(newValue.id, newValue, () => socket.broadcast.emit(MessageStore.SetField.Message, newValue)); // broadcast set value to all other clients - if (newValue.type === Types.Text) { - // if the newValue has sring type, then it's suitable for searching -- pass it to SOLR - Search.updateDocument({ id: newValue.id, data: { set: newValue.data } }); - } - } - - function GetRefFieldLocal([id, callback]: [string, (result?: Transferable) => void]) { + function GetRefFieldLocal([id, callback]: [string, (result?: serializedDoctype) => void]) { return Database.Instance.getDocument(id, callback); } - function GetRefField([id, callback]: [string, (result?: Transferable) => void]) { + function GetRefField([id, callback]: [string, (result?: serializedDoctype) => void]) { process.stdout.write(`+`); GetRefFieldLocal([id, callback]); } - function GetRefFields([ids, callback]: [string[], (result?: Transferable[]) => void]) { + function GetRefFields([ids, callback]: [string[], (result?: serializedDoctype[]) => void]) { process.stdout.write(`${ids.length}…`); Database.Instance.getDocuments(ids, callback); } @@ -151,11 +121,11 @@ export namespace WebSocket { const { diff, socket } = next; if (diff.diff.$addToSet) { // eslint-disable-next-line no-use-before-define - return GetRefFieldLocal([diff.id, (result?: Transferable) => addToListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own + return GetRefFieldLocal([diff.id, (result?: serializedDoctype) => addToListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own } if (diff.diff.$remFromSet) { // eslint-disable-next-line no-use-before-define - return GetRefFieldLocal([diff.id, (result?: Transferable) => remFromListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own + return GetRefFieldLocal([diff.id, (result?: serializedDoctype) => remFromListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own } // eslint-disable-next-line no-use-before-define return SetField(socket, diff); @@ -163,37 +133,41 @@ export namespace WebSocket { return !pendingOps.get(id)!.length && pendingOps.delete(id); } - function addToListField(socket: Socket, diffIn: Diff, curListItems?: Transferable): void { + function addToListField(socket: Socket, diffIn: Diff, listDoc?: serializedDoctype): void { const diff = diffIn; diff.diff.$set = diff.diff.$addToSet; delete diff.diff.$addToSet; // convert add to set to a query of the current fields, and then a set of the composition of the new fields with the old ones - const updatefield = Array.from(Object.keys(diff.diff.$set))[0]; - const newListItems = diff.diff.$set[updatefield]?.fields; + const updatefield = Array.from(Object.keys(diff.diff.$set ?? {}))[0]; + const newListItems = diff.diff.$set?.[updatefield]?.fields; if (!newListItems) { console.log('Error: addToListField - no new list items'); return; } - const curList = (curListItems as any)?.fields?.[updatefield.replace('fields.', '')]?.fields.filter((item: any) => item !== undefined) || []; - diff.diff.$set[updatefield].fields = [...curList, ...newListItems]; // , ...newListItems.filter((newItem: any) => newItem === null || !curList.some((curItem: any) => curItem.fieldId ? curItem.fieldId === newItem.fieldId : curItem.heading ? curItem.heading === newItem.heading : curItem === newItem))]; - const sendBack = diff.diff.length !== diff.diff.$set[updatefield].fields.length; - delete diff.diff.length; - Database.Instance.update( - diff.id, - diff.diff, - () => { - if (sendBack) { - console.log('Warning: list modified during update. Composite list is being returned.'); - const { id } = socket; - (socket as any).id = ''; // bcz: HACK. this prevents the update message from going back to the client that made the change. - socket.broadcast.emit(MessageStore.UpdateField.Message, diff); - (socket as any).id = id; - } else { - socket.broadcast.emit(MessageStore.UpdateField.Message, diff); - } - dispatchNextOp(diff.id); - }, - false - ); + const listItems = listDoc?.fields?.[updatefield.replace('fields.', '')]?.fields.filter(item => item !== undefined) ?? []; + if (diff.diff.$set?.[updatefield]?.fields !== undefined) { + diff.diff.$set[updatefield]!.fields = [...listItems, ...newListItems]; // , ...newListItems.filter((newItem: any) => newItem === null || !curList.some((curItem: any) => curItem.fieldId ? curItem.fieldId === newItem.fieldId : curItem.heading ? curItem.heading === newItem.heading : curItem === newItem))]; + const sendBack = diff.diff.length !== diff.diff.$set[updatefield]!.fields?.length; + delete diff.diff.length; + Database.Instance.update( + diff.id, + diff.diff, + () => { + if (sendBack) { + console.log('Warning: list modified during update. Composite list is being returned.'); + const { id } = socket; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (socket as any).id = ''; // bcz: HACK to reference private variable. this allows the update message to go back to the client that made the change. + socket.broadcast.emit(MessageStore.UpdateField.Message, diff); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (socket as any).id = id; + } else { + socket.broadcast.emit(MessageStore.UpdateField.Message, diff); + } + dispatchNextOp(diff.id); + }, + false + ); + } } /** @@ -208,7 +182,7 @@ export namespace WebSocket { * the data * @returns the closest index with the same value or -1 if the element was not found. */ - function findClosestIndex(list: any, indexesToDelete: number[], value: any, hintIndex: number) { + function findClosestIndex(list: { fieldId: string; __type: string }[], indexesToDelete: number[], value: { fieldId: string; __type: string }, hintIndex: number) { let closestIndex = -1; for (let i = 0; i < list.length; i++) { if (list[i] === value && !indexesToDelete.includes(i)) { @@ -232,63 +206,63 @@ export namespace WebSocket { * items to delete) * @param curListItems the server's current copy of the data */ - function remFromListField(socket: Socket, diffIn: Diff, curListItems?: Transferable): void { + function remFromListField(socket: Socket, diffIn: Diff, curListItems?: serializedDoctype): void { const diff = diffIn; - diff.diff.$set = diff.diff.$remFromSet; + diff.diff.$set = diff.diff.$remFromSet as serializedFieldsType; + const hint = diff.diff.$remFromSet?.hint; delete diff.diff.$remFromSet; - const updatefield = Array.from(Object.keys(diff.diff.$set))[0]; - const remListItems = diff.diff.$set[updatefield].fields; - const curList = (curListItems as any)?.fields?.[updatefield.replace('fields.', '')]?.fields.filter((f: any) => f !== null) || []; - const { hint } = diff.diff.$set; - - if (hint) { - // indexesToRemove stores the indexes that we mark for deletion, which is later used to filter the list (delete the elements) - const indexesToRemove: number[] = []; - for (let i = 0; i < hint.deleteCount; i++) { - if (curList.length > i + hint.start && _.isEqual(curList[i + hint.start], remListItems[i])) { - indexesToRemove.push(i + hint.start); - } else { - const closestIndex = findClosestIndex(curList, indexesToRemove, remListItems[i], i + hint.start); - if (closestIndex !== -1) { - indexesToRemove.push(closestIndex); + const updatefield = Array.from(Object.keys(diff.diff.$set ?? {}))[0]; + const remListItems = diff.diff.$set[updatefield]?.fields; + if (diff.diff.$set[updatefield] !== undefined && remListItems) { + const curList = curListItems?.fields?.[updatefield.replace('fields.', '')]?.fields.filter(f => f !== null) || []; + + if (hint) { + // indexesToRemove stores the indexes that we mark for deletion, which is later used to filter the list (delete the elements) + const indexesToRemove: number[] = []; + for (let i = 0; i < hint.deleteCount; i++) { + if (curList.length > i + hint.start && _.isEqual(curList[i + hint.start], remListItems[i])) { + indexesToRemove.push(i + hint.start); } else { - console.log('Item to delete was not found - index = -1'); + const closestIndex = findClosestIndex(curList, indexesToRemove, remListItems[i], i + hint.start); + if (closestIndex !== -1) { + indexesToRemove.push(closestIndex); + } else { + console.log('Item to delete was not found - index = -1'); + } } } + diff.diff.$set[updatefield]!.fields = curList.filter((curItem, index) => !indexesToRemove.includes(index)); + } else { + // go back to the original way to delete if we didn't receive + // a hint from the client + diff.diff.$set[updatefield]!.fields = curList?.filter(curItem => !remListItems.some(remItem => (remItem.fieldId ? remItem.fieldId === curItem.fieldId : remItem.heading ? remItem.heading === curItem.heading : remItem === curItem))); } - - diff.diff.$set[updatefield].fields = curList?.filter((curItem: any, index: number) => !indexesToRemove.includes(index)); - } else { - // go back to the original way to delete if we didn't receive - // a hint from the client - diff.diff.$set[updatefield].fields = curList?.filter( - (curItem: any) => !remListItems.some((remItem: any) => (remItem.fieldId ? remItem.fieldId === curItem.fieldId : remItem.heading ? remItem.heading === curItem.heading : remItem === curItem)) + // if the client and server have different versions of the data after + // deletion, they will have different lengths and the server will + // send its version of the data to the client + const sendBack = diff.diff.length !== remListItems.length; + delete diff.diff.length; + Database.Instance.update( + diff.id, + diff.diff, + () => { + if (sendBack) { + // the two copies are different, so the server sends its copy. + console.log('SEND BACK'); + const { id } = socket; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (socket as any).id = ''; // bcz: HACK to access private variable this allows the update message to go back to the client that made the change. + socket.broadcast.emit(MessageStore.UpdateField.Message, diff); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (socket as any).id = id; + } else { + socket.broadcast.emit(MessageStore.UpdateField.Message, diff); + } + dispatchNextOp(diff.id); + }, + false ); } - - // if the client and server have different versions of the data after - // deletion, they will have different lengths and the server will - // send its version of the data to the client - const sendBack = diff.diff.length !== diff.diff.$set[updatefield].fields.length; - delete diff.diff.length; - Database.Instance.update( - diff.id, - diff.diff, - () => { - if (sendBack) { - // the two copies are different, so the server sends its copy. - console.log('SEND BACK'); - const { id } = socket; - (socket as any).id = ''; // bcz: HACK. this prevents the update message from going back to the client that made the change. - socket.broadcast.emit(MessageStore.UpdateField.Message, diff); - (socket as any).id = id; - } else { - socket.broadcast.emit(MessageStore.UpdateField.Message, diff); - } - dispatchNextOp(diff.id); - }, - false - ); } function UpdateField(socket: Socket, diff: Diff) { @@ -307,43 +281,16 @@ export namespace WebSocket { } pendingOps.set(diff.id, [{ diff, socket }]); if (diff.diff.$addToSet) { - return GetRefFieldLocal([diff.id, (result?: Transferable) => addToListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own + return GetRefFieldLocal([diff.id, (result?: serializedDoctype) => addToListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own } if (diff.diff.$remFromSet) { - return GetRefFieldLocal([diff.id, (result?: Transferable) => remFromListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own + return GetRefFieldLocal([diff.id, (result?: serializedDoctype) => remFromListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own } // eslint-disable-next-line no-use-before-define return SetField(socket, diff); } function SetField(socket: Socket, diff: Diff /* , curListItems?: Transferable */) { Database.Instance.update(diff.id, diff.diff, () => socket.broadcast.emit(MessageStore.UpdateField.Message, diff), false); - const docfield = diff.diff.$set || diff.diff.$unset; - if (docfield) { - const update: any = { id: diff.id }; - let dynfield = false; - // eslint-disable-next-line no-restricted-syntax - for (let key in docfield) { - // eslint-disable-next-line no-continue - if (!key.startsWith('fields.')) continue; - dynfield = true; - const val = docfield[key]; - key = key.substring(7); - Object.values(suffixMap).forEach(suf => { - update[key + getSuffix(suf)] = { set: null }; - }); - const term = ToSearchTerm(val); - if (term !== undefined) { - const { suffix, value } = term; - update[key + suffix] = { set: value }; - if (key.endsWith('modificationDate')) { - update['modificationDate' + suffix] = value; - } - } - } - if (dynfield) { - Search.updateDocument(update); - } - } dispatchNextOp(diff.id); } @@ -351,21 +298,15 @@ export namespace WebSocket { Database.Instance.delete({ _id: id }).then(() => { socket.broadcast.emit(MessageStore.DeleteField.Message, id); }); - - Search.deleteDocuments([id]); } function DeleteFields(socket: Socket, ids: string[]) { Database.Instance.delete({ _id: { $in: ids } }).then(() => { socket.broadcast.emit(MessageStore.DeleteFields.Message, ids); }); - Search.deleteDocuments(ids); } - function CreateField(newValue: any) { - Database.Instance.insert(newValue); - } - export async function initialize(isRelease: boolean, credentials: any) { + export async function initialize(isRelease: boolean, credentials: SecureContextOptions) { let io: Server; if (isRelease) { const { socketPort } = process.env; @@ -422,21 +363,14 @@ export namespace WebSocket { ServerUtils.Emit(socket, MessageStore.Foo, 'handshooken'); ServerUtils.AddServerHandler(socket, MessageStore.Bar, guid => barReceived(socket, guid)); - ServerUtils.AddServerHandler(socket, MessageStore.SetField, args => setField(socket, args)); - ServerUtils.AddServerHandlerCallback(socket, MessageStore.GetField, getField); - ServerUtils.AddServerHandlerCallback(socket, MessageStore.GetFields, getFields); if (isRelease) { ServerUtils.AddServerHandler(socket, MessageStore.DeleteAll, () => doDelete(false)); } - ServerUtils.AddServerHandler(socket, MessageStore.CreateField, CreateField); ServerUtils.AddServerHandler(socket, MessageStore.UpdateField, diff => UpdateField(socket, diff)); ServerUtils.AddServerHandler(socket, MessageStore.DeleteField, id => DeleteField(socket, id)); ServerUtils.AddServerHandler(socket, MessageStore.DeleteFields, ids => DeleteFields(socket, ids)); ServerUtils.AddServerHandler(socket, MessageStore.GesturePoints, content => processGesturePoints(socket, content)); - ServerUtils.AddServerHandler(socket, MessageStore.MobileInkOverlayTrigger, content => processOverlayTrigger(socket, content)); - ServerUtils.AddServerHandler(socket, MessageStore.UpdateMobileInkOverlayPosition, content => processUpdateOverlayPosition(socket, content)); - ServerUtils.AddServerHandler(socket, MessageStore.MobileDocumentUpload, content => processMobileDocumentUpload(socket, content)); ServerUtils.AddServerHandlerCallback(socket, MessageStore.GetRefField, GetRefField); ServerUtils.AddServerHandlerCallback(socket, MessageStore.GetRefFields, GetRefFields); -- cgit v1.2.3-70-g09d2 From 5960fa9635c28c2b609826005cb7595ec6b9fb75 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 13 Aug 2024 16:31:13 -0400 Subject: fixed bugs introduced cleaning up database list ops. --- src/client/DocServer.ts | 16 ++++++++-------- src/fields/Doc.ts | 2 +- src/server/Message.ts | 2 +- src/server/websocket.ts | 7 ++++++- 4 files changed, 16 insertions(+), 11 deletions(-) (limited to 'src/server/websocket.ts') diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index 33fa928f2..c644308b7 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -34,7 +34,7 @@ export namespace DocServer { throw new Error("Can't use DocServer without calling init first"); } let _UpdateField: (id: string, diff: serverOpType) => void = errorFunc; - let _CreateField: (field: Doc) => void = errorFunc; + let _CreateDocField: (field: Doc) => void = errorFunc; export function AddServerHandler(socket: Socket, message: Message, handler: (args: T) => void) { socket.on(message.Message, Utils.loggingCallback('Incoming', handler, message.Name)); @@ -132,7 +132,7 @@ export namespace DocServer { export function makeReadOnly() { if (!_isReadOnly) { _isReadOnly = true; - _CreateField = field => { + _CreateDocField = field => { _cache[field[Id]] = field; }; _UpdateField = emptyFunction; @@ -357,20 +357,20 @@ export namespace DocServer { } /** - * A wrapper around the function local variable _createField. + * A wrapper around the function local variable _CreateDocField. * This allows us to swap in different executions while comfortably * calling the same function throughout the code base (such as in Util.makeReadonly()) * @param field the [RefField] to be serialized and sent to the server to be stored in the database */ - export function CreateField(field: Doc) { + export function CreateDocField(field: Doc) { _cacheNeedsUpdate = true; - _CreateField(field); + _CreateDocField(field); } - function _CreateFieldImpl(field: Doc) { + function _CreateDocFieldImpl(field: Doc) { _cache[field[Id]] = field; const initialState = SerializationHelper.Serialize(field); - ClientUtils.CurrentUserEmail() !== 'guest' && DocServer.Emit(_socket, MessageStore.CreateField, initialState); + ClientUtils.CurrentUserEmail() !== 'guest' && DocServer.Emit(_socket, MessageStore.CreateDocField, initialState); } // NOTIFY THE SERVER OF AN UPDATE TO A DOC'S STATE @@ -462,7 +462,7 @@ export namespace DocServer { _GetCachedRefField = _GetCachedRefFieldImpl; SetObjGetRefField((_GetRefField = _GetRefFieldImpl)); SetObjGetRefFields((_GetRefFields = _GetRefFieldsImpl)); - _CreateField = _CreateFieldImpl; + _CreateDocField = _CreateDocFieldImpl; _UpdateField = _UpdateFieldImpl; /** diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index ad7609895..2ae9dbf02 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -329,7 +329,7 @@ export class Doc extends RefField { }); this[SelfProxy] = docProxy; if (!id || forceSave) { - DocServer.CreateField(docProxy); + DocServer.CreateDocField(docProxy); } // eslint-disable-next-line no-constructor-return return docProxy; // need to return the proxy from the constructor so that all our added fields will get called diff --git a/src/server/Message.ts b/src/server/Message.ts index 4599708c9..b904a5ba3 100644 --- a/src/server/Message.ts +++ b/src/server/Message.ts @@ -56,7 +56,7 @@ export namespace MessageStore { export const GetRefField = new Message('Get Ref Field'); export const GetRefFields = new Message('Get Ref Fields'); export const UpdateField = new Message('Update Ref Field'); - export const CreateField = new Message('Create Ref Field'); + export const CreateDocField = new Message('Create Ref Field'); export const DeleteField = new Message('Delete field'); export const DeleteFields = new Message('Delete fields'); diff --git a/src/server/websocket.ts b/src/server/websocket.ts index f10455680..f588151a5 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -240,7 +240,7 @@ export namespace WebSocket { // if the client and server have different versions of the data after // deletion, they will have different lengths and the server will // send its version of the data to the client - const sendBack = diff.diff.length !== remListItems.length; + const sendBack = diff.diff.length !== diff.diff.$set[updatefield].fields.length; delete diff.diff.length; Database.Instance.update( diff.id, @@ -306,6 +306,10 @@ export namespace WebSocket { }); } + function CreateDocField(newValue: serializedDoctype) { + Database.Instance.insert(newValue); + } + export async function initialize(isRelease: boolean, credentials: SecureContextOptions) { let io: Server; if (isRelease) { @@ -367,6 +371,7 @@ export namespace WebSocket { ServerUtils.AddServerHandler(socket, MessageStore.DeleteAll, () => doDelete(false)); } + ServerUtils.AddServerHandler(socket, MessageStore.CreateDocField, CreateDocField); ServerUtils.AddServerHandler(socket, MessageStore.UpdateField, diff => UpdateField(socket, diff)); ServerUtils.AddServerHandler(socket, MessageStore.DeleteField, id => DeleteField(socket, id)); ServerUtils.AddServerHandler(socket, MessageStore.DeleteFields, ids => DeleteFields(socket, ids)); -- cgit v1.2.3-70-g09d2 From 25ea424ab2e6c32272e828b98822eb32f1fe2cab Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 15 Aug 2024 11:14:04 -0400 Subject: cleaned up server list add/rem. --- src/ServerUtils.ts | 10 +- src/Utils.ts | 16 +- src/client/views/DocComponent.tsx | 4 +- src/client/views/StyleProvider.tsx | 3 +- src/client/views/collections/TabDocView.tsx | 10 +- src/client/views/collections/TreeView.tsx | 6 +- src/client/views/nodes/DocumentContentsView.tsx | 3 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 38 ++-- src/client/views/nodes/trails/PresBox.tsx | 98 ++++---- src/client/views/nodes/trails/SlideEffect.tsx | 2 +- src/fields/ObjectField.ts | 5 +- src/fields/RichTextUtils.ts | 56 +++-- src/fields/util.ts | 4 +- src/server/database.ts | 2 +- src/server/websocket.ts | 248 +++++++-------------- 15 files changed, 201 insertions(+), 304 deletions(-) (limited to 'src/server/websocket.ts') diff --git a/src/ServerUtils.ts b/src/ServerUtils.ts index 7e821cda2..904541fc7 100644 --- a/src/ServerUtils.ts +++ b/src/ServerUtils.ts @@ -9,20 +9,20 @@ export namespace ServerUtils { socket.emit(message.Message, args); } - export function AddServerHandler(socket: Socket, message: Message, handler: (args: T) => any) { + export function AddServerHandler(socket: Socket, message: Message, handler: (args: T) => void) { socket.on(message.Message, Utils.loggingCallback('Incoming', handler, message.Name)); } - export function AddServerHandlerCallback(socket: Socket, message: Message, handler: (args: [T, (res: any) => any]) => any) { - socket.on(message.Message, (arg: T, fn: (res: any) => any) => { + export function AddServerHandlerCallback(socket: Socket, message: Message, handler: (args: [T, (res: unknown) => void]) => void) { + socket.on(message.Message, (arg: T, fn: (res: unknown) => void) => { Utils.log('S receiving', message.Name, arg, true); handler([arg, Utils.loggingCallback('S sending', fn, message.Name)]); }); } - export type RoomHandler = (socket: Socket, room: string) => any; + export type RoomHandler = (socket: Socket, room: string) => void; export type UsedSockets = Socket; export type RoomMessage = 'create or join' | 'created' | 'joined'; export function AddRoomHandler(socket: Socket, message: RoomMessage, handler: RoomHandler) { - socket.on(message, (room: any) => handler(socket, room)); + socket.on(message, room => handler(socket, room)); } } diff --git a/src/Utils.ts b/src/Utils.ts index 23ae38bdb..0590c6930 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-namespace */ import * as uuid from 'uuid'; export function clamp(n: number, lower: number, upper: number) { @@ -23,6 +24,7 @@ export namespace Utils { export const loggingEnabled = false; export const logFilter: number | undefined = undefined; + // eslint-disable-next-line @typescript-eslint/no-explicit-any export function log(prefixIn: string, messageName: string, messageIn: any, receiving: boolean) { let prefix = prefixIn; let message = messageIn; @@ -38,8 +40,9 @@ export namespace Utils { console.log(`${prefix}: ${idString}, ${receiving ? 'receiving' : 'sending'} ${messageName} with data ${JSON.stringify(message)} `); } - export function loggingCallback(prefix: string, func: (args: any) => any, messageName: string) { - return (args: any) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + export function loggingCallback(prefix: string, func: (args: any) => void, messageName: string) { + return (args: unknown) => { log(prefix, messageName, args, true); func(args); }; @@ -47,7 +50,9 @@ export namespace Utils { export function TraceConsoleLog() { ['log', 'warn'].forEach(method => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any const old = (console as any)[method]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any (console as any)[method] = function (...args: any[]) { let stack = new Error('').stack?.split(/\n/); // Chrome includes a single "Error" line, FF doesn't. @@ -158,7 +163,7 @@ export function timenow() { const now = new Date(); let ampm = 'am'; let h = now.getHours(); - let m: any = now.getMinutes(); + let m: string | number = now.getMinutes(); if (h >= 12) { if (h > 12) h -= 12; ampm = 'pm'; @@ -201,7 +206,7 @@ export function intersectRect(r1: { left: number; top: number; width: number; he export function stringHash(s?: string) { // eslint-disable-next-line no-bitwise - return !s ? undefined : Math.abs(s.split('').reduce((a: any, b: any) => (n => n & n)((a << 5) - a + b.charCodeAt(0)), 0)); + return !s ? undefined : Math.abs(s.split('').reduce((a, b) => (n => n & n)((a << 5) - a + b.charCodeAt(0)), 0)); } export function percent2frac(percent: string) { @@ -224,8 +229,6 @@ export function emptyFunction() { return undefined; } -export const emptyPath: any[] = []; - export function unimplementedFunction() { throw new Error('This function is not implemented, but should be.'); } @@ -246,6 +249,7 @@ export function DeepCopy(source: Map, predicate?: Predicate) { export namespace JSONUtils { export function tryParse(source: string) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any let results: any; try { results = JSON.parse(source); diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index e5752dcd2..e351e2dec 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -93,7 +93,7 @@ export function ViewBoxBaseComponent

() { * This is the unique data repository for a dcoument that stores the intrinsic document data */ @computed get dataDoc() { - return this.Document.isTemplateForField || this.Document.isTemplateDoc ? this._props.TemplateDataDocument ?? this.Document[DocData] : this.Document[DocData]; + return this.Document.isTemplateForField || this.Document.isTemplateDoc ? (this._props.TemplateDataDocument ?? this.Document[DocData]) : this.Document[DocData]; } /** @@ -151,7 +151,7 @@ export function ViewBoxAnnotatableComponent

() { * This is the unique data repository for a dcoument that stores the intrinsic document data */ @computed get dataDoc() { - return this.Document.isTemplateForField || this.Document.isTemplateDoc ? this._props.TemplateDataDocument ?? this.Document[DocData] : this.Document[DocData]; + return this.Document.isTemplateForField || this.Document.isTemplateDoc ? (this._props.TemplateDataDocument ?? this.Document[DocData]) : this.Document[DocData]; } /** diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 2792955a0..374f8ca3a 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -13,7 +13,6 @@ import { Id } from '../../fields/FieldSymbols'; import { ScriptField } from '../../fields/ScriptField'; import { BoolCast, Cast, DocCast, ImageCast, NumCast, ScriptCast, StrCast } from '../../fields/Types'; import { AudioAnnoState } from '../../server/SharedMediaTypes'; -import { emptyPath } from '../../Utils'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { IsFollowLinkScript } from '../documents/DocUtils'; import { SnappingManager } from '../util/SnappingManager'; @@ -406,5 +405,5 @@ export function DashboardStyleProvider(doc: Opt, props: Opt } export function returnEmptyDocViewList() { - return emptyPath; + return [] as DocumentView[]; } diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index f168db81b..31b6be927 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -7,7 +7,7 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import ResizeObserver from 'resize-observer-polyfill'; -import { ClientUtils, DashColor, lightOrDark, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '../../../ClientUtils'; +import { ClientUtils, DashColor, lightOrDark, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '../../../ClientUtils'; import { emptyFunction } from '../../../Utils'; import { Doc, Opt, returnEmptyDoclist } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; @@ -157,8 +157,8 @@ export class TabMinimapView extends ObservableReactComponent { PanelWidth={this.PanelWidth} PanelHeight={this.PanelHeight} styleProvider={DefaultStyleProvider} - childFilters={CollectionDockingView.Instance?.childDocFilters ?? returnEmptyDocViewList} - childFiltersByRanges={CollectionDockingView.Instance?.childDocRangeFilters ?? returnEmptyDocViewList} + childFilters={CollectionDockingView.Instance?.childDocFilters ?? returnEmptyFilter} + childFiltersByRanges={CollectionDockingView.Instance?.childDocRangeFilters ?? returnEmptyFilter} searchFilterDocs={CollectionDockingView.Instance?.searchFilterDocs ?? returnEmptyDoclist} addDocument={undefined} removeDocument={this.remDocTab} diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index c0fe7a894..b10a521ca 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -6,7 +6,7 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { ClientUtils, lightOrDark, return18, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick } from '../../../ClientUtils'; import { emptyFunction } from '../../../Utils'; -import { Doc, DocListCast, Field, FieldResult, FieldType, Opt, StrListCast, returnEmptyDoclist } from '../../../fields/Doc'; +import { Doc, DocListCast, Field, FieldType, Opt, StrListCast, returnEmptyDoclist } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; @@ -249,7 +249,7 @@ export class TreeView extends ObservableReactComponent { return []; } - const runningChildren: FieldResult[] = []; + const runningChildren: Doc[] = []; childList.forEach(child => { if (child.runProcess && TreeView.GetRunningChildren.get(child)) { if (child.runProcess) { @@ -261,7 +261,7 @@ export class TreeView extends ObservableReactComponent { return runningChildren; }; - static GetRunningChildren = new Map FieldResult[]>(); + static GetRunningChildren = new Map Doc[]>(); static ToggleChildrenRun = new Map void>(); constructor(props: TreeViewProps) { super(props); diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index b178d6554..15baebae1 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -192,6 +192,7 @@ export class DocumentContentsView extends ObservableReactComponent 12 || !layoutFrame || !this.layoutDoc || GetEffectiveAcl(this.layoutDoc) === AclPrivate ? null : ( new FormattedTextBoxComment() }), + ], + }; + } private static nodeViews: (self: FormattedTextBox) => { [key: string]: NodeViewConstructor }; /** * Initialize the class with all the plugin node view components @@ -108,7 +123,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent; - private _keymap: KeyMap | undefined = undefined; private _rules: RichTextRules | undefined; private _forceUncollapse = true; // if the cursor doesn't move between clicks, then the selection will disappear for some reason. This flags the 2nd click as happening on a selection which allows bullet points to toggle private _break = true; @@ -128,20 +142,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent new FormattedTextBoxComment() }), - ], - }; + return FormattedTextBox.MakeConfig(this._rules, this._props); } public get EditorView() { @@ -1380,11 +1382,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { - this._props.rootSelected?.() && RichTextMenu.Instance && (RichTextMenu.Instance.view = newView); - return new RichTextMenuPlugin({ editorProps: this._props }); + props?.rootSelected?.() && RichTextMenu.Instance && (RichTextMenu.Instance.view = newView); + return new RichTextMenuPlugin({ editorProps: props }); }), }); } diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 0c73400a9..c403f9415 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -1,5 +1,3 @@ -/* eslint-disable jsx-a11y/no-static-element-interactions */ -/* eslint-disable jsx-a11y/click-events-have-key-events */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; import Slider from '@mui/material/Slider'; @@ -32,7 +30,7 @@ import { dropActionType } from '../../../util/DropActionTypes'; import { ScriptingGlobals } from '../../../util/ScriptingGlobals'; import { SerializationHelper } from '../../../util/SerializationHelper'; import { SnappingManager } from '../../../util/SnappingManager'; -import { undoBatch, UndoManager } from '../../../util/UndoManager'; +import { undoable, undoBatch, UndoManager } from '../../../util/UndoManager'; import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; import { CollectionFreeFormPannableContents } from '../../collections/collectionFreeForm/CollectionFreeFormPannableContents'; import { CollectionView } from '../../collections/CollectionView'; @@ -191,7 +189,7 @@ export class PresBox extends ViewBoxBaseComponent() { @computed get isTreeOrStack() { - return [CollectionViewType.Tree, CollectionViewType.Stacking].includes(StrCast(this.layoutDoc._type_collection) as any); + return [CollectionViewType.Tree, CollectionViewType.Stacking].includes(StrCast(this.layoutDoc._type_collection) as CollectionViewType); } @computed get isTree() { return this.layoutDoc._type_collection === CollectionViewType.Tree; @@ -304,7 +302,7 @@ export class PresBox extends ViewBoxBaseComponent() { // 'Play on next' for audio or video therefore first navigate to the audio/video before it should be played startTempMedia = (targetDoc: Doc, activeItem: Doc) => { const duration: number = NumCast(activeItem.config_clipEnd) - NumCast(activeItem.config_clipStart); - if ([DocumentType.VID, DocumentType.AUDIO].includes(targetDoc.type as any)) { + if ([DocumentType.VID, DocumentType.AUDIO].includes(targetDoc.type as DocumentType)) { const targMedia = DocumentView.getDocumentView(targetDoc); targMedia?.ComponentView?.playFrom?.(NumCast(activeItem.config_clipStart), NumCast(activeItem.config_clipStart) + duration); } @@ -312,7 +310,7 @@ export class PresBox extends ViewBoxBaseComponent() { stopTempMedia = (targetDocField: FieldResult) => { const targetDoc = DocCast(DocCast(targetDocField).annotationOn) ?? DocCast(targetDocField); - if ([DocumentType.VID, DocumentType.AUDIO].includes(targetDoc.type as any)) { + if ([DocumentType.VID, DocumentType.AUDIO].includes(targetDoc.type as DocumentType)) { const targMedia = DocumentView.getDocumentView(targetDoc); targMedia?.ComponentView?.Pause?.(); } @@ -364,7 +362,7 @@ export class PresBox extends ViewBoxBaseComponent() { this.setIsRecording(false); this.setIsLoading(true); - const currSlideProperties: { [key: string]: any } = {}; + const currSlideProperties: { [key: string]: FieldResult } = {}; gptSlideProperties.forEach(key => { if (this.activeItem[key]) { currSlideProperties[key] = this.activeItem[key]; @@ -554,7 +552,7 @@ export class PresBox extends ViewBoxBaseComponent() { } }); static pinDataTypes(target?: Doc): dataTypes { - const targetType = target?.type as any; + const targetType = target?.type as DocumentType; const inkable = [DocumentType.INK].includes(targetType); const scrollable = [DocumentType.PDF, DocumentType.RTF, DocumentType.WEB].includes(targetType) || target?._type_collection === CollectionViewType.Stacking; const pannable = [DocumentType.IMG, DocumentType.PDF].includes(targetType) || (targetType === DocumentType.COL && target?._type_collection === CollectionViewType.Freeform); @@ -759,8 +757,8 @@ export class PresBox extends ViewBoxBaseComponent() { const doc = DocCast(DocServer.GetCachedRefField(data.id)); if (doc) { transitioned.add(doc); - const field = !data.data ? undefined : await SerializationHelper.Deserialize(data.data); - const tfield = !data.text ? undefined : await SerializationHelper.Deserialize(data.text); + const field = !data.data ? undefined : ((await SerializationHelper.Deserialize(data.data)) as FieldType); + const tfield = !data.text ? undefined : ((await SerializationHelper.Deserialize(data.text)) as FieldType); doc._dataTransition = `all ${transTime}ms`; doc.x = data.x; doc.y = data.y; @@ -858,7 +856,7 @@ export class PresBox extends ViewBoxBaseComponent() { effect: activeItem, noSelect: true, openLocation: targetDoc.type === DocumentType.PRES ? ((OpenWhere.replace + ':' + PresBox.PanelName) as OpenWhere) : OpenWhere.addLeft, - easeFunc: StrCast(activeItem.presentation_easeFunc, 'ease') as any, + easeFunc: StrCast(activeItem.presentation_easeFunc, 'ease') as 'linear' | 'ease', zoomTextSelections: BoolCast(activeItem.presentation_zoomText), playAudio: BoolCast(activeItem.presentation_playAudio), playMedia: activeItem.presentation_mediaStart === 'auto', @@ -1101,7 +1099,7 @@ export class PresBox extends ViewBoxBaseComponent() { */ @undoBatch viewChanged = action((e: React.ChangeEvent) => { - const typeCollection = (e.target as any).selectedOptions[0].value as CollectionViewType; + const typeCollection = (e.target as HTMLSelectElement).selectedOptions[0].value as CollectionViewType; this.layoutDoc.presFieldKey = this.fieldKey + (typeCollection === CollectionViewType.Tree ? '-linearized' : ''); // pivot field may be set by the user in timeline view (or some other way) -- need to reset it here [CollectionViewType.Tree || CollectionViewType.Stacking].includes(typeCollection) && (this.Document._pivotField = undefined); @@ -1111,30 +1109,8 @@ export class PresBox extends ViewBoxBaseComponent() { } }); - /** - * Called when the user changes the view type - * Either 'List' (stacking) or 'Slides' (carousel) - */ - // @undoBatch - mediaStopChanged = action((e: React.ChangeEvent) => { - const { activeItem } = this; - const stopDoc = (e.target as any).selectedOptions[0].value as string; - const stopDocIndex = Number(stopDoc[0]); - activeItem.mediaStopDoc = stopDocIndex; - if (this.childDocs[stopDocIndex - 1].mediaStopTriggerList) { - const list = DocListCast(this.childDocs[stopDocIndex - 1].mediaStopTriggerList); - list.push(activeItem); - // this.childDocs[stopDocIndex - 1].mediaStopTriggerList = list;\ - } else { - this.childDocs[stopDocIndex - 1].mediaStopTriggerList = new List(); - const list = DocListCast(this.childDocs[stopDocIndex - 1].mediaStopTriggerList); - list.push(activeItem); - // this.childDocs[stopDocIndex - 1].mediaStopTriggerList = list; - } - }); - movementName = action((activeItem: Doc) => { - if (![PresMovement.Zoom, PresMovement.Pan, PresMovement.Center, PresMovement.Jump, PresMovement.None].includes(StrCast(activeItem.presentation_movement) as any)) { + if (![PresMovement.Zoom, PresMovement.Pan, PresMovement.Center, PresMovement.Jump, PresMovement.None].includes(StrCast(activeItem.presentation_movement) as PresMovement)) { return PresMovement.Zoom; } return StrCast(activeItem.presentation_movement); @@ -1185,7 +1161,7 @@ export class PresBox extends ViewBoxBaseComponent() { * Method to get the list of selected items in the order in which they have been selected */ @computed get listOfSelected() { - return Array.from(this.selectedArray).map((doc: Doc, index: any) => { + return Array.from(this.selectedArray).map((doc, index) => { const curDoc = Cast(doc, Doc, null); const tagDoc = Cast(curDoc.presentation_targetDoc, Doc, null); if (curDoc && curDoc === this.activeItem) @@ -1193,7 +1169,7 @@ export class PresBox extends ViewBoxBaseComponent() { // eslint-disable-next-line react/no-array-index-key

- {index + 1}. {curDoc.title} + {index + 1}. {StrCast(curDoc.title)})
); @@ -1201,14 +1177,14 @@ export class PresBox extends ViewBoxBaseComponent() { return ( // eslint-disable-next-line react/no-array-index-key
- {index + 1}. {curDoc.title} + {index + 1}. {StrCast(curDoc.title)}
); if (curDoc) return ( // eslint-disable-next-line react/no-array-index-key
- {index + 1}. {curDoc.title} + {index + 1}. {StrCast(curDoc.title)}
); return null; @@ -1301,13 +1277,14 @@ export class PresBox extends ViewBoxBaseComponent() { switch (e.key) { case 'Backspace': if (this.layoutDoc.presentation_status === 'edit') { - undoBatch( + undoable( action(() => { Array.from(this.selectedArray).forEach(doc => this.removeDocument(doc)); this.clearSelectedArray(); this._eleArray.length = 0; this._dragArray.length = 0; - }) + }), + 'delete slides' )(); handled = true; } @@ -1488,7 +1465,7 @@ export class PresBox extends ViewBoxBaseComponent() { ); }; // Converts seconds to ms and updates presentation_transition - public static SetTransitionTime = (number: String, setter: (timeInMS: number) => void, change?: number) => { + public static SetTransitionTime = (number: string, setter: (timeInMS: number) => void, change?: number) => { let timeInMS = Number(number) * 1000; if (change) timeInMS += change; if (timeInMS < 100) timeInMS = 100; @@ -1497,7 +1474,7 @@ export class PresBox extends ViewBoxBaseComponent() { }; @undoBatch - updateTransitionTime = (number: String, change?: number) => { + updateTransitionTime = (number: string, change?: number) => { PresBox.SetTransitionTime( number, (timeInMS: number) => @@ -1510,7 +1487,7 @@ export class PresBox extends ViewBoxBaseComponent() { // Converts seconds to ms and updates presentation_transition @undoBatch - updateZoom = (number: String, change?: number) => { + updateZoom = (number: string, change?: number) => { let scale = Number(number) / 100; if (change) scale += change; if (scale < 0.01) scale = 0.01; @@ -1524,7 +1501,7 @@ export class PresBox extends ViewBoxBaseComponent() { * Converts seconds to ms and updates presentation_duration */ @undoBatch - updateDurationTime = (number: String, change?: number) => { + updateDurationTime = (number: string, change?: number) => { let timeInMS = Number(number) * 1000; if (change) timeInMS += change; if (timeInMS < 100) timeInMS = 100; @@ -1608,9 +1585,9 @@ export class PresBox extends ViewBoxBaseComponent() { }); }; - static _sliderBatch: any; + static _sliderBatch: UndoManager.Batch | undefined; static endBatch = () => { - PresBox._sliderBatch.end(); + PresBox._sliderBatch?.end(); document.removeEventListener('pointerup', PresBox.endBatch, true); }; public static inputter = (min: string, step: string, max: string, value: number, active: boolean, change: (val: string) => void, hmargin?: number) => ( @@ -1704,7 +1681,7 @@ export class PresBox extends ViewBoxBaseComponent() { - {[DocumentType.AUDIO, DocumentType.VID].includes(targetType as any as DocumentType) ? null : ( + {[DocumentType.AUDIO, DocumentType.VID].includes(targetType as DocumentType) ? null : ( <>
Slide Duration
@@ -1847,7 +1824,7 @@ export class PresBox extends ViewBoxBaseComponent() { if (activeItem && this.targetDoc) { const transitionSpeed = activeItem.presentation_transition ? NumCast(activeItem.presentation_transition) / 1000 : 0.5; const zoom = NumCast(activeItem.config_zoom, 1) * 100; - const effect = StrCast(activeItem.presentation_effect) ? (StrCast(activeItem.presentation_effect) as any as PresEffect) : PresEffect.None; + const effect = StrCast(activeItem.presentation_effect) ? (StrCast(activeItem.presentation_effect) as PresEffect) : PresEffect.None; const direction = StrCast(activeItem.presentation_effectDirection) as PresEffectDirection; return ( @@ -2660,24 +2637,26 @@ export class PresBox extends ViewBoxBaseComponent() {
e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
{ this.enterMinimize(); this.turnOffEdit(true); this.gotoDocument(this.itemIndex, this.activeItem); - }) + }), + 'minimze presentation' )}> Mini-player
{ this.layoutDoc.presentation_status = 'manual'; this.initializePresState(this.itemIndex); this.turnOffEdit(true); this.gotoDocument(this.itemIndex, this.activeItem); - }) + }), + 'make presentation manual' )}> Sidebar player
@@ -2773,13 +2752,13 @@ export class PresBox extends ViewBoxBaseComponent() {
{ + onClick={undoable(() => { if (this.childDocs.length) { this.layoutDoc.presentation_status = 'manual'; this.initializePresState(this.itemIndex); this.gotoDocument(this.itemIndex, this.activeItem); } - })}> + }, 'start presentation')}>
200 ? 'inline-flex' : 'none' }}>  Present
@@ -2911,11 +2890,12 @@ export class PresBox extends ViewBoxBaseComponent() { {this._props.PanelWidth() > 250 ? (
{ this.layoutDoc.presentation_status = PresStatus.Edit; clearTimeout(this._presTimer); - }) + }), + 'edit presetnation' )}> EXIT
@@ -2988,7 +2968,7 @@ export class PresBox extends ViewBoxBaseComponent() { }; sort = (treeViewMap: Map) => [...treeViewMap.entries()].sort((a: [Doc, number], b: [Doc, number]) => (a[1] > b[1] ? 1 : a[1] < b[1] ? -1 : 0)).map(kv => kv[0]); - + emptyHierarchy = []; render() { // needed to ensure that the childDocs are loaded for looking up fields this.childDocs.slice(); @@ -3086,7 +3066,7 @@ export class PresBox extends ViewBoxBaseComponent() { ScreenToLocalTransform={this.getTransform} AddToMap={this.AddToMap} RemFromMap={this.RemFromMap} - hierarchyIndex={emptyPath} + hierarchyIndex={this.emptyHierarchy} /> ) : null}
diff --git a/src/client/views/nodes/trails/SlideEffect.tsx b/src/client/views/nodes/trails/SlideEffect.tsx index 00039e3cb..a114c231f 100644 --- a/src/client/views/nodes/trails/SlideEffect.tsx +++ b/src/client/views/nodes/trails/SlideEffect.tsx @@ -103,7 +103,7 @@ export default function SpringAnimation({ doc, dir, springSettings, presEffect, api.start({ loop: infinite, delay: infinite ? 500 : 0 }); } }, [inView]); - const animatedDiv = (style: any) => ( + const animatedDiv = (style: object) => ( `${val}`) }}> {children} diff --git a/src/fields/ObjectField.ts b/src/fields/ObjectField.ts index 5f31208eb..c533cb596 100644 --- a/src/fields/ObjectField.ts +++ b/src/fields/ObjectField.ts @@ -12,9 +12,8 @@ export interface serializedDoctype { export type serverOpType = { $set?: serializedFieldsType; // $unset?: { [key: string]: unknown }; - $remFromSet?: { [key: string]: { fields: serializedFieldType[] } | { deleteCount: number; start: number } | undefined; hint?: { deleteCount: number; start: number } }; - $addToSet?: serializedFieldsType; - length?: number; + $remFromSet?: { [key: string]: { fields: serializedFieldType[] } | { deleteCount: number; start: number } | number | undefined; length: number; hint: { deleteCount: number; start: number } | undefined }; + $addToSet?: { [key: string]: { fields: serializedFieldType[] } | number | undefined; length: number }; }; export abstract class ObjectField { // prettier-ignore diff --git a/src/fields/RichTextUtils.ts b/src/fields/RichTextUtils.ts index 3763dcd2c..d1316d256 100644 --- a/src/fields/RichTextUtils.ts +++ b/src/fields/RichTextUtils.ts @@ -1,9 +1,10 @@ +/* eslint-disable @typescript-eslint/no-namespace */ /* eslint-disable no-await-in-loop */ /* eslint-disable no-use-before-define */ import { AssertionError } from 'assert'; import * as Color from 'color'; import { docs_v1 as docsV1 } from 'googleapis'; -import { Fragment, Mark, Node } from 'prosemirror-model'; +import { Fragment, Mark, Node, Schema } from 'prosemirror-model'; import { sinkListItem } from 'prosemirror-schema-list'; import { EditorState, TextSelection, Transaction } from 'prosemirror-state'; import { ClientUtils, DashColor } from '../ClientUtils'; @@ -26,7 +27,7 @@ export namespace RichTextUtils { const joiner = ''; export const Initialize = (initial?: string) => { - const content: any[] = []; + const content: object[] = []; const state = { doc: { type: 'doc', @@ -80,8 +81,10 @@ export namespace RichTextUtils { // Preserve the current state, but re-write the content to be the blocks const parsed = JSON.parse(oldState ? oldState.Data : Initialize()); parsed.doc.content = elements.map(text => { - const paragraph: any = { type: 'paragraph' }; - text.length && (paragraph.content = [{ type: 'text', marks: [], text }]); // An empty paragraph gets treated as a line break + const paragraph: object = { + type: 'paragraph', + content: text.length ? [{ type: 'text', marks: [], text }] : undefined, // An empty paragraph gets treated as a line break + }; return paragraph; }); @@ -164,7 +167,7 @@ export namespace RichTextUtils { const inlineObjectMap = await parseInlineObjects(document); const title = document.title!; const { text, paragraphs } = GoogleApiClientUtils.Docs.Utils.extractText(document); - let state = EditorState.create(new FormattedTextBox({} as any).config); + let state = EditorState.create(FormattedTextBox.MakeConfig()); const structured = parseLists(paragraphs); let position = 3; @@ -253,17 +256,20 @@ export namespace RichTextUtils { return groups; }; - const listItem = (lschema: any, runs: docsV1.Schema$TextRun[]): Node => lschema.node('list_item', null, paragraphNode(lschema, runs)); + const listItem = (lschema: Schema, runs: docsV1.Schema$TextRun[]): Node => lschema.node('list_item', null, paragraphNode(lschema, runs)); - const list = (lschema: any, items: Node[]): Node => lschema.node('ordered_list', { mapStyle: 'bullet' }, items); + const list = (lschema: Schema, items: Node[]): Node => lschema.node('ordered_list', { mapStyle: 'bullet' }, items); - const paragraphNode = (lschema: any, runs: docsV1.Schema$TextRun[]): Node => { - const children = runs.map(run => textNode(lschema, run)).filter(child => child !== undefined); + const paragraphNode = (lschema: Schema, runs: docsV1.Schema$TextRun[]): Node => { + const children = runs + .map(run => textNode(lschema, run)) + .filter(child => child !== undefined) + .map(child => child!); const fragment = children.length ? Fragment.from(children) : undefined; return lschema.node('paragraph', null, fragment); }; - const imageNode = (lschema: any, image: ImageTemplate, textNote: Doc) => { + const imageNode = (lschema: Schema, image: ImageTemplate, textNote: Doc) => { const { url: src, width, agnostic } = image; let docId: string; const guid = Utils.GenerateDeterministicGuid(agnostic); @@ -279,7 +285,7 @@ export namespace RichTextUtils { return lschema.node('image', { src, agnostic, width, docId, float: null }); }; - const textNode = (lschema: any, run: docsV1.Schema$TextRun) => { + const textNode = (lschema: Schema, run: docsV1.Schema$TextRun) => { const text = run.content!.removeTrailingNewlines(); return text.length ? lschema.text(text, styleToMarks(lschema, run.textStyle)) : undefined; }; @@ -291,29 +297,33 @@ export namespace RichTextUtils { ['fontSize', 'pFontSize'], ]); - const styleToMarks = (lschema: any, textStyle?: docsV1.Schema$TextStyle) => { + const styleToMarks = (lschema: Schema, textStyle?: docsV1.Schema$TextStyle) => { if (!textStyle) { return undefined; } const marks: Mark[] = []; Object.keys(textStyle).forEach(key => { const targeted = key as keyof docsV1.Schema$TextStyle; - const value = textStyle[targeted] as any; + const value = textStyle[targeted]; if (value) { - const attributes: any = {}; + const attributes: { [key: string]: number | string } = {}; let converted = StyleToMark.get(targeted) || targeted; - value.url && (attributes.href = value.url); - if (value.color) { - const object = value.color.rgbColor; - attributes.color = Color.rgb(['red', 'green', 'blue'].map(color => object[color] * 255 || 0)).hex(); + const urlValue = value as docsV1.Schema$Link; + urlValue.url && (attributes.href = urlValue.url); + const colValue = value as docsV1.Schema$OptionalColor; + const object = colValue.color?.rgbColor; + if (object) { + attributes.color = Color.rgb(['red', 'green', 'blue'].map(color => (object as { [key: string]: number })[color] * 255 || 0)).hex(); } - if (value.magnitude) { - attributes.fontSize = value.magnitude; + const magValue = value as docsV1.Schema$Dimension; + if (magValue.magnitude) { + attributes.fontSize = magValue.magnitude; } + const fontValue = value as docsV1.Schema$WeightedFontFamily; if (converted === 'weightedFontFamily') { - converted = ImportFontFamilyMapping.get(value.fontFamily) || 'timesNewRoman'; + converted = (fontValue.fontFamily && ImportFontFamilyMapping.get(fontValue.fontFamily)) || 'timesNewRoman'; } const mapped = lschema.marks[converted]; @@ -388,7 +398,7 @@ export namespace RichTextUtils { continue; } let converted = MarkToStyle.get(markName) || (markName as keyof docsV1.Schema$TextStyle); - let value: any = true; + let value: unknown = true; if (!converted) { // eslint-disable-next-line no-continue continue; @@ -436,7 +446,7 @@ export namespace RichTextUtils { converted = 'fontSize'; value = { magnitude: parseInt(matches[1].replace('px', '')), unit: 'PT' }; } - textStyle[converted] = value; + textStyle[converted] = value as undefined; } if (Object.keys(textStyle).length) { requests.push(EncodeStyleUpdate(information)); diff --git a/src/fields/util.ts b/src/fields/util.ts index a5c56607c..60eadcdfd 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -398,9 +398,9 @@ export function containedFieldChangedHandler(container: ListImpl | Do const serializeItems = () => ({ __type: 'list', fields: diff?.items?.map((item: FieldType) => SerializationHelper.Serialize(item) as serializedFieldType) ?? [] }); // prettier-ignore const serverOp: serverOpType = diff?.op === '$addToSet' - ? { $addToSet: { ['fields.' + prop]: serializeItems() }, length: diff.length } + ? { $addToSet: { ['fields.' + prop]: serializeItems(), length: diff.length ??0 }} : diff?.op === '$remFromSet' - ? { $remFromSet: { ['fields.' + prop]: serializeItems(), hint: diff.hint}, length: diff.length } + ? { $remFromSet: { ['fields.' + prop]: serializeItems(), hint: diff.hint, length: diff.length ?? 0 } } : { $set: { ['fields.' + prop]: SerializationHelper.Serialize(liveContainedField) as {fields: serializedFieldType[]}} }; if (!(container instanceof Doc) || !container[UpdatingFromServer]) { diff --git a/src/server/database.ts b/src/server/database.ts index a93117349..975b9eb80 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -32,7 +32,7 @@ export namespace Database { try { const { connection } = mongoose; disconnect = async () => - new Promise(resolve => { + new Promise(resolve => { connection.close().then(resolve); }); if (connection.readyState === ConnectionStates.disconnected) { diff --git a/src/server/websocket.ts b/src/server/websocket.ts index f588151a5..ccbcb1c5f 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -49,12 +49,12 @@ export namespace WebSocket { DashStats.logUserLogin(userEmail); } - function GetRefFieldLocal([id, callback]: [string, (result?: serializedDoctype) => void]) { + function GetRefFieldLocal(id: string, callback: (result?: serializedDoctype | undefined) => void) { return Database.Instance.getDocument(id, callback); } function GetRefField([id, callback]: [string, (result?: serializedDoctype) => void]) { process.stdout.write(`+`); - GetRefFieldLocal([id, callback]); + GetRefFieldLocal(id, callback); } function GetRefFields([ids, callback]: [string[], (result?: serializedDoctype[]) => void]) { @@ -62,112 +62,46 @@ export namespace WebSocket { Database.Instance.getDocuments(ids, callback); } - const suffixMap: { [type: string]: string | [string, string | ((json: any) => any)] } = { - number: '_n', - string: '_t', - boolean: '_b', - image: ['_t', 'url'], - video: ['_t', 'url'], - pdf: ['_t', 'url'], - audio: ['_t', 'url'], - web: ['_t', 'url'], - map: ['_t', 'url'], - script: ['_t', value => value.script.originalScript], - RichTextField: ['_t', value => value.Text], - date: ['_d', value => new Date(value.date).toISOString()], - proxy: ['_i', 'fieldId'], - list: [ - '_l', - list => { - const results: any[] = []; - // eslint-disable-next-line no-use-before-define - list.fields.forEach((value: any) => ToSearchTerm(value) && results.push(ToSearchTerm(value)!.value)); - return results.length ? results : null; - }, - ], - }; - - function ToSearchTerm(valIn: any): { suffix: string; value: any } | undefined { - let val = valIn; - if (val === null || val === undefined) { - return undefined; - } - const type = val.__type || typeof val; - - let suffix = suffixMap[type]; - if (!suffix) { - return undefined; - } - if (Array.isArray(suffix)) { - const accessor = suffix[1]; - if (typeof accessor === 'function') { - val = accessor(val); - } else { - val = val[accessor]; - } - [suffix] = suffix; - } - return { suffix, value: val }; - } - - function getSuffix(value: string | [string, any]): string { - return typeof value === 'string' ? value : value[0]; - } const pendingOps = new Map(); - function dispatchNextOp(id: string) { - const next = pendingOps.get(id)!.shift(); + function dispatchNextOp(id: string): unknown { + const next = pendingOps.get(id)?.shift(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const nextOp = (res: boolean) => dispatchNextOp(id); if (next) { const { diff, socket } = next; - if (diff.diff.$addToSet) { - // eslint-disable-next-line no-use-before-define - return GetRefFieldLocal([diff.id, (result?: serializedDoctype) => addToListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own + // ideally, we'd call the Database update method for all actions, but for now we handle list insertion/removal on our own + switch (diff.diff.$addToSet ? 'add' : diff.diff.$remFromSet ? 'rem' : 'set') { + case 'add': return GetRefFieldLocal(id, (result) => addToListField(socket, diff, result, nextOp)); // prettier-ignore + case 'rem': return GetRefFieldLocal(id, (result) => remFromListField(socket, diff, result, nextOp)); // prettier-ignore + default: return Database.Instance.update(id, diff.diff, + () => nextOp(socket.broadcast.emit(MessageStore.UpdateField.Message, diff)), + false + ); // prettier-ignore } - if (diff.diff.$remFromSet) { - // eslint-disable-next-line no-use-before-define - return GetRefFieldLocal([diff.id, (result?: serializedDoctype) => remFromListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own - } - // eslint-disable-next-line no-use-before-define - return SetField(socket, diff); } - return !pendingOps.get(id)!.length && pendingOps.delete(id); + return !pendingOps.get(id)?.length && pendingOps.delete(id); } - function addToListField(socket: Socket, diffIn: Diff, listDoc?: serializedDoctype): void { - const diff = diffIn; - diff.diff.$set = diff.diff.$addToSet; - delete diff.diff.$addToSet; // convert add to set to a query of the current fields, and then a set of the composition of the new fields with the old ones - const updatefield = Array.from(Object.keys(diff.diff.$set ?? {}))[0]; - const newListItems = diff.diff.$set?.[updatefield]?.fields; - if (!newListItems) { - console.log('Error: addToListField - no new list items'); - return; - } - const listItems = listDoc?.fields?.[updatefield.replace('fields.', '')]?.fields.filter(item => item !== undefined) ?? []; - if (diff.diff.$set?.[updatefield]?.fields !== undefined) { + function addToListField(socket: Socket, diff: Diff, listDoc: serializedDoctype | undefined, cb: (res: boolean) => void): void { + const $addToSet = diff.diff.$addToSet as serializedFieldsType; + const updatefield = Array.from(Object.keys($addToSet ?? {}))[0]; + const newListItems = $addToSet?.[updatefield]?.fields; + + if (newListItems) { + const length = diff.diff.$addToSet?.length; + diff.diff.$set = $addToSet; // convert add to set to a query of the current fields, and then a set of the composition of the new fields with the old ones + delete diff.diff.$addToSet; // can't pass $set to Mongo, or it will do that insetead of $addToSet + const listItems = listDoc?.fields?.[updatefield.replace('fields.', '')]?.fields.filter(item => item) ?? []; diff.diff.$set[updatefield]!.fields = [...listItems, ...newListItems]; // , ...newListItems.filter((newItem: any) => newItem === null || !curList.some((curItem: any) => curItem.fieldId ? curItem.fieldId === newItem.fieldId : curItem.heading ? curItem.heading === newItem.heading : curItem === newItem))]; - const sendBack = diff.diff.length !== diff.diff.$set[updatefield]!.fields?.length; - delete diff.diff.length; - Database.Instance.update( - diff.id, - diff.diff, - () => { - if (sendBack) { - console.log('Warning: list modified during update. Composite list is being returned.'); - const { id } = socket; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (socket as any).id = ''; // bcz: HACK to reference private variable. this allows the update message to go back to the client that made the change. - socket.broadcast.emit(MessageStore.UpdateField.Message, diff); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (socket as any).id = id; - } else { - socket.broadcast.emit(MessageStore.UpdateField.Message, diff); - } - dispatchNextOp(diff.id); - }, - false - ); - } + + // if the client's list length is not the same as what we're writing to the server, + // then we need to send the server's version back to the client so that they are in synch. + // this could happen if another client made a change before the server receives the update from the first client + const target = length !== diff.diff.$set[updatefield].fields.length ? socket : socket.broadcast; + target === socket && console.log('Warning: SEND BACK: list modified during add update. Composite list is being returned.'); + Database.Instance.update(diff.id, diff.diff, () => cb(target.emit(MessageStore.UpdateField.Message, diff)), false); + } else cb(false); } /** @@ -206,15 +140,17 @@ export namespace WebSocket { * items to delete) * @param curListItems the server's current copy of the data */ - function remFromListField(socket: Socket, diffIn: Diff, curListItems?: serializedDoctype): void { - const diff = diffIn; - diff.diff.$set = diff.diff.$remFromSet as serializedFieldsType; - const hint = diff.diff.$remFromSet?.hint; - delete diff.diff.$remFromSet; - const updatefield = Array.from(Object.keys(diff.diff.$set ?? {}))[0]; - const remListItems = diff.diff.$set[updatefield]?.fields; - if (diff.diff.$set[updatefield] !== undefined && remListItems) { - const curList = curListItems?.fields?.[updatefield.replace('fields.', '')]?.fields.filter(f => f !== null) || []; + function remFromListField(socket: Socket, diff: Diff, curListItems: serializedDoctype | undefined, cb: (res: boolean) => void): void { + const $remFromSet = diff.diff.$remFromSet as serializedFieldsType; + const updatefield = Array.from(Object.keys($remFromSet ?? {}))[0]; + const remListItems = $remFromSet?.[updatefield]?.fields; + + if (remListItems) { + const hint = diff.diff.$remFromSet?.hint; + const length = diff.diff.$remFromSet?.length; + diff.diff.$set = $remFromSet; // convert rem from set to a query of the current fields, and then a set of the old fields minus the removed ones + delete diff.diff.$remFromSet; // can't pass $set to Mongo, or it will do that insetead of $remFromSet + const curList = curListItems?.fields?.[updatefield.replace('fields.', '')]?.fields.filter(f => f) ?? []; if (hint) { // indexesToRemove stores the indexes that we mark for deletion, which is later used to filter the list (delete the elements) @@ -227,83 +163,51 @@ export namespace WebSocket { if (closestIndex !== -1) { indexesToRemove.push(closestIndex); } else { - console.log('Item to delete was not found - index = -1'); + console.log('Item to delete was not found'); } } } diff.diff.$set[updatefield]!.fields = curList.filter((curItem, index) => !indexesToRemove.includes(index)); } else { - // go back to the original way to delete if we didn't receive - // a hint from the client + // if we didn't get a hint, remove all matching items from the list diff.diff.$set[updatefield]!.fields = curList?.filter(curItem => !remListItems.some(remItem => (remItem.fieldId ? remItem.fieldId === curItem.fieldId : remItem.heading ? remItem.heading === curItem.heading : remItem === curItem))); } - // if the client and server have different versions of the data after - // deletion, they will have different lengths and the server will - // send its version of the data to the client - const sendBack = diff.diff.length !== diff.diff.$set[updatefield].fields.length; - delete diff.diff.length; - Database.Instance.update( - diff.id, - diff.diff, - () => { - if (sendBack) { - // the two copies are different, so the server sends its copy. - console.log('SEND BACK'); - const { id } = socket; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (socket as any).id = ''; // bcz: HACK to access private variable this allows the update message to go back to the client that made the change. - socket.broadcast.emit(MessageStore.UpdateField.Message, diff); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (socket as any).id = id; - } else { - socket.broadcast.emit(MessageStore.UpdateField.Message, diff); - } - dispatchNextOp(diff.id); - }, - false - ); - } + + // if the client's list length is not the same as what we're writing to the server, + // then we need to send the server's version back to the client so that they are in synch. + // this could happen if another client made a change before the server receives the update from the first client + const target = length !== diff.diff.$set[updatefield].fields.length ? socket : socket.broadcast; + target === socket && console.log('Warning: SEND BACK: list modified during remove update. Composite list is being returned.'); + Database.Instance.update(diff.id, diff.diff, () => cb(target.emit(MessageStore.UpdateField.Message, diff)), false); + } else cb(false); } function UpdateField(socket: Socket, diff: Diff) { const curUser = socketMap.get(socket); - if (!curUser) return false; - const currentUsername = curUser.split(' ')[0]; - userOperations.set(currentUsername, userOperations.get(currentUsername) !== undefined ? userOperations.get(currentUsername)! + 1 : 0); + if (curUser) { + const currentUsername = curUser.split(' ')[0]; + userOperations.set(currentUsername, userOperations.get(currentUsername) !== undefined ? userOperations.get(currentUsername)! + 1 : 0); - if (CurUser !== socketMap.get(socket)) { - CurUser = socketMap.get(socket); - console.log('Switch User: ' + CurUser); - } - if (pendingOps.has(diff.id)) { - pendingOps.get(diff.id)!.push({ diff, socket }); - return true; - } - pendingOps.set(diff.id, [{ diff, socket }]); - if (diff.diff.$addToSet) { - return GetRefFieldLocal([diff.id, (result?: serializedDoctype) => addToListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own - } - if (diff.diff.$remFromSet) { - return GetRefFieldLocal([diff.id, (result?: serializedDoctype) => remFromListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own + if (CurUser !== socketMap.get(socket)) { + CurUser = socketMap.get(socket); + console.log('Switch User: ' + CurUser); + } + if (pendingOps.has(diff.id)) { + pendingOps.get(diff.id)!.push({ diff, socket }); + return true; + } + pendingOps.set(diff.id, [{ diff, socket }]); + return dispatchNextOp(diff.id); } - // eslint-disable-next-line no-use-before-define - return SetField(socket, diff); - } - function SetField(socket: Socket, diff: Diff /* , curListItems?: Transferable */) { - Database.Instance.update(diff.id, diff.diff, () => socket.broadcast.emit(MessageStore.UpdateField.Message, diff), false); - dispatchNextOp(diff.id); + return false; } function DeleteField(socket: Socket, id: string) { - Database.Instance.delete({ _id: id }).then(() => { - socket.broadcast.emit(MessageStore.DeleteField.Message, id); - }); + Database.Instance.delete({ _id: id }).then(() => socket.broadcast.emit(MessageStore.DeleteField.Message, id)); } function DeleteFields(socket: Socket, ids: string[]) { - Database.Instance.delete({ _id: { $in: ids } }).then(() => { - socket.broadcast.emit(MessageStore.DeleteFields.Message, ids); - }); + Database.Instance.delete({ _id: { $in: ids } }).then(() => socket.broadcast.emit(MessageStore.DeleteFields.Message, ids)); } function CreateDocField(newValue: serializedDoctype) { @@ -343,21 +247,19 @@ export namespace WebSocket { socket.in(room).emit('message', message); }); - socket.on('ipaddr', () => { + socket.on('ipaddr', () => networkInterfaces().keys?.forEach(dev => { if (dev.family === 'IPv4' && dev.address !== '127.0.0.1') { socket.emit('ipaddr', dev.address); } - }); - }); + }) + ); - socket.on('bye', () => { - console.log('received bye'); - }); + socket.on('bye', () => console.log('received bye')); socket.on('disconnect', () => { const currentUser = socketMap.get(socket); - if (!(currentUser === undefined)) { + if (currentUser !== undefined) { const currentUsername = currentUser.split(' ')[0]; DashStats.logUserLogout(currentUsername); delete timeMap[currentUsername]; -- cgit v1.2.3-70-g09d2 From 166d40bd856b85bd4bbde9f9ffe2c1ec0fb648d5 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 21 Aug 2024 10:57:53 -0400 Subject: more lint fixes after update --- eslint.config.mjs | 45 ++++++++++++++++++++++++- package-lock.json | 46 ++++++++++---------------- src/ClientUtils.ts | 1 - src/ServerUtils.ts | 1 - src/client/Network.ts | 2 +- src/client/documents/DocUtils.ts | 3 +- src/client/documents/Documents.ts | 4 +-- src/client/util/DictationManager.ts | 4 --- src/client/util/DragManager.ts | 1 - src/client/util/History.ts | 1 - src/client/util/InteractionUtils.tsx | 1 - src/client/util/ScriptingGlobals.ts | 2 +- src/client/util/SearchUtil.ts | 1 - src/client/util/SerializationHelper.ts | 1 - src/client/util/UndoManager.ts | 1 - src/client/views/DocViewUtils.ts | 1 - src/pen-gestures/GestureUtils.ts | 1 - src/server/DashStats.ts | 2 +- src/server/DashUploadUtils.ts | 1 - src/server/Message.ts | 1 - src/server/Search.ts | 1 - src/server/SharedMediaTypes.ts | 2 -- src/server/apis/google/GoogleApiServerUtils.ts | 2 +- src/server/server_Initialization.ts | 9 +++++ src/server/websocket.ts | 1 - 25 files changed, 77 insertions(+), 58 deletions(-) (limited to 'src/server/websocket.ts') diff --git a/eslint.config.mjs b/eslint.config.mjs index b35601abd..04655ce13 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -3,4 +3,47 @@ import pluginReactConfig from 'eslint-plugin-react/configs/recommended.js'; import globals from 'globals'; import tseslint from 'typescript-eslint'; -export default [{ languageOptions: { globals: { ...globals.browser, ...globals.node } } }, pluginJs.configs.recommended, ...tseslint.configs.recommended, pluginReactConfig]; +export default [ + { + languageOptions: { globals: { ...globals.browser, ...globals.node } }, + }, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + { + rules: { + 'node/no-missing-import': 0, + 'no-console': 'off', + 'func-names': 'off', + 'no-process-exit': 'off', + 'object-shorthand': 'off', + 'class-methods-use-this': 'off', + 'single-quote': 'off', + 'max-classes-per-file': 0, + + 'react/jsx-filename-extension': [ + 2, + { + extensions: ['.js', '.jsx', '.ts', '.tsx'], + }, + ], + + 'import/prefer-default-export': 'off', + 'no-unused-expressions': 'off', + 'prefer-template': 'off', + 'no-inner-declarations': 'off', + 'no-plusplus': 'off', + 'no-multi-assign': 'off', + 'no-underscore-dangle': 'off', + 'no-nested-ternary': 'off', + 'lines-between-class-members': 'off', + 'no-shadow': 'off', + '@typescript-eslint/no-shadow': 'warn', + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': 'error', + '@typescript-eslint/no-namespace': 'off', + 'react/destructuring-assignment': 0, + 'no-restricted-globals': ['error', 'event'], + }, + }, + pluginReactConfig, +]; diff --git a/package-lock.json b/package-lock.json index 41922228a..565463980 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2423,14 +2423,14 @@ "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" }, "node_modules/@emotion/react": { - "version": "11.13.0", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.0.tgz", - "integrity": "sha512-WkL+bw1REC2VNV1goQyfxjx1GYJkcc23CRQkXX+vZNLINyfI7o+uUn/rTGPt/xJ3bJHd5GcljgnxHf4wRw5VWQ==", + "version": "11.13.3", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz", + "integrity": "sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==", "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.12.0", "@emotion/cache": "^11.13.0", - "@emotion/serialize": "^1.3.0", + "@emotion/serialize": "^1.3.1", "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", "@emotion/utils": "^1.4.0", "@emotion/weak-memoize": "^0.4.0", @@ -2446,13 +2446,13 @@ } }, "node_modules/@emotion/serialize": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.0.tgz", - "integrity": "sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.1.tgz", + "integrity": "sha512-dEPNKzBPU+vFPGa+z3axPRn8XVDetYORmDC0wAiej+TNcOZE70ZMJa0X7JdeoM6q/nWTMZeLpN/fTnD9o8MQBA==", "dependencies": { "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", - "@emotion/unitless": "^0.9.0", + "@emotion/unitless": "^0.10.0", "@emotion/utils": "^1.4.0", "csstype": "^3.0.2" } @@ -2491,9 +2491,9 @@ "peer": true }, "node_modules/@emotion/unitless": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.9.0.tgz", - "integrity": "sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ==" + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==" }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { "version": "1.1.0", @@ -17245,9 +17245,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.12.tgz", - "integrity": "sha512-tIhPkdlEoCL1Y+PToq3zRNehUaKp3wBX/sr7aclAWdIWjvqAe/Im/H0SiCM4c1Q8BLPHCdoJTol+ZblflydehA==" + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", + "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==" }, "node_modules/elkjs": { "version": "0.9.3", @@ -20304,14 +20304,6 @@ "node": ">= 12.20" } }, - "node_modules/formdata-node/node_modules/web-streams-polyfill": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", - "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", - "engines": { - "node": ">= 14" - } - }, "node_modules/formidable": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz", @@ -41328,13 +41320,11 @@ } }, "node_modules/web-streams-polyfill": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0.tgz", - "integrity": "sha512-0zJXHRAYEjM2tUfZ2DiSOHAa2aw1tisnnhU3ufD57R8iefL+DcdJyRBRyJpG+NUimDgbTI/lH+gAE1PAvV3Cgw==", - "optional": true, - "peer": true, + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", "engines": { - "node": ">= 8" + "node": ">= 14" } }, "node_modules/web-worker": { diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts index fc048b155..55801df81 100644 --- a/src/ClientUtils.ts +++ b/src/ClientUtils.ts @@ -82,7 +82,6 @@ export function returnEmptyFilter() { return [] as string[]; } -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace ClientUtils { export const CLICK_TIME = 300; export const DRAG_THRESHOLD = 4; diff --git a/src/ServerUtils.ts b/src/ServerUtils.ts index 8b2d0b9f6..715341ab3 100644 --- a/src/ServerUtils.ts +++ b/src/ServerUtils.ts @@ -2,7 +2,6 @@ import { Socket } from 'socket.io'; import { Message } from './server/Message'; import { Utils } from './Utils'; -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace ServerUtils { export function Emit(socket: Socket, message: Message, args: T) { Utils.log('Emit', message.Name, args, false); diff --git a/src/client/Network.ts b/src/client/Network.ts index 8876d8190..6c60c4151 100644 --- a/src/client/Network.ts +++ b/src/client/Network.ts @@ -8,7 +8,7 @@ import { Upload } from '../server/SharedMediaTypes'; * mainly provides methods that the client can use to begin the process of * interacting with the server, such as fetching or uploading files. */ -// eslint-disable-next-line @typescript-eslint/no-namespace + export namespace Networking { export async function FetchFromServer(relativeRoute: string) { return (await fetch(relativeRoute)).text(); diff --git a/src/client/documents/DocUtils.ts b/src/client/documents/DocUtils.ts index a503d732b..5ee7d0f9c 100644 --- a/src/client/documents/DocUtils.ts +++ b/src/client/documents/DocUtils.ts @@ -40,7 +40,6 @@ const { DFLT_IMAGE_NATIVE_DIM } = require('../views/global/globalCssVariables.mo const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace('px', '')); -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace DocUtils { function matchFieldValue(doc: Doc, key: string, valueIn: unknown): boolean { let value = valueIn; @@ -467,7 +466,7 @@ export namespace DocUtils { .concat(userTypes) .concat(clickFuncs) .map(btnDoc => (btnDoc.dragFactory as Doc) || btnDoc) - .filter(doc => doc.isTemplateDoc); + .filter(d => d.isTemplateDoc); // bcz: this is hacky -- want to have different templates be applied depending on the "type" of a document. but type is not reliable and there could be other types of template searches so this should be generalized // first try to find a template that matches the specific document type (_). otherwise, fallback to a general match on !docLayoutTemplate && diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index b108b73db..41c6ce39b 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -487,9 +487,7 @@ export class DocumentOptions { export const DocOptions = new DocumentOptions(); -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace Docs { - // eslint-disable-next-line @typescript-eslint/no-namespace export namespace Prototypes { type LayoutSource = { LayoutString: (key: string) => string }; type PrototypeTemplate = { @@ -647,7 +645,7 @@ export namespace Docs { * Encapsulates the factory used to create new document instances * delegated from top-level prototypes */ - // eslint-disable-next-line @typescript-eslint/no-namespace + export namespace Create { /** * This function receives the relevant document prototype and uses diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index 16a0df120..a0e1413b6 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -32,14 +32,12 @@ import { UndoManager } from './UndoManager'; * to add new commands as classes or components are constructed. */ -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace DictationManager { /** * Some type maneuvering to access Webkit's built-in * speech recognizer. */ - // eslint-disable-next-line @typescript-eslint/no-namespace namespace CORE { export interface IWindow extends Window { webkitSpeechRecognition: { new (): SpeechRecognition }; @@ -48,7 +46,6 @@ export namespace DictationManager { const { webkitSpeechRecognition }: CORE.IWindow = window as unknown as CORE.IWindow; export const placeholder = 'Listening...'; - // eslint-disable-next-line @typescript-eslint/no-namespace export namespace Controls { export const Infringed = 'unable to process: dictation manager still involved in previous session'; const browser = (() => { @@ -230,7 +227,6 @@ export namespace DictationManager { }; } - // eslint-disable-next-line @typescript-eslint/no-namespace export namespace Commands { export const dictationFadeDuration = 2000; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index c237a75de..7db13689d 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -70,7 +70,6 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () return onItemDown; } -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace DragManager { export const dragClassName = 'collectionFreeFormDocumentView-container'; let dragDiv: HTMLDivElement; diff --git a/src/client/util/History.ts b/src/client/util/History.ts index 067c28c6b..0d0c056a4 100644 --- a/src/client/util/History.ts +++ b/src/client/util/History.ts @@ -10,7 +10,6 @@ import { OmitKeys, ClientUtils } from '../../ClientUtils'; import { DocServer } from '../DocServer'; import { DashboardView } from '../views/DashboardView'; -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace HistoryUtil { export interface DocInitializerList { [key: string]: string | number; diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx index f3ede596d..4231c2ca8 100644 --- a/src/client/util/InteractionUtils.tsx +++ b/src/client/util/InteractionUtils.tsx @@ -4,7 +4,6 @@ import { Utils } from '../../Utils'; import { Gestures } from '../../pen-gestures/GestureTypes'; import './InteractionUtils.scss'; -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace InteractionUtils { export const MOUSETYPE = 'mouse'; export const TOUCHTYPE = 'touch'; diff --git a/src/client/util/ScriptingGlobals.ts b/src/client/util/ScriptingGlobals.ts index 4a1a70633..444e8fc0a 100644 --- a/src/client/util/ScriptingGlobals.ts +++ b/src/client/util/ScriptingGlobals.ts @@ -6,7 +6,7 @@ const _scriptingGlobals: { [name: string]: unknown } = {}; const _scriptingDescriptions: { [name: string]: string } = {}; const _scriptingParams: { [name: string]: string } = {}; export let scriptingGlobals: { [name: string]: unknown } = _scriptingGlobals; -// eslint-disable-next-line @typescript-eslint/no-namespace + export namespace ScriptingGlobals { export function getGlobals() { return Object.keys(_scriptingGlobals); } // prettier-ignore export function getGlobalObj() { return _scriptingGlobals; } // prettier-ignore diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index 6cad7060b..733eae5f4 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -5,7 +5,6 @@ import { StrCast } from '../../fields/Types'; import { DocumentType } from '../documents/DocumentTypes'; import { DocOptions, FInfo } from '../documents/Documents'; -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace SearchUtil { export type HighlightingResult = { [id: string]: { [key: string]: string[] } }; diff --git a/src/client/util/SerializationHelper.ts b/src/client/util/SerializationHelper.ts index 0386b2455..ccb02fb79 100644 --- a/src/client/util/SerializationHelper.ts +++ b/src/client/util/SerializationHelper.ts @@ -12,7 +12,6 @@ export function afterDocDeserialize(cb: (err: unknown, val: unknown) => void, er const serializationTypes: { [name: string]: { ctor: { new (): unknown }; afterDeserialize?: (obj: unknown) => void | Promise } } = {}; const reverseMap: { [ctor: string]: string } = {}; -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace SerializationHelper { export function IsSerializing() { return serializing > 0; diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts index 5fd935370..ce0e7768b 100644 --- a/src/client/util/UndoManager.ts +++ b/src/client/util/UndoManager.ts @@ -83,7 +83,6 @@ export function undoBatch(target: any, key?: string | symbol, descriptor?: Typed return descriptor; } -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace UndoManager { export interface UndoEvent { undo: () => void; diff --git a/src/client/views/DocViewUtils.ts b/src/client/views/DocViewUtils.ts index 49a30aa08..1f5f29c7e 100644 --- a/src/client/views/DocViewUtils.ts +++ b/src/client/views/DocViewUtils.ts @@ -6,7 +6,6 @@ import { Doc, SetActiveAudioLinker } from '../../fields/Doc'; import { DocUtils } from '../documents/DocUtils'; import { FieldViewProps } from './nodes/FieldView'; -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace DocViewUtils { export const ActiveRecordings: { props: FieldViewProps; getAnchor: (addAsAnnotation: boolean) => Doc }[] = []; diff --git a/src/pen-gestures/GestureUtils.ts b/src/pen-gestures/GestureUtils.ts index bf5475042..c7051c87c 100644 --- a/src/pen-gestures/GestureUtils.ts +++ b/src/pen-gestures/GestureUtils.ts @@ -2,7 +2,6 @@ import { Rect } from 'react-measure'; import { Gestures, PointData } from './GestureTypes'; import { NDollarRecognizer } from './ndollar'; -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace GestureUtils { export class GestureEvent { readonly gesture: Gestures; diff --git a/src/server/DashStats.ts b/src/server/DashStats.ts index 6b9fb8971..8e1d4661f 100644 --- a/src/server/DashStats.ts +++ b/src/server/DashStats.ts @@ -9,7 +9,7 @@ import { socketMap, timeMap, userOperations } from './SocketData'; * This includes time connected, number of operations, and * the rate of their operations */ -// eslint-disable-next-line @typescript-eslint/no-namespace + export namespace DashStats { export const SAMPLING_INTERVAL = 1000; // in milliseconds (ms) - Time interval to update the frontend. export const RATE_INTERVAL = 10; // in seconds (s) - Used to calculate rate diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index 5e58db103..8f012f783 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -47,7 +47,6 @@ function usingAzure() { return process.env.USE_AZURE === 'true'; } -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace DashUploadUtils { export interface Size { width: number; diff --git a/src/server/Message.ts b/src/server/Message.ts index b904a5ba3..01a42fc68 100644 --- a/src/server/Message.ts +++ b/src/server/Message.ts @@ -43,7 +43,6 @@ export interface RoomMessage { readonly room: string; } -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace MessageStore { export const Foo = new Message('Foo'); export const Bar = new Message('Bar'); diff --git a/src/server/Search.ts b/src/server/Search.ts index 06af18776..b21ee853a 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -3,7 +3,6 @@ import * as rp from 'request-promise'; const pathTo = (relative: string) => `http://localhost:8983/solr/dash/${relative}`; -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace Search { export async function updateDocument(document: any) { try { diff --git a/src/server/SharedMediaTypes.ts b/src/server/SharedMediaTypes.ts index 680db9cd0..9aa4b120f 100644 --- a/src/server/SharedMediaTypes.ts +++ b/src/server/SharedMediaTypes.ts @@ -1,7 +1,6 @@ import { ExifData } from 'exif'; import { File } from 'formidable'; -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace AcceptableMedia { export const gifs = ['.gif']; export const pngs = ['.png']; @@ -19,7 +18,6 @@ export enum AudioAnnoState { playing = 'playing', } -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace Upload { export function isImageInformation(uploadResponse: Upload.FileInformation): uploadResponse is Upload.ImageInformation { return 'nativeWidth' in uploadResponse; diff --git a/src/server/apis/google/GoogleApiServerUtils.ts b/src/server/apis/google/GoogleApiServerUtils.ts index 47206f415..21c405bee 100644 --- a/src/server/apis/google/GoogleApiServerUtils.ts +++ b/src/server/apis/google/GoogleApiServerUtils.ts @@ -21,7 +21,7 @@ const scope = ['documents.readonly', 'documents', 'presentations', 'presentation * This namespace manages server side authentication for Google API queries, either * from the standard v1 APIs or the Google Photos REST API. */ -// eslint-disable-next-line @typescript-eslint/no-namespace + export namespace GoogleApiServerUtils { /** * As we expand out to more Google APIs that are accessible from diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts index 2190e27c7..8d3afc3ad 100644 --- a/src/server/server_Initialization.ts +++ b/src/server/server_Initialization.ts @@ -113,6 +113,7 @@ function registerEmbeddedBrowseRelativePathHandler(server: express.Express) { }); } +// eslint-disable-next-line @typescript-eslint/no-explicit-any function proxyServe(req: any, requrl: string, response: any) { // eslint-disable-next-line global-require, @typescript-eslint/no-var-requires const htmlBodyMemoryStream = new (require('memorystream'))(); @@ -137,8 +138,10 @@ function proxyServe(req: any, requrl: string, response: any) { response.send(header?.includes('gzip') ? zlib.gzipSync(htmlText) : htmlText); } else { req.pipe(request(requrl)) + // eslint-disable-next-line @typescript-eslint/no-explicit-any .on('error', (e: any) => console.log('requrl ', e)) .pipe(response) + // eslint-disable-next-line @typescript-eslint/no-explicit-any .on('error', (e: any) => console.log('response pipe error', e)); console.log('EMPTY body:' + req.url); } @@ -147,14 +150,17 @@ function proxyServe(req: any, requrl: string, response: any) { } } else { req.pipe(htmlBodyMemoryStream) + // eslint-disable-next-line @typescript-eslint/no-explicit-any .on('error', (e: any) => console.log('html body memorystream error', e)) .pipe(response) + // eslint-disable-next-line @typescript-eslint/no-explicit-any .on('error', (e: any) => console.log('html body memory stream response error', e)); } }; const retrieveHTTPBody = () => { // req.headers.cookie = ''; req.pipe(request(requrl)) + // eslint-disable-next-line @typescript-eslint/no-explicit-any .on('error', (e: any) => { console.log(`CORS url error: ${requrl}`, e); response.send(` @@ -163,6 +169,7 @@ function proxyServe(req: any, requrl: string, response: any) {

${e}

`); }) + // eslint-disable-next-line @typescript-eslint/no-explicit-any .on('response', (res: any) => { res.headers; const headers = Object.keys(res.headers); @@ -187,6 +194,7 @@ function proxyServe(req: any, requrl: string, response: any) { }) .on('end', sendModifiedBody) .pipe(htmlBodyMemoryStream) + // eslint-disable-next-line @typescript-eslint/no-explicit-any .on('error', (e: any) => console.log('http body pipe error', e)); }; retrieveHTTPBody(); @@ -244,6 +252,7 @@ export default async function InitializeServer(routeSetter: RouteSetter) { app.use(whm(compiler)); app.get(/^\/+$/, (req, res) => res.redirect(req.user ? '/home' : '/login')); // target urls that consist of one or more '/'s with nothing in between app.use(express.static(publicDirectory, { setHeaders: res => res.setHeader('Access-Control-Allow-Origin', '*') })); // all urls that start with dash's public directory: /files/ (e.g., /files/images, /files/audio, etc) + // eslint-disable-next-line @typescript-eslint/no-explicit-any app.use(cors({ origin: (_origin: any, callback: any) => callback(null, true) })); registerAuthenticationRoutes(app); // this adds routes to authenticate a user (login, etc) registerCorsProxy(app); // this adds a /corsProxy/ route to allow clients to get to urls that would otherwise be blocked by cors policies diff --git a/src/server/websocket.ts b/src/server/websocket.ts index ccbcb1c5f..1e25a8a27 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -15,7 +15,6 @@ import { resolvedPorts, socketMap, timeMap, userOperations } from './SocketData' import { initializeGuest } from './authentication/DashUserModel'; import { Database } from './database'; -// eslint-disable-next-line @typescript-eslint/no-namespace export namespace WebSocket { let CurUser: string | undefined; export let _socket: Socket; -- cgit v1.2.3-70-g09d2