aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package-lock.json1
-rw-r--r--package.json1
-rw-r--r--src/client/apis/google_docs/GoogleApiClientUtils.ts49
-rw-r--r--src/client/cognitive_services/CognitiveServices.ts46
-rw-r--r--src/client/util/CurrentUserUtils.ts26
-rw-r--r--src/client/util/DictationManager.ts7
-rw-r--r--src/client/util/HypothesisUtils.ts21
-rw-r--r--src/client/util/Scripting.ts4
-rw-r--r--src/client/util/SelectionManager.ts2
-rw-r--r--src/client/views/newlightbox/ExploreView/utils.ts21
-rw-r--r--src/client/views/newlightbox/components/Recommendation/utils.ts38
-rw-r--r--src/client/views/nodes/MapBox/AnimationUtility.ts3
-rw-r--r--src/client/views/nodes/MapBox/MapBox.tsx293
-rw-r--r--src/fields/RichTextUtils.ts194
14 files changed, 371 insertions, 335 deletions
diff --git a/package-lock.json b/package-lock.json
index 642e978cd..80aef5232 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -42,6 +42,7 @@
"@types/find-in-files": "^0.5.3",
"@types/fluent-ffmpeg": "^2.1.24",
"@types/formidable": "3.4.5",
+ "@types/geojson": "^7946.0.14",
"@types/google-maps": "^3.2.6",
"@types/mapbox-gl": "^3.1.0",
"@types/pdf-parse": "^1.1.4",
diff --git a/package.json b/package.json
index 90e3f39c0..d826c855e 100644
--- a/package.json
+++ b/package.json
@@ -127,6 +127,7 @@
"@types/find-in-files": "^0.5.3",
"@types/fluent-ffmpeg": "^2.1.24",
"@types/formidable": "3.4.5",
+ "@types/geojson": "^7946.0.14",
"@types/google-maps": "^3.2.6",
"@types/mapbox-gl": "^3.1.0",
"@types/pdf-parse": "^1.1.4",
diff --git a/src/client/apis/google_docs/GoogleApiClientUtils.ts b/src/client/apis/google_docs/GoogleApiClientUtils.ts
index 3c2f923ea..0b303eacf 100644
--- a/src/client/apis/google_docs/GoogleApiClientUtils.ts
+++ b/src/client/apis/google_docs/GoogleApiClientUtils.ts
@@ -1,4 +1,7 @@
-import { docs_v1 } from 'googleapis';
+/* eslint-disable no-restricted-syntax */
+/* eslint-disable no-use-before-define */
+import { docs_v1 as docsV1 } from 'googleapis';
+// eslint-disable-next-line node/no-deprecated-api
import { isArray } from 'util';
import { EditorState } from 'prosemirror-state';
import { Opt } from '../../../fields/Doc';
@@ -15,12 +18,12 @@ export namespace GoogleApiClientUtils {
}
export namespace Docs {
- export type RetrievalResult = Opt<docs_v1.Schema$Document>;
- export type UpdateResult = Opt<docs_v1.Schema$BatchUpdateDocumentResponse>;
+ export type RetrievalResult = Opt<docsV1.Schema$Document>;
+ export type UpdateResult = Opt<docsV1.Schema$BatchUpdateDocumentResponse>;
export interface UpdateOptions {
documentId: DocumentId;
- requests: docs_v1.Schema$Request[];
+ requests: docsV1.Schema$Request[];
}
export enum WriteMode {
@@ -32,7 +35,7 @@ export namespace GoogleApiClientUtils {
export type Reference = DocumentId | CreateOptions;
export interface Content {
text: string | string[];
- requests: docs_v1.Schema$Request[];
+ requests: docsV1.Schema$Request[];
}
export type IdHandler = (id: DocumentId) => any;
export type CreationResult = Opt<DocumentId>;
@@ -81,7 +84,7 @@ export namespace GoogleApiClientUtils {
},
};
try {
- const schema: docs_v1.Schema$Document = await Networking.PostToServer(path, parameters);
+ const schema: docsV1.Schema$Document = await Networking.PostToServer(path, parameters);
return schema.documentId === null ? undefined : schema.documentId;
} catch {
return undefined;
@@ -90,13 +93,13 @@ export namespace GoogleApiClientUtils {
export namespace Utils {
export type ExtractResult = { text: string; paragraphs: DeconstructedParagraph[] };
- export const extractText = (document: docs_v1.Schema$Document, removeNewlines = false): ExtractResult => {
+ export const extractText = (document: docsV1.Schema$Document, removeNewlines = false): ExtractResult => {
const paragraphs = extractParagraphs(document);
let text = paragraphs
.map(paragraph =>
paragraph.contents
.filter(content => !('inlineObjectId' in content))
- .map(run => (run as docs_v1.Schema$TextRun).content)
+ .map(run => (run as docsV1.Schema$TextRun).content)
.join('')
)
.join('');
@@ -105,9 +108,9 @@ export namespace GoogleApiClientUtils {
return { text, paragraphs };
};
- export type ContentArray = (docs_v1.Schema$TextRun | docs_v1.Schema$InlineObjectElement)[];
+ export type ContentArray = (docsV1.Schema$TextRun | docsV1.Schema$InlineObjectElement)[];
export type DeconstructedParagraph = { contents: ContentArray; bullet: Opt<number> };
- const extractParagraphs = (document: docs_v1.Schema$Document, filterEmpty = true): DeconstructedParagraph[] => {
+ const extractParagraphs = (document: docsV1.Schema$Document, filterEmpty = true): DeconstructedParagraph[] => {
const fragments: DeconstructedParagraph[] = [];
if (document.body && document.body.content) {
for (const element of document.body.content) {
@@ -136,7 +139,7 @@ export namespace GoogleApiClientUtils {
return fragments;
};
- export const endOf = (schema: docs_v1.Schema$Document): number | undefined => {
+ export const endOf = (schema: docsV1.Schema$Document): number | undefined => {
if (schema.body && schema.body.content) {
const paragraphs = schema.body.content.filter(el => el.paragraph);
if (paragraphs.length) {
@@ -150,6 +153,7 @@ export namespace GoogleApiClientUtils {
}
}
}
+ return undefined;
};
export const initialize = async (reference: Reference) => (typeof reference === 'string' ? reference : create(reference));
@@ -182,26 +186,26 @@ export namespace GoogleApiClientUtils {
}
};
- export const read = async (options: ReadOptions): Promise<Opt<ReadResult>> => {
- return retrieve({ documentId: options.documentId }).then(document => {
+ export const read = async (options: ReadOptions): Promise<Opt<ReadResult>> =>
+ retrieve({ documentId: options.documentId }).then(document => {
if (document) {
const title = document.title!;
const body = Utils.extractText(document, options.removeNewlines).text;
return { title, body };
}
+ return undefined;
});
- };
- export const readLines = async (options: ReadOptions): Promise<Opt<ReadLinesResult>> => {
- return retrieve({ documentId: options.documentId }).then(document => {
+ export const readLines = async (options: ReadOptions): Promise<Opt<ReadLinesResult>> =>
+ retrieve({ documentId: options.documentId }).then(document => {
if (document) {
- const title = document.title;
+ const { title } = document;
let bodyLines = Utils.extractText(document).text.split('\n');
options.removeNewlines && (bodyLines = bodyLines.filter(line => line.length));
return { title: title ?? '', bodyLines };
}
+ return undefined;
});
- };
export const setStyle = async (options: UpdateOptions) => {
const replies: any = await update({
@@ -216,15 +220,16 @@ export namespace GoogleApiClientUtils {
};
export const write = async (options: WriteOptions): Promise<UpdateResult> => {
- const requests: docs_v1.Schema$Request[] = [];
+ const requests: docsV1.Schema$Request[] = [];
const documentId = await Utils.initialize(options.reference);
if (!documentId) {
return undefined;
}
- let index = options.index;
- const mode = options.mode;
+ let { index } = options;
+ const { mode } = options;
if (!(index && mode === WriteMode.Insert)) {
const schema = await retrieve({ documentId });
+ // eslint-disable-next-line no-cond-assign
if (!schema || !(index = Utils.endOf(schema))) {
return undefined;
}
@@ -241,7 +246,7 @@ export namespace GoogleApiClientUtils {
});
index = 1;
}
- const text = options.content.text;
+ const { text } = options.content;
text.length &&
requests.push({
insertText: {
diff --git a/src/client/cognitive_services/CognitiveServices.ts b/src/client/cognitive_services/CognitiveServices.ts
index 4ad03aab4..9808b6a01 100644
--- a/src/client/cognitive_services/CognitiveServices.ts
+++ b/src/client/cognitive_services/CognitiveServices.ts
@@ -1,9 +1,14 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
+/* eslint-disable camelcase */
+/* eslint-disable no-useless-catch */
+/* eslint-disable no-use-before-define */
import * as rp from 'request-promise';
import { Doc, FieldType } from '../../fields/Doc';
import { InkData } from '../../fields/InkField';
import { List } from '../../fields/List';
import { Cast } from '../../fields/Types';
import { UndoManager } from '../util/UndoManager';
+import { ClientUtils } from '../../ClientUtils';
type APIManager<D> = { converter: BodyConverter<D>; requester: RequestExecutor };
type RequestExecutor = (apiKey: string, body: string, service: Service) => Promise<string>;
@@ -40,7 +45,7 @@ export enum Confidence {
*/
export namespace CognitiveServices {
const ExecuteQuery = async <D>(service: Service, manager: APIManager<D>, data: D): Promise<any> => {
- let apiKey = process.env[service.toUpperCase()];
+ const apiKey = process.env[service.toUpperCase()];
if (!apiKey) {
console.log(`No API key found for ${service}: ensure youe root directory has .env file with _CLIENT_${service.toUpperCase()}.`);
return undefined;
@@ -51,7 +56,6 @@ export namespace CognitiveServices {
results = await manager.requester(apiKey, manager.converter(data), service).then(json => JSON.parse(json));
} catch (e) {
throw e;
- results = undefined;
}
return results;
};
@@ -70,7 +74,7 @@ export namespace CognitiveServices {
parameters = {
returnFaceId: 'true',
returnFaceLandmarks: 'false',
- returnFaceAttributes: 'age,gender,headPose,smile,facialHair,glasses,' + 'emotion,hair,makeup,occlusion,accessories,blur,exposure,noise',
+ returnFaceAttributes: 'age,gender,headPose,smile,facialHair,glasses,emotion,hair,makeup,occlusion,accessories,blur,exposure,noise',
};
break;
case Service.ComputerVision:
@@ -81,6 +85,7 @@ export namespace CognitiveServices {
language: 'en',
};
break;
+ default:
}
const options = {
@@ -109,12 +114,10 @@ export namespace CognitiveServices {
const results = await ExecuteQuery(service, Manager, url);
if (!results) {
toStore = 'Cognitive Services could not process the given image URL.';
+ } else if (!results.length) {
+ toStore = converter(results);
} else {
- if (!results.length) {
- toStore = converter(results);
- } else {
- toStore = results.length > 0 ? converter(results) : 'Empty list returned.';
- }
+ toStore = results.length > 0 ? converter(results) : 'Empty list returned.';
}
target[storageKey] = toStore;
@@ -148,7 +151,7 @@ export namespace CognitiveServices {
const endpoint = serverAddress + '/inkrecognizer/v1.0-preview/recognize';
return new Promise<string>((resolve, reject) => {
- xhttp.onreadystatechange = function () {
+ xhttp.onreadystatechange = function (this: XMLHttpRequest) {
if (this.readyState === 4) {
const result = xhttp.responseText;
switch (this.status) {
@@ -159,6 +162,7 @@ export namespace CognitiveServices {
return reject(result);
}
}
+ return undefined;
};
xhttp.open('PUT', endpoint, true);
@@ -211,15 +215,13 @@ export namespace CognitiveServices {
export namespace BingSearch {
export const Manager: APIManager<string> = {
- converter: (data: string) => {
- return data;
- },
+ converter: (data: string) => data,
requester: async (apiKey: string, query: string) => {
const xhttp = new XMLHttpRequest();
const serverAddress = 'https://api.cognitive.microsoft.com';
const endpoint = serverAddress + '/bing/v5.0/search?q=' + encodeURIComponent(query);
const promisified = (resolve: any, reject: any) => {
- xhttp.onreadystatechange = function () {
+ xhttp.onreadystatechange = function (this: XMLHttpRequest) {
if (this.readyState === 4) {
const result = xhttp.responseText;
switch (this.status) {
@@ -230,6 +232,7 @@ export namespace CognitiveServices {
return reject(result);
}
}
+ return undefined;
};
if (apiKey) {
@@ -257,15 +260,13 @@ export namespace CognitiveServices {
export namespace HathiTrust {
export const Manager: APIManager<string> = {
- converter: (data: string) => {
- return data;
- },
+ converter: (data: string) => data,
requester: async (apiKey: string, query: string) => {
const xhttp = new XMLHttpRequest();
const serverAddress = 'https://babel.hathitrust.org/cgi/htd/​';
const endpoint = serverAddress + '/bing/v5.0/search?q=' + encodeURIComponent(query);
const promisified = (resolve: any, reject: any) => {
- xhttp.onreadystatechange = function () {
+ xhttp.onreadystatechange = function (this: XMLHttpRequest) {
if (this.readyState === 4) {
const result = xhttp.responseText;
switch (this.status) {
@@ -276,6 +277,7 @@ export namespace CognitiveServices {
return reject(result);
}
}
+ return undefined;
};
if (apiKey) {
@@ -303,8 +305,8 @@ export namespace CognitiveServices {
export namespace Text {
export const Manager: APIManager<string> = {
- converter: (data: string) => {
- return JSON.stringify({
+ converter: (data: string) =>
+ JSON.stringify({
documents: [
{
id: 1,
@@ -312,8 +314,7 @@ export namespace CognitiveServices {
text: data,
},
],
- });
- },
+ }),
requester: async (apiKey: string, body: string, service: Service) => {
const serverAddress = 'https://eastus.api.cognitive.microsoft.com';
const endpoint = serverAddress + '/text/analytics/v2.1/keyPhrases';
@@ -367,11 +368,12 @@ export namespace CognitiveServices {
const { keyterms, external_recommendations, kp_string } = await converter(results, data);
target[keys[0]] = keyterms;
if (isInternal) {
- //await vectorize([data], dataDoc, isMainDoc);
+ // await vectorize([data], dataDoc, isMainDoc);
await vectorize(kp_string, dataDoc, isMainDoc);
} else {
return { recs: external_recommendations, keyterms: keyterms };
}
+ return undefined;
};
// export async function countFrequencies()
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 65dce34a5..eae5b2d6a 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -735,19 +735,19 @@ pie title Minerals in my tap water
{ title: "Header", icon: "heading", toolTip: "Doc Titlebar Color", btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, scripts: { script: 'return setHeaderColor(value, _readOnly_)'} },
{ title: "Template",icon: "scroll", toolTip: "Default Note Template",btnType: ButtonType.ToggleButton, expertMode: false, toolType:DocumentType.RTF, scripts: { onClick: '{ return setDefaultTemplate(_readOnly_); }'} },
{ title: "Fill", icon: "fill-drip", toolTip: "Fill/Background Color",btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, width: 30, scripts: { script: 'return setBackgroundColor(value, _readOnly_)'}, funcs: {hidden: "IsNoneSelected()"}}, // Only when a document is selected
- { title: "Overlay", icon: "layer-group", toolTip: "Overlay", btnType: ButtonType.ToggleButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(this.toolType, this.expertMode, true)'}, scripts: { onClick: '{ return toggleOverlay(_readOnly_); }'}}, // Only when floating document is selected in freeform
- { title: "Back", icon: "chevron-left", toolTip: "Prev Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(this.toolType, this.expertMode)'}, width: 30, scripts: { onClick: 'prevKeyFrame(_readOnly_)'}},
- { title: "Num", icon:"", toolTip: "Frame # (click to toggle edit mode)",btnType: ButtonType.TextButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(this.toolType, this.expertMode)', buttonText: 'selectedDocs()?.lastElement()?.currentFrame?.toString()'}, width: 20, scripts: { onClick: '{ return curKeyFrame(_readOnly_);}'}},
- { title: "Fwd", icon: "chevron-right", toolTip: "Next Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(this.toolType, this.expertMode)'}, width: 30, scripts: { onClick: 'nextKeyFrame(_readOnly_)'}},
- { title: "Text", icon: "Text", toolTip: "Text functions", subMenu: CurrentUserUtils.textTools(), expertMode: false, toolType:DocumentType.RTF, funcs: { linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Always available
- { title: "Ink", icon: "Ink", toolTip: "Ink functions", subMenu: CurrentUserUtils.inkTools(), expertMode: false, toolType:DocumentType.INK, funcs: {hidden: `IsExploreMode()`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`}, scripts: { onClick: 'setInkToolDefaults()'} }, // Always available
- { title: "Doc", icon: "Doc", toolTip: "Freeform Doc tools", subMenu: CurrentUserUtils.freeTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode, true)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Always available
- { title: "View", icon: "View", toolTip: "View tools", subMenu: CurrentUserUtils.viewTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Always available
- { title: "Stack", icon: "View", toolTip: "Stacking tools", subMenu: CurrentUserUtils.stackTools(), expertMode: false, toolType:CollectionViewType.Stacking, funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Always available
- { title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Only when Web is selected
- { title: "Video", icon: "Video", toolTip: "Video functions", subMenu: CurrentUserUtils.videoTools(), expertMode: false, toolType:DocumentType.VID, funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Only when video is selected
- { title: "Image", icon: "Image", toolTip: "Image functions", subMenu: CurrentUserUtils.imageTools(), expertMode: false, toolType:DocumentType.IMG, funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Only when image is selected
- { title: "Schema", icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(),expertMode: false,toolType:CollectionViewType.Schema,funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Only when Schema is selected
+ { title: "Overlay", icon: "layer-group", toolTip: "Overlay", btnType: ButtonType.ToggleButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode, true)'}, scripts: { onClick: '{ return toggleOverlay(_readOnly_); }'}}, // Only when floating document is selected in freeform
+ { title: "Back", icon: "chevron-left", toolTip: "Prev Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, width: 30, scripts: { onClick: 'prevKeyFrame(_readOnly_)'}},
+ { title: "Num", icon:"", toolTip: "Frame # (click to toggle edit mode)",btnType: ButtonType.TextButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)', buttonText: 'selectedDocs()?.lastElement()?.currentFrame?.toString()'}, width: 20, scripts: { onClick: '{ return curKeyFrame(_readOnly_);}'}},
+ { title: "Fwd", icon: "chevron-right", toolTip: "Next Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, width: 30, scripts: { onClick: 'nextKeyFrame(_readOnly_)'}},
+ { title: "Text", icon: "Text", toolTip: "Text functions", subMenu: CurrentUserUtils.textTools(), expertMode: false, toolType:DocumentType.RTF, funcs: { linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
+ { title: "Ink", icon: "Ink", toolTip: "Ink functions", subMenu: CurrentUserUtils.inkTools(), expertMode: false, toolType:DocumentType.INK, funcs: {hidden: `IsExploreMode()`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`}, scripts: { onClick: 'setInkToolDefaults()'} }, // Always available
+ { title: "Doc", icon: "Doc", toolTip: "Freeform Doc tools", subMenu: CurrentUserUtils.freeTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode, true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
+ { title: "View", icon: "View", toolTip: "View tools", subMenu: CurrentUserUtils.viewTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
+ { title: "Stack", icon: "View", toolTip: "Stacking tools", subMenu: CurrentUserUtils.stackTools(), expertMode: false, toolType:CollectionViewType.Stacking, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
+ { title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Web is selected
+ { title: "Video", icon: "Video", toolTip: "Video functions", subMenu: CurrentUserUtils.videoTools(), expertMode: false, toolType:DocumentType.VID, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when video is selected
+ { title: "Image", icon: "Image", toolTip: "Image functions", subMenu: CurrentUserUtils.imageTools(), expertMode: false, toolType:DocumentType.IMG, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when image is selected
+ { title: "Schema", icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(),expertMode: false,toolType:CollectionViewType.Schema,funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Schema is selected
];
}
diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts
index 08fd80882..9026b368f 100644
--- a/src/client/util/DictationManager.ts
+++ b/src/client/util/DictationManager.ts
@@ -63,7 +63,7 @@ export namespace DictationManager {
const intraSession = '. ';
const interSession = ' ... ';
- export let isListening = false;
+ let isListening = false;
let isManuallyStopped = false;
let current: string | undefined;
@@ -235,7 +235,10 @@ export namespace DictationManager {
export type DependentEntry = { expression: RegExp; action: DependentAction; restrictTo?: DocumentType[] };
export const RegisterIndependent = (key: string, value: IndependentEntry) => Independent.set(key, value);
- export const RegisterDependent = (entry: DependentEntry) => Dependent.push(entry);
+ export const RegisterDependent = (entry: DependentEntry) => {
+ const { expression, action, restrictTo } = entry;
+ return Dependent.push({ expression, action, restrictTo: restrictTo ?? [] });
+ };
export const execute = async (phrase: string) =>
UndoManager.RunInBatch(async () => {
diff --git a/src/client/util/HypothesisUtils.ts b/src/client/util/HypothesisUtils.ts
index 6dc96f1b5..dd18b2533 100644
--- a/src/client/util/HypothesisUtils.ts
+++ b/src/client/util/HypothesisUtils.ts
@@ -15,6 +15,7 @@ export namespace Hypothesis {
* If none exist, create and return a new WebDocument.
*/
export const getSourceWebDoc = async (uri: string) => {
+ // eslint-disable-next-line no-use-before-define
const result = await findWebDoc(uri);
console.log(result ? 'existing doc found' : 'existing doc NOT found');
return result || Docs.Create.WebDocument(uri, { title: uri, _nativeWidth: 850, _height: 512, _width: 400, data_useCors: true }); // create and return a new Web doc with given uri if no matching docs are found
@@ -75,17 +76,19 @@ export namespace Hypothesis {
/**
* Send message to Hypothes.is client to edit an annotation to add a Dash hyperlink
*/
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
export const makeLink = async (title: string, url: string, annotationId: string, annotationSourceDoc: Doc) => {
// if the annotation's source webpage isn't currently loaded in Dash, we're not able to access and edit the annotation from the client
// so we're loading the webpage and its annotations invisibly in a WebBox in MainView.tsx, until the editing is done
- //!DocumentManager.Instance.getFirstDocumentView(annotationSourceDoc) && runInAction(() => DocumentLinksButton.invisibleWebDoc = annotationSourceDoc);
+ //! DocumentManager.Instance.getFirstDocumentView(annotationSourceDoc) && runInAction(() => DocumentLinksButton.invisibleWebDoc = annotationSourceDoc);
- var success = false;
+ let success = false;
const onSuccess = action(() => {
console.log('Edit success!!');
success = true;
+ // eslint-disable-next-line no-use-before-define
clearTimeout(interval);
- //DocumentLinksButton.invisibleWebDoc = undefined;
+ // DocumentLinksButton.invisibleWebDoc = undefined;
document.removeEventListener('editSuccess', onSuccess);
});
@@ -107,7 +110,7 @@ export namespace Hypothesis {
action(() => {
if (!success) {
clearInterval(interval);
- //DocumentLinksButton.invisibleWebDoc = undefined;
+ // DocumentLinksButton.invisibleWebDoc = undefined;
}
}),
10000
@@ -121,12 +124,13 @@ export namespace Hypothesis {
export const deleteLink = async (linkDoc: Doc, sourceDoc: Doc, destinationDoc: Doc) => {
if (Cast(destinationDoc.data, WebField)?.url.href !== StrCast(linkDoc.annotationUri)) return; // check that the destinationDoc is a WebDocument containing the target annotation
- //!DocumentManager.Instance.getFirstDocumentView(destinationDoc) && runInAction(() => DocumentLinksButton.invisibleWebDoc = destinationDoc); // see note in makeLink
+ //! DocumentManager.Instance.getFirstDocumentView(destinationDoc) && runInAction(() => DocumentLinksButton.invisibleWebDoc = destinationDoc); // see note in makeLink
- var success = false;
+ let success = false;
const onSuccess = action(() => {
console.log('Edit success!');
success = true;
+ // eslint-disable-next-line no-use-before-define
clearTimeout(interval);
// DocumentLinksButton.invisibleWebDoc = undefined;
document.removeEventListener('editSuccess', onSuccess);
@@ -149,7 +153,7 @@ export namespace Hypothesis {
action(() => {
if (!success) {
clearInterval(interval);
- //DocumentLinksButton.invisibleWebDoc = undefined;
+ // DocumentLinksButton.invisibleWebDoc = undefined;
}
}),
10000
@@ -161,10 +165,11 @@ export namespace Hypothesis {
* Send message to Hypothes.is client to scroll to an annotation when it loads
*/
export const scrollToAnnotation = (annotationId: string, target: Doc) => {
- var success = false;
+ let success = false;
const onSuccess = () => {
console.log('Scroll success!!');
document.removeEventListener('scrollSuccess', onSuccess);
+ // eslint-disable-next-line no-use-before-define
clearInterval(interval);
success = true;
};
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index f7d7ba6a4..8df579e75 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -1,9 +1,9 @@
+/* eslint-disable import/no-unresolved */
+/* eslint-disable import/no-webpack-loader-syntax */
// export const ts = (window as any).ts;
// // @ts-ignore
// import * as typescriptlib from '!!raw-loader!../../../node_modules/typescript/lib/lib.d.ts'
-// // @ts-ignore
// import * as typescriptes5 from '!!raw-loader!../../../node_modules/typescript/lib/lib.es5.d.ts'
-// @ts-ignore
// eslint-disable-next-line node/no-unpublished-import
import * as ts from 'typescript';
import * as typescriptlib from '!!raw-loader!./type_decls.d';
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 1328e90e9..7e8f42de9 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -75,7 +75,7 @@ export class SelectionManager {
}
// eslint-disable-next-line prefer-arrow-callback
-ScriptingGlobals.add(function SelectionManager_selectedDocType(type: string, expertMode: boolean, checkContext?: boolean) {
+ScriptingGlobals.add(function SelectedDocType(type: string, expertMode: boolean, checkContext?: boolean) {
if (Doc.noviceMode && expertMode) return false;
if (type === 'tab') {
return SelectionManager.Views.lastElement()?._props.renderDepth === 0;
diff --git a/src/client/views/newlightbox/ExploreView/utils.ts b/src/client/views/newlightbox/ExploreView/utils.ts
index 7d9cf226d..2d1bd75a9 100644
--- a/src/client/views/newlightbox/ExploreView/utils.ts
+++ b/src/client/views/newlightbox/ExploreView/utils.ts
@@ -1,20 +1,21 @@
-import { IRecommendation } from "../components";
+import { IRecommendation } from '../components';
export interface IExploreView {
- recs?: IRecommendation[],
- bounds?: IBounds
+ recs?: IRecommendation[];
+ // eslint-disable-next-line no-use-before-define
+ bounds?: IBounds;
}
export const emptyBounds = {
max_x: 0,
max_y: 0,
min_x: 0,
- min_y: 0
-}
+ min_y: 0,
+};
export interface IBounds {
- max_x: number,
- max_y: number,
- min_x: number,
- min_y: number
-} \ No newline at end of file
+ max_x: number;
+ max_y: number;
+ min_x: number;
+ min_y: number;
+}
diff --git a/src/client/views/newlightbox/components/Recommendation/utils.ts b/src/client/views/newlightbox/components/Recommendation/utils.ts
index 796ce0eb0..4a55d394e 100644
--- a/src/client/views/newlightbox/components/Recommendation/utils.ts
+++ b/src/client/views/newlightbox/components/Recommendation/utils.ts
@@ -1,23 +1,23 @@
-import { DocumentType } from "../../../../documents/DocumentTypes"
+import { DocumentType } from '../../../../documents/DocumentTypes';
export interface IRecommendation {
- loading?: boolean
- type?: DocumentType | string,
- data?: string,
- title?: string,
- text?: string,
- source?: string,
- previewUrl?: string,
+ loading?: boolean;
+ type?: DocumentType | string;
+ data?: string;
+ title?: string;
+ text?: string;
+ source?: string;
+ previewUrl?: string;
transcript?: {
- text: string,
- start: number,
- duration: number
- }[],
+ text: string;
+ start: number;
+ duration: number;
+ }[];
embedding?: {
- x: number,
- y: number
- },
- distance?: number,
- related_concepts?: string[],
- docId?: string
-} \ No newline at end of file
+ x: number;
+ y: number;
+ };
+ distance?: number;
+ related_concepts?: string[];
+ docId?: string;
+}
diff --git a/src/client/views/nodes/MapBox/AnimationUtility.ts b/src/client/views/nodes/MapBox/AnimationUtility.ts
index cf5315da3..3a2679ecf 100644
--- a/src/client/views/nodes/MapBox/AnimationUtility.ts
+++ b/src/client/views/nodes/MapBox/AnimationUtility.ts
@@ -1,6 +1,7 @@
import * as turf from '@turf/turf';
import { Position } from '@turf/turf';
import * as d3 from 'd3';
+// eslint-disable-next-line import/no-extraneous-dependencies
import { Feature, GeoJsonProperties, Geometry } from 'geojson';
import mapboxgl, { MercatorCoordinate } from 'mapbox-gl';
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
@@ -214,6 +215,7 @@ export class AnimationUtility {
updateAnimationPhase: (newAnimationPhase: number) => void;
updateFrameId: (newFrameId: number) => void;
}) =>
+ // eslint-disable-next-line no-async-promise-executor
new Promise<void>(async resolve => {
let startTime: number | null = null;
@@ -288,6 +290,7 @@ export class AnimationUtility {
});
public flyInAndRotate = async ({ map, updateFrameId }: { map: MapRef; updateFrameId: (newFrameId: number) => void }) =>
+ // eslint-disable-next-line no-async-promise-executor
new Promise<{ bearing: number; altitude: number }>(async resolve => {
let start: number | null;
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index 7009977d0..6495cf440 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -1,11 +1,14 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
import { IconLookup, faCircleXmark, faGear, faPause, faPlay, faRotate } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Checkbox, FormControlLabel, TextField } from '@mui/material';
import * as turf from '@turf/turf';
import { IconButton, Size, Type } from 'browndash-components';
import * as d3 from 'd3';
+// eslint-disable-next-line import/no-extraneous-dependencies
import { Feature, FeatureCollection, GeoJsonProperties, Geometry, LineString, Position } from 'geojson';
-import mapboxgl, { LngLat, LngLatBoundsLike, MapLayerMouseEvent } from 'mapbox-gl';
+import mapboxgl, { LngLatBoundsLike, MapLayerMouseEvent } from 'mapbox-gl';
import { IReactionDisposer, ObservableMap, action, autorun, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -21,7 +24,6 @@ import { DocUtils, Docs } from '../../../documents/Documents';
import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
import { LinkManager } from '../../../util/LinkManager';
-import { SnappingManager } from '../../../util/SnappingManager';
import { UndoManager, undoable } from '../../../util/UndoManager';
import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent';
import { SidebarAnnos } from '../../SidebarAnnos';
@@ -54,8 +56,6 @@ import { MarkerIcons } from './MarkerIcons';
*/
const MAPBOX_ACCESS_TOKEN = 'pk.eyJ1IjoiemF1bHRhdmFuZ2FyIiwiYSI6ImNscHgwNDd1MDA3MXIydm92ODdianp6cGYifQ.WFAqbhwxtMHOWSPtu0l2uQ';
-const MAPBOX_FORWARD_GEOCODE_BASE_URL = 'https://api.mapbox.com/geocoding/v5/mapbox.places/';
-const MAPBOX_REVERSE_GEOCODE_BASE_URL = 'https://api.mapbox.com/geocoding/v5/mapbox.places/';
type PopupInfo = {
longitude: number;
@@ -287,7 +287,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
setupMoveUpEvents(
this,
e,
- (e, down, delta) =>
+ (moveEv, down, delta) =>
runInAction(() => {
const localDelta = this._props
.ScreenToLocalTransform()
@@ -362,10 +362,10 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
const docView = this.DocumentView?.();
docView &&
DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(docView, sourceAnchorCreator, targetCreator), e.pageX, e.pageY, {
- dragComplete: e => {
- if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) {
- e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this.Document;
- e.annoDragData.linkSourceDoc.followLinkZoom = false;
+ dragComplete: dragEv => {
+ if (!dragEv.aborted && dragEv.annoDragData && dragEv.annoDragData.linkSourceDoc && dragEv.annoDragData.dropDocument && dragEv.linkDocument) {
+ dragEv.annoDragData.linkSourceDoc.followLinkToggle = dragEv.annoDragData.dropDocument.annotationOn === this.Document;
+ dragEv.annoDragData.linkSourceDoc.followLinkZoom = false;
}
},
});
@@ -437,7 +437,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
this.toggleSidebar();
options.didMove = true;
}
- return new Promise<Opt<DocumentView>>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv)));
+ return new Promise<Opt<DocumentView>>(res => {
+ DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv));
+ });
};
/*
@@ -528,6 +530,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
document.removeEventListener('pointerdown', this.tryHideMapAnchorMenu);
};
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
recolorPin = (pin: Doc, color?: string) => {
// this._bingMap.current.entities.remove(this.map_docToPinMap.get(pin));
// this.map_docToPinMap.delete(pin);
@@ -582,6 +585,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
MapAnchorMenu.Instance.fadeOut(true);
return mapRoute;
}
+ return undefined;
// TODO: Display error that can't create route to same location
}, 'createmaproute');
@@ -654,9 +658,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
console.error(features);
if (features && features.length > 0 && features[0].properties && features[0].geometry) {
- const geometry = features[0].geometry as LineString;
const { routeTitle } = features[0].properties;
- const routeDoc: Doc | undefined = this.allRoutes.find(routeDoc => routeDoc.title === routeTitle);
+ const routeDoc: Doc | undefined = this.allRoutes.find(rtDoc => rtDoc.title === routeTitle);
this.deselectPinOrRoute(); // TODO: Also deselect route if selected
if (routeDoc) {
this._selectedPinOrRoute = routeDoc;
@@ -700,7 +703,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
*/
handleMapDblClick = async (e: MapLayerMouseEvent) => {
e.preventDefault();
- const { lngLat }: LngLat = e;
+ const { lngLat } = e;
const longitude: number = lngLat.lng;
const latitude: number = lngLat.lat;
@@ -836,6 +839,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
if (!this._isAnimating) {
return this.mapboxMapViewState;
}
+ return undefined;
}
@action
@@ -919,69 +923,73 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
this.path = path;
this._isAnimating = true;
- runInAction(() => {
- return new Promise<void>(async resolve => {
- const targetLngLat = {
- lng: this.selectedRouteCoordinates[0][0],
- lat: this.selectedRouteCoordinates[0][1],
- };
-
- const animationUtil = new AnimationUtility(targetLngLat, this.selectedRouteCoordinates, this._isStreetViewAnimation, this._animationSpeed, this._showTerrain, this._mapRef.current);
- runInAction(() => this.setAnimationUtility(animationUtil));
+ runInAction(
+ () =>
+ // eslint-disable-next-line no-async-promise-executor
+ new Promise<void>(async resolve => {
+ const targetLngLat = {
+ lng: this.selectedRouteCoordinates[0][0],
+ lat: this.selectedRouteCoordinates[0][1],
+ };
+
+ const animationUtil = new AnimationUtility(targetLngLat, this.selectedRouteCoordinates, this._isStreetViewAnimation, this._animationSpeed, this._showTerrain, this._mapRef.current);
+ runInAction(() => this.setAnimationUtility(animationUtil));
+
+ const updateFrameId = (newFrameId: number) => this.setFrameId(newFrameId);
+ const updateAnimationPhase = (newAnimationPhase: number) => this.setAnimationPhase(newAnimationPhase);
+
+ if (status !== AnimationStatus.RESUME) {
+ const result = await animationUtil.flyInAndRotate({
+ map: this._mapRef.current!,
+ // targetLngLat,
+ // duration 3000
+ // startAltitude: 3000000,
+ // endAltitude: this.isStreetViewAnimation ? 80 : 12000,
+ // startBearing: 0,
+ // endBearing: -20,
+ // startPitch: 40,
+ // endPitch: this.isStreetViewAnimation ? 80 : 50,
+ updateFrameId,
+ });
+
+ console.log('Bearing: ', result.bearing);
+ console.log('Altitude: ', result.altitude);
+ }
- const updateFrameId = (newFrameId: number) => this.setFrameId(newFrameId);
- const updateAnimationPhase = (newAnimationPhase: number) => this.setAnimationPhase(newAnimationPhase);
+ runInAction(() => {
+ this._finishedFlyTo = true;
+ });
- if (status !== AnimationStatus.RESUME) {
- const result = await animationUtil.flyInAndRotate({
+ // follow the path while slowly rotating the camera, passing in the camera bearing and altitude from the previous animation
+ await animationUtil.animatePath({
map: this._mapRef.current!,
- // targetLngLat,
- // duration 3000
- // startAltitude: 3000000,
- // endAltitude: this.isStreetViewAnimation ? 80 : 12000,
- // startBearing: 0,
- // endBearing: -20,
- // startPitch: 40,
- // endPitch: this.isStreetViewAnimation ? 80 : 50,
+ // path: this.path,
+ // startBearing: -20,
+ // startAltitude: this.isStreetViewAnimation ? 80 : 12000,
+ // pitch: this.isStreetViewAnimation ? 80: 50,
+ currentAnimationPhase: this._animationPhase,
+ updateAnimationPhase,
updateFrameId,
});
- console.log('Bearing: ', result.bearing);
- console.log('Altitude: ', result.altitude);
- }
+ // get the bounds of the linestring, use fitBounds() to animate to a final view
+ const bbox3d = turf.bbox(this.path);
- runInAction(() => (this._finishedFlyTo = true));
-
- // follow the path while slowly rotating the camera, passing in the camera bearing and altitude from the previous animation
- await animationUtil.animatePath({
- map: this._mapRef.current!,
- // path: this.path,
- // startBearing: -20,
- // startAltitude: this.isStreetViewAnimation ? 80 : 12000,
- // pitch: this.isStreetViewAnimation ? 80: 50,
- currentAnimationPhase: this._animationPhase,
- updateAnimationPhase,
- updateFrameId,
- });
+ const bbox2d: LngLatBoundsLike = [bbox3d[0], bbox3d[1], bbox3d[2], bbox3d[3]];
- // get the bounds of the linestring, use fitBounds() to animate to a final view
- const bbox3d = turf.bbox(this.path);
-
- const bbox2d: LngLatBoundsLike = [bbox3d[0], bbox3d[1], bbox3d[2], bbox3d[3]];
-
- this._mapRef.current!.fitBounds(bbox2d, {
- duration: 3000,
- pitch: 30,
- bearing: 0,
- padding: 120,
- });
+ this._mapRef.current!.fitBounds(bbox2d, {
+ duration: 3000,
+ pitch: 30,
+ bearing: 0,
+ padding: 120,
+ });
- setTimeout(() => {
- this._isStreetViewAnimation = false;
- resolve();
- }, 10000);
- });
- });
+ setTimeout(() => {
+ this._isStreetViewAnimation = false;
+ resolve();
+ }, 10000);
+ })
+ );
};
@action
@@ -1010,53 +1018,49 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
}
};
- getRouteAnimationOptions = (): JSX.Element => {
- return (
- <>
+ getRouteAnimationOptions = (): JSX.Element => (
+ <>
+ <IconButton
+ tooltip={this._isAnimating && this._finishedFlyTo ? 'Pause Animation' : 'Play Animation'}
+ onPointerDown={() => {
+ if (this._isAnimating && this._finishedFlyTo) {
+ this.pauseAnimation();
+ } else if (this._animationPhase > 0) {
+ this.playAnimation(AnimationStatus.RESUME); // Resume from the current phase
+ } else {
+ this.playAnimation(AnimationStatus.START); // Play from the beginning
+ }
+ }}
+ icon={this._isAnimating && this._finishedFlyTo ? <FontAwesomeIcon icon={faPause as IconLookup} /> : <FontAwesomeIcon icon={faPlay as IconLookup} />}
+ color="black"
+ size={Size.MEDIUM}
+ />
+ {this._isAnimating && this._finishedFlyTo && (
<IconButton
- tooltip={this._isAnimating && this._finishedFlyTo ? 'Pause Animation' : 'Play Animation'}
+ tooltip="Restart animation"
onPointerDown={() => {
- if (this._isAnimating && this._finishedFlyTo) {
- this.pauseAnimation();
- } else if (this._animationPhase > 0) {
- this.playAnimation(AnimationStatus.RESUME); // Resume from the current phase
- } else {
- this.playAnimation(AnimationStatus.START); // Play from the beginning
- }
+ this.stopAnimation(false);
+ this.playAnimation(AnimationStatus.START);
}}
- icon={this._isAnimating && this._finishedFlyTo ? <FontAwesomeIcon icon={faPause as IconLookup} /> : <FontAwesomeIcon icon={faPlay as IconLookup} />}
+ icon={<FontAwesomeIcon icon={faRotate as IconLookup} />}
color="black"
size={Size.MEDIUM}
/>
- {this._isAnimating && this._finishedFlyTo && (
- <IconButton
- tooltip="Restart animation"
- onPointerDown={() => {
- this.stopAnimation(false);
- this.playAnimation(AnimationStatus.START);
- }}
- icon={<FontAwesomeIcon icon={faRotate as IconLookup} />}
- color="black"
- size={Size.MEDIUM}
- />
- )}
- <IconButton style={{ marginRight: '10px' }} tooltip="Stop and close animation" onPointerDown={() => this.stopAnimation(true)} icon={<FontAwesomeIcon icon={faCircleXmark as IconLookup} />} color="black" size={Size.MEDIUM} />
- <>
- <div className="animation-suboptions">
- <div>|</div>
- <FormControlLabel className="first-person-label" label="1st person animation:" labelPlacement="start" control={<Checkbox color="success" checked={this._isStreetViewAnimation} onChange={this.toggleIsStreetViewAnimation} />} />
- <div id="divider">|</div>
- <IconButton tooltip={this.animationSpeedTooltipText} onPointerDown={this.updateAnimationSpeed} icon={this.animationSpeedIcon} size={Size.MEDIUM} />
- <div id="divider">|</div>
- <div style={{ display: 'flex', alignItems: 'center' }}>
- <div>Select Line Color: </div>
- <CirclePicker circleSize={12} circleSpacing={5} width="100%" colors={['#ffff00', '#03a9f4', '#ff0000', '#ff5722', '#000000', '#673ab7']} onChange={(color: any) => this.setAnimationLineColor(color)} />
- </div>
- </div>
- </>
- </>
- );
- };
+ )}
+ <IconButton style={{ marginRight: '10px' }} tooltip="Stop and close animation" onPointerDown={() => this.stopAnimation(true)} icon={<FontAwesomeIcon icon={faCircleXmark as IconLookup} />} color="black" size={Size.MEDIUM} />
+ <div className="animation-suboptions">
+ <div>|</div>
+ <FormControlLabel className="first-person-label" label="1st person animation:" labelPlacement="start" control={<Checkbox color="success" checked={this._isStreetViewAnimation} onChange={this.toggleIsStreetViewAnimation} />} />
+ <div id="divider">|</div>
+ <IconButton tooltip={this.animationSpeedTooltipText} onPointerDown={this.updateAnimationSpeed} icon={this.animationSpeedIcon} size={Size.MEDIUM} />
+ <div id="divider">|</div>
+ <div style={{ display: 'flex', alignItems: 'center' }}>
+ <div>Select Line Color: </div>
+ <CirclePicker circleSize={12} circleSpacing={5} width="100%" colors={['#ffff00', '#03a9f4', '#ff0000', '#ff5722', '#000000', '#673ab7']} onChange={(color: any) => this.setAnimationLineColor(color)} />
+ </div>
+ </div>
+ </>
+ );
@action
hideRoute = () => {
@@ -1068,7 +1072,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
@action
toggleSettings = () => {
- if (!this._isAnimating && this._animationPhase == 0) {
+ if (!this._isAnimating && this._animationPhase === 0) {
this._featuresFromGeocodeResults = [];
this._settingsOpen = !this._settingsOpen;
}
@@ -1125,7 +1129,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
};
@action
- onMapZoom = (e: ViewStateChangeEvent) => (this.dataDoc.map_zoom = e.viewState.zoom);
+ onMapZoom = (e: ViewStateChangeEvent) => {
+ this.dataDoc.map_zoom = e.viewState.zoom;
+ };
@action
onMapMove = (e: ViewStateChangeEvent) => {
@@ -1134,7 +1140,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
};
@action
- toggleShowTerrain = () => (this._showTerrain = !this._showTerrain);
+ toggleShowTerrain = () => {
+ this._showTerrain = !this._showTerrain;
+ };
getMarkerIcon = (pinDoc: Doc): JSX.Element | null => {
const markerType = StrCast(pinDoc.markerType);
@@ -1148,7 +1156,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
const scale = this._props.NativeDimScaling?.() || 1;
const parscale = scale === 1 ? 1 : this.ScreenToLocalBoxXf().Scale ?? 1;
- const renderAnnotations = (childFilters?: () => string[]) => null;
return (
<div className="mapBox" ref={this._ref}>
<div
@@ -1156,15 +1163,12 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
onWheel={e => e.stopPropagation()}
onPointerDown={e => e.button === 0 && !e.ctrlKey && e.stopPropagation()}
style={{ transformOrigin: 'top left', transform: `scale(${scale})`, width: `calc(100% - ${this.sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}>
- <div style={{ mixBlendMode: 'multiply' }}>{renderAnnotations(this.transparentFilter)}</div>
- {renderAnnotations(this.opaqueFilter)}
- {SnappingManager.IsDragging ? null : renderAnnotations()}
{!this._routeToAnimate && (
<div className="mapBox-searchbar" style={{ width: `${100 / scale}%`, zIndex: 1, position: 'relative', background: 'lightGray' }}>
<TextField ref={this._textRef} fullWidth placeholder="Enter a location" onKeyDown={this.searchbarKeyDown} onChange={(e: any) => this.handleSearchChange(e.target.value)} />
- <IconButton icon={<FontAwesomeIcon icon={faGear as IconLookup} size="1x" />} type={Type.TERT} onClick={e => this.toggleSettings()} />
+ <IconButton icon={<FontAwesomeIcon icon={faGear as IconLookup} size="1x" />} type={Type.TERT} onClick={() => this.toggleSettings()} />
<div style={{ opacity: 0 }}>
- <IconButton icon={<FontAwesomeIcon icon={faGear as IconLookup} size="1x" />} type={Type.TERT} onClick={e => this.toggleSettings()} />
+ <IconButton icon={<FontAwesomeIcon icon={faGear as IconLookup} size="1x" />} type={Type.TERT} onClick={() => this.toggleSettings()} />
</div>
</div>
)}
@@ -1212,22 +1216,21 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
)}
{this._featuresFromGeocodeResults.length > 0 && (
<div className="mapbox-geocoding-search-results">
- <>
- <h4>Choose a location for your pin: </h4>
- {this._featuresFromGeocodeResults
- .filter(feature => feature.place_name)
- .map((feature, idx) => (
- <div
- key={idx}
- className="search-result-container"
- onClick={() => {
- this.handleSearchChange('');
- this.addMarkerForFeature(feature);
- }}>
- <div className="search-result-place-name">{feature.place_name}</div>
- </div>
- ))}
- </>
+ <h4>Choose a location for your pin: </h4>
+ {this._featuresFromGeocodeResults
+ .filter(feature => feature.place_name)
+ .map((feature, idx) => (
+ <div
+ // eslint-disable-next-line react/no-array-index-key
+ key={idx}
+ className="search-result-container"
+ onClick={() => {
+ this.handleSearchChange('');
+ this.addMarkerForFeature(feature);
+ }}>
+ <div className="search-result-place-name">{feature.place_name}</div>
+ </div>
+ ))}
</div>
)}
<MapProvider>
@@ -1254,7 +1257,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
<Source id="temporary-route" type="geojson" data={this._temporaryRouteSource} />
<Source id="map-routes" type="geojson" data={this.allRoutesGeoJson} />
<Layer id="temporary-route-layer" type="line" source="temporary-route" layout={{ 'line-join': 'round', 'line-cap': 'round' }} paint={{ 'line-color': '#36454F', 'line-width': 4, 'line-dasharray': [1, 1] }} />
- {!this._isAnimating && this._animationPhase == 0 && (
+ {!this._isAnimating && this._animationPhase === 0 && (
<Layer id="map-routes-layer" type="line" source="map-routes" layout={{ 'line-join': 'round', 'line-cap': 'round' }} paint={{ 'line-color': '#FF0000', 'line-width': 4 }} />
)}
{this._routeToAnimate && (this._isAnimating || this._animationPhase > 0) && (
@@ -1318,16 +1321,15 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
</>
)}
- <>
- {!this._isAnimating &&
- this._animationPhase == 0 &&
- this.allPushpins // .filter(anno => !anno.layout_unrendered)
- .map((pushpin, idx) => (
- <Marker key={idx} longitude={NumCast(pushpin.longitude)} latitude={NumCast(pushpin.latitude)} anchor="bottom" onClick={(e: MarkerEvent<mapboxgl.Marker, MouseEvent>) => this.handleMarkerClick(e, pushpin)}>
- {this.getMarkerIcon(pushpin)}
- </Marker>
- ))}
- </>
+ {!this._isAnimating &&
+ this._animationPhase === 0 &&
+ this.allPushpins // .filter(anno => !anno.layout_unrendered)
+ .map((pushpin, idx) => (
+ // eslint-disable-next-line react/no-array-index-key
+ <Marker key={idx} longitude={NumCast(pushpin.longitude)} latitude={NumCast(pushpin.latitude)} anchor="bottom" onClick={(e: MarkerEvent<mapboxgl.Marker, MouseEvent>) => this.handleMarkerClick(e, pushpin)}>
+ {this.getMarkerIcon(pushpin)}
+ </Marker>
+ ))}
{/* {this.mapMarkers.length > 0 && this.mapMarkers.map((marker, idx) => (
<Marker key={idx} longitude={marker.longitude} latitude={marker.latitude}/>
@@ -1338,12 +1340,13 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
<div className="mapBox-sidebar" style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
<SidebarAnnos
ref={this._sidebarRef}
+ // eslint-disable-next-line react/jsx-props-no-spreading
{...this._props}
fieldKey={this.fieldKey}
Document={this.Document}
layoutDoc={this.layoutDoc}
dataDoc={this.dataDoc}
- usePanelWidth={true}
+ usePanelWidth
showSidebar={this.SidebarShown}
nativeWidth={NumCast(this.layoutDoc._nativeWidth)}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
diff --git a/src/fields/RichTextUtils.ts b/src/fields/RichTextUtils.ts
index d75d66bf8..a2cc47a43 100644
--- a/src/fields/RichTextUtils.ts
+++ b/src/fields/RichTextUtils.ts
@@ -1,6 +1,8 @@
+/* eslint-disable no-await-in-loop */
+/* eslint-disable no-use-before-define */
import { AssertionError } from 'assert';
import * as Color from 'color';
-import { docs_v1 } from 'googleapis';
+import { docs_v1 as docsV1 } from 'googleapis';
import { Fragment, Mark, Node } from 'prosemirror-model';
import { sinkListItem } from 'prosemirror-schema-list';
import { EditorState, TextSelection, Transaction } from 'prosemirror-state';
@@ -48,13 +50,11 @@ export namespace RichTextUtils {
return JSON.stringify(state);
};
- export const Synthesize = (plainText: string, oldState?: RichTextField) => {
- return new RichTextField(ToProsemirrorState(plainText, oldState), plainText);
- };
+ export const Synthesize = (plainText: string, oldState?: RichTextField) => new RichTextField(ToProsemirrorState(plainText, oldState), plainText);
export const ToPlainText = (state: EditorState) => {
// Because we're working with plain text, just concatenate all paragraphs
- const content = state.doc.content;
+ const { content } = state.doc;
const paragraphs: Node[] = [];
content.forEach(node => node.type.name === 'paragraph' && paragraphs.push(node));
@@ -113,9 +113,9 @@ export namespace RichTextUtils {
agnostic: string;
}
- const parseInlineObjects = async (document: docs_v1.Schema$Document): Promise<Map<string, ImageTemplate>> => {
+ const parseInlineObjects = async (document: docsV1.Schema$Document): Promise<Map<string, ImageTemplate>> => {
const inlineObjectMap = new Map<string, ImageTemplate>();
- const inlineObjects = document.inlineObjects;
+ const { inlineObjects } = document;
if (inlineObjects) {
const objects = Object.keys(inlineObjects).map(objectId => inlineObjects[objectId]);
@@ -171,10 +171,12 @@ export namespace RichTextUtils {
const indentMap = new Map<ListGroup, BulletPosition[]>();
let globalOffset = 0;
const nodes: Node[] = [];
+ // eslint-disable-next-line no-restricted-syntax
for (const element of structured) {
if (Array.isArray(element)) {
lists.push(element);
const positions: BulletPosition[] = [];
+ // eslint-disable-next-line no-loop-func
const items = element.map(paragraph => {
const item = listItem(state.schema, paragraph.contents);
const sinks = paragraph.bullet!;
@@ -188,41 +190,42 @@ export namespace RichTextUtils {
});
indentMap.set(element, positions);
nodes.push(list(state.schema, items));
+ } else if (element.contents.some(child => 'inlineObjectId' in child)) {
+ const group = element.contents;
+ // eslint-disable-next-line no-loop-func
+ group.forEach((child, i) => {
+ let node: Opt<Node>;
+ if ('inlineObjectId' in child) {
+ node = imageNode(state.schema, inlineObjectMap.get(child.inlineObjectId!)!, textNote);
+ } else if ('content' in child && (i !== group.length - 1 || child.content!.removeTrailingNewlines().length)) {
+ node = paragraphNode(state.schema, [child]);
+ }
+ if (node) {
+ position += node.nodeSize;
+ nodes.push(node);
+ }
+ });
} else {
- if (element.contents.some(child => 'inlineObjectId' in child)) {
- const group = element.contents;
- group.forEach((child, i) => {
- let node: Opt<Node>;
- if ('inlineObjectId' in child) {
- node = imageNode(state.schema, inlineObjectMap.get(child.inlineObjectId!)!, textNote);
- } else if ('content' in child && (i !== group.length - 1 || child.content!.removeTrailingNewlines().length)) {
- node = paragraphNode(state.schema, [child]);
- }
- if (node) {
- position += node.nodeSize;
- nodes.push(node);
- }
- });
- } else {
- const paragraph = paragraphNode(state.schema, element.contents);
- nodes.push(paragraph);
- position += paragraph.nodeSize;
- }
+ const paragraph = paragraphNode(state.schema, element.contents);
+ nodes.push(paragraph);
+ position += paragraph.nodeSize;
}
}
state = state.apply(state.tr.replaceWith(0, 2, nodes));
const sink = sinkListItem(state.schema.nodes.list_item);
- const dispatcher = (tr: Transaction) => (state = state.apply(tr));
- for (const list of lists) {
- for (const pos of indentMap.get(list)!) {
+ const dispatcher = (tr: Transaction) => {
+ state = state.apply(tr);
+ };
+ lists.forEach(list => {
+ indentMap.get(list)?.forEach(pos => {
const resolved = state.doc.resolve(pos.value);
state = state.apply(state.tr.setSelection(new TextSelection(resolved)));
for (let i = 0; i < pos.sinks; i++) {
sink(state, dispatcher);
}
- }
- }
+ });
+ });
return { title, text, state };
};
@@ -234,7 +237,7 @@ export namespace RichTextUtils {
const parseLists = (paragraphs: ListGroup) => {
const groups: PreparedParagraphs = [];
let group: ListGroup = [];
- for (const paragraph of paragraphs) {
+ paragraphs.forEach(paragraph => {
if (paragraph.bullet !== undefined) {
group.push(paragraph);
} else {
@@ -244,26 +247,22 @@ export namespace RichTextUtils {
}
groups.push(paragraph);
}
- }
+ });
group.length && groups.push(group);
return groups;
};
- const listItem = (schema: any, runs: docs_v1.Schema$TextRun[]): Node => {
- return schema.node('list_item', null, paragraphNode(schema, runs));
- };
+ const listItem = (lschema: any, runs: docsV1.Schema$TextRun[]): Node => lschema.node('list_item', null, paragraphNode(lschema, runs));
- const list = (schema: any, items: Node[]): Node => {
- return schema.node('ordered_list', { mapStyle: 'bullet' }, items);
- };
+ const list = (lschema: any, items: Node[]): Node => lschema.node('ordered_list', { mapStyle: 'bullet' }, items);
- const paragraphNode = (schema: any, runs: docs_v1.Schema$TextRun[]): Node => {
- const children = runs.map(run => textNode(schema, run)).filter(child => child !== undefined);
+ const paragraphNode = (lschema: any, runs: docsV1.Schema$TextRun[]): Node => {
+ const children = runs.map(run => textNode(lschema, run)).filter(child => child !== undefined);
const fragment = children.length ? Fragment.from(children) : undefined;
- return schema.node('paragraph', null, fragment);
+ return lschema.node('paragraph', null, fragment);
};
- const imageNode = (schema: any, image: ImageTemplate, textNote: Doc) => {
+ const imageNode = (lschema: any, image: ImageTemplate, textNote: Doc) => {
const { url: src, width, agnostic } = image;
let docId: string;
const guid = Utils.GenerateDeterministicGuid(agnostic);
@@ -276,30 +275,30 @@ export namespace RichTextUtils {
} else {
docId = backingDocId;
}
- return schema.node('image', { src, agnostic, width, docId, float: null });
+ return lschema.node('image', { src, agnostic, width, docId, float: null });
};
- const textNode = (schema: any, run: docs_v1.Schema$TextRun) => {
+ const textNode = (lschema: any, run: docsV1.Schema$TextRun) => {
const text = run.content!.removeTrailingNewlines();
- return text.length ? schema.text(text, styleToMarks(schema, run.textStyle)) : undefined;
+ return text.length ? lschema.text(text, styleToMarks(lschema, run.textStyle)) : undefined;
};
- const StyleToMark = new Map<keyof docs_v1.Schema$TextStyle, keyof typeof schema.marks>([
+ const StyleToMark = new Map<keyof docsV1.Schema$TextStyle, keyof typeof schema.marks>([
['bold', 'strong'],
['italic', 'em'],
['foregroundColor', 'pFontColor'],
['fontSize', 'pFontSize'],
]);
- const styleToMarks = (schema: any, textStyle?: docs_v1.Schema$TextStyle) => {
+ const styleToMarks = (lschema: any, textStyle?: docsV1.Schema$TextStyle) => {
if (!textStyle) {
return undefined;
}
const marks: Mark[] = [];
Object.keys(textStyle).forEach(key => {
- let value: any;
- const targeted = key as keyof docs_v1.Schema$TextStyle;
- if ((value = textStyle[targeted])) {
+ const targeted = key as keyof docsV1.Schema$TextStyle;
+ const value = textStyle[targeted] as any;
+ if (value) {
const attributes: any = {};
let converted = StyleToMark.get(targeted) || targeted;
@@ -316,20 +315,20 @@ export namespace RichTextUtils {
converted = ImportFontFamilyMapping.get(value.fontFamily) || 'timesNewRoman';
}
- const mapped = schema.marks[converted];
+ const mapped = lschema.marks[converted];
if (!mapped) {
alert(`No mapping found for ${converted}!`);
return;
}
- const mark = schema.mark(mapped, attributes);
+ const mark = lschema.mark(mapped, attributes);
mark && marks.push(mark);
}
});
return marks;
};
- const MarkToStyle = new Map<keyof typeof schema.marks, keyof docs_v1.Schema$TextStyle>([
+ const MarkToStyle = new Map<keyof typeof schema.marks, keyof docsV1.Schema$TextStyle>([
['strong', 'bold'],
['em', 'italic'],
['pFontColor', 'foregroundColor'],
@@ -361,16 +360,18 @@ export namespace RichTextUtils {
const ignored = ['user_mark'];
- const marksToStyle = async (nodes: (Node | null)[]): Promise<docs_v1.Schema$Request[]> => {
- const requests: docs_v1.Schema$Request[] = [];
+ const marksToStyle = async (nodes: (Node | null)[]): Promise<docsV1.Schema$Request[]> => {
+ const requests: docsV1.Schema$Request[] = [];
let position = 1;
+ // eslint-disable-next-line no-restricted-syntax
for (const node of nodes) {
if (node === null) {
position += 2;
+ // eslint-disable-next-line no-continue
continue;
}
const { marks, attrs, nodeSize } = node;
- const textStyle: docs_v1.Schema$TextStyle = {};
+ const textStyle: docsV1.Schema$TextStyle = {};
const information: LinkInformation = {
startIndex: position,
endIndex: position + nodeSize,
@@ -378,36 +379,45 @@ export namespace RichTextUtils {
};
let mark: Mark;
const markMap = BuildMarkMap(marks);
+ // eslint-disable-next-line no-restricted-syntax
for (const markName of Object.keys(schema.marks)) {
+ // eslint-disable-next-line no-cond-assign
if (ignored.includes(markName) || !(mark = markMap[markName])) {
+ // eslint-disable-next-line no-continue
continue;
}
- let converted = MarkToStyle.get(markName) || (markName as keyof docs_v1.Schema$TextStyle);
+ let converted = MarkToStyle.get(markName) || (markName as keyof docsV1.Schema$TextStyle);
let value: any = true;
if (!converted) {
+ // eslint-disable-next-line no-continue
continue;
}
+ // eslint-disable-next-line @typescript-eslint/no-shadow
const { attrs } = mark;
switch (converted) {
case 'link':
- let url = attrs.allLinks.length ? attrs.allLinks[0].href : '';
- const delimiter = '/doc/';
- const alreadyShared = '?sharing=true';
- if (new RegExp(window.location.origin + delimiter).test(url) && !url.endsWith(alreadyShared)) {
- const linkDoc = await DocServer.GetRefField(url.split(delimiter)[1]);
- if (linkDoc instanceof Doc) {
- let exported = (await Cast(linkDoc.link_anchor_2, Doc))!;
- if (!exported.customLayout) {
- exported = Doc.MakeEmbedding(exported);
- DocUtils.makeCustomViewClicked(exported, Docs.Create.FreeformDocument);
- linkDoc.link_anchor_2 = exported;
+ {
+ let url = attrs.allLinks.length ? attrs.allLinks[0].href : '';
+ const docDelimeter = '/doc/';
+ const alreadyShared = '?sharing=true';
+ if (new RegExp(window.location.origin + docDelimeter).test(url) && !url.endsWith(alreadyShared)) {
+ // eslint-disable-next-line no-await-in-loop
+ const linkDoc = await DocServer.GetRefField(url.split(docDelimeter)[1]);
+ if (linkDoc instanceof Doc) {
+ // eslint-disable-next-line no-await-in-loop
+ let exported = (await Cast(linkDoc.link_anchor_2, Doc))!;
+ if (!exported.customLayout) {
+ exported = Doc.MakeEmbedding(exported);
+ DocUtils.makeCustomViewClicked(exported, Docs.Create.FreeformDocument);
+ linkDoc.link_anchor_2 = exported;
+ }
+ url = ClientUtils.shareUrl(exported[Id]);
}
- url = ClientUtils.shareUrl(exported[Id]);
}
+ value = { url };
+ textStyle.foregroundColor = fromRgb.blue;
+ textStyle.bold = true;
}
- value = { url };
- textStyle.foregroundColor = fromRgb.blue;
- textStyle.bold = true;
break;
case 'fontSize':
value = { magnitude: attrs.fontSize, unit: 'PT' };
@@ -417,9 +427,11 @@ export namespace RichTextUtils {
break;
case 'weightedFontFamily':
value = { fontFamily: ExportFontFamilyMapping.get(markName) };
+ break;
+ default:
}
- let matches: RegExpExecArray | null;
- if ((matches = /p(\d+)/g.exec(markName)) !== null) {
+ const matches = /p(\d+)/g.exec(markName);
+ if (matches !== null) {
converted = 'fontSize';
value = { magnitude: parseInt(matches[1].replace('px', '')), unit: 'PT' };
}
@@ -429,7 +441,7 @@ export namespace RichTextUtils {
requests.push(EncodeStyleUpdate(information));
}
if (node.type.name === 'image') {
- const width = attrs.width;
+ const { width } = attrs;
requests.push(
await EncodeImage({
startIndex: position + nodeSize - 1,
@@ -445,14 +457,16 @@ export namespace RichTextUtils {
const BuildMarkMap = (marks: readonly Mark[]) => {
const markMap: { [type: string]: Mark } = {};
- marks.forEach(mark => (markMap[mark.type.name] = mark));
+ marks.forEach(mark => {
+ markMap[mark.type.name] = mark;
+ });
return markMap;
};
interface LinkInformation {
startIndex: number;
endIndex: number;
- textStyle: docs_v1.Schema$TextStyle;
+ textStyle: docsV1.Schema$TextStyle;
}
interface ImageInformation {
@@ -462,36 +476,34 @@ export namespace RichTextUtils {
}
namespace fromRgb {
- export const convert = (red: number, green: number, blue: number): docs_v1.Schema$OptionalColor => {
- return {
- color: {
- rgbColor: {
- red: red / 255,
- green: green / 255,
- blue: blue / 255,
- },
+ export const convert = (red: number, green: number, blue: number): docsV1.Schema$OptionalColor => ({
+ color: {
+ rgbColor: {
+ red: red / 255,
+ green: green / 255,
+ blue: blue / 255,
},
- };
- };
+ },
+ });
export const red = convert(255, 0, 0);
export const green = convert(0, 255, 0);
export const blue = convert(0, 0, 255);
}
- const fromHex = (color: string): docs_v1.Schema$OptionalColor => {
+ const fromHex = (color: string): docsV1.Schema$OptionalColor => {
const c = DashColor(color);
return fromRgb.convert(c.red(), c.green(), c.blue());
};
- const EncodeStyleUpdate = (information: LinkInformation): docs_v1.Schema$Request => {
+ const EncodeStyleUpdate = (information: LinkInformation): docsV1.Schema$Request => {
const { startIndex, endIndex, textStyle } = information;
return {
updateTextStyle: {
fields: '*',
range: { startIndex, endIndex },
textStyle,
- } as docs_v1.Schema$UpdateTextStyleRequest,
+ } as docsV1.Schema$UpdateTextStyleRequest,
};
};