Skip to content

Commit

Permalink
Merge pull request #4 from solid/attribution-image
Browse files Browse the repository at this point in the history
Attribution image
  • Loading branch information
angelo-v authored Aug 23, 2020
2 parents c2f3a1e + ee36753 commit 0c171be
Show file tree
Hide file tree
Showing 18 changed files with 298 additions and 8 deletions.
10 changes: 10 additions & 0 deletions .molid/notes/by-as-actor$.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@prefix : <#> .
@prefix XML: <http://www.w3.org/2001/XMLSchema#> .
@prefix as: <https://www.w3.org/ns/activitystreams#> .
@prefix pro: </profile/actor#> .

:it
a as:Note ;
as:attributedTo pro:me ;
as:content "This is an ActivityStreams Note attributed to an Actor" ;
as:published "2020-08-23T14:26:44+0200"^^XML:dateTime .
10 changes: 10 additions & 0 deletions .molid/notes/by-foaf-person$.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@prefix : <#> .
@prefix XML: <http://www.w3.org/2001/XMLSchema#> .
@prefix as: <https://www.w3.org/ns/activitystreams#> .
@prefix pro: </profile/foaf#> .

:it
a as:Note ;
as:attributedTo pro:me ;
as:content "This is an ActivityStreams Note attributed to a FOAF Person" ;
as:published "2020-08-23T14:26:44+0200"^^XML:dateTime .
10 changes: 10 additions & 0 deletions .molid/notes/by-vcard-individual$.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@prefix : <#> .
@prefix XML: <http://www.w3.org/2001/XMLSchema#> .
@prefix as: <https://www.w3.org/ns/activitystreams#> .
@prefix pro: </profile/vcard#> .

:it
a as:Note ;
as:attributedTo pro:me ;
as:content "This is an ActivityStreams Note attributed to a vcard Individual" ;
as:published "2020-08-23T14:26:44+0200"^^XML:dateTime .
11 changes: 11 additions & 0 deletions .molid/profile/actor$.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@prefix : <#> .
@prefix as: <https://www.w3.org/ns/activitystreams#> .

:me
a as:Person ;
as:name "Activity Streams Actor" ;
as:image :image .

:image
a as:Image;
as:url <https://i.pravatar.cc/300> .
7 changes: 7 additions & 0 deletions .molid/profile/foaf$.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@prefix : <#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

:me
a foaf:Person ;
foaf:name "A. N. Other" ;
foaf:img <https://i.pravatar.cc/300> .
7 changes: 7 additions & 0 deletions .molid/profile/vcard$.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@prefix : <#> .
@prefix vcard: <http://www.w3.org/2006/vcard/ns#> .

:me
a vcard:Individual ;
vcard:fn "A. N. Other" ;
vcard:hasPhoto <https://i.pravatar.cc/300> .
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Start a webpack dev server:
npm start
```

Visit `http://localhost:8080/` to render the pane. Adjust ´const noteUri` in `./dev/index.ts` to show a
Visit `http://localhost:8080/` to render the pane. Adjust `const noteUri` in `./dev/index.ts` to show a
different resource.

### Build
Expand Down
5 changes: 3 additions & 2 deletions dev/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { sym } from "rdflib";
import { default as pane } from "../src";
import { context, fetcher } from "./context";

const noteUri =
"https://angelo.veltens.org/public/tweets/2020/01#1216690474544771072";
const noteUri = "http://localhost:3333/notes/by-as-actor#it";
//const noteUri = "http://localhost:3333/notes/by-foaf-person#it";
// const noteUri = "http://localhost:3333/notes/by-vcard-individual#it";

