Completed general infrastructure

main
Ailin Luca 2 years ago
parent 1ce4e46d50
commit 93514fd11a
  1. 9
      packages/demo-react/src/dashboard/Dashboard.tsx
  2. 13
      packages/demo-react/src/dashboard/UploadButton.tsx
  3. 6
      packages/demo-react/src/index.tsx
  4. 14
      packages/demo-react/src/media/MediaPage.tsx
  5. 37
      packages/demo-react/src/media/MediaPost.tsx
  6. 16
      packages/demo-react/src/media/PostedBy.tsx
  7. 1
      packages/solid-react/src/useResource.ts
  8. 21
      packages/solid-react/src/util/TrackingProxyContext.ts
  9. 9
      packages/solid/src/resource/Container.ts
  10. 4
      packages/solid/src/resource/Resource.ts

@ -1,4 +1,4 @@
import React from "react";
import React, { Fragment } from "react";
import type { FunctionComponent } from "react";
import type { BuildMainContainerChildProps } from "./BuildMainContainer";
import { useResource } from "@ldo/solid-react";
@ -9,7 +9,7 @@ export const Dashboard: FunctionComponent<BuildMainContainerChildProps> = ({
mainContainerUri,
}) => {
const mainContainer = useResource(mainContainerUri);
if (mainContainer.isLoading()) {
if (mainContainer.isDoingInitialFetch()) {
return <p>Loading Main Container</p>;
}
@ -20,7 +20,10 @@ export const Dashboard: FunctionComponent<BuildMainContainerChildProps> = ({
</div>
<hr />
{mainContainer.children().map((child) => (
<MediaPost key={child.uri} uri={child.uri} />
<Fragment key={child.uri}>
<MediaPost uri={child.uri} />
<hr />
</Fragment>
))}
</div>
);

@ -4,7 +4,6 @@ import type { Container, Leaf, LeafUri } from "@ldo/solid";
import { v4 } from "uuid";
import { useLdo, useSolidAuth } from "@ldo/solid-react";
import { PostShShapeType } from "../.ldo/post.shapeTypes";
import { transactionChanges } from "@ldo/ldo";
export const UploadButton: FunctionComponent<{ mainContainer: Container }> = ({
mainContainer,
@ -51,12 +50,6 @@ export const UploadButton: FunctionComponent<{ mainContainer: Container }> = ({
indexResource.uri,
indexResource,
);
console.log("Created Data");
const changes = transactionChanges(post);
console.log("added");
console.log(changes.added?.toString());
console.log("removed");
console.log(changes.removed?.toString());
post.articleBody = message;
if (uploadedImage) {
post.image = { "@id": uploadedImage.uri };
@ -64,12 +57,6 @@ export const UploadButton: FunctionComponent<{ mainContainer: Container }> = ({
if (session.webId) {
post.publisher = { "@id": session.webId };
}
console.log("Created Data 2");
const changes2 = transactionChanges(post);
console.log("added");
console.log(changes2.added?.toString());
console.log("removed");
console.log(changes2.removed?.toString());
post.type = { "@id": "SocialMediaPosting" };
post.uploadDate = new Date().toISOString();
const result = await commitData(post);

@ -5,8 +5,4 @@ import App from "./App";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement,
);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>,
);
root.render(<App />);

@ -1,12 +1,16 @@
import React from "react";
import type { FunctionComponent } from "react";
import { useParams } from "react-router-dom";
import { useNavigate, useParams } from "react-router-dom";
import { MediaPost } from "./MediaPost";
export const MediaPage: FunctionComponent = () => {
const navigate = useNavigate();
const { uri } = useParams();
if (!uri) {
return <p>No URI present</p>;
}
return <MediaPost uri={uri} />;
return (
<div>
<button onClick={() => navigate("/")}>Back to Feed</button>
{uri ? <MediaPost uri={uri} /> : <p>No URI Present</p>}
</div>
);
};

@ -1,11 +1,42 @@
import React from "react";
import React, { useCallback } from "react";
import type { FunctionComponent } from "react";
import { useLdo, useResource, useSubject } from "@ldo/solid-react";
import { PostShShapeType } from "../.ldo/post.shapeTypes";
import { useNavigate } from "react-router-dom";
import { PostedBy } from "./PostedBy";
export const MediaPost: FunctionComponent<{ uri: string }> = ({ uri }) => {
const navigate = useNavigate();
const mediaResource = useResource(`${uri}index.ttl`);
const post = useSubject(PostShShapeType, mediaResource.uri);
const { getResource } = useLdo();
const deletePost = useCallback(async () => {
const postContainer = getResource(uri);
const result = await postContainer.delete();
if (result.isError) {
alert(result.message);
}
}, [uri]);
if (mediaResource.isReading()) {
return <p>Loading Post...</p>;
} else if (mediaResource.status.isError) {
return <p>Error: {mediaResource.status.message}</p>;
} else if (mediaResource.isAbsent()) {
return <p>Post does not exist.</p>;
}
return (
<div>
<p>Media: {uri}</p>
<hr />
{post.publisher?.["@id"] && <PostedBy webId={post.publisher["@id"]} />}
<div
onClick={() => navigate(`/media/${encodeURIComponent(uri)}`)}
style={{ cursor: "pointer" }}
>
{post.articleBody && <p>{post.articleBody}</p>}
{post.image && <img src={post.image["@id"]} style={{ height: 300 }} />}
</div>
<button onClick={deletePost}>Delete Post</button>
</div>
);
};

@ -0,0 +1,16 @@
import type { FunctionComponent } from "react";
import React from "react";
import { useResource, useSubject } from "@ldo/solid-react";
import { SolidProfileShapeShapeType } from "../.ldo/solidProfile.shapeTypes";
export const PostedBy: FunctionComponent<{ webId: string }> = ({ webId }) => {
const webIdResource = useResource(webId);
const profile = useSubject(SolidProfileShapeShapeType, webId);
if (webIdResource.isReading()) {
return <p>Loading Profile...</p>;
} else if (webIdResource.status.isError) {
return <p>Error: {webIdResource.status.message}</p>;
}
return <p>Posted By: {profile.fn}</p>;
};

@ -29,6 +29,7 @@ export function useResource(
): Leaf | Container {
const { getResource } = useLdo();
const resource = useMemo(() => {
console.log(uri);
const resource = getResource(uri);
if (!options?.suppressInitialRead) {
if (options?.reloadOnMount) {

@ -4,6 +4,7 @@ import type {
ProxyContextOptions,
} from "@ldo/jsonld-dataset-proxy";
import { ProxyContext } from "@ldo/jsonld-dataset-proxy";
import type { QuadMatch } from "@ldo/rdf-utils";
import type { SubscribableDataset } from "@ldo/subscribable-dataset";
import { namedNode } from "@rdfjs/data-model";
import type { Quad } from "@rdfjs/types";
@ -22,6 +23,14 @@ export class TrackingProxyContext extends ProxyContext {
this.listener = listener;
}
// Adds the listener to the subscribable dataset while ensuring deduping of the listener
private addListener(eventName: QuadMatch) {
const listeners = this.subscribableDataset.listeners(eventName);
if (!listeners.includes(this.listener)) {
this.subscribableDataset.on(eventName, this.listener);
}
}
protected createSubjectHandler(): ProxyHandler<SubjectProxyTarget> {
const baseHandler = super.createSubjectHandler();
const oldGetFunction = baseHandler.get;
@ -34,13 +43,10 @@ export class TrackingProxyContext extends ProxyContext {
if (typeof key === "symbol") {
// Do Nothing
} else if (key === "@id") {
this.subscribableDataset.on([subject, null, null, null], this.listener);
this.addListener([subject, null, null, null]);
} else if (!this.contextUtil.isArray(key)) {
const predicate = namedNode(this.contextUtil.keyToIri(key));
this.subscribableDataset.on(
[subject, predicate, null, null],
this.listener,
);
this.addListener([subject, predicate, null, null]);
}
return oldGetFunction && oldGetFunction(target, key, receiver);
};
@ -63,10 +69,7 @@ export class TrackingProxyContext extends ProxyContext {
receiver,
) => {
if (qualifiedArrayMethods.has(key)) {
this.subscribableDataset.on(
[target[0][0], target[0][1], target[0][2], null],
this.listener,
);
this.addListener([target[0][0], target[0][1], target[0][2], null]);
}
return oldGetFunction && oldGetFunction(target, key, receiver);
};

@ -60,6 +60,7 @@ export class Container extends Resource {
protected updateWithReadSuccess(
result: ContainerReadSuccess | AbsentReadSuccess,
): void {
super.updateWithReadSuccess(result);
if (result.type === "containerReadSuccess") {
this.rootContainer = result.isRootContainer;
}
@ -113,9 +114,11 @@ export class Container extends Resource {
}
async getRootContainer(): Promise<Container | CheckRootResultError> {
const checkResult = await this.checkIfIsRootContainer();
if (checkResult.isError) return checkResult;
if (this.rootContainer) {
if (this.rootContainer === undefined) {
const checkResult = await this.checkIfIsRootContainer();
if (checkResult.isError) return checkResult;
}
if (this.rootContainer === true) {
return this;
}
const parentUri = getParentUri(this.uri);

@ -64,6 +64,9 @@ export abstract class Resource extends (EventEmitter as new () => TypedEmitter<{
isDoingInitialFetch(): boolean {
return this.isReading() && !this.isFetched();
}
isReloading(): boolean {
return this.isReading() && this.isFetched();
}
// Checkers
isFetched(): boolean {
@ -116,6 +119,7 @@ export abstract class Resource extends (EventEmitter as new () => TypedEmitter<{
async readIfUnfetched(): Promise<
ResourceResult<ReadLeafResult | ReadContainerResult, Container | Leaf>
> {
console.log("didInitialFetch", this.didInitialFetch);
if (this.didInitialFetch) {
const readResult = this.toReadResult();
this.status = readResult;

Loading…
Cancel
Save