useResource works

main
Ailin Luca 2 years ago
parent 6d8ff2515f
commit 3791babfa2
  1. 2
      package-lock.json
  2. 4
      packages/demo-react/src/Layout.tsx
  3. 45
      packages/demo-react/src/dashboard/BuildMainContainer.tsx
  4. 31
      packages/demo-react/src/dashboard/Dashboard.tsx
  5. 12
      packages/demo-react/src/media/MediaPage.tsx
  6. 5
      packages/demo-react/src/media/MediaPost.tsx
  7. 22
      packages/solid-react/src/useResource.ts
  8. 6
      packages/solid-react/src/util/useForceReload.ts
  9. 4
      packages/solid/src/SolidLdoDataset.ts
  10. 4
      packages/solid/src/resource/Container.ts
  11. 4
      packages/solid/src/resource/Leaf.ts
  12. 26
      packages/solid/src/resource/Resource.ts
  13. 1
      packages/solid/src/util/RequestBatcher.ts

2
package-lock.json generated

@ -46961,7 +46961,7 @@
"@ldo/solid": { "@ldo/solid": {
"version": "file:packages/solid", "version": "file:packages/solid",
"requires": { "requires": {
"@inrupt/solid-client": "*", "@inrupt/solid-client": "^1.30.0",
"@inrupt/solid-client-authn-core": "^1.17.1", "@inrupt/solid-client-authn-core": "^1.17.1",
"@ldo/cli": "^0.0.0", "@ldo/cli": "^0.0.0",
"@ldo/dataset": "^0.0.0", "@ldo/dataset": "^0.0.0",

@ -3,8 +3,8 @@ import React, { useState } from "react";
import type { FunctionComponent } from "react"; import type { FunctionComponent } from "react";
import { createBrowserRouter, RouterProvider } from "react-router-dom"; import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { Dashboard } from "./dashboard/Dashboard"; import { Dashboard } from "./dashboard/Dashboard";
import { Media } from "./media/Media";
import { BuildMainContainer } from "./dashboard/BuildMainContainer"; import { BuildMainContainer } from "./dashboard/BuildMainContainer";
import { MediaPage } from "./media/MediaPage";
const router = createBrowserRouter([ const router = createBrowserRouter([
{ {
@ -13,7 +13,7 @@ const router = createBrowserRouter([
}, },
{ {
path: "/media/:uri", path: "/media/:uri",
element: <Media />, element: <MediaPage />,
}, },
]); ]);

@ -1,10 +1,10 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import type { FunctionComponent } from "react"; import type { FunctionComponent } from "react";
import type { Container, LeafUri } from "@ldo/solid"; import type { Container, ContainerUri, LeafUri } from "@ldo/solid";
import { useSolidAuth, useLdo } from "@ldo/solid-react"; import { useSolidAuth, useLdo } from "@ldo/solid-react";
export interface BuildMainContainerChildProps { export interface BuildMainContainerChildProps {
mainContainer: Container; mainContainerUri: ContainerUri;
} }
export const BuildMainContainer: FunctionComponent<{ export const BuildMainContainer: FunctionComponent<{
@ -23,29 +23,28 @@ export const BuildMainContainer: FunctionComponent<{
alert(rootContainer.message); alert(rootContainer.message);
return; return;
} }
const mainContainer = const mainContainer = getResource(`${rootContainer.uri}demo-react/`);
await rootContainer.createChildIfAbsent("demo-react/");
if (mainContainer.type === "error") {
alert(mainContainer.message);
return;
}
setMainContainer(mainContainer); setMainContainer(mainContainer);
mainContainer.setAccessRules({ await mainContainer.read();
public: { if (mainContainer.isAbsent()) {
read: true, await mainContainer.createIfAbsent();
write: false, await mainContainer.setAccessRules({
append: false, public: {
control: false,
},
agent: {
[session.webId!]: {
read: true, read: true,
write: true, write: false,
append: true, append: false,
control: true, control: false,
}, },
}, agent: {
}); [session.webId!]: {
read: true,
write: true,
append: true,
control: true,
},
},
});
}
}); });
} }
}, [session.webId]); }, [session.webId]);
@ -55,5 +54,5 @@ export const BuildMainContainer: FunctionComponent<{
return <p>Loading</p>; return <p>Loading</p>;
} }
return <Child mainContainer={mainContainer} />; return <Child mainContainerUri={mainContainer.uri} />;
}; };

