Skip to content
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
f5d42cb
feat(serialization): add first pass at serialization
tefkah May 7, 2025
ce77fcd
feat(ui): add new show more component
tefkah Apr 30, 2025
204fa4f
feat(serialization): add proper serialization libs
tefkah Apr 30, 2025
c33097f
refactor(serialization): parse and convert prosemirror tree during
tefkah Apr 30, 2025
8f49b17
feat(fts|serialization): properly index html
tefkah May 1, 2025
d9f4f20
fix(serialization): sort of fix loading
tefkah May 7, 2025
e92f261
fix: fix weird redis install issue
tefkah May 7, 2025
550c767
dev: make legacy seed have useful richtext
tefkah May 7, 2025
71439d6
dev: make legacy seed have useful richtext
tefkah May 8, 2025
642bbd1
feat(math): serialize math to mathml and back reliably
tefkah May 8, 2025
9997e8f
feat(serialization): find a happy way to store html and serialize on …
tefkah May 12, 2025
2b3c8b5
chore: remove old validation function, fix test
tefkah May 12, 2025
e5bf99f
fix: fix the stories
tefkah May 12, 2025
b83d855
fix: really fix math, cleanup
tefkah May 12, 2025
e2b5978
feat: add migration to clear current richtext values
tefkah May 12, 2025
276fffe
Merge branch 'main' into tfk/html-richtext
tefkah May 12, 2025
6c740c6
chore: meaningless change to trigger ci
tefkah May 12, 2025
53bb547
fix: fix fts related type issues
tefkah May 12, 2025
162b545
fix: fix contexteditor related type issues
tefkah May 12, 2025
0ced401
chore: don't format html
tefkah May 12, 2025
76e70e8
fix: fix test to work with figures
tefkah May 12, 2025
7831b83
chore: revert and merge with main
tefkah May 15, 2025
ec44cc8
fix: modify tests
tefkah May 15, 2025
39b0628
Merge branch 'main' into tfk/html-richtext
tefkah May 19, 2025
829eb08
chore: remove silly console.log messages in cache layer
tefkah May 20, 2025
b892c62
refactor: move the html/prosemirror boundary to the form
tefkah May 20, 2025
0dded00
chore: merge with main
tefkah May 20, 2025
114206f
fix: handle no value for richtext
tefkah May 21, 2025
e0f038d
fix: use more predictable handling of temp richtext value, add explan…
tefkah May 21, 2025
7a6ea14
refactor: get rid of forward ref, it is cringe
tefkah May 21, 2025
971e977
Merge branch 'main' into tfk/html-richtext
tefkah May 21, 2025
81d60fc
fix: make ref optional
tefkah May 21, 2025
848a258
fix: use consolidate prosemirror/html conversion fns a bit
tefkah May 21, 2025
1bbb209
Merge branch 'main' into tfk/html-richtext
tefkah May 22, 2025
05564bd
docs: update rich text docs
tefkah May 22, 2025
a3d9614
fix: find math display correctly
tefkah May 22, 2025
22c80b2
Merge branch 'main' into tfk/html-richtext
tefkah May 27, 2025
25f761d
fix?: use localhost instead of docker-host for minio init
tefkah May 27, 2025
3edd460
debug: add some logs
tefkah May 27, 2025
4b4c059
fix?: upgrade aws?
tefkah May 27, 2025
7ced2c4
fix(minio): use new minio client syntax after breaking change
tefkah May 27, 2025
243d4ea
Merge branch 'main' into tfk/html-richtext
tefkah May 27, 2025
9881d52
chore: merge
tefkah May 27, 2025
e77d8a5
chore: merge
tefkah May 29, 2025
0aa25f9
fix: cave to erics CRAZY demands
tefkah May 29, 2025
71984ef
fix: remove unnecessary memo
tefkah May 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion core/.prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
app/c/\[communitySlug\]/developers/docs/stoplight.styles.css
vitest-bench.local.json
vitest-bench.local.json
**/*.html
15 changes: 12 additions & 3 deletions core/app/c/[communitySlug]/pubs/[pubId]/components/PubValues.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import { Button } from "ui/button";
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "ui/collapsible";
import { ColorCircle, ColorLabel, ColorValue } from "ui/color";
import { ChevronDown, ChevronRight } from "ui/icon";
import { ShowMore } from "ui/show-more";

import type { FileUpload } from "~/lib/fields/fileUpload";
import { FileUploadPreview } from "~/app/components/forms/FileUpload";
import { getPubTitle, valuesWithoutTitle } from "~/lib/pubs";

Expand Down Expand Up @@ -208,8 +208,6 @@ const PubValue = ({ value }: { value: FullProcessedPubWithForm["values"][number]
);
}

// Currently, we are only rendering string versions of fields, except for file uploads
// For file uploads, because Unjournal doesn't have schemaNames yet, we check the value structure
const fileUploadSchema = getJsonSchemaByCoreSchemaType(CoreSchemaType.FileUpload);
if (Value.Check(fileUploadSchema, value.value)) {
return <FileUploadPreview files={value.value} />;
Expand All @@ -222,6 +220,17 @@ const PubValue = ({ value }: { value: FullProcessedPubWithForm["values"][number]
}
}

if (value.schemaName === CoreSchemaType.RichText) {
return (
<ShowMore animate={false}>
<div
className="prose prose-sm"
dangerouslySetInnerHTML={{ __html: value.value as string }}
/>
</ShowMore>
);
}
Comment on lines +223 to +232

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ideally we wouldnt do manual check here, but have InputComponents maybe define some default ReadOnly version of themselves which can be displayed here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i might look into this here #1209


if (value.schemaName === CoreSchemaType.Color) {
return (
<ColorLabel>
Expand Down
61 changes: 29 additions & 32 deletions core/app/components/ContextEditor/ContextEditorClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { ContextAtom } from "./AtomRenderer";

import "context-editor/style.css";

import React from "react";

import type { ContextEditorPub } from "./ContextEditorContext";
import { useServerAction } from "~/lib/serverActions";

Expand All @@ -20,59 +22,54 @@ const ContextEditor = dynamic(() => import("context-editor").then((mod) => mod.C
loading: () => <Skeleton className="h-16 w-full" />,
});

export const ContextEditorClient = ({
pubs,
pubTypes,
pubId,
pubTypeId,
className,
initialDoc,
onChange,
disabled,
hideMenu,
}: {
pubs: ContextEditorPub[];
pubTypes: GetPubTypesResult;
pubId: PubsId;
pubTypeId: PubTypesId;
// Might be able to use more of this type in the future—for now, this component is a lil more stricty typed than context-editor
} & Pick<
ContextEditorProps,
"onChange" | "initialDoc" | "className" | "disabled" | "hideMenu"
>) => {
export const ContextEditorClient = (
props: {
pubs: ContextEditorPub[];
pubTypes: GetPubTypesResult;
pubId: PubsId;
pubTypeId: PubTypesId;
// Might be able to use more of this type in the future—for now, this component is a lil more stricty typed than context-editor
} & Pick<
ContextEditorProps,
"onChange" | "initialDoc" | "className" | "disabled" | "hideMenu" | "getterRef"
>
) => {
const runUpload = useServerAction(upload);

const getPubs = useCallback(
(filter: string) => {
return new Promise<any[]>((resolve, reject) => {
resolve(pubs);
resolve(props.pubs);
});
},
[pubs]
[props.pubs]
);

const signedUploadUrl = (fileName: string) => {
return runUpload(pubId, fileName);
return runUpload(props.pubId, fileName);
};

const memoEditor = useMemo(() => {
return (
<ContextEditor
pubId={pubId}
pubTypeId={pubTypeId}
pubTypes={pubTypes}
pubId={props.pubId}
pubTypeId={props.pubTypeId}
pubTypes={props.pubTypes}
getPubs={getPubs}
getPubById={() => {
return {};
}}
atomRenderingComponent={ContextAtom}
onChange={onChange}
initialDoc={initialDoc}
disabled={disabled}
className={className}
hideMenu={hideMenu}
onChange={props.onChange}
initialDoc={props.initialDoc}
disabled={props.disabled}
className={props.className}
hideMenu={props.hideMenu}
upload={signedUploadUrl}
getterRef={props.getterRef}
/>
);
}, [pubs, pubTypes, disabled]);
}, [props.pubs, props.pubTypes, props.disabled]);

return memoEditor;
};
49 changes: 44 additions & 5 deletions core/app/components/ContextEditor/ContextEditorContext.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"use client";

import type { PropsWithChildren } from "react";
import type { ContextEditorGetter } from "context-editor";
import type { PropsWithChildren, RefObject } from "react";

import { createContext, useContext, useState } from "react";
import { createContext, useCallback, useContext, useMemo, useState } from "react";

import type { ProcessedPub } from "contracts";
import type { PubsId, PubTypesId } from "db/public";
Expand All @@ -14,11 +15,28 @@ export type ContextEditorContext = {
pubTypes: GetPubTypesResult;
pubId?: PubsId;
pubTypeId?: PubTypesId;
/**
* Refs which are able to retrieve the current state of the context editor
* on demand, rather than having the form state manage the value (which is slower)
*/
contextEditorGetters: ContextEditorGetters;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good comments!