fetcher.load(noteUri).then(() => {
const app = pane.render(sym(noteUri), context);
Expand Down
14 changes: 13 additions & 1 deletion e2e-tests/note-fetching-attribution.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { fetcher, graph, parse, sym } from "rdflib";
import { default as pane } from "../src";
import { DataBrowserContext } from "pane-registry";

import { getByText, waitFor } from "@testing-library/react";
import { getByText, getByAltText, waitFor } from "@testing-library/react";
import { givenMolid } from "molid/lib/molid-jest";

describe("note with fetching attribution", () => {
Expand Down Expand Up @@ -49,6 +49,18 @@ describe("note with fetching attribution", () => {
{ container: html }
);
});

it("AND the person's picture is shown eventually", async () => {
await waitFor(
() => {
expect(getByAltText(html, "A. N. Other")).toHaveAttribute(
"src",
"https://i.pravatar.cc/300"
);
},
{ container: html }
);
});
});
});
});
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "activitystreams-pane",
"version": "0.4.1",
"version": "0.5.0",
"description": "",
"repository": {
"type": "git",
"url": "https://github.com/solid/activitystreams-pane.git"
},
"main": "lib/index.js",
"scripts": {
"start": "webpack-dev-server --config webpack.dev.config.js",
"start": "molid & webpack-dev-server --config webpack.dev.config.js",
"build": "tsc",
"test": "jest",
"lint": "eslint ./src",
Expand Down
1 change: 1 addition & 0 deletions src/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ReactElement } from "react";

export function createElement(jsx: ReactElement): HTMLElement {
const element = document.createElement("div");
element.style.padding = "1em";
render(jsx, element);
return element;
}
55 changes: 55 additions & 0 deletions src/note/AttributionTag.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import * as React from "react";
import { render, screen } from "@testing-library/react";
import { AttributionTag } from "./AttributionTag";

describe("AttributionTag", () => {
describe("attribution to person without image", () => {
beforeEach(() => {
render(
<AttributionTag
to={{
discriminator: "PersonAttribution",
webId: "https://pod.example/person#me",
name: "Jane Doe",
}}
/>
);
});

it("renders name", () => {
expect(screen.getByText("Jane Doe")).toBeInTheDocument();
});

it("links name to WebID", () => {
const name = screen.getByText("Jane Doe");
expect(name).toContainHTML(
'<a href="https://pod.example/person#me">Jane Doe</a>'
);
});

it("does not show an image", () => {
expect(screen.queryByAltText("Jane Doe")).not.toBeInTheDocument();
});
});

describe("attribution to person with image", () => {
beforeEach(() => {
render(
<AttributionTag
to={{
discriminator: "PersonAttribution",
webId: "https://pod.example/person#me",
name: "Jane Doe",
imageSrc: "https://pod.example/person.png",
}}
/>
);
});

it("does show an image", () => {
const element = screen.getByAltText("Jane Doe");
expect(element.tagName).toEqual("IMG");
expect(element).toHaveAttribute("src", "https://pod.example/person.png");
});
});
});
22 changes: 20 additions & 2 deletions src/note/AttributionTag.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import * as React from "react";
import { ReactElement } from "react";
import { Attribution, isLinkAttribution, isPersonAttribution } from "./types";
import {
Attribution,
isLinkAttribution,
isPersonAttribution,
PersonAttribution,
} from "./types";

