diff --git a/apps/roam/src/components/settings/AdminPanel.tsx b/apps/roam/src/components/settings/AdminPanel.tsx index 85ba13269..4baac12b4 100644 --- a/apps/roam/src/components/settings/AdminPanel.tsx +++ b/apps/roam/src/components/settings/AdminPanel.tsx @@ -14,7 +14,6 @@ import { } from "@blueprintjs/core"; import Description from "roamjs-components/components/Description"; import { Select } from "@blueprintjs/select"; -import { getSetting, setSetting } from "~/utils/extensionSettings"; import { getSupabaseContext, getLoggedInClient, @@ -27,8 +26,6 @@ import { type NodeSignature, type PConceptFull, } from "@repo/database/lib/queries"; -import migrateRelations from "~/utils/migrateRelations"; -import { countReifiedRelations } from "~/utils/createReifiedBlock"; import type { DGSupabaseClient } from "@repo/database/lib/client"; import internalError from "~/utils/internalError"; import SuggestiveModeSettings from "./SuggestiveModeSettings"; @@ -36,8 +33,6 @@ import { getFormattedConfigTree } from "~/utils/discourseConfigRef"; import refreshConfigTree from "~/utils/refreshConfigTree"; import createBlock from "roamjs-components/writes/createBlock"; import deleteBlock from "roamjs-components/writes/deleteBlock"; -import { USE_REIFIED_RELATIONS } from "~/data/userSettings"; -import posthog from "posthog-js"; import { setFeatureFlag } from "~/components/settings/utils/accessors"; const NodeRow = ({ node }: { node: PConceptFull }) => { @@ -258,98 +253,7 @@ const NodeListTab = (): React.ReactElement => { ); }; -const MigrationTab = (): React.ReactElement => { - let initial = true; - const [useMigrationResults, setMigrationResults] = useState(""); - const [useOngoing, setOngoing] = useState(false); - const [useDryRun, setDryRun] = useState(false); - const enabled = getSetting(USE_REIFIED_RELATIONS, false); - const doMigrateRelations = async () => { - setOngoing(true); - try { - posthog.capture("Reified Relations: Migration Started", { - dryRun: useDryRun, - }); - const before = await countReifiedRelations(); - const numProcessed = await migrateRelations(useDryRun); - const after = await countReifiedRelations(); - if (after - before < numProcessed) - setMigrationResults( - `${after - before} new relations created out of ${numProcessed} distinct relations processed`, - ); - else setMigrationResults(`${numProcessed} new relations created`); - posthog.capture("Reified Relations: Migration Completed", { - dryRun: useDryRun, - processed: numProcessed, - before, - after, - created: after - before, - }); - } catch (e) { - console.error("Relation migration failed", e); - setMigrationResults( - `Migration failed: ${(e as Error).message ?? "see console for details"}`, - ); - posthog.capture("Reified Relations: Migration Failed", { - dryRun: useDryRun, - error: (e as Error).message ?? "unknown error", - }); - } finally { - setOngoing(false); - } - }; - useEffect(() => { - void (async () => { - if (initial) { - const numRelations = await countReifiedRelations(); - setMigrationResults( - numRelations > 0 - ? `${numRelations} already migrated` - : "No migrated relations", - ); - // eslint-disable-next-line react-hooks/exhaustive-deps - initial = false; - } - })(); - return () => { - initial; - }; - }, []); - - return ( - <> -

- - { - const target = e.target as HTMLInputElement; - setDryRun(target.checked); - }} - labelElement={<>Dry run} - /> -

- {useOngoing ? ( - - ) : ( -

{useMigrationResults}

- )} - - ); -}; - const FeatureFlagsTab = (): React.ReactElement => { - const [useReifiedRelations, setUseReifiedRelations] = useState( - getSetting(USE_REIFIED_RELATIONS, false), - ); const settings = useMemo(() => { refreshConfigTree(); return getFormattedConfigTree(); @@ -442,31 +346,6 @@ const FeatureFlagsTab = (): React.ReactElement => {

- { - const target = e.target as HTMLInputElement; - setUseReifiedRelations(target.checked); - void setSetting(USE_REIFIED_RELATIONS, target.checked).catch( - () => undefined, - ); - setFeatureFlag("Reified relation triples", target.checked); - posthog.capture("Reified Relations: Toggled", { - enabled: target.checked, - }); - }} - labelElement={ - <> - Reified relation triples - - - } - /> - + + + + + )} + + + { + setActiveRelationMigration(RelationMigrationDialog.none); + }} + > +
+

+ Deactivating the faster relations system will mean that any + relations created using it will no longer be accessible. The + discourse context overlay will still be usable with the previous + relations system. Any relations created with the faster system will + be accessible should you choose to reactivate. +

+
+ + +
+
+
+ { + setActiveRelationMigration(RelationMigrationDialog.none); + }} + > +
+ {isOngoing ? ( +

Migrating relations, please wait

+ ) : ( +
+

+ Activating the stored relations system will migrate all + previously created relations and newly created relations will + use the new system. You can deactivate this setting to revert to + the old system, and your newly created relations will not be + deleted; however, they will not be accessible until you + reactivate the stored relation system. +

+
+ + +
+
+ )} +
+
); }; diff --git a/apps/roam/src/components/settings/utils/zodSchema.example.ts b/apps/roam/src/components/settings/utils/zodSchema.example.ts index f413d26e2..e71c73ef4 100644 --- a/apps/roam/src/components/settings/utils/zodSchema.example.ts +++ b/apps/roam/src/components/settings/utils/zodSchema.example.ts @@ -89,13 +89,11 @@ const discourseNodeSettings: DiscourseNodeSettings = { const featureFlags: FeatureFlags = { "Enable left sidebar": true, "Suggestive mode enabled": true, - "Reified relation triples": false, }; const defaultFeatureFlags: FeatureFlags = { "Enable left sidebar": false, "Suggestive mode enabled": false, - "Reified relation triples": false, }; const exportSettings: ExportSettings = { @@ -373,6 +371,7 @@ const personalSettings: PersonalSettings = { "Streamline styling": true, "Auto canvas relations": true, "Disable product diagnostics": false, + "Reified relation triples": true, Query: { "Hide query metadata": true, "Default page size": 25, @@ -401,6 +400,7 @@ const defaultPersonalSettings: PersonalSettings = { "Streamline styling": false, "Auto canvas relations": false, "Disable product diagnostics": false, + "Reified relation triples": false, Query: { "Hide query metadata": false, "Default page size": 10, diff --git a/apps/roam/src/components/settings/utils/zodSchema.ts b/apps/roam/src/components/settings/utils/zodSchema.ts index 378020d42..60ec5f331 100644 --- a/apps/roam/src/components/settings/utils/zodSchema.ts +++ b/apps/roam/src/components/settings/utils/zodSchema.ts @@ -156,7 +156,6 @@ export const DiscourseRelationSchema = z.object({ export const FeatureFlagsSchema = z.object({ "Enable left sidebar": z.boolean().default(false), "Suggestive mode enabled": z.boolean().default(false), - "Reified relation triples": z.boolean().default(false), }); export const ExportSettingsSchema = z.object({ @@ -248,6 +247,7 @@ export const PersonalSettingsSchema = z.object({ .object({ modifiers: z.number(), key: z.string() }) .default({ modifiers: 0, key: "" }), "Discourse context overlay": z.boolean().default(false), + "Reified relation triples": z.boolean().default(false), "Suggestive mode overlay": z.boolean().default(false), "Overlay in canvas": z.boolean().default(false), "Text selection popup": z.boolean().default(true), diff --git a/apps/roam/src/utils/migrateRelations.ts b/apps/roam/src/utils/migrateRelations.ts index 41cba8014..3f4ecb027 100644 --- a/apps/roam/src/utils/migrateRelations.ts +++ b/apps/roam/src/utils/migrateRelations.ts @@ -4,6 +4,7 @@ import type { json } from "./getBlockProps"; import setBlockProps from "./setBlockProps"; import { getSetting, setSetting } from "./extensionSettings"; import { USE_REIFIED_RELATIONS } from "~/data/userSettings"; +import internalError from "./internalError"; import { createReifiedRelation, DISCOURSE_GRAPH_PROP_NAME, @@ -11,11 +12,9 @@ import { const MIGRATION_PROP_NAME = "relation-migration"; -const migrateRelations = async (dryRun = false): Promise => { - const authorized = getSetting(USE_REIFIED_RELATIONS, false); - if (!authorized) return 0; +const migrateRelations = async (): Promise => { let numProcessed = 0; - await setSetting(USE_REIFIED_RELATIONS, false); // so queries use patterns + let didError = false; // wait for the settings to propagate await new Promise((resolve) => setTimeout(resolve, 150)); try { @@ -25,49 +24,47 @@ const migrateRelations = async (dryRun = false): Promise => { const key = `${rel.source}:${rel.relUid}:${rel.target}`; if (processed.has(key)) continue; processed.add(key); - if (!dryRun) { - const uid = (await createReifiedRelation({ - sourceUid: rel.source, - destinationUid: rel.target, - relationBlockUid: rel.relUid, - }))!; - const sourceProps = getBlockProps(rel.source); - const dgDataOrig = sourceProps[DISCOURSE_GRAPH_PROP_NAME]; - const dgData: Record = - dgDataOrig !== null && - typeof dgDataOrig === "object" && - !Array.isArray(dgDataOrig) - ? dgDataOrig - : {}; - const migrationDataOrig = dgData[MIGRATION_PROP_NAME]; - let migrationData: Record = - migrationDataOrig !== null && - typeof migrationDataOrig === "object" && - !Array.isArray(migrationDataOrig) - ? migrationDataOrig - : {}; - if (migrationData[uid] !== undefined) { - console.debug(`reprocessed ${key}`); - } - // clean up old migration entries - migrationData = Object.fromEntries( - Object.entries(migrationData).filter( - ([uid]) => - window.roamAlphaAPI.q( - `[:find ?p :where [?p :block/uid "${uid}"]]`, - ).length > 0, - ), - ); - migrationData[uid] = new Date().valueOf(); - dgData[MIGRATION_PROP_NAME] = migrationData; - setBlockProps(rel.source, { [DISCOURSE_GRAPH_PROP_NAME]: dgData }); + const uid = (await createReifiedRelation({ + sourceUid: rel.source, + destinationUid: rel.target, + relationBlockUid: rel.relUid, + }))!; + const sourceProps = getBlockProps(rel.source); + const dgDataOrig = sourceProps[DISCOURSE_GRAPH_PROP_NAME]; + const dgData: Record = + dgDataOrig !== null && + typeof dgDataOrig === "object" && + !Array.isArray(dgDataOrig) + ? dgDataOrig + : {}; + const migrationDataOrig = dgData[MIGRATION_PROP_NAME]; + let migrationData: Record = + migrationDataOrig !== null && + typeof migrationDataOrig === "object" && + !Array.isArray(migrationDataOrig) + ? migrationDataOrig + : {}; + if (migrationData[uid] !== undefined) { + console.debug(`reprocessed ${key}`); } + // clean up old migration entries + migrationData = Object.fromEntries( + Object.entries(migrationData).filter( + ([uid]) => + window.roamAlphaAPI.q(`[:find ?p :where [?p :block/uid "${uid}"]]`) + .length > 0, + ), + ); + migrationData[uid] = new Date().valueOf(); + dgData[MIGRATION_PROP_NAME] = migrationData; + setBlockProps(rel.source, { [DISCOURSE_GRAPH_PROP_NAME]: dgData }); numProcessed++; } - } finally { - await setSetting(USE_REIFIED_RELATIONS, true); + } catch (error) { + internalError({ error }); + didError = true; } - return numProcessed; + return didError ? false : numProcessed; }; export default migrateRelations;