/**
* Register a new context editor getter, which is able to retrieve the current state of the context editor
* on demand, rather than having the form state manage the value (which is slower)
* @param key - The key to register the getter under
* @param ref - The ref to the context editor
*/
registerGetter: (key: string, ref: ContextEditorGetterRef) => void;
};

export type ContextEditorGetterRef = RefObject<ContextEditorGetter | null>;
export type ContextEditorGetters = Record<string, ContextEditorGetterRef>;

const ContextEditorContext = createContext<ContextEditorContext>({
pubs: [],
pubTypes: [],
contextEditorGetters: {},
registerGetter: () => {},
});

export type ContextEditorPub = ProcessedPub<{
Expand All @@ -31,12 +49,33 @@ type Props = PropsWithChildren<
}
>;

export const ContextEditorContextProvider = (props: Props) => {
const [cachedPubId] = useState(props.pubId);
export const ContextEditorContextProvider = (
props: Omit<Props, "contextEditorGetters" | "registerGetter">
) => {
const cachedPubId = useMemo(() => {
return props.pubId;
}, [props.pubId]);

const [contextEditorGetters, setContextEditorGetters] = useState<
Record<string, ContextEditorGetterRef>
>({});

const registerGetter = useCallback((key: string, ref: ContextEditorGetterRef) => {
setContextEditorGetters((prev) => ({ ...prev, [key]: ref }));
}, []);

const { children, pubId, pubs, ...value } = props;

return (
<ContextEditorContext.Provider value={{ ...value, pubs, pubId: cachedPubId }}>
<ContextEditorContext.Provider
value={{
...value,
pubs,
pubId: cachedPubId,
contextEditorGetters,
registerGetter,
}}
>
{children}
</ContextEditorContext.Provider>
);
Expand Down
Loading
Loading