Completed Demo

main
jaxoncreed 2 years ago
parent fd38eae41a
commit 039ab8b0e9
  1. 5
      packages/demo-react/src/App.tsx
  2. 4
      packages/demo-react/src/Header.tsx
  3. 5
      packages/demo-react/src/Layout.tsx
  4. 28
      packages/demo-react/src/MainContainerProvider.tsx
  5. 2
      packages/demo-react/src/dashboard/Dashboard.tsx
  6. 6
      packages/solid-react/src/BrowserSolidLdoProvider.tsx
  7. 36
      packages/solid-react/src/useResource.ts
  8. 7
      packages/solid-react/src/util/createWrapperProxy.ts
  9. 1
      packages/solid/src/SolidLdoDataset.ts
  10. 1
      packages/solid/src/resource/Resource.ts

@ -2,14 +2,11 @@ import type { FunctionComponent } from "react";
import React from "react"; import React from "react";
import { Layout } from "./Layout"; import { Layout } from "./Layout";
import { BrowserSolidLdoProvider } from "@ldo/solid-react"; import { BrowserSolidLdoProvider } from "@ldo/solid-react";
import { MainContainerProvider } from "./MainContainerProvider";
const ProfileApp: FunctionComponent = () => { const ProfileApp: FunctionComponent = () => {
return ( return (
<BrowserSolidLdoProvider> <BrowserSolidLdoProvider>
<MainContainerProvider> <Layout />
<Layout />
</MainContainerProvider>
</BrowserSolidLdoProvider> </BrowserSolidLdoProvider>
); );
}; };