interface Props {
to: Attribution;
Expand All @@ -10,8 +15,21 @@ export const AttributionTag = ({ to }: Props): ReactElement => {
if (isLinkAttribution(to)) {
return <a href={to.uri}>{to.uri}</a>;
} else if (isPersonAttribution(to)) {
return <a href={to.webId}>{to.name}</a>;
return <PersonAttributionTag {...to} />;
} else {
return null;
}
};

const PersonAttributionTag = ({
webId,
name,
imageSrc,
}: PersonAttribution): ReactElement => {
return (
<>
{imageSrc && <img height="47" width="47" alt={name} src={imageSrc} />}
<a href={webId}>{name}</a>
</>
);
};
8 changes: 8 additions & 0 deletions src/note/NoteCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const useStyles = createUseStyles({
padding: "1em",
boxShadow: "0 1px 5px rgba(0,0,0,0.2)",
transition: "all .25s ease-in-out",
maxWidth: 632,
},
content: {
fontSize: "larger",
Expand All @@ -25,6 +26,8 @@ const useStyles = createUseStyles({
color: "rgb(0, 0, 0, 60%)",
},
attribution: {
display: "flex",
alignItems: "center",
fontWeight: "bold",
"& a": {
color: "black",
Expand All @@ -33,6 +36,11 @@ const useStyles = createUseStyles({
"& a:hover": {
textDecoration: "underline",
},
"& img": {
marginRight: 5,
width: 47,
borderRadius: 5,
},
},
});

Expand Down
121 changes: 121 additions & 0 deletions src/note/store/attribution-image.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { graph, sym } from "rdflib";
import { readAttribution } from "./attribution";
import { ns } from "solid-ui";

describe("read note attribution", () => {
describe("GIVEN a note attributed to as:Person with image", () => {
let store;
beforeEach(() => {
store = graph();
store.add(
sym("https://pod.example/note#it"),
ns.as("attributedTo"),
sym("https://pod.example/person#me"),
sym("https://pod.example/note")
);
store.add(
sym("https://pod.example/person#me"),
ns.rdf("type"),
ns.as("Person"),
sym("https://pod.example/person")
);
store.add(
sym("https://pod.example/person#me"),
ns.as("image"),
sym("https://pod.example/person#image"),
sym("https://pod.example/person")
);
store.add(
sym("https://pod.example/person#image"),
ns.as("url"),
sym("https://pod.example/person.png"),
sym("https://pod.example/person")
);
});
describe("WHEN trying to read the attribution", () => {
let attribution;
beforeEach(() => {
attribution = readAttribution(
sym("https://pod.example/note#it"),
store
);
});
it("THEN the note attributes to the person with image", () => {
expect(attribution.imageSrc).toEqual("https://pod.example/person.png");
});
});
});

describe("GIVEN a note attributed to foaf:Person with img", () => {
let store;
beforeEach(() => {
store = graph();
store.add(
sym("https://pod.example/note#it"),
ns.as("attributedTo"),
sym("https://pod.example/person#me"),
sym("https://pod.example/note")
);
store.add(
sym("https://pod.example/person#me"),
ns.rdf("type"),
ns.foaf("Person"),
sym("https://pod.example/person")
);
store.add(
sym("https://pod.example/person#me"),
ns.foaf("img"),
sym("https://pod.example/person.png"),
sym("https://pod.example/person")
);
});
describe("WHEN trying to read the attribution", () => {
let attribution;
beforeEach(() => {
attribution = readAttribution(
sym("https://pod.example/note#it"),
store
);
});
it("THEN the note attributes to the person with image", () => {
expect(attribution.imageSrc).toEqual("https://pod.example/person.png");
});
});
});
describe("GIVEN a note attributed to vcard:Individual that hasPhoto", () => {
let store;
beforeEach(() => {
store = graph();
store.add(
sym("https://pod.example/note#it"),
ns.as("attributedTo"),
sym("https://pod.example/person#me"),
sym("https://pod.example/note")
);
store.add(
sym("https://pod.example/person#me"),
ns.rdf("type"),
ns.vcard("Individual"),
sym("https://pod.example/person")
);
store.add(
sym("https://pod.example/person#me"),
ns.vcard("hasPhoto"),
sym("https://pod.example/person.png"),
sym("https://pod.example/person")
);
});
describe("WHEN trying to read the attribution", () => {
let attribution;
beforeEach(() => {
attribution = readAttribution(
sym("https://pod.example/note#it"),
store
);
});
it("THEN the note attributes to the person with image", () => {
expect(attribution.imageSrc).toEqual("https://pod.example/person.png");
});
});
});
});
Loading

0 comments on commit 0c171be

Please sign in to comment.