diff --git a/ng-sdk-js/example-webapp-react/src/.ldo/contact.context.ts b/ng-sdk-js/example-webapp-react/src/.ldo/contact.context.ts new file mode 100644 index 0000000..804c77b --- /dev/null +++ b/ng-sdk-js/example-webapp-react/src/.ldo/contact.context.ts @@ -0,0 +1,68 @@ +import { LdoJsonldContext } from "@ldo/ldo"; + +/** + * ============================================================================= + * contactContext: JSONLD Context for contact + * ============================================================================= + */ +export const contactContext: LdoJsonldContext = { + type: { + "@id": "@type", + }, + Individual: { + "@id": "http://www.w3.org/2006/vcard/ns#Individual", + "@context": { + type: { + "@id": "@type", + }, + fn: { + "@id": "http://www.w3.org/2006/vcard/ns#fn", + "@type": "http://www.w3.org/2001/XMLSchema#string", + }, + hasEmail: { + "@id": "http://www.w3.org/2006/vcard/ns#hasEmail", + "@type": "http://www.w3.org/2001/XMLSchema#string", + }, + }, + }, + Person: { + "@id": "http://schema.org/Person", + "@context": { + type: { + "@id": "@type", + }, + fn: { + "@id": "http://www.w3.org/2006/vcard/ns#fn", + "@type": "http://www.w3.org/2001/XMLSchema#string", + }, + hasEmail: { + "@id": "http://www.w3.org/2006/vcard/ns#hasEmail", + "@type": "http://www.w3.org/2001/XMLSchema#string", + }, + }, + }, + Person2: { + "@id": "http://xmlns.com/foaf/0.1/Person", + "@context": { + type: { + "@id": "@type", + }, + fn: { + "@id": "http://www.w3.org/2006/vcard/ns#fn", + "@type": "http://www.w3.org/2001/XMLSchema#string", + }, + hasEmail: { + "@id": "http://www.w3.org/2006/vcard/ns#hasEmail", + "@type": "http://www.w3.org/2001/XMLSchema#string", + }, + }, + }, + fn: { + "@id": "http://www.w3.org/2006/vcard/ns#fn", + "@type": "http://www.w3.org/2001/XMLSchema#string", + }, + hasEmail: { + "@id": "http://www.w3.org/2006/vcard/ns#hasEmail", + "@type": "http://www.w3.org/2001/XMLSchema#string", + }, +}; diff --git a/ng-sdk-js/example-webapp-react/src/.ldo/contact.schema.ts b/ng-sdk-js/example-webapp-react/src/.ldo/contact.schema.ts new file mode 100644 index 0000000..6fa9056 --- /dev/null +++ b/ng-sdk-js/example-webapp-react/src/.ldo/contact.schema.ts @@ -0,0 +1,115 @@ +import { Schema } from "shexj"; + +/** + * ============================================================================= + * contactSchema: ShexJ Schema for contact + * ============================================================================= + */ +export const contactSchema: Schema = { + type: "Schema", + shapes: [ + { + id: "did:ng:n:g:x:social:contact#NGSocialContact", + type: "ShapeDecl", + shapeExpr: { + type: "Shape", + expression: { + type: "EachOf", + expressions: [ + { + type: "TripleConstraint", + predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", + valueExpr: { + type: "NodeConstraint", + values: ["http://www.w3.org/2006/vcard/ns#Individual"], + }, + annotations: [ + { + type: "Annotation", + predicate: "http://www.w3.org/2000/01/rdf-schema#comment", + object: { + value: "Defines the node as an Individual (from vcard)", + }, + }, + ], + }, + { + type: "TripleConstraint", + predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", + valueExpr: { + type: "NodeConstraint", + values: ["http://schema.org/Person"], + }, + annotations: [ + { + type: "Annotation", + predicate: "http://www.w3.org/2000/01/rdf-schema#comment", + object: { + value: "Defines the node as a Person (from Schema.org)", + }, + }, + ], + }, + { + type: "TripleConstraint", + predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", + valueExpr: { + type: "NodeConstraint", + values: ["http://xmlns.com/foaf/0.1/Person"], + }, + annotations: [ + { + type: "Annotation", + predicate: "http://www.w3.org/2000/01/rdf-schema#comment", + object: { + value: "Defines the node as a Person (from foaf)", + }, + }, + ], + }, + { + type: "TripleConstraint", + predicate: "http://www.w3.org/2006/vcard/ns#fn", + valueExpr: { + type: "NodeConstraint", + datatype: "http://www.w3.org/2001/XMLSchema#string", + }, + min: 0, + max: 1, + annotations: [ + { + type: "Annotation", + predicate: "http://www.w3.org/2000/01/rdf-schema#comment", + object: { + value: + "The formatted name of a person. Example: John Smith", + }, + }, + ], + }, + { + type: "TripleConstraint", + predicate: "http://www.w3.org/2006/vcard/ns#hasEmail", + valueExpr: { + type: "NodeConstraint", + datatype: "http://www.w3.org/2001/XMLSchema#string", + }, + min: 0, + max: 1, + annotations: [ + { + type: "Annotation", + predicate: "http://www.w3.org/2000/01/rdf-schema#comment", + object: { + value: "The person's email.", + }, + }, + ], + }, + ], + }, + extra: ["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"], + }, + }, + ], +}; diff --git a/ng-sdk-js/example-webapp-react/src/.ldo/contact.shapeTypes.ts b/ng-sdk-js/example-webapp-react/src/.ldo/contact.shapeTypes.ts new file mode 100644 index 0000000..3af9d3b --- /dev/null +++ b/ng-sdk-js/example-webapp-react/src/.ldo/contact.shapeTypes.ts @@ -0,0 +1,19 @@ +import { ShapeType } from "@ldo/ldo"; +import { contactSchema } from "./contact.schema"; +import { contactContext } from "./contact.context"; +import { NGSocialContact } from "./contact.typings"; + +/** + * ============================================================================= + * LDO ShapeTypes contact + * ============================================================================= + */ + +/** + * NGSocialContact ShapeType + */ +export const NGSocialContactShapeType: ShapeType = { + schema: contactSchema, + shape: "did:ng:n:g:x:social:contact#NGSocialContact", + context: contactContext, +}; diff --git a/ng-sdk-js/example-webapp-react/src/.ldo/contact.typings.ts b/ng-sdk-js/example-webapp-react/src/.ldo/contact.typings.ts new file mode 100644 index 0000000..0899613 --- /dev/null +++ b/ng-sdk-js/example-webapp-react/src/.ldo/contact.typings.ts @@ -0,0 +1,37 @@ +import { LdoJsonldContext, LdSet } from "@ldo/ldo"; + +/** + * ============================================================================= + * Typescript Typings for contact + * ============================================================================= + */ + +/** + * NGSocialContact Type + */ +export interface NGSocialContact { + "@id"?: string; + "@context"?: LdoJsonldContext; + /** + * Defines the node as an Individual (from vcard) | Defines the node as a Person (from Schema.org) | Defines the node as a Person (from foaf) + */ + type: LdSet< + | { + "@id": "Individual"; + } + | { + "@id": "Person"; + } + | { + "@id": "Person2"; + } + >; + /** + * The formatted name of a person. Example: John Smith + */ + fn?: string; + /** + * The person's email. + */ + hasEmail?: string; +} diff --git a/ng-sdk-js/example-webapp-react/src/.shapes/contact.shex b/ng-sdk-js/example-webapp-react/src/.shapes/contact.shex new file mode 100644 index 0000000..717d068 --- /dev/null +++ b/ng-sdk-js/example-webapp-react/src/.shapes/contact.shex @@ -0,0 +1,26 @@ + +# Platform ontologies: +PREFIX rdf: +PREFIX rdfs: +PREFIX owl: +PREFIX xsd: +PREFIX dc: + +# Domain ontology for Contacts in vcard-like form +PREFIX vcard: +PREFIX schem: +PREFIX foaf: +PREFIX ngx: + +ngx:NGSocialContact EXTRA a { + a [vcard:Individual ] + // rdfs:comment "Defines the node as an Individual (from vcard)" ; + a [ schem:Person ] + // rdfs:comment "Defines the node as a Person (from Schema.org)" ; + a [ foaf:Person ] + // rdfs:comment "Defines the node as a Person (from foaf)" ; + vcard:fn xsd:string ? + // rdfs:comment "The formatted name of a person. Example: John Smith" ; + vcard:hasEmail xsd:string ? + // rdfs:comment "The person's email." ; +} \ No newline at end of file diff --git a/ng-sdk-js/example-webapp-react/src/App.css b/ng-sdk-js/example-webapp-react/src/App.css index 8b13789..d2cc91f 100644 --- a/ng-sdk-js/example-webapp-react/src/App.css +++ b/ng-sdk-js/example-webapp-react/src/App.css @@ -1 +1,56 @@ + +.centered { + /*max-width: 1280px;*/ + margin: 0 auto; + padding: 0rem; + text-align: center; + width: fit-content; +} + +.contact { + width: 300px; + height: 100px; + background-color: #f6f6f6; + position: relative; + overflow-wrap: anywhere; +} + +.name { + width: 300px; + position: absolute; + left: 0; + top: 0; + padding: 5px; + height: 35px; + overflow: hidden; + background-color: #e0e0e0d0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.email-logo { + position: absolute; + left: 5px; + top: 35px; +} + +.email { + width: 270px; + position: absolute; + left: 30px; + top: 30px; + padding: 5px; + overflow-wrap: anywhere; +} + +input { + margin: 5px; +} + +#save { + background-color:rgb(73, 114, 165); + color:white; + cursor:pointer; +} \ No newline at end of file diff --git a/ng-sdk-js/example-webapp-react/src/App.tsx b/ng-sdk-js/example-webapp-react/src/App.tsx index 2f96f08..ecb4a8b 100644 --- a/ng-sdk-js/example-webapp-react/src/App.tsx +++ b/ng-sdk-js/example-webapp-react/src/App.tsx @@ -1,34 +1,19 @@ -import { useState } from 'react' + import React, { FunctionComponent } from 'react'; import { Header } from './Header'; -import { Contact } from './Contact'; -import { BrowserNGLdoProvider, useNextGraphAuth } from './reactMethods'; +import { Contacts } from './Contacts'; +import { BrowserNGLdoProvider } from './reactMethods'; import './App.css' - import "../../../common/src/styles.css"; -// function App() { -// const [count, setCount] = useState(0) - -// return ( -//
-//

Hello, Tailwind!

-//

Tailwind CSS is working in Vite!

-//
-// ) -// } - const App: FunctionComponent = () => { - //const { session } = useNextGraphAuth(); return (
- - - +
); diff --git a/ng-sdk-js/example-webapp-react/src/Contact.tsx b/ng-sdk-js/example-webapp-react/src/Contact.tsx index a5e6dcf..ff4f107 100644 --- a/ng-sdk-js/example-webapp-react/src/Contact.tsx +++ b/ng-sdk-js/example-webapp-react/src/Contact.tsx @@ -1,22 +1,29 @@ import { FunctionComponent } from "react"; import { useNextGraphAuth } from "./reactMethods"; -import { ContainerShapeType } from "./.ldo/container.shapeTypes.ts"; +import { NGSocialContactShapeType } from "./.ldo/contact.shapeTypes.ts"; import { useSubscribeToResource, useResource, useSubject } from "./reactMethods.ts"; -export const Contact: FunctionComponent = () => { +export const Contact: FunctionComponent = ({nuri}) => { const { session } = useNextGraphAuth(); - - let container_overlay; - - useResource(session.sessionId ? "did:ng:"+session.privateStoreId : undefined); - let myContainer = useSubject(ContainerShapeType, session.sessionId ? "did:ng:"+(session.privateStoreId.substring(0,46)) : undefined); - if (session.sessionId) { - container_overlay = session.privateStoreId.substring(46); - console.log(container_overlay); - } - - if (!session.sessionId) return <>; + useResource(session.sessionId && nuri ? nuri : undefined, { subscribe: true }); + let contact = useSubject(NGSocialContactShapeType, session.sessionId && nuri ? nuri.substring(0,53) : undefined); + + if (!session.sessionId || !nuri) return <>; - return <>{myContainer.contains?.map((contained) =>

{contained["@id"]}

)}; + return <> + {contact.fn? ( +
+ {contact.fn} + + + email: {contact.hasEmail} + +
+ ) : <>} + ; }; \ No newline at end of file diff --git a/ng-sdk-js/example-webapp-react/src/Contacts.tsx b/ng-sdk-js/example-webapp-react/src/Contacts.tsx new file mode 100644 index 0000000..86dbfea --- /dev/null +++ b/ng-sdk-js/example-webapp-react/src/Contacts.tsx @@ -0,0 +1,40 @@ +import { FunctionComponent } from "react"; +import { useNextGraphAuth } from "./reactMethods"; +import { ContainerShapeType } from "./.ldo/container.shapeTypes.ts"; +import { useSubscribeToResource, useResource, useSubject } from "./reactMethods.ts"; +import { Contact } from "./Contact"; +import { MakeContact } from "./MakeContact"; + +export const Contacts: FunctionComponent = () => { + const { session } = useNextGraphAuth(); + + let container_overlay: string; + + useResource(session.sessionId ? "did:ng:"+session.privateStoreId : undefined, { subscribe: true }); + let myContainer = useSubject(ContainerShapeType, session.sessionId ? "did:ng:"+(session.privateStoreId.substring(0,46)) : undefined); + + if (session.sessionId) { + container_overlay = session.privateStoreId.substring(46) as string; + } + + if (!session.sessionId) return <>; + + return <> + +
+
+ +
+
+ + { + myContainer.contains?.map((contained) => + + + )} +
+
+ ; + +}; + diff --git a/ng-sdk-js/example-webapp-react/src/MakeContact.tsx b/ng-sdk-js/example-webapp-react/src/MakeContact.tsx index ccc6af8..a78438c 100644 --- a/ng-sdk-js/example-webapp-react/src/MakeContact.tsx +++ b/ng-sdk-js/example-webapp-react/src/MakeContact.tsx @@ -1,13 +1,39 @@ import { FormEvent, FunctionComponent, useCallback, useState } from "react"; +import { BrowserNGLdoProvider, useLdo, dataset } from './reactMethods'; +import { NGSocialContactShapeType } from "./.ldo/contact.shapeTypes.ts"; +import { LdSet } from "@ldo/ldo"; -export const MakePost: FunctionComponent = () => { +export const MakeContact: FunctionComponent = () => { const [name, setName] = useState(""); const [email, setEmail] = useState(""); + const { createData, commitData } = useLdo(); + const onSubmit = useCallback( async (e: FormEvent) => { e.preventDefault(); + if (name.trim().length > 2 && email.trim().length > 6 && email.indexOf("@") >= 0) { + + const resource = await dataset.createResource("nextgraph"); + if (!resource.isError) { + console.log("Created resource:", resource.uri); + + const contact = createData( + NGSocialContactShapeType, + resource.uri.substring(0,53), + resource + ); + + contact.type = { "@id": "Individual" }; + contact.fn = name.trim(); + contact.hasEmail = email.trim(); + const result = await commitData(contact); + if (result.isError) { + console.error(result.message); + } + } + } }, [name, email] ); @@ -26,7 +52,7 @@ export const MakePost: FunctionComponent = () => { value={email} onChange={(e) => setEmail(e.target.value)} /> - + ); }; \ No newline at end of file