@ -28,8 +28,8 @@ export const Header: FunctionComponent = () => {
const { login, signUp, session } = useSolidAuth(); const { login, signUp, session } = useSolidAuth();
return ( return (
<header style={{ display: "flex" }}> <header style={{ display: "flex" }}>
{session.webId ? ( {session.isLoggedIn ? (
<LoggedInHeader webId={session.webId} /> <LoggedInHeader webId={session.webId!} />
) : ( ) : (
<> <>
<input <input

@ -5,6 +5,7 @@ import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { Dashboard } from "./dashboard/Dashboard"; import { Dashboard } from "./dashboard/Dashboard";
import { MediaPage } from "./media/MediaPage"; import { MediaPage } from "./media/MediaPage";
import { Header } from "./Header"; import { Header } from "./Header";
import { MainContainerProvider } from "./MainContainerProvider";
const router = createBrowserRouter([ const router = createBrowserRouter([
{ {
@ -26,7 +27,9 @@ export const Layout: FunctionComponent = () => {
<div> <div>
<Header /> <Header />
<hr /> <hr />
{session.isLoggedIn ? <RouterProvider router={router} /> : undefined} <MainContainerProvider>
{session.isLoggedIn ? <RouterProvider router={router} /> : undefined}
</MainContainerProvider>
</div> </div>
); );
}; };

@ -1,11 +1,23 @@
import React, { useState, useEffect, createContext } from "react"; import React, { useState, useEffect, createContext } from "react";
import type { FunctionComponent, PropsWithChildren } from "react"; import type { FunctionComponent, PropsWithChildren } from "react";
import type { Container, LeafUri } from "@ldo/solid"; import type { Container, LeafUri } from "@ldo/solid";
import { useSolidAuth, useLdo } from "@ldo/solid-react"; import { useSolidAuth, useLdo, useResource } from "@ldo/solid-react";
export const MainContainerContext = createContext<Container | undefined>( // Context will be set before any of it's children are rendered.
undefined, // eslint-disable-next-line @typescript-eslint/ban-ts-comment
); // @ts-ignore
export const MainContainerContext = createContext<Container>(undefined);
const MainContainerSubProvider: FunctionComponent<
PropsWithChildren<{ uri: string }>
> = ({ uri, children }) => {
const mainContainer = useResource(uri);
return (
<MainContainerContext.Provider value={mainContainer as Container}>
{children}
</MainContainerContext.Provider>
);
};
export const MainContainerProvider: FunctionComponent<PropsWithChildren> = ({ export const MainContainerProvider: FunctionComponent<PropsWithChildren> = ({
children, children,
@ -48,9 +60,13 @@ export const MainContainerProvider: FunctionComponent<PropsWithChildren> = ({
} }
}, [session.webId]); }, [session.webId]);
if (!mainContainer) {
return null;
}
return ( return (
<MainContainerContext.Provider value={mainContainer}> <MainContainerSubProvider uri={mainContainer.uri}>
{children} {children}
</MainContainerContext.Provider> </MainContainerSubProvider>
); );
}; };

@ -13,8 +13,6 @@ export const Dashboard: FunctionComponent = () => {
return <p>Loading Main Container</p>; return <p>Loading Main Container</p>;
} }
console.log(mainContainer.children());
return ( return (
<div> <div>
<div> <div>

@ -28,7 +28,6 @@ export const BrowserSolidLdoProvider: FunctionComponent<PropsWithChildren> = ({
restorePreviousSession: true, restorePreviousSession: true,
}); });
setSession({ ...getDefaultSession().info }); setSession({ ...getDefaultSession().info });
window.history.replaceState( window.history.replaceState(
{}, {},
"", "",
@ -40,19 +39,14 @@ export const BrowserSolidLdoProvider: FunctionComponent<PropsWithChildren> = ({
}, []); }, []);
const login = useCallback(async (issuer: string, options?: LoginOptions) => { const login = useCallback(async (issuer: string, options?: LoginOptions) => {
console.log("Before full options");
const fullOptions = { const fullOptions = {
redirectUrl: window.location.href, redirectUrl: window.location.href,
clientName: "Solid App", clientName: "Solid App",
oidcIssuer: issuer, oidcIssuer: issuer,
...options, ...options,
}; };
console.log("After full options");
window.localStorage.setItem(PRE_REDIRECT_URI, fullOptions.redirectUrl); window.localStorage.setItem(PRE_REDIRECT_URI, fullOptions.redirectUrl);
console.log("Set Item");
console.log(fullOptions);
await libraryLogin(fullOptions); await libraryLogin(fullOptions);
console.log("After login");
setSession({ ...getDefaultSession().info }); setSession({ ...getDefaultSession().info });
}, []); }, []);

@ -1,4 +1,4 @@
import { useMemo, useEffect, useRef } from "react"; import { useMemo, useEffect, useRef, useState, useCallback } from "react";
import type { import type {
Container, Container,
ContainerUri, ContainerUri,
@ -7,7 +7,6 @@ import type {
Leaf, Leaf,
} from "@ldo/solid"; } from "@ldo/solid";
import { useLdo } from "./SolidLdoProvider"; import { useLdo } from "./SolidLdoProvider";
import { useForceReload } from "./util/useForceReload";
export interface UseResourceOptions { export interface UseResourceOptions {
suppressInitialRead?: boolean; suppressInitialRead?: boolean;
@ -28,9 +27,11 @@ export function useResource(
options?: UseResourceOptions, options?: UseResourceOptions,
): Leaf | Container { ): Leaf | Container {
const { getResource } = useLdo(); const { getResource } = useLdo();
// Get the resource
const resource = useMemo(() => { const resource = useMemo(() => {
console.log(uri);
const resource = getResource(uri); const resource = getResource(uri);
// Run read operations if necissary
if (!options?.suppressInitialRead) { if (!options?.suppressInitialRead) {
if (options?.reloadOnMount) { if (options?.reloadOnMount) {
resource.read(); resource.read();
@ -40,18 +41,37 @@ export function useResource(
} }
return resource; return resource;
}, [getResource, uri]); }, [getResource, uri]);
const pastResource = useRef<Resource | undefined>(); const [resourceRepresentation, setResourceRepresentation] =
const forceReload = useForceReload(); useState(resource);
const pastResource = useRef<
{ resource: Resource; callback: () => void } | undefined
>();
// Callback function to force the react dom to reload.
const forceReload = useCallback(
// Wrap the resource in a proxy so it's techically a different object
() => {
setResourceRepresentation(new Proxy(resource, {}));
},
[resource],
);
useEffect(() => { useEffect(() => {
// Remove listeners for the previous resource
if (pastResource.current) { if (pastResource.current) {
pastResource.current.off("update", forceReload); pastResource.current.resource.off(
"update",
pastResource.current.callback,
);
} }
pastResource.current = resource; // Set a new past resource to the current resource
pastResource.current = { resource, callback: forceReload };
// Add listener
resource.on("update", forceReload); resource.on("update", forceReload);
// Unsubscribe on unmount
return () => { return () => {
resource.off("update", forceReload); resource.off("update", forceReload);
}; };
}, [resource]); }, [resource]);
return resource; return resourceRepresentation;
} }

@ -0,0 +1,7 @@
import type { Resource } from "@ldo/solid";
export function createWrapperProxy<ResourceType extends Resource>(
target: ResourceType,
): ResourceType {
return new Proxy(target, {});
}

@ -44,7 +44,6 @@ export class SolidLdoDataset extends LdoDataset {
| AggregateError<UpdateResultError | InvalidUriError> | AggregateError<UpdateResultError | InvalidUriError>
> { > {
const changesByGraph = splitChangesByGraph(changes); const changesByGraph = splitChangesByGraph(changes);
console.log(changesByGraph);
const results: [ const results: [
GraphNode, GraphNode,
DatasetChanges<Quad>, DatasetChanges<Quad>,

@ -119,7 +119,6 @@ export abstract class Resource extends (EventEmitter as new () => TypedEmitter<{
async readIfUnfetched(): Promise< async readIfUnfetched(): Promise<
ResourceResult<ReadLeafResult | ReadContainerResult, Container | Leaf> ResourceResult<ReadLeafResult | ReadContainerResult, Container | Leaf>
> { > {
console.log("didInitialFetch", this.didInitialFetch);
if (this.didInitialFetch) { if (this.didInitialFetch) {
const readResult = this.toReadResult(); const readResult = this.toReadResult();
this.status = readResult; this.status = readResult;

Loading…
Cancel
Save