Skip to content

Commit

Permalink
Merge pull request rowyio#1158 from rowyio/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
shamsmosowi authored Mar 13, 2023
2 parents 189b106 + 2ef0255 commit 9382d8c
Show file tree
Hide file tree
Showing 12 changed files with 198 additions and 63 deletions.
38 changes: 37 additions & 1 deletion src/components/CodeEditor/CodeEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from "react";
import Editor, { EditorProps } from "@monaco-editor/react";
import Editor, { EditorProps, Monaco } from "@monaco-editor/react";
import type { editor } from "monaco-editor/esm/vs/editor/editor.api";

import { useTheme, Box, BoxProps, AppBar, Toolbar } from "@mui/material";
Expand Down Expand Up @@ -72,6 +72,36 @@ export default function CodeEditor({
onValidate?.(markers);
};

const validate = (monaco: Monaco, model: editor.ITextModel) => {
const markers = [];
for (let i = 1; i < model.getLineCount() + 1; i++) {
const range = {
startLineNumber: i,
startColumn: 1,
endLineNumber: i,
endColumn: model.getLineLength(i) + 1,
};
const line = model.getValueInRange(range);
for (const keyword of ["console.log", "console.warn", "console.error"]) {
const consoleLogIndex = line.indexOf(keyword);
if (consoleLogIndex >= 0) {
markers.push({
message: `Replace with ${keyword.replace(
"console",
"logging"
)}: Rowy Cloud Logging provides a better experience to view logs. Simply replace 'console' with 'logging'. \n\nhttps://docs.rowy.io/cloud-logs`,
severity: monaco.MarkerSeverity.Warning,
startLineNumber: range.startLineNumber,
endLineNumber: range.endLineNumber,
startColumn: consoleLogIndex + 1,
endColumn: consoleLogIndex + keyword.length + 1,
});
}
}
}
monaco.editor.setModelMarkers(model, "owner", markers);
};

return (
<TrapFocus open={fullScreen}>
<Box
Expand All @@ -94,6 +124,12 @@ export default function CodeEditor({
beforeMount={(monaco) => {
monaco.editor.defineTheme("github-light", githubLightTheme as any);
monaco.editor.defineTheme("github-dark", githubDarkTheme as any);
monaco.editor.onDidCreateModel((model) => {
validate(monaco, model);
model.onDidChangeContent(() => {
validate(monaco, model);
});
});
}}
onMount={(editor) => {
if (onFocus) editor.onDidFocusEditorWidget(onFocus);
Expand Down
59 changes: 48 additions & 11 deletions src/components/CodeEditor/useMonacoCustomizations.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import { useEffect } from "react";
// import {
// quicktype,
// InputData,
// jsonInputForTargetLanguage,
// } from "quicktype-core";
import { useAtom } from "jotai";

import {
Expand All @@ -13,15 +8,10 @@ import {
} from "@src/atoms/tableScope";
import { useMonaco } from "@monaco-editor/react";
import type { languages } from "monaco-editor/esm/vs/editor/editor.api";
import githubLightTheme from "./github-light-default.json";
import githubDarkTheme from "./github-dark-default.json";

import { useTheme } from "@mui/material";
import type { SystemStyleObject, Theme } from "@mui/system";

// TODO:
// import { getFieldType, getFieldProp } from "@src/components/fields";

/* eslint-disable import/no-webpack-loader-syntax */
import firestoreDefs from "!!raw-loader!./firestore.d.ts";
import firebaseAuthDefs from "!!raw-loader!./firebaseAuth.d.ts";
Expand Down Expand Up @@ -72,7 +62,6 @@ export default function useMonacoCustomizations({
};
}, []);

// Initialize external libs & TypeScript compiler options
useEffect(() => {
if (!monaco) return;

Expand All @@ -95,6 +84,8 @@ export default function useMonacoCustomizations({
"ts:filename/utils.d.ts"
);
monaco.languages.typescript.javascriptDefaults.addExtraLib(rowyUtilsDefs);

setLoggingReplacementActions();
} catch (error) {
console.error(
"An error occurred during initialization of Monaco: ",
Expand Down Expand Up @@ -135,6 +126,52 @@ export default function useMonacoCustomizations({
}
}, [monaco, stringifiedDiagnosticsOptions]);

const setLoggingReplacementActions = () => {
if (!monaco) return;
const { dispose } = monaco.languages.registerCodeActionProvider(
"javascript",
{
provideCodeActions: (model, range, context, token) => {
const actions = context.markers
.filter((error) => {
return error.message.includes("Rowy Cloud Logging");
})
.map((error) => {
// first sentence of the message is "Replace with logging.[log/warn/error]"
const firstSentence = error.message.split(":")[0];
const replacement = firstSentence.split("with ")[1];
return {
title: firstSentence,
diagnostics: [error],
kind: "quickfix",
edit: {
edits: [
{
resource: model.uri,
edit: {
range: error,
text: replacement,
},
},
],
},
isPreferred: true,
};
});
return {
actions: actions,
dispose: () => {},
};
},
}
);
monaco.editor.onWillDisposeModel((model) => {
// dispose code action provider when model is disposed
// this makes sure code actions are not displayed multiple times
dispose();
});
};

const addJsonFieldDefinition = async (
columnKey: string,
interfaceName: string
Expand Down
2 changes: 1 addition & 1 deletion src/components/Table/ColumnHeader/useSaveTableSorts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ function useSaveTableSorts(canEditColumns: boolean) {
const [updateTableSchema] = useAtom(updateTableSchemaAtom, tableScope);
const [updateUserSettings] = useAtom(updateUserSettingsAtom, projectScope);
const [tableId] = useAtom(tableIdAtom, tableScope);
if (!updateTableSchema) throw new Error("Cannot update table schema");
const { enqueueSnackbar, closeSnackbar } = useSnackbar();
const [snackbarId, setSnackbarId] = useState<SnackbarKey | null>(null);

// Offer to save when table sorts changes
const trigger = useCallback(
(sorts: TableSort[]) => {
if (!updateTableSchema) throw new Error("Cannot update table schema");
if (updateUserSettings) {
updateUserSettings({
tables: {
Expand Down
12 changes: 9 additions & 3 deletions src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useMemo, useRef, useState, useEffect, useCallback } from "react";
import useStateRef from "react-usestateref";
// import useStateRef from "react-usestateref"; // testing with useStateWithRef
import { useAtom, useSetAtom } from "jotai";
import { useThrottledCallback } from "use-debounce";
import {
Expand Down Expand Up @@ -41,6 +41,7 @@ import { useMenuAction } from "./useMenuAction";
import { useSaveColumnSizing } from "./useSaveColumnSizing";
import useHotKeys from "./useHotKey";
import type { TableRow, ColumnConfig } from "@src/types/table";
import useStateWithRef from "./useStateWithRef"; // testing with useStateWithRef

export const DEFAULT_ROW_HEIGHT = 41;
export const DEFAULT_COL_WIDTH = 150;
Expand Down Expand Up @@ -110,7 +111,9 @@ export default function Table({
// so the state can re-render `TableBody`, preventing virtualization
// not detecting scroll if the container element was initially `null`
const [containerEl, setContainerEl, containerRef] =
useStateRef<HTMLDivElement | null>(null);
// useStateRef<HTMLDivElement | null>(null); // <-- older approach with useStateRef
useStateWithRef<HTMLDivElement | null>(null); // <-- newer approach with custom hook

const gridRef = useRef<HTMLDivElement>(null);

// Get column defs from table schema
Expand Down Expand Up @@ -255,7 +258,10 @@ export default function Table({

return (
<div
ref={(el) => setContainerEl(el)}
ref={(el) => {
if (!el) return;
setContainerEl(el);
}}
onScroll={(e) => fetchMoreOnBottomReached(e.target as HTMLDivElement)}
style={{ overflow: "auto", width: "100%", height: "100%" }}
>
Expand Down
29 changes: 29 additions & 0 deletions src/components/Table/useStateWithRef.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {
MutableRefObject,
useCallback,
useRef,
useSyncExternalStore,
} from "react";

// NOTE: This is not the final solution. But is a potential solution for this problem.
export default function useStateWithRef<T>(
initialState: T
): [T, (newValue: T) => void, MutableRefObject<T>] {
const value = useRef<T>(initialState);
const get = useCallback(() => value.current, []);
const subscribers = useRef(new Set<() => void>());

const set = useCallback((newValue: T) => {
value.current = newValue;
subscribers.current.forEach((callback) => callback());
}, []);

const subscribe = useCallback((callback: () => void) => {
subscribers.current.add(callback);
return () => subscribers.current.delete(callback);
}, []);

const state = useSyncExternalStore(subscribe, get);

return [state, set, value];
}
22 changes: 22 additions & 0 deletions src/components/Table/useTraceUpdates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useEffect, useRef } from "react";

// This hook is used to log changes to props in a component.
export default function useTraceUpdates(
props: { [key: string]: any },
printMessage: string = "Changed props:"
) {
const prev = useRef(props);
useEffect(() => {
const changedProps = Object.entries(props).reduce((ps, [k, v]) => {
if (prev.current[k] !== v) {
// @ts-ignore
ps[k] = [prev.current[k], v];
}
return ps;
}, {});
if (Object.keys(changedProps).length > 0) {
console.log(printMessage, changedProps);
}
prev.current = props;
});
}
9 changes: 1 addition & 8 deletions src/components/fields/Formula/PreviewTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,7 @@ const PreviewTable = ({ tableSchema }: { tableSchema: TableSchema }) => {
scope={tableScope}
initialValues={[
[currentUserAtom, currentUser],
[
tableSettingsAtom,
{
...tableSettings,
id: "preview-table",
collection: "preview-collection",
},
],
[tableSettingsAtom, tableSettings],
[tableRowsDbAtom, []],
]}
>
Expand Down
37 changes: 11 additions & 26 deletions src/components/fields/Formula/TableSourcePreview.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useCallback, useEffect } from "react";
import { useSetAtom } from "jotai";
import { useAtom, useSetAtom } from "jotai";
import { useAtomCallback } from "jotai/utils";
import { cloneDeep, findIndex, sortBy } from "lodash-es";

Expand All @@ -10,39 +10,24 @@ import {
tableRowsDbAtom,
tableSchemaAtom,
tableScope,
tableSettingsAtom,
} from "@src/atoms/tableScope";

import { TableRow, TableSchema } from "@src/types/table";
import { updateRowData } from "@src/utils/table";

const initialRows = [
{
_rowy_ref: {
id: "zzzzzzzzzzzzzzzzzzzw",
path: "preview-collection/zzzzzzzzzzzzzzzzzzzw",
},
},
{
_rowy_ref: {
id: "zzzzzzzzzzzzzzzzzzzx",
path: "preview-collection/zzzzzzzzzzzzzzzzzzzx",
},
},
{
_rowy_ref: {
id: "zzzzzzzzzzzzzzzzzzzy",
path: "preview-collection/zzzzzzzzzzzzzzzzzzzy",
},
},
];
import { serializeRef } from "./util";

const TableSourcePreview = ({ tableSchema }: { tableSchema: TableSchema }) => {
const [tableSettings] = useAtom(tableSettingsAtom, tableScope);
const setTableSchemaAtom = useSetAtom(tableSchemaAtom, tableScope);
const setRows = useSetAtom(tableRowsDbAtom, tableScope);

useEffect(() => {
setRows(initialRows);
}, [setRows]);
setRows(
["preview-doc-1", "preview-doc-2", "preview-doc-3"].map((docId) => ({
_rowy_ref: serializeRef(`${tableSettings.collection}/${docId}`),
}))
);
}, [setRows, tableSettings.collection]);

useEffect(() => {
setTableSchemaAtom(() => ({
Expand All @@ -52,7 +37,7 @@ const TableSourcePreview = ({ tableSchema }: { tableSchema: TableSchema }) => {
}, [tableSchema, setTableSchemaAtom]);

const readRowsDb = useAtomCallback(
useCallback((get) => get(tableRowsDbAtom) || initialRows, []),
useCallback((get) => get(tableRowsDbAtom) || [], []),
tableScope
);

Expand Down
7 changes: 3 additions & 4 deletions src/components/fields/Formula/formula.d.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
type RowRef = Pick<FirebaseFirestore.DocumentReference, "id", "path">;
type RowRef<T> = { id: string; path: string; parent: T };
interface Ref extends RowRef<Ref> {}

type FormulaContext = {
row: Row;
ref: RowRef;
// storage: firebasestorage.Storage;
// db: FirebaseFirestore.Firestore;
ref: Ref;
};

type Formula = (context: FormulaContext) => "PLACEHOLDER_OUTPUT_TYPE";
18 changes: 12 additions & 6 deletions src/components/fields/Formula/useFormula.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import { useAtom } from "jotai";
import { TableRow, TableRowRef } from "@src/types/table";
import { tableColumnsOrderedAtom, tableScope } from "@src/atoms/tableScope";

import { listenerFieldTypes, useDeepCompareMemoize } from "./util";
import {
listenerFieldTypes,
serializeRef,
useDeepCompareMemoize,
} from "./util";

export const useFormula = ({
row,
Expand Down Expand Up @@ -60,11 +64,13 @@ export const useFormula = ({
setLoading(false);
};

worker.postMessage({
formulaFn,
row: JSON.stringify(availableFields),
ref: { id: ref.id, path: ref.path },
});
worker.postMessage(
JSON.stringify({
formulaFn,
row: availableFields,
ref: serializeRef(ref.path),
})
);

return () => {
worker.terminate();
Expand Down
Loading

0 comments on commit 9382d8c

Please sign in to comment.