@ -1,18 +1,27 @@
import React from "react"; import React from "react";
import type { FunctionComponent } from "react"; import type { FunctionComponent } from "react";
import type { BuildMainContainerChildProps } from "./BuildMainContainer"; import type { BuildMainContainerChildProps } from "./BuildMainContainer";
import { useResource } from "@ldo/solid-react";
import { MediaPost } from "../media/MediaPost";
import { UploadButton } from "./UploadButton";
export const Dashboard: FunctionComponent<BuildMainContainerChildProps> = ({ export const Dashboard: FunctionComponent<BuildMainContainerChildProps> = ({
mainContainer, mainContainerUri,
}) => { }) => {
return <p>{mainContainer.uri}</p>; const mainContainer = useResource(mainContainerUri);
// return ( if (mainContainer.isLoading()) {
// <div> return <p>Loading Main Container</p>;
// <div> }
// <UploadButton />
// </div> return (
// <hr /> <div>
// <div>{mainContainer.isLoading ? "Loading" : "Not Loading"}</div> <div>
// </div> <UploadButton />
// ); </div>
<hr />
{mainContainer.children().map((child) => (
<MediaPost key={child.uri} uri={child.uri} />
))}
</div>
);
}; };

@ -0,0 +1,12 @@
import React from "react";
import type { FunctionComponent } from "react";
import { useParams } from "react-router-dom";
import { MediaPost } from "./MediaPost";
export const MediaPage: FunctionComponent = () => {
const { uri } = useParams();
if (!uri) {
return <p>No URI present</p>;
}
return <MediaPost uri={uri} />;
};

@ -1,12 +1,11 @@
import React from "react"; import React from "react";
import type { FunctionComponent } from "react"; import type { FunctionComponent } from "react";
import { useParams } from "react-router-dom";
export const Media: FunctionComponent = () => { export const MediaPost: FunctionComponent<{ uri: string }> = ({ uri }) => {
const { uri } = useParams();
return ( return (
<div> <div>
<p>Media: {uri}</p> <p>Media: {uri}</p>
<hr />
</div> </div>
); );
}; };

@ -1,4 +1,4 @@
import { useMemo } from "react"; import { useMemo, useEffect, useRef } from "react";
import type { import type {
Container, Container,
ContainerUri, ContainerUri,
@ -7,11 +7,25 @@ import type {
Leaf, Leaf,
} from "@ldo/solid"; } from "@ldo/solid";
import { useLdo } from "./SolidLdoProvider"; import { useLdo } from "./SolidLdoProvider";
import { useForceReload } from "./util/useForceReload";
export function useResource(uri: ContainerUri): Container; export function useResource(uri: ContainerUri): Container;
export function useResource(uri: LeafUri): Leaf; export function useResource(uri: LeafUri): Leaf;
export function useResource(uri: string): Resource; export function useResource(uri: string): Leaf | Container;
export function useResource(uri: string): Resource { export function useResource(uri: string): Leaf | Container {
const { getResource } = useLdo(); const { getResource } = useLdo();
return useMemo(() => getResource(uri), [getResource, uri]); const resource = useMemo(() => getResource(uri), [getResource, uri]);
const pastResource = useRef<Resource | undefined>();
const forceReload = useForceReload();
useEffect(() => {
if (pastResource.current) {
pastResource.current.off("update", forceReload);
}
pastResource.current = resource;
resource.on("update", forceReload);
return () => {
resource.off("update", forceReload);
};
}, [resource]);
return resource;
} }

@ -1,6 +1,6 @@
import { useState } from "react"; import { useState, useCallback } from "react";
export function useForceUpdate() { export function useForceReload() {
const [, setValue] = useState(0); const [, setValue] = useState(0);
return () => setValue((value) => value + 1); return useCallback(() => setValue((value) => value + 1), []);
} }

@ -21,8 +21,8 @@ export class SolidLdoDataset extends LdoDataset {
getResource(uri: ContainerUri, options?: ResourceGetterOptions): Container; getResource(uri: ContainerUri, options?: ResourceGetterOptions): Container;
getResource(uri: LeafUri, options?: ResourceGetterOptions): Leaf; getResource(uri: LeafUri, options?: ResourceGetterOptions): Leaf;
getResource(uri: string, options?: ResourceGetterOptions): Resource; getResource(uri: string, options?: ResourceGetterOptions): Leaf | Container;
getResource(uri: string, options?: ResourceGetterOptions): Resource { getResource(uri: string, options?: ResourceGetterOptions): Leaf | Container {
return this.context.resourceStore.get(uri, options); return this.context.resourceStore.get(uri, options);
} }
} }

