contacts-pane 2.4.8 → 2.4.12-beta4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc +3 -1
- package/.github/workflows/ci.yml +74 -0
- package/.nvmrc +1 -1
- package/LICENSE.md +0 -0
- package/Makefile +0 -0
- package/README.md +0 -0
- package/__tests__/unit/data-reformat-test.js +166 -0
- package/__tests__/unit/data-reformat-test.ts +185 -0
- package/__tests__/unit/setup.js +74 -0
- package/__tests__/unit/setup.ts +77 -0
- package/babel.config.js +13 -0
- package/card.ai +0 -0
- package/card.png +0 -0
- package/contactLogic.js +84 -7
- package/contactsPane.js +64 -20
- package/diff.txt +0 -0
- package/exampleOfOpenData/mit-wikidata-details.ttl +0 -0
- package/exampleOfOpenData/mit-wikidata-query.sparql +0 -0
- package/exampleOfOpenData/wikidata-get.json +0 -0
- package/groupMembershipControl.js +56 -13
- package/individual.js +3 -2
- package/individualForm.js +0 -0
- package/jest.config.js +11 -0
- package/jest.setup.ts +10 -0
- package/lib/autocompleteBar.js +99 -0
- package/lib/autocompleteBar.js.map +1 -0
- package/lib/autocompleteField.js +157 -0
- package/lib/autocompleteField.js.map +1 -0
- package/lib/autocompletePicker.js +240 -0
- package/lib/autocompletePicker.js.map +1 -0
- package/lib/forms.js +315 -0
- package/lib/instituteDetailsQuery.js +38 -0
- package/lib/publicData.js +387 -0
- package/lib/publicData.js.map +1 -0
- package/lib/vcard.js +916 -0
- package/mintNewAddressBook.js +5 -4
- package/mugshotGallery.js +16 -4
- package/organizationForm.js +0 -0
- package/organizationForm.ttl +0 -0
- package/package.json +26 -13
- package/shapes/contacts-shapes.ttl +0 -0
- package/src/autocompleteBar.ts +92 -0
- package/src/autocompleteField.ts +180 -0
- package/src/autocompletePicker.ts +253 -0
- package/src/forms.ttl +1 -1
- package/src/instituteDetailsQuery.sparql +0 -0
- package/src/publicData.ts +385 -0
- package/src/vcard.ttl +0 -0
- package/toolsPane.js +70 -19
- package/tsconfig.json +16 -0
- package/webidControl.js +49 -4
package/.eslintrc
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
+
"root": true,
|
|
3
|
+
"parser": "@typescript-eslint/parser",
|
|
4
|
+
"plugins": ["@typescript-eslint"],
|
|
2
5
|
"env": {
|
|
3
6
|
"browser": true,
|
|
4
7
|
"es6": true,
|
|
5
8
|
"node": true
|
|
6
9
|
},
|
|
7
|
-
"extends": "standard",
|
|
8
10
|
"globals": {
|
|
9
11
|
"Atomics": "readonly",
|
|
10
12
|
"SharedArrayBuffer": "readonly"
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- "**"
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- "**"
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
node-version:
|
|
18
|
+
- 16.x
|
|
19
|
+
- 18.x
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v2
|
|
22
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
23
|
+
uses: actions/setup-node@v1
|
|
24
|
+
with:
|
|
25
|
+
node-version: ${{ matrix.node-version }}
|
|
26
|
+
- run: npm ci
|
|
27
|
+
- run: npm test
|
|
28
|
+
- run: npm run build
|
|
29
|
+
- name: Save build
|
|
30
|
+
if: matrix.node-version == '16.x'
|
|
31
|
+
uses: actions/upload-artifact@v2
|
|
32
|
+
with:
|
|
33
|
+
name: build
|
|
34
|
+
path: |
|
|
35
|
+
.
|
|
36
|
+
!node_modules
|
|
37
|
+
retention-days: 1
|
|
38
|
+
|
|
39
|
+
npm-publish-build:
|
|
40
|
+
needs: test
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/download-artifact@v2
|
|
44
|
+
with:
|
|
45
|
+
name: build
|
|
46
|
+
- uses: actions/setup-node@v1
|
|
47
|
+
with:
|
|
48
|
+
node-version: 16.x
|
|
49
|
+
- uses: rlespinasse/github-slug-action@v3.x
|
|
50
|
+
- name: Append commit hash to package version
|
|
51
|
+
run: 'sed -i -E "s/(\"version\": *\"[^\"]+)/\1-${GITHUB_SHA_SHORT}/" package.json'
|
|
52
|
+
- name: Disable pre- and post-publish actions
|
|
53
|
+
run: 'sed -i -E "s/\"((pre|post)publish)/\"ignore:\1/" package.json'
|
|
54
|
+
- uses: JS-DevTools/npm-publish@v1
|
|
55
|
+
with:
|
|
56
|
+
token: ${{ secrets.NPM_TOKEN }}
|
|
57
|
+
tag: ${{ env.GITHUB_REF_SLUG }}
|
|
58
|
+
npm-publish-latest:
|
|
59
|
+
needs: test
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
if: github.ref == 'refs/heads/main'
|
|
62
|
+
steps:
|
|
63
|
+
- uses: actions/download-artifact@v2
|
|
64
|
+
with:
|
|
65
|
+
name: build
|
|
66
|
+
- uses: actions/setup-node@v1
|
|
67
|
+
with:
|
|
68
|
+
node-version: 16.x
|
|
69
|
+
- name: Disable pre- and post-publish actions
|
|
70
|
+
run: 'sed -i -E "s/\"((pre|post)publish)/\"ignore:\1/" package.json'
|
|
71
|
+
- uses: JS-DevTools/npm-publish@v1
|
|
72
|
+
with:
|
|
73
|
+
token: ${{ secrets.NPM_TOKEN }}
|
|
74
|
+
tag: latest
|
package/.nvmrc
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
v18.19.0
|
package/LICENSE.md
CHANGED
|
File without changes
|
package/Makefile
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
File without changes
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { getDataModelIssues } from '../../contactLogic';
|
|
11
|
+
import fetchMock from "jest-fetch-mock";
|
|
12
|
+
import pane from "../../contactsPane";
|
|
13
|
+
import { parse } from "rdflib";
|
|
14
|
+
import { context, doc, mockFetchFunction, mockUpdate, ns, store, prefixes, web } from "./setup";
|
|
15
|
+
// This was at testingsolidos.solidcommunity.net
|
|
16
|
+
const base = doc.dir().uri;
|
|
17
|
+
const webid1 = store.sym(base + 'People/localPerson/index.ttl#this');
|
|
18
|
+
const exampleData = prefixes + `
|
|
19
|
+
|
|
20
|
+
:homeGroup1 a vcard:Group;
|
|
21
|
+
vcard:fn "Happy Home";
|
|
22
|
+
vcard:hasMember ${webid1} .
|
|
23
|
+
|
|
24
|
+
:homeGroup2 a vcard:Group;
|
|
25
|
+
vcard:fn "Home";
|
|
26
|
+
vcard:hasMember :localPerson.
|
|
27
|
+
|
|
28
|
+
:homeGroup3 a vcard:Group;
|
|
29
|
+
vcard:fn "Home";
|
|
30
|
+
vcard:hasMember :localPerson.
|
|
31
|
+
|
|
32
|
+
`;
|
|
33
|
+
const book = store.sym(base + 'book.ttl#this');
|
|
34
|
+
const aliceLocal = store.sym(base + 'People/aaaaaaaaaa/index.ttl#this');
|
|
35
|
+
const aliceWebId = store.sym('https://alice.example/card#me');
|
|
36
|
+
web[aliceLocal.doc().uri] = `<#this> a vcard:Individual, schema:Person; vcard:fn "Alice".`;
|
|
37
|
+
const bobLocal = store.sym(base + 'People/bbbbbbbbbb/index.ttl#this');
|
|
38
|
+
const bobWebId = store.sym('https://bob.example.net/#me');
|
|
39
|
+
web[bobLocal.doc().uri] = `<#this> a vcard:Individual, schema:Person;
|
|
40
|
+
vcard:hasURL [ vcard:type vcard:WebId; vcard:value ${bobWebId} ];
|
|
41
|
+
vcard:fn "Bob".`;
|
|
42
|
+
web[base + 'book.ttl'] = `
|
|
43
|
+
<#this> a vcard:AddressBook;
|
|
44
|
+
vcard:fn """Contacts: Test address book""";
|
|
45
|
+
vcard:nameEmailIndex <people.ttl>;
|
|
46
|
+
vcard:groupIndex <groups.ttl>.
|
|
47
|
+
`;
|
|
48
|
+
web[base + 'groups.ttl'] = `
|
|
49
|
+
<Group/Test.ttl#this> a vcard:Group ;
|
|
50
|
+
vcard:fn "Test group".
|
|
51
|
+
<Group/Home.ttl#this> a vcard:Group ;
|
|
52
|
+
vcard:fn "Home group".
|
|
53
|
+
<Group/Work.ttl#this> a vcard:Group ;
|
|
54
|
+
vcard:fn "Work group".
|
|
55
|
+
`;
|
|
56
|
+
const testGroup = store.sym(base + 'Group/Test.ttl#this');
|
|
57
|
+
web[testGroup.doc().uri] = `
|
|
58
|
+
<#this> a vcard:Group;
|
|
59
|
+
vcard:fn "Test Group";
|
|
60
|
+
vcard:hasMember ${aliceLocal} .
|
|
61
|
+
# <https://alice.example/card#me>,
|
|
62
|
+
# <../People/aaaaaaaaaa/index.ttl#this>,
|
|
63
|
+
# <../People/bbbbbbbbbbb/index.ttl#this> .
|
|
64
|
+
|
|
65
|
+
${aliceLocal} = ${aliceWebId} .
|
|
66
|
+
`;
|
|
67
|
+
const homeGroup = store.sym(base + 'Group/Home.ttl#this');
|
|
68
|
+
web[homeGroup.doc().uri] = `
|
|
69
|
+
<#this> a vcard:Group;
|
|
70
|
+
vcard:fn "Home Group";
|
|
71
|
+
vcard:hasMember
|
|
72
|
+
<../People/aaaaaaaaaa/index.ttl#this>,
|
|
73
|
+
<../People/bbbbbbbbbb/index.ttl#this> .
|
|
74
|
+
`;
|
|
75
|
+
const workGroup = store.sym(base + 'Group/Work.ttl#this');
|
|
76
|
+
web[workGroup.doc().uri] = `
|
|
77
|
+
<#this> a vcard:Group;
|
|
78
|
+
vcard:fn "Work Group";
|
|
79
|
+
vcard:hasMember
|
|
80
|
+
<https://alice.example/card#me>,
|
|
81
|
+
<https://bob.example/card#me>,
|
|
82
|
+
<https://charlie.example/card#me> .`;
|
|
83
|
+
web[base + 'People/aaaaaaaaaa/index.ttl'] = `
|
|
84
|
+
<#this> vcard:fn "Alice" .
|
|
85
|
+
`;
|
|
86
|
+
const groups = [testGroup, homeGroup, workGroup];
|
|
87
|
+
for (const uri in web) {
|
|
88
|
+
console.log(` parsing "${uri}" (${web[uri].length})`);
|
|
89
|
+
parse(prefixes + web[uri], store, uri);
|
|
90
|
+
}
|
|
91
|
+
describe("contacts-pane", () => {
|
|
92
|
+
describe("returns right label", () => {
|
|
93
|
+
beforeAll(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
94
|
+
store.removeDocument(doc);
|
|
95
|
+
// parse(exampleData, store, doc.uri);
|
|
96
|
+
// const label = pane.label(subject, context);
|
|
97
|
+
}));
|
|
98
|
+
/*
|
|
99
|
+
if (t[ns.vcard('Individual').uri]) return 'Contact'
|
|
100
|
+
if (t[ns.vcard('Organization').uri]) return 'contact'
|
|
101
|
+
if (t[ns.foaf('Person').uri]) return 'Person'
|
|
102
|
+
if (t[ns.schema('Person').uri]) return 'Person'
|
|
103
|
+
if (t[ns.vcard('Group').uri]) return 'Group'
|
|
104
|
+
if (t[ns.vcard('AddressBook').uri]) return 'Address book'
|
|
105
|
+
*/
|
|
106
|
+
it("returns a good label contact if Organization", () => {
|
|
107
|
+
let thing = store.sym(base + 'thing1');
|
|
108
|
+
store.add(thing, ns.rdf('type'), ns.vcard('Organization'), doc);
|
|
109
|
+
expect(pane.label(thing, context)).toEqual('contact');
|
|
110
|
+
});
|
|
111
|
+
it("returns a good label Contact for Individual", () => {
|
|
112
|
+
let thing = store.sym(base + 'thing2');
|
|
113
|
+
store.add(thing, ns.rdf('type'), ns.vcard('Individual'), doc);
|
|
114
|
+
expect(pane.label(thing, context)).toEqual('Contact');
|
|
115
|
+
});
|
|
116
|
+
it("returns a good label Person if Person", () => {
|
|
117
|
+
let thing = store.sym(base + 'thing3');
|
|
118
|
+
store.add(thing, ns.rdf('type'), ns.schema('Person'), doc);
|
|
119
|
+
expect(pane.label(thing, context)).toEqual('Person');
|
|
120
|
+
});
|
|
121
|
+
it("returns a good label Person if foaf:Person", () => {
|
|
122
|
+
let thing = store.sym(base + 'thing4');
|
|
123
|
+
store.add(thing, ns.rdf('type'), ns.foaf('Person'), doc);
|
|
124
|
+
expect(pane.label(thing, context)).toEqual('Person');
|
|
125
|
+
});
|
|
126
|
+
it("returns a good label Group if Group", () => {
|
|
127
|
+
let thing = store.sym(base + 'thing5');
|
|
128
|
+
store.add(thing, ns.rdf('type'), ns.vcard('Group'), doc);
|
|
129
|
+
expect(pane.label(thing, context)).toEqual('Group');
|
|
130
|
+
});
|
|
131
|
+
it("returns a good label AddressBook if AddressBook", () => {
|
|
132
|
+
let thing = store.sym(base + 'thing6');
|
|
133
|
+
store.add(thing, ns.rdf('type'), ns.vcard('AddressBook'), doc);
|
|
134
|
+
expect(pane.label(thing, context)).toEqual('Address book');
|
|
135
|
+
});
|
|
136
|
+
it("returns a null label if not a person", () => {
|
|
137
|
+
let thing = store.sym(base + 'thing7');
|
|
138
|
+
expect(pane.label(store.sym('https://random.example.com/'), context)).toEqual(null);
|
|
139
|
+
// done()
|
|
140
|
+
});
|
|
141
|
+
}); // label tests
|
|
142
|
+
describe("render tests", () => {
|
|
143
|
+
it("renders an empty UI of an address book", () => {
|
|
144
|
+
const div = pane.render(book, context);
|
|
145
|
+
expect(div.outerHTML).toMatch("<div class=\"contactPane\"></div>");
|
|
146
|
+
expect(div.innerHTML).toMatch("");
|
|
147
|
+
});
|
|
148
|
+
}); // render tests
|
|
149
|
+
describe("data format tests", () => {
|
|
150
|
+
beforeAll(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
151
|
+
store.removeDocument(doc);
|
|
152
|
+
parse(exampleData, store, doc.uri);
|
|
153
|
+
fetchMock.mockIf(/^https?.*$/, mockFetchFunction);
|
|
154
|
+
}));
|
|
155
|
+
it("converts a bad format into a good one", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
156
|
+
expect(store.the(testGroup, ns.vcard('hasMember'), null, testGroup.doc())).toEqual(aliceLocal);
|
|
157
|
+
const { del, ins } = yield getDataModelIssues(groups);
|
|
158
|
+
expect(del.length).toEqual(1);
|
|
159
|
+
expect(ins.length).toEqual(1);
|
|
160
|
+
expect(del.toString()).toEqual('<https://janedoe.example/profile/Group/Test.ttl#this> <http://www.w3.org/2006/vcard/ns#hasMember> <https://janedoe.example/profile/People/aaaaaaaaaa/index.ttl#this> .');
|
|
161
|
+
expect(ins.toString()).toEqual('<https://janedoe.example/profile/Group/Test.ttl#this> <http://www.w3.org/2006/vcard/ns#hasMember> <https://alice.example/card#me> .');
|
|
162
|
+
mockUpdate(store, del, ins);
|
|
163
|
+
expect(store.the(testGroup, ns.vcard('hasMember'), null, testGroup.doc())).toEqual(aliceWebId);
|
|
164
|
+
}));
|
|
165
|
+
}); // data format tests
|
|
166
|
+
}); // all tests
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { getDataModelIssues } from '../../contactLogic'
|
|
2
|
+
import fetchMock from "jest-fetch-mock";
|
|
3
|
+
|
|
4
|
+
import pane from "../../contactsPane";
|
|
5
|
+
import { parse, NamedNode } from "rdflib";
|
|
6
|
+
import { context, doc, subject, mockFetchFunction, mockUpdate, ns, store, prefixes, web } from "./setup";
|
|
7
|
+
|
|
8
|
+
// This was at testingsolidos.solidcommunity.net
|
|
9
|
+
|
|
10
|
+
const base = doc.dir().uri
|
|
11
|
+
const webid1 = store.sym(base + 'People/localPerson/index.ttl#this')
|
|
12
|
+
|
|
13
|
+
const exampleData = prefixes + `
|
|
14
|
+
|
|
15
|
+
:homeGroup1 a vcard:Group;
|
|
16
|
+
vcard:fn "Happy Home";
|
|
17
|
+
vcard:hasMember ${webid1} .
|
|
18
|
+
|
|
19
|
+
:homeGroup2 a vcard:Group;
|
|
20
|
+
vcard:fn "Home";
|
|
21
|
+
vcard:hasMember :localPerson.
|
|
22
|
+
|
|
23
|
+
:homeGroup3 a vcard:Group;
|
|
24
|
+
vcard:fn "Home";
|
|
25
|
+
vcard:hasMember :localPerson.
|
|
26
|
+
|
|
27
|
+
`
|
|
28
|
+
|
|
29
|
+
const book = store.sym(base + 'book.ttl#this')
|
|
30
|
+
|
|
31
|
+
const aliceLocal = store.sym(base + 'People/aaaaaaaaaa/index.ttl#this');
|
|
32
|
+
const aliceWebId = store.sym('https://alice.example/card#me')
|
|
33
|
+
|
|
34
|
+
web[aliceLocal.doc().uri] = `<#this> a vcard:Individual, schema:Person; vcard:fn "Alice".`;
|
|
35
|
+
|
|
36
|
+
const bobLocal = store.sym(base + 'People/bbbbbbbbbb/index.ttl#this')
|
|
37
|
+
const bobWebId = store.sym('https://bob.example.net/#me')
|
|
38
|
+
web[bobLocal.doc().uri] = `<#this> a vcard:Individual, schema:Person;
|
|
39
|
+
vcard:hasURL [ vcard:type vcard:WebId; vcard:value ${bobWebId} ];
|
|
40
|
+
vcard:fn "Bob".`;
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
web[base + 'book.ttl'] = `
|
|
45
|
+
<#this> a vcard:AddressBook;
|
|
46
|
+
vcard:fn """Contacts: Test address book""";
|
|
47
|
+
vcard:nameEmailIndex <people.ttl>;
|
|
48
|
+
vcard:groupIndex <groups.ttl>.
|
|
49
|
+
`;
|
|
50
|
+
|
|
51
|
+
web[base + 'groups.ttl'] = `
|
|
52
|
+
<Group/Test.ttl#this> a vcard:Group ;
|
|
53
|
+
vcard:fn "Test group".
|
|
54
|
+
<Group/Home.ttl#this> a vcard:Group ;
|
|
55
|
+
vcard:fn "Home group".
|
|
56
|
+
<Group/Work.ttl#this> a vcard:Group ;
|
|
57
|
+
vcard:fn "Work group".
|
|
58
|
+
`;
|
|
59
|
+
|
|
60
|
+
const testGroup = store.sym(base + 'Group/Test.ttl#this')
|
|
61
|
+
web[testGroup.doc().uri] = `
|
|
62
|
+
<#this> a vcard:Group;
|
|
63
|
+
vcard:fn "Test Group";
|
|
64
|
+
vcard:hasMember ${aliceLocal} .
|
|
65
|
+
# <https://alice.example/card#me>,
|
|
66
|
+
# <../People/aaaaaaaaaa/index.ttl#this>,
|
|
67
|
+
# <../People/bbbbbbbbbbb/index.ttl#this> .
|
|
68
|
+
|
|
69
|
+
${aliceLocal} = ${aliceWebId} .
|
|
70
|
+
`;
|
|
71
|
+
const homeGroup = store.sym(base + 'Group/Home.ttl#this')
|
|
72
|
+
web[homeGroup.doc().uri] = `
|
|
73
|
+
<#this> a vcard:Group;
|
|
74
|
+
vcard:fn "Home Group";
|
|
75
|
+
vcard:hasMember
|
|
76
|
+
<../People/aaaaaaaaaa/index.ttl#this>,
|
|
77
|
+
<../People/bbbbbbbbbb/index.ttl#this> .
|
|
78
|
+
`;
|
|
79
|
+
|
|
80
|
+
const workGroup = store.sym(base + 'Group/Work.ttl#this')
|
|
81
|
+
web[workGroup.doc().uri] = `
|
|
82
|
+
<#this> a vcard:Group;
|
|
83
|
+
vcard:fn "Work Group";
|
|
84
|
+
vcard:hasMember
|
|
85
|
+
<https://alice.example/card#me>,
|
|
86
|
+
<https://bob.example/card#me>,
|
|
87
|
+
<https://charlie.example/card#me> .`;
|
|
88
|
+
|
|
89
|
+
web[base + 'People/aaaaaaaaaa/index.ttl'] = `
|
|
90
|
+
<#this> vcard:fn "Alice" .
|
|
91
|
+
`;
|
|
92
|
+
|
|
93
|
+
const groups = [ testGroup, homeGroup, workGroup ];
|
|
94
|
+
|
|
95
|
+
for (const uri in web) {
|
|
96
|
+
console.log(` parsing "${uri}" (${web[uri].length})`)
|
|
97
|
+
parse(prefixes + web[uri], store, uri);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
describe("contacts-pane", () => {
|
|
101
|
+
|
|
102
|
+
describe("returns right label", () => {
|
|
103
|
+
beforeAll(async () => {
|
|
104
|
+
store.removeDocument(doc);
|
|
105
|
+
// parse(exampleData, store, doc.uri);
|
|
106
|
+
// const label = pane.label(subject, context);
|
|
107
|
+
});
|
|
108
|
+
/*
|
|
109
|
+
if (t[ns.vcard('Individual').uri]) return 'Contact'
|
|
110
|
+
if (t[ns.vcard('Organization').uri]) return 'contact'
|
|
111
|
+
if (t[ns.foaf('Person').uri]) return 'Person'
|
|
112
|
+
if (t[ns.schema('Person').uri]) return 'Person'
|
|
113
|
+
if (t[ns.vcard('Group').uri]) return 'Group'
|
|
114
|
+
if (t[ns.vcard('AddressBook').uri]) return 'Address book'
|
|
115
|
+
*/
|
|
116
|
+
it("returns a good label contact if Organization", () => {
|
|
117
|
+
let thing = store.sym(base + 'thing1')
|
|
118
|
+
store.add(thing, ns.rdf('type'), ns.vcard('Organization'), doc)
|
|
119
|
+
expect(pane.label(thing, context)).toEqual('contact');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("returns a good label Contact for Individual", () => {
|
|
123
|
+
let thing = store.sym(base + 'thing2')
|
|
124
|
+
store.add(thing, ns.rdf('type'), ns.vcard('Individual'), doc)
|
|
125
|
+
expect(pane.label(thing, context)).toEqual('Contact');
|
|
126
|
+
});
|
|
127
|
+
it("returns a good label Person if Person", () => {
|
|
128
|
+
let thing = store.sym(base + 'thing3')
|
|
129
|
+
store.add(thing, ns.rdf('type'), ns.schema('Person'), doc)
|
|
130
|
+
expect(pane.label(thing, context)).toEqual('Person');
|
|
131
|
+
});
|
|
132
|
+
it("returns a good label Person if foaf:Person", () => {
|
|
133
|
+
let thing = store.sym(base + 'thing4')
|
|
134
|
+
store.add(thing, ns.rdf('type'), ns.foaf('Person'), doc)
|
|
135
|
+
expect(pane.label(thing, context)).toEqual('Person');
|
|
136
|
+
});
|
|
137
|
+
it("returns a good label Group if Group", () => {
|
|
138
|
+
let thing = store.sym(base + 'thing5')
|
|
139
|
+
|
|
140
|
+
store.add(thing, ns.rdf('type'), ns.vcard('Group'), doc)
|
|
141
|
+
expect(pane.label(thing, context)).toEqual('Group');
|
|
142
|
+
});
|
|
143
|
+
it("returns a good label AddressBook if AddressBook", () => {
|
|
144
|
+
let thing = store.sym(base + 'thing6')
|
|
145
|
+
store.add(thing, ns.rdf('type'), ns.vcard('AddressBook'), doc)
|
|
146
|
+
expect(pane.label(thing, context)).toEqual('Address book');
|
|
147
|
+
});
|
|
148
|
+
it("returns a null label if not a person", () => {
|
|
149
|
+
let thing = store.sym(base + 'thing7')
|
|
150
|
+
expect(pane.label(store.sym('https://random.example.com/'), context)).toEqual(null);
|
|
151
|
+
// done()
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
}); // label tests
|
|
155
|
+
|
|
156
|
+
describe("render tests", () => { // How to get the UI which comes over time?
|
|
157
|
+
it("renders an empty UI of an address book", () => {
|
|
158
|
+
const div = pane.render(book, context)
|
|
159
|
+
expect(div.outerHTML).toMatch("<div class=\"contactPane\"></div>");
|
|
160
|
+
expect(div.innerHTML).toMatch("");
|
|
161
|
+
});
|
|
162
|
+
}); // render tests
|
|
163
|
+
|
|
164
|
+
describe("data format tests", () => {
|
|
165
|
+
beforeAll(async () => {
|
|
166
|
+
store.removeDocument(doc);
|
|
167
|
+
parse(exampleData, store, doc.uri);
|
|
168
|
+
fetchMock.mockIf(/^https?.*$/, mockFetchFunction)
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("converts a bad format into a good one", async () => {
|
|
172
|
+
expect(store.the(testGroup, ns.vcard('hasMember'), null, testGroup.doc())).toEqual(aliceLocal)
|
|
173
|
+
const { del, ins } = await getDataModelIssues(groups)
|
|
174
|
+
expect(del.length).toEqual(1)
|
|
175
|
+
expect(ins.length).toEqual(1)
|
|
176
|
+
expect(del.toString()).toEqual('<https://janedoe.example/profile/Group/Test.ttl#this> <http://www.w3.org/2006/vcard/ns#hasMember> <https://janedoe.example/profile/People/aaaaaaaaaa/index.ttl#this> .')
|
|
177
|
+
expect(ins.toString()).toEqual('<https://janedoe.example/profile/Group/Test.ttl#this> <http://www.w3.org/2006/vcard/ns#hasMember> <https://alice.example/card#me> .')
|
|
178
|
+
mockUpdate(store, del, ins)
|
|
179
|
+
expect(store.the(testGroup, ns.vcard('hasMember'), null, testGroup.doc())).toEqual(aliceWebId)
|
|
180
|
+
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
}); // data format tests
|
|
184
|
+
|
|
185
|
+
}); // all tests
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { ns, store } from "solid-ui";
|
|
11
|
+
export { ns, store, rdf } from "solid-ui";
|
|
12
|
+
// console.log('@@ store', store)
|
|
13
|
+
// console.log('@@ store.sym', store.sym)
|
|
14
|
+
export const subject = store.sym("https://janedoe.example/profile/card#me");
|
|
15
|
+
export const doc = subject.doc();
|
|
16
|
+
export const context = {
|
|
17
|
+
dom: document,
|
|
18
|
+
getOutliner: () => null,
|
|
19
|
+
session: {
|
|
20
|
+
paneRegistry: {
|
|
21
|
+
byName: (name) => {
|
|
22
|
+
return {
|
|
23
|
+
render: () => {
|
|
24
|
+
return document.createElement('div')
|
|
25
|
+
.appendChild(document.createTextNode(`mock ${name} pane`));
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
store,
|
|
31
|
+
logic: {},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
const prefs = Object.keys(ns).filter(x => x !== 'default'); // default is bogus value
|
|
35
|
+
export const prefixes = prefs.map(prefix => `@prefix ${prefix}: ${ns[prefix]('')}.\n`).join(''); // In turtle
|
|
36
|
+
export let web = {};
|
|
37
|
+
export let requests = [];
|
|
38
|
+
export function mockFetchFunction(req) {
|
|
39
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
40
|
+
if (req.method !== 'GET') {
|
|
41
|
+
requests.push(req);
|
|
42
|
+
if (req.method === 'PUT') {
|
|
43
|
+
const contents = yield req.text();
|
|
44
|
+
web[req.url] = contents; // Update our dummy web
|
|
45
|
+
console.log(`Tetst: Updated ${req.url} on PUT to <<<${web[req.url]}>>>`);
|
|
46
|
+
}
|
|
47
|
+
return { status: 200 };
|
|
48
|
+
}
|
|
49
|
+
const contents = web[req.url];
|
|
50
|
+
if (contents !== undefined) { //
|
|
51
|
+
return {
|
|
52
|
+
body: prefixes + contents,
|
|
53
|
+
status: 200,
|
|
54
|
+
headers: {
|
|
55
|
+
"Content-Type": "text/turtle",
|
|
56
|
+
"WAC-Allow": 'user="write", public="read"',
|
|
57
|
+
"Accept-Patch": "application/sparql-update"
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
} // if contents
|
|
61
|
+
return {
|
|
62
|
+
status: 404,
|
|
63
|
+
body: 'Not Found'
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
export function mockUpdate(store, del, ins) {
|
|
68
|
+
for (const st of del) {
|
|
69
|
+
store.remove(st);
|
|
70
|
+
}
|
|
71
|
+
for (const st of ins) {
|
|
72
|
+
store.addStatement(st);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { DataBrowserContext, PaneRegistry } from "pane-registry";
|
|
2
|
+
|
|
3
|
+
import { Statement, LiveStore } from "rdflib";
|
|
4
|
+
import { ns, store, rdf } from "solid-ui"
|
|
5
|
+
export { ns, store, rdf } from "solid-ui"
|
|
6
|
+
|
|
7
|
+
import { SolidLogic } from "solid-logic";
|
|
8
|
+
|
|
9
|
+
// console.log('@@ store', store)
|
|
10
|
+
// console.log('@@ store.sym', store.sym)
|
|
11
|
+
|
|
12
|
+
export const subject = store.sym("https://janedoe.example/profile/card#me");
|
|
13
|
+
export const doc = subject.doc();
|
|
14
|
+
|
|
15
|
+
export const context = {
|
|
16
|
+
dom: document,
|
|
17
|
+
getOutliner: () => null,
|
|
18
|
+
session: {
|
|
19
|
+
paneRegistry: {
|
|
20
|
+
byName: (name: string) => {
|
|
21
|
+
return {
|
|
22
|
+
render: () => {
|
|
23
|
+
return document.createElement('div')
|
|
24
|
+
.appendChild(
|
|
25
|
+
document.createTextNode(`mock ${name} pane`)
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
} as PaneRegistry,
|
|
31
|
+
store,
|
|
32
|
+
logic: {} as SolidLogic,
|
|
33
|
+
},
|
|
34
|
+
} as unknown as DataBrowserContext;
|
|
35
|
+
|
|
36
|
+
const prefs = Object.keys(ns).filter(x => x !== 'default') // default is bogus value
|
|
37
|
+
export const prefixes = prefs.map(prefix => `@prefix ${prefix}: ${ns[prefix]('')}.\n`).join('') // In turtle
|
|
38
|
+
|
|
39
|
+
export let web = {}
|
|
40
|
+
export let requests = []
|
|
41
|
+
|
|
42
|
+
export async function mockFetchFunction (req) {
|
|
43
|
+
if (req.method !== 'GET') {
|
|
44
|
+
requests.push(req)
|
|
45
|
+
if (req.method === 'PUT') {
|
|
46
|
+
const contents = await req.text()
|
|
47
|
+
web[req.url] = contents // Update our dummy web
|
|
48
|
+
console.log(`Tetst: Updated ${req.url} on PUT to <<<${web[req.url]}>>>`)
|
|
49
|
+
}
|
|
50
|
+
return { status: 200 }
|
|
51
|
+
}
|
|
52
|
+
const contents = web[req.url]
|
|
53
|
+
if (contents !== undefined) { //
|
|
54
|
+
return {
|
|
55
|
+
body: prefixes + contents, // Add namespaces to anything
|
|
56
|
+
status: 200,
|
|
57
|
+
headers: {
|
|
58
|
+
"Content-Type": "text/turtle",
|
|
59
|
+
"WAC-Allow": 'user="write", public="read"',
|
|
60
|
+
"Accept-Patch": "application/sparql-update"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} // if contents
|
|
64
|
+
return {
|
|
65
|
+
status: 404,
|
|
66
|
+
body: 'Not Found'
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function mockUpdate (store: LiveStore, del: Statement[], ins: Statement[]) {
|
|
71
|
+
for (const st of del) {
|
|
72
|
+
store.remove(st)
|
|
73
|
+
}
|
|
74
|
+
for (const st of ins) {
|
|
75
|
+
store.addStatement(st)
|
|
76
|
+
}
|
|
77
|
+
}
|
package/babel.config.js
ADDED
package/card.ai
CHANGED
|
File without changes
|
package/card.png
CHANGED
|
File without changes
|