aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/apis/google_docs/GoogleApiClientUtils.ts111
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx15
-rw-r--r--src/new_fields/RichTextField.ts4
-rw-r--r--src/server/index.ts35
4 files changed, 99 insertions, 66 deletions
diff --git a/src/client/apis/google_docs/GoogleApiClientUtils.ts b/src/client/apis/google_docs/GoogleApiClientUtils.ts
index f4fb87e0b..c6c7d7bd4 100644
--- a/src/client/apis/google_docs/GoogleApiClientUtils.ts
+++ b/src/client/apis/google_docs/GoogleApiClientUtils.ts
@@ -1,7 +1,7 @@
import { docs_v1 } from "googleapis";
import { PostToServer } from "../../../Utils";
import { RouteStore } from "../../../server/RouteStore";
-import { Opt, Doc } from "../../../new_fields/Doc";
+import { Opt } from "../../../new_fields/Doc";
import { isArray } from "util";
export namespace GoogleApiClientUtils {
@@ -14,9 +14,42 @@ export namespace GoogleApiClientUtils {
Update = "update"
}
+ export type DocumentId = string;
+ export type Reference = DocumentId | CreateOptions;
+ export type TextContent = string | string[];
+ export type IdHandler = (id: DocumentId) => any;
+
+ export type CreationResult = Opt<DocumentId>;
+ export type RetrievalResult = Opt<docs_v1.Schema$Document>;
+ export type UpdateResult = Opt<docs_v1.Schema$BatchUpdateDocumentResponse>;
+ export type ReadLinesResult = Opt<string[]>;
+ export type ReadResult = Opt<string>;
+
+ export interface CreateOptions {
+ handler: IdHandler; // callback to process the documentId of the newly created Google Doc
+ title?: string; // if excluded, will use a default title annotated with the current date
+ }
+
+ export interface RetrieveOptions {
+ documentId: DocumentId;
+ }
+
+ export type ReadOptions = RetrieveOptions & { removeNewlines?: boolean };
+
+ export interface WriteOptions {
+ content: TextContent;
+ reference: Reference;
+ index?: number; // if excluded, will compute the last index of the document and append the content there
+ }
+
+ export interface UpdateOptions {
+ documentId: DocumentId;
+ requests: docs_v1.Schema$Request[];
+ }
+
export namespace Utils {
- export const extractText = (document: docs_v1.Schema$Document, removeNewlines = false) => {
+ export const extractText = (document: docs_v1.Schema$Document, removeNewlines = false): string => {
const fragments: string[] = [];
if (document.body && document.body.content) {
for (const element of document.body.content) {
@@ -34,7 +67,7 @@ export namespace GoogleApiClientUtils {
return removeNewlines ? text.ReplaceAll("\n", "") : text;
};
- export const EndOf = (schema: docs_v1.Schema$Document): Opt<number> => {
+ export const endOf = (schema: docs_v1.Schema$Document): number | undefined => {
if (schema.body && schema.body.content) {
const paragraphs = schema.body.content.filter(el => el.paragraph);
if (paragraphs.length) {
@@ -50,27 +83,8 @@ export namespace GoogleApiClientUtils {
}
};
- }
+ export const initialize = async (reference: Reference) => typeof reference === "string" ? reference : create(reference);
- export type IdHandler = (id: DocumentId) => any;
- export interface CreateOptions {
- handler: IdHandler;
- // if excluded, will use a default title annotated with the current date
- title?: string;
- }
-
- export interface ReadOptions {
- documentId: string;
- // if exluded, will preserve newlines
- removeNewlines?: boolean;
- }
-
- export type DocumentId = string;
- export interface WriteOptions {
- content: string | string[];
- reference: DocumentId | CreateOptions;
- // if excluded, will compute the last index of the document and append the content there
- index?: number;
}
/**
@@ -82,7 +96,7 @@ export namespace GoogleApiClientUtils {
* to store the new documentId returned from the creation process
* @returns the documentId of the newly generated document, or undefined if the creation process fails.
*/
- const Create = async (options: CreateOptions): Promise<string | undefined> => {
+ export const create = async (options: CreateOptions): Promise<CreationResult> => {
const path = RouteStore.googleDocs + Actions.Create;
const parameters = {
requestBody: {
@@ -101,43 +115,40 @@ export namespace GoogleApiClientUtils {
}
};
- const Retrieve = async (documentId: string): Promise<docs_v1.Schema$Document | undefined> => {
+ export const retrieve = async (options: RetrieveOptions): Promise<RetrievalResult> => {
const path = RouteStore.googleDocs + Actions.Retrieve;
- const parameters = {
- documentId
- };
try {
- const schema: docs_v1.Schema$Document = await PostToServer(path, parameters);
+ const schema: RetrievalResult = await PostToServer(path, options);
return schema;
} catch {
return undefined;
}
};
- const Update = async (documentId: string, requests: docs_v1.Schema$Request[]): Promise<docs_v1.Schema$BatchUpdateDocumentResponse | undefined> => {
+ export const update = async (options: UpdateOptions): Promise<UpdateResult> => {
const path = RouteStore.googleDocs + Actions.Update;
const parameters = {
- documentId,
+ documentId: options.documentId,
requestBody: {
- requests
+ requests: options.requests
}
};
try {
- const replies: docs_v1.Schema$BatchUpdateDocumentResponse = await PostToServer(path, parameters);
+ const replies: UpdateResult = await PostToServer(path, parameters);
return replies;
} catch {
return undefined;
}
};
- export const Read = async (options: ReadOptions): Promise<string | undefined> => {
- return Retrieve(options.documentId).then(schema => {
+ export const read = async (options: ReadOptions): Promise<ReadResult> => {
+ return retrieve(options).then(schema => {
return schema ? Utils.extractText(schema, options.removeNewlines) : undefined;
});
};
- export const ReadLines = async (options: ReadOptions) => {
- return Retrieve(options.documentId).then(schema => {
+ export const readLines = async (options: ReadOptions): Promise<ReadLinesResult> => {
+ return retrieve(options).then(schema => {
if (!schema) {
return undefined;
}
@@ -146,27 +157,29 @@ export namespace GoogleApiClientUtils {
});
};
- export const Write = async (options: WriteOptions): Promise<docs_v1.Schema$BatchUpdateDocumentResponse | undefined> => {
- let documentId: string | undefined;
- const ref = options.reference;
- if (!(documentId = typeof ref === "string" ? ref : await Create(ref))) {
+ export const write = async (options: WriteOptions): Promise<UpdateResult> => {
+ const documentId = await Utils.initialize(options.reference);
+ if (!documentId) {
return undefined;
}
let index = options.index;
if (!index) {
- let schema = await Retrieve(documentId);
- if (!schema || !(index = Utils.EndOf(schema))) {
+ let schema = await retrieve({ documentId });
+ if (!schema || !(index = Utils.endOf(schema))) {
return undefined;
}
}
const text = options.content;
- const request = {
- insertText: {
- text: isArray(text) ? text.join("\n") : text,
- location: { index }
- }
+ const updateOptions = {
+ documentId,
+ requests: [{
+ insertText: {
+ text: isArray(text) ? text.join("\n") : text,
+ location: { index }
+ }
+ }]
};
- return Update(documentId, [request]);
+ return update(updateOptions);
};
}
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 50ec27259..46aed9b2d 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -288,6 +288,19 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
}
}
+ componentWillMount() {
+ this.pollExportedCounterpart();
+ }
+
+ pollExportedCounterpart = async () => {
+ let dataDoc = Doc.GetProto(this.props.Document);
+ let documentId = StrCast(dataDoc[googleDocKey]);
+ if (documentId) {
+ let contents = await GoogleApiClientUtils.Docs.read({ documentId });
+ contents ? console.log(contents) : delete dataDoc[googleDocKey];
+ }
+ }
+
componentDidMount() {
const config = {
schema,
@@ -675,7 +688,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
if (!data) {
return;
}
- GoogleApiClientUtils.Docs.Write({
+ GoogleApiClientUtils.Docs.write({
reference: {
title: StrCast(dataDoc.title),
handler: id => dataDoc[googleDocKey] = id
diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts
index 3e8803a34..4f782816c 100644
--- a/src/new_fields/RichTextField.ts
+++ b/src/new_fields/RichTextField.ts
@@ -9,7 +9,7 @@ import { scriptingGlobal } from "../client/util/Scripting";
export class RichTextField extends ObjectField {
@serializable(true)
readonly Data: string;
- private Extractor = /,\"text\":\"([^\"\}]*)\"\}/g;
+ private Extractor = /,\"text\":\"([^\}]*)\"\}/g;
constructor(data: string) {
super();
@@ -33,6 +33,6 @@ export class RichTextField extends ObjectField {
considering = considering.substring(matches.index + matches[0].length);
this.Extractor.lastIndex = 0;
}
- return contents;
+ return contents.ReplaceAll("\\", "");
}
} \ No newline at end of file
diff --git a/src/server/index.ts b/src/server/index.ts
index abaa29658..ef1829f30 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -43,6 +43,8 @@ import * as YoutubeApi from "./apis/youtube/youtubeApiSample";
import { Response } from 'express-serve-static-core';
import { GoogleApiServerUtils } from "./apis/google/GoogleApiServerUtils";
import { GaxiosResponse } from 'gaxios';
+import { Opt } from '../new_fields/Doc';
+import { docs_v1 } from 'googleapis';
const MongoStore = require('connect-mongo')(session);
const mongoose = require('mongoose');
const probe = require("probe-image-size");
@@ -797,23 +799,28 @@ function HandleYoutubeQuery([query, callback]: [YoutubeQueryInput, (result?: any
const credentials = path.join(__dirname, "./credentials/google_docs_credentials.json");
const token = path.join(__dirname, "./credentials/google_docs_token.json");
+type ApiResponse = Promise<GaxiosResponse>;
+type ApiHandler = (endpoint: docs_v1.Resource$Documents, parameters: any) => ApiResponse;
+type Action = "create" | "retrieve" | "update";
+
+const EndpointHandlerMap = new Map<Action, ApiHandler>([
+ ["create", (api, params) => api.create(params)],
+ ["retrieve", (api, params) => api.get(params)],
+ ["update", (api, params) => api.batchUpdate(params)],
+]);
+
app.post(RouteStore.googleDocs + ":action", (req, res) => {
GoogleApiServerUtils.Docs.GetEndpoint({ credentials, token }).then(endpoint => {
- let results: Promise<GaxiosResponse> | undefined;
- let documents = endpoint.documents;
- let parameters = req.body;
- switch (req.params.action) {
- case "create":
- results = documents.create(parameters);
- break;
- case "retrieve":
- results = documents.get(parameters);
- break;
- case "update":
- results = documents.batchUpdate(parameters);
- break;
+ let handler = EndpointHandlerMap.get(req.params.action);
+ if (handler) {
+ let execute = handler(endpoint.documents, req.body).then(
+ response => res.send(response.data),
+ rejection => res.send(rejection)
+ );
+ execute.catch(exception => res.send(exception));
+ return;
}
- !results ? res.send(undefined) : results.then(response => res.send(response.data));
+ res.send(undefined);
});
});