@ -18,12 +18,14 @@ import type { Leaf } from "./Leaf";
import { Resource } from "./Resource"; import { Resource } from "./Resource";
export class Container extends Resource { export class Container extends Resource {
readonly uri: ContainerUri;
protected requester: ContainerRequester; protected requester: ContainerRequester;
protected rootContainer: boolean | undefined; protected rootContainer: boolean | undefined;
readonly type = "container" as const; readonly type = "container" as const;
constructor(uri: ContainerUri, context: SolidLdoDatasetContext) { constructor(uri: ContainerUri, context: SolidLdoDatasetContext) {
super(uri, context); super(context);
this.uri = uri;
this.requester = new ContainerRequester(uri, context); this.requester = new ContainerRequester(uri, context);
} }

@ -19,13 +19,15 @@ import type { Container } from "./Container";
import { Resource } from "./Resource"; import { Resource } from "./Resource";
export class Leaf extends Resource { export class Leaf extends Resource {
readonly uri: LeafUri;
protected requester: Requester; protected requester: Requester;
readonly type = "leaf" as const; readonly type = "leaf" as const;
protected binaryData: { data: Blob; mimeType: string } | undefined; protected binaryData: { data: Blob; mimeType: string } | undefined;
constructor(uri: LeafUri, context: SolidLdoDatasetContext) { constructor(uri: LeafUri, context: SolidLdoDatasetContext) {
super(uri, context); super(context);
this.uri = uri;
this.requester = new LeafRequester(uri, context); this.requester = new LeafRequester(uri, context);
} }

@ -19,18 +19,22 @@ import type {
} from "../requester/requestResults/AccessRule"; } from "../requester/requestResults/AccessRule";
import { getAccessRules } from "../requester/requests/getAccessRules"; import { getAccessRules } from "../requester/requests/getAccessRules";
import { setAccessRules } from "../requester/requests/setAccessRules"; import { setAccessRules } from "../requester/requests/setAccessRules";
import type TypedEmitter from "typed-emitter";
import EventEmitter from "events";
export abstract class Resource { export abstract class Resource extends (EventEmitter as new () => TypedEmitter<{
update: () => void;
}>) {
// All intance variables // All intance variables
protected readonly context: SolidLdoDatasetContext; protected readonly context: SolidLdoDatasetContext;
readonly uri: string; abstract readonly uri: string;
abstract readonly type: string; abstract readonly type: string;
protected abstract readonly requester: Requester; protected abstract readonly requester: Requester;
protected didInitialFetch: boolean = false; protected didInitialFetch: boolean = false;
protected absent: boolean | undefined; protected absent: boolean | undefined;
constructor(uri: string, context: SolidLdoDatasetContext) { constructor(context: SolidLdoDatasetContext) {
this.uri = uri; super();
this.context = context; this.context = context;
} }
@ -74,18 +78,26 @@ export abstract class Resource {
protected parseResult<PossibleErrors extends ErrorResult>( protected parseResult<PossibleErrors extends ErrorResult>(
result: AbsentResult | BinaryResult | DataResult | PossibleErrors, result: AbsentResult | BinaryResult | DataResult | PossibleErrors,
): this | PossibleErrors { ): this | PossibleErrors {
let toReturn: this | PossibleErrors;
switch (result.type) { switch (result.type) {
case "error": case "error":
return result; toReturn = result;
break;
case "absent": case "absent":
this.didInitialFetch = true; this.didInitialFetch = true;
this.absent = true; this.absent = true;
return this; // eslint-disable-next-line @typescript-eslint/no-this-alias
toReturn = this;
break;
default: default:
this.didInitialFetch = true; this.didInitialFetch = true;
this.absent = false; this.absent = false;
return this; // eslint-disable-next-line @typescript-eslint/no-this-alias
toReturn = this;
break;
} }
this.emit("update");
return toReturn;
} }
// Read Methods // Read Methods

@ -141,6 +141,7 @@ export class RequestBatcher {
waitingProcess as unknown as WaitingProcess<any[], any>, waitingProcess as unknown as WaitingProcess<any[], any>,
); );
this.loadingMap[waitingProcess.name] = true; this.loadingMap[waitingProcess.name] = true;
this.loadingMap[ANY_KEY] = true;
this.triggerOrWaitProcess(); this.triggerOrWaitProcess();
}); });
} }

Loading…
Cancel
Save