solid-panes 4.2.4-test.4 → 4.2.4-test.5
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/dist/dashboard/basicPreferences.js +146 -0
- package/dist/dashboard/dashboardPane.js +67 -0
- package/dist/dashboard/homepage.js +72 -0
- package/dist/home/homePane.js +72 -0
- package/dist/index.js +108 -0
- package/dist/internal/internalPane.js +183 -0
- package/dist/mainPage/footer.js +21 -0
- package/dist/mainPage/header.js +85 -0
- package/dist/mainPage/index.js +24 -0
- package/dist/outline/context.js +18 -0
- package/dist/outline/propertyViews.js +43 -0
- package/dist/outline/viewAsImage.js +14 -0
- package/dist/outline/viewAsMbox.js +21 -0
- package/dist/pad/padPane.js +410 -0
- package/dist/sharing/sharingPane.js +48 -0
- package/dist/tabbed/tabbedPane.js +57 -0
- package/dist/trustedApplications/trustedApplications.dom.js +145 -0
- package/dist/trustedApplications/trustedApplications.utils.js +23 -0
- package/dist/trustedApplications/trustedApplications.view.js +55 -0
- package/dist/versionInfo.js +35 -0
- package/package.json +5 -5
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.createHeader = createHeader;
|
|
7
|
+
var _solidLogic = require("solid-logic");
|
|
8
|
+
var _solidUi = require("solid-ui");
|
|
9
|
+
/**
|
|
10
|
+
* menu icons
|
|
11
|
+
*/
|
|
12
|
+
const HELP_MENU_ICON = _solidUi.icons.iconBase + 'noun_help.svg';
|
|
13
|
+
const SOLID_ICON_URL = 'https://solidproject.org/assets/img/solid-emblem.svg';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* menu elements
|
|
17
|
+
*/
|
|
18
|
+
const USER_GUIDE_MENU_ITEM = 'User guide';
|
|
19
|
+
const REPORT_A_PROBLEM_MENU_ITEM = 'Report a problem';
|
|
20
|
+
const SHOW_YOUR_PROFILE_MENU_ITEM = 'Show your profile';
|
|
21
|
+
const LOG_OUT_MENU_ITEM = 'Log out';
|
|
22
|
+
/**
|
|
23
|
+
* URLS
|
|
24
|
+
*/
|
|
25
|
+
const USER_GUIDE_MENU_URL = 'https://solidos.github.io/userguide/';
|
|
26
|
+
const REPORT_A_PROBLEM_MENU_URL = 'https://github.com/solidos/solidos/issues';
|
|
27
|
+
async function createHeader(store, outliner) {
|
|
28
|
+
(0, _solidUi.initHeader)(store, await setUserMenu(outliner), setHeaderOptions());
|
|
29
|
+
}
|
|
30
|
+
function setHeaderOptions() {
|
|
31
|
+
const helpMenuList = [{
|
|
32
|
+
label: USER_GUIDE_MENU_ITEM,
|
|
33
|
+
url: USER_GUIDE_MENU_URL,
|
|
34
|
+
target: '_blank'
|
|
35
|
+
}, {
|
|
36
|
+
label: REPORT_A_PROBLEM_MENU_ITEM,
|
|
37
|
+
url: REPORT_A_PROBLEM_MENU_URL,
|
|
38
|
+
target: '_blank'
|
|
39
|
+
}];
|
|
40
|
+
const headerOptions = {
|
|
41
|
+
logo: SOLID_ICON_URL,
|
|
42
|
+
helpIcon: HELP_MENU_ICON,
|
|
43
|
+
helpMenuList
|
|
44
|
+
};
|
|
45
|
+
return headerOptions;
|
|
46
|
+
}
|
|
47
|
+
async function setUserMenu(outliner) {
|
|
48
|
+
// @ts-ignore: showProfile is used conditionally
|
|
49
|
+
const showProfile = {
|
|
50
|
+
label: SHOW_YOUR_PROFILE_MENU_ITEM,
|
|
51
|
+
onclick: () => openUserProfile(outliner)
|
|
52
|
+
};
|
|
53
|
+
const logOut = {
|
|
54
|
+
label: LOG_OUT_MENU_ITEM,
|
|
55
|
+
onclick: () => {
|
|
56
|
+
_solidLogic.authSession.logout();
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// the order of the menu is important here, show profile first and logout last
|
|
61
|
+
let userMenuList = []; // was [showProfile]
|
|
62
|
+
userMenuList = userMenuList.concat(await getMenuItems(outliner));
|
|
63
|
+
userMenuList.push(logOut);
|
|
64
|
+
return userMenuList;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Does not work to jump to user profile,
|
|
68
|
+
function openUserProfile(outliner) {
|
|
69
|
+
outliner.GotoSubject(_solidLogic.authn.currentUser(), true, undefined, true, undefined);
|
|
70
|
+
location.reload();
|
|
71
|
+
}
|
|
72
|
+
async function getMenuItems(outliner) {
|
|
73
|
+
const items = await outliner.getDashboardItems();
|
|
74
|
+
return items.map(element => {
|
|
75
|
+
return {
|
|
76
|
+
label: element.label,
|
|
77
|
+
onclick: () => openDashboardPane(outliner, element.tabName || element.paneName)
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
async function openDashboardPane(outliner, pane) {
|
|
82
|
+
outliner.showDashboard({
|
|
83
|
+
pane
|
|
84
|
+
});
|
|
85
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = initMainPage;
|
|
7
|
+
var _index = require("../index");
|
|
8
|
+
var _header = require("./header");
|
|
9
|
+
var _footer = require("./footer");
|
|
10
|
+
/* Main Page
|
|
11
|
+
**
|
|
12
|
+
** This code is called in mashlib and renders the header and footer of the Databrowser.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
async function initMainPage(store, uri) {
|
|
16
|
+
const outliner = (0, _index.getOutliner)(document);
|
|
17
|
+
uri = uri || window.location.href;
|
|
18
|
+
let subject = uri;
|
|
19
|
+
if (typeof uri === 'string') subject = store.sym(uri);
|
|
20
|
+
outliner.GotoSubject(subject, true, undefined, true, undefined);
|
|
21
|
+
const header = await (0, _header.createHeader)(store, outliner);
|
|
22
|
+
const footer = (0, _footer.createFooter)(store);
|
|
23
|
+
return Promise.all([header, footer]);
|
|
24
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.createContext = createContext;
|
|
7
|
+
var _index = require("../index");
|
|
8
|
+
function createContext(dom, paneRegistry, store, logic) {
|
|
9
|
+
return {
|
|
10
|
+
dom,
|
|
11
|
+
getOutliner: _index.getOutliner,
|
|
12
|
+
session: {
|
|
13
|
+
paneRegistry,
|
|
14
|
+
store,
|
|
15
|
+
logic
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.propertyViews = propertyViews;
|
|
7
|
+
exports.viewsAddPropertyView = viewsAddPropertyView;
|
|
8
|
+
var _solidUi = require("solid-ui");
|
|
9
|
+
var _viewAsImage = _interopRequireDefault(require("./viewAsImage"));
|
|
10
|
+
var _viewAsMbox = _interopRequireDefault(require("./viewAsMbox"));
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
/** some builtin simple views **/
|
|
13
|
+
|
|
14
|
+
function propertyViews(dom) {
|
|
15
|
+
// view that applies to items that are objects of certain properties.
|
|
16
|
+
const views = {
|
|
17
|
+
properties: [],
|
|
18
|
+
defaults: [],
|
|
19
|
+
classes: []
|
|
20
|
+
}; // views
|
|
21
|
+
|
|
22
|
+
const asImage = (0, _viewAsImage.default)(dom);
|
|
23
|
+
const asMbox = (0, _viewAsMbox.default)(dom);
|
|
24
|
+
viewsAddPropertyView(views, _solidUi.ns.foaf('depiction').uri, asImage, true);
|
|
25
|
+
viewsAddPropertyView(views, _solidUi.ns.foaf('img').uri, asImage, true);
|
|
26
|
+
viewsAddPropertyView(views, _solidUi.ns.foaf('thumbnail').uri, asImage, true);
|
|
27
|
+
viewsAddPropertyView(views, _solidUi.ns.foaf('logo').uri, asImage, true);
|
|
28
|
+
viewsAddPropertyView(views, _solidUi.ns.schema('image').uri, asImage, true);
|
|
29
|
+
viewsAddPropertyView(views, _solidUi.ns.foaf('mbox').uri, asMbox, true);
|
|
30
|
+
return views;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** add a property view function **/
|
|
34
|
+
function viewsAddPropertyView(views, property, pviewfunc, isDefault) {
|
|
35
|
+
if (!views.properties[property]) {
|
|
36
|
+
views.properties[property] = [];
|
|
37
|
+
}
|
|
38
|
+
views.properties[property].push(pviewfunc);
|
|
39
|
+
if (isDefault) {
|
|
40
|
+
// will override an existing default!
|
|
41
|
+
views.defaults[property] = pviewfunc;
|
|
42
|
+
}
|
|
43
|
+
} // viewsAddPropertyView
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var UI = _interopRequireWildcard(require("solid-ui"));
|
|
8
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
9
|
+
var _default = dom => function viewAsImage(obj) {
|
|
10
|
+
const img = UI.utils.AJARImage(obj.uri, UI.utils.label(obj), UI.utils.label(obj), dom);
|
|
11
|
+
img.setAttribute('class', 'outlineImage');
|
|
12
|
+
return img;
|
|
13
|
+
};
|
|
14
|
+
exports.default = _default;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _default = dom => function viewAsMbox(obj) {
|
|
8
|
+
const anchor = dom.createElement('a');
|
|
9
|
+
// previous implementation assumed email address was Literal. fixed.
|
|
10
|
+
|
|
11
|
+
// FOAF mboxs must NOT be literals -- must be mailto: URIs.
|
|
12
|
+
|
|
13
|
+
let address = obj.termType === 'NamedNode' ? obj.uri : obj.value; // this way for now
|
|
14
|
+
// if (!address) return viewAsBoringDefault(obj)
|
|
15
|
+
const index = address.indexOf('mailto:');
|
|
16
|
+
address = index >= 0 ? address.slice(index + 7) : address;
|
|
17
|
+
anchor.setAttribute('href', 'mailto:' + address);
|
|
18
|
+
anchor.appendChild(dom.createTextNode(address));
|
|
19
|
+
return anchor;
|
|
20
|
+
};
|
|
21
|
+
exports.default = _default;
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _solidUi = require("solid-ui");
|
|
8
|
+
var _solidLogic = require("solid-logic");
|
|
9
|
+
var _rdflib = require("rdflib");
|
|
10
|
+
/* pad Pane
|
|
11
|
+
**
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const paneDef = {
|
|
15
|
+
// icon: (module.__dirname || __dirname) + 'images/ColourOn.png',
|
|
16
|
+
icon: _solidUi.icons.iconBase + 'noun_79217.svg',
|
|
17
|
+
name: 'pad',
|
|
18
|
+
audience: [_solidUi.ns.solid('PowerUser')],
|
|
19
|
+
// Does the subject deserve an pad pane?
|
|
20
|
+
label: function (subject, context) {
|
|
21
|
+
const t = context.session.store.findTypeURIs(subject);
|
|
22
|
+
if (t['http://www.w3.org/ns/pim/pad#Notepad']) {
|
|
23
|
+
return 'pad';
|
|
24
|
+
}
|
|
25
|
+
return null; // No under other circumstances
|
|
26
|
+
},
|
|
27
|
+
mintClass: _solidUi.ns.pad('Notepad'),
|
|
28
|
+
mintNew: function (context, newPaneOptions) {
|
|
29
|
+
const store = context.session.store;
|
|
30
|
+
const updater = store.updater;
|
|
31
|
+
if (newPaneOptions.me && !newPaneOptions.me.uri) {
|
|
32
|
+
throw new Error('notepad mintNew: Invalid userid');
|
|
33
|
+
}
|
|
34
|
+
const newInstance = newPaneOptions.newInstance = newPaneOptions.newInstance || store.sym(newPaneOptions.newBase + 'index.ttl#this');
|
|
35
|
+
// const newInstance = kb.sym(newBase + 'pad.ttl#thisPad');
|
|
36
|
+
const newPadDoc = newInstance.doc();
|
|
37
|
+
store.add(newInstance, _solidUi.ns.rdf('type'), _solidUi.ns.pad('Notepad'), newPadDoc);
|
|
38
|
+
store.add(newInstance, _solidUi.ns.dc('title'), 'Shared Notes', newPadDoc);
|
|
39
|
+
store.add(newInstance, _solidUi.ns.dc('created'), new Date(), newPadDoc); // @@ TODO Remove casting
|
|
40
|
+
if (newPaneOptions.me) {
|
|
41
|
+
store.add(newInstance, _solidUi.ns.dc('author'), newPaneOptions.me, newPadDoc);
|
|
42
|
+
}
|
|
43
|
+
// kb.add(newInstance, ns.pad('next'), newInstance, newPadDoc);
|
|
44
|
+
// linked list empty @@
|
|
45
|
+
const chunk = store.sym(newInstance.uri + '_line0');
|
|
46
|
+
store.add(newInstance, _solidUi.ns.pad('next'), chunk, newPadDoc); // Linked list has one entry
|
|
47
|
+
store.add(chunk, _solidUi.ns.pad('next'), newInstance, newPadDoc);
|
|
48
|
+
store.add(chunk, _solidUi.ns.dc('author'), newPaneOptions.me, newPadDoc);
|
|
49
|
+
store.add(chunk, _solidUi.ns.sioc('content'), '', newPadDoc);
|
|
50
|
+
return new Promise(function (resolve, reject) {
|
|
51
|
+
if (!updater) {
|
|
52
|
+
reject(new Error('Have no updater'));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
updater.put(newPadDoc, store.statementsMatching(undefined, undefined, undefined, newPadDoc), 'text/turtle', function (uri2, ok, message) {
|
|
56
|
+
if (ok) {
|
|
57
|
+
resolve(newPaneOptions);
|
|
58
|
+
} else {
|
|
59
|
+
reject(new Error('FAILED to save new tool at: ' + uri2 + ' : ' + message));
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
// and follow instructions there
|
|
65
|
+
// @@ TODO Set better type for paneOptions
|
|
66
|
+
render: function (subject, context, paneOptions) {
|
|
67
|
+
const dom = context.dom;
|
|
68
|
+
const store = context.session.store;
|
|
69
|
+
// Utility functions
|
|
70
|
+
const complainIfBad = function (ok, message) {
|
|
71
|
+
if (!ok) {
|
|
72
|
+
div.appendChild(_solidUi.widgets.errorMessageBlock(dom, message, 'pink'));
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const clearElement = function (ele) {
|
|
76
|
+
while (ele.firstChild) {
|
|
77
|
+
ele.removeChild(ele.firstChild);
|
|
78
|
+
}
|
|
79
|
+
return ele;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Access control
|
|
83
|
+
|
|
84
|
+
// Two constiations of ACL for this app, public read and public read/write
|
|
85
|
+
// In all cases owner has read write control
|
|
86
|
+
const genACLtext = function (docURI, aclURI, allWrite) {
|
|
87
|
+
const g = (0, _rdflib.graph)();
|
|
88
|
+
const auth = (0, _rdflib.Namespace)('http://www.w3.org/ns/auth/acl#');
|
|
89
|
+
let a = g.sym(aclURI + '#a1');
|
|
90
|
+
const acl = g.sym(aclURI);
|
|
91
|
+
const doc = g.sym(docURI);
|
|
92
|
+
g.add(a, _solidUi.ns.rdf('type'), auth('Authorization'), acl);
|
|
93
|
+
g.add(a, auth('accessTo'), doc, acl);
|
|
94
|
+
g.add(a, auth('agent'), me, acl);
|
|
95
|
+
g.add(a, auth('mode'), auth('Read'), acl);
|
|
96
|
+
g.add(a, auth('mode'), auth('Write'), acl);
|
|
97
|
+
g.add(a, auth('mode'), auth('Control'), acl);
|
|
98
|
+
a = g.sym(aclURI + '#a2');
|
|
99
|
+
g.add(a, _solidUi.ns.rdf('type'), auth('Authorization'), acl);
|
|
100
|
+
g.add(a, auth('accessTo'), doc, acl);
|
|
101
|
+
g.add(a, auth('agentClass'), _solidUi.ns.foaf('Agent'), acl);
|
|
102
|
+
g.add(a, auth('mode'), auth('Read'), acl);
|
|
103
|
+
if (allWrite) {
|
|
104
|
+
g.add(a, auth('mode'), auth('Write'), acl);
|
|
105
|
+
}
|
|
106
|
+
// TODO: Figure out why `serialize` isn't on the type definition according to TypeScript:
|
|
107
|
+
return (0, _rdflib.serialize)(acl, g, aclURI, 'text/turtle');
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @param docURI
|
|
112
|
+
* @param allWrite
|
|
113
|
+
* @param callbackFunction
|
|
114
|
+
*
|
|
115
|
+
* @returns {Promise<Response>}
|
|
116
|
+
*/
|
|
117
|
+
const setACL = function setACL(docURI, allWrite, callbackFunction) {
|
|
118
|
+
const aclDoc = store.any((0, _rdflib.sym)(docURI), (0, _rdflib.sym)('http://www.iana.org/assignments/link-relations/acl')); // @@ check that this get set by web.js
|
|
119
|
+
if (!fetcher) {
|
|
120
|
+
throw new Error('Have no fetcher');
|
|
121
|
+
}
|
|
122
|
+
if (aclDoc) {
|
|
123
|
+
// Great we already know where it is
|
|
124
|
+
const aclText = genACLtext(docURI, aclDoc.uri, allWrite);
|
|
125
|
+
return fetcher.webOperation('PUT', aclDoc.uri, {
|
|
126
|
+
data: aclText,
|
|
127
|
+
contentType: 'text/turtle'
|
|
128
|
+
}).then(() => callbackFunction(true)).catch(err => {
|
|
129
|
+
callbackFunction(false, err.message);
|
|
130
|
+
});
|
|
131
|
+
} else {
|
|
132
|
+
return fetcher.load(docURI).catch(err => {
|
|
133
|
+
callbackFunction(false, 'Getting headers for ACL: ' + err);
|
|
134
|
+
}).then(() => {
|
|
135
|
+
const aclDoc = store.any((0, _rdflib.sym)(docURI), (0, _rdflib.sym)('http://www.iana.org/assignments/link-relations/acl'));
|
|
136
|
+
if (!aclDoc) {
|
|
137
|
+
// complainIfBad(false, "No Link rel=ACL header for " + docURI);
|
|
138
|
+
throw new Error('No Link rel=ACL header for ' + docURI);
|
|
139
|
+
}
|
|
140
|
+
const aclText = genACLtext(docURI, aclDoc.uri, allWrite);
|
|
141
|
+
return fetcher.webOperation('PUT', aclDoc.uri, {
|
|
142
|
+
data: aclText,
|
|
143
|
+
contentType: 'text/turtle'
|
|
144
|
+
});
|
|
145
|
+
}).then(() => callbackFunction(true)).catch(err => {
|
|
146
|
+
callbackFunction(false, err.message);
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// Reproduction: spawn a new instance
|
|
152
|
+
//
|
|
153
|
+
// Viral growth path: user of app decides to make another instance
|
|
154
|
+
const newInstanceButton = function () {
|
|
155
|
+
const button = div.appendChild(dom.createElement('button'));
|
|
156
|
+
button.textContent = 'Start another pad';
|
|
157
|
+
button.addEventListener('click', function () {
|
|
158
|
+
return showBootstrap(subject, spawnArea, 'pad');
|
|
159
|
+
});
|
|
160
|
+
return button;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// Option of either using the workspace system or just typing in a URI
|
|
164
|
+
const showBootstrap = function showBootstrap(thisInstance, container, noun) {
|
|
165
|
+
const div = clearElement(container);
|
|
166
|
+
const appDetails = {
|
|
167
|
+
noun: 'notepad'
|
|
168
|
+
};
|
|
169
|
+
div.appendChild(_solidUi.login.newAppInstance(dom, appDetails, (workspace, newBase) => {
|
|
170
|
+
// FIXME: not sure if this will work at all, just
|
|
171
|
+
// trying to get the types to match - Michiel.
|
|
172
|
+
return initializeNewInstanceInWorkspace(new _rdflib.NamedNode(workspace || newBase));
|
|
173
|
+
}));
|
|
174
|
+
div.appendChild(dom.createElement('hr')); // @@
|
|
175
|
+
|
|
176
|
+
const p = div.appendChild(dom.createElement('p'));
|
|
177
|
+
p.textContent = 'Where would you like to store the data for the ' + noun + '? ' + 'Give the URL of the directory where you would like the data stored.';
|
|
178
|
+
const baseField = div.appendChild(dom.createElement('input'));
|
|
179
|
+
baseField.setAttribute('type', 'text');
|
|
180
|
+
baseField.size = 80 // really a string
|
|
181
|
+
;
|
|
182
|
+
baseField.label = 'base URL';
|
|
183
|
+
baseField.autocomplete = 'on';
|
|
184
|
+
div.appendChild(dom.createElement('br')); // @@
|
|
185
|
+
|
|
186
|
+
const button = div.appendChild(dom.createElement('button'));
|
|
187
|
+
button.textContent = 'Start new ' + noun + ' at this URI';
|
|
188
|
+
button.addEventListener('click', function (_e) {
|
|
189
|
+
let newBase = baseField.value;
|
|
190
|
+
if (newBase.slice(-1) !== '/') {
|
|
191
|
+
newBase += '/';
|
|
192
|
+
}
|
|
193
|
+
initializeNewInstanceAtBase(thisInstance, newBase);
|
|
194
|
+
});
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// Create new document files for new instance of app
|
|
198
|
+
const initializeNewInstanceInWorkspace = function (ws) {
|
|
199
|
+
// @@ TODO Clean up type for newBase
|
|
200
|
+
let newBase = store.any(ws, _solidUi.ns.space('uriPrefix'));
|
|
201
|
+
if (!newBase) {
|
|
202
|
+
newBase = ws.uri.split('#')[0];
|
|
203
|
+
} else {
|
|
204
|
+
newBase = newBase.value;
|
|
205
|
+
}
|
|
206
|
+
if (newBase.slice(-1) !== '/') {
|
|
207
|
+
_rdflib.log.error(appPathSegment + ': No / at end of uriPrefix ' + newBase); // @@ paramater?
|
|
208
|
+
newBase = newBase + '/';
|
|
209
|
+
}
|
|
210
|
+
const now = new Date();
|
|
211
|
+
newBase += appPathSegment + '/id' + now.getTime() + '/'; // unique id
|
|
212
|
+
|
|
213
|
+
initializeNewInstanceAtBase(thisInstance, newBase);
|
|
214
|
+
};
|
|
215
|
+
const initializeNewInstanceAtBase = function (thisInstance, newBase) {
|
|
216
|
+
const here = (0, _rdflib.sym)(thisInstance.uri.split('#')[0]);
|
|
217
|
+
const base = here; // @@ ???
|
|
218
|
+
|
|
219
|
+
const newPadDoc = store.sym(newBase + 'pad.ttl');
|
|
220
|
+
const newIndexDoc = store.sym(newBase + 'index.html');
|
|
221
|
+
const toBeCopied = [{
|
|
222
|
+
local: 'index.html',
|
|
223
|
+
contentType: 'text/html'
|
|
224
|
+
}];
|
|
225
|
+
const newInstance = store.sym(newPadDoc.uri + '#thisPad');
|
|
226
|
+
|
|
227
|
+
// log.debug("\n Ready to put " + kb.statementsMatching(undefined, undefined, undefined, there)); //@@
|
|
228
|
+
|
|
229
|
+
const agenda = [];
|
|
230
|
+
let f; // @@ This needs some form of visible progress bar
|
|
231
|
+
for (f = 0; f < toBeCopied.length; f++) {
|
|
232
|
+
const item = toBeCopied[f];
|
|
233
|
+
const fun = function copyItem(item) {
|
|
234
|
+
agenda.push(function () {
|
|
235
|
+
const newURI = newBase + item.local;
|
|
236
|
+
console.log('Copying ' + base + item.local + ' to ' + newURI);
|
|
237
|
+
const setThatACL = function () {
|
|
238
|
+
setACL(newURI, false, function (ok, message) {
|
|
239
|
+
if (!ok) {
|
|
240
|
+
complainIfBad(ok, 'FAILED to set ACL ' + newURI + ' : ' + message);
|
|
241
|
+
console.log('FAILED to set ACL ' + newURI + ' : ' + message);
|
|
242
|
+
} else {
|
|
243
|
+
agenda.shift()(); // beware too much nesting
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
};
|
|
247
|
+
if (!store.fetcher) {
|
|
248
|
+
throw new Error('Store has no fetcher');
|
|
249
|
+
}
|
|
250
|
+
store.fetcher.webCopy(base + item.local, newBase + item.local, item.contentType).then(() => _solidLogic.authn.checkUser()).then(webId => {
|
|
251
|
+
me = webId;
|
|
252
|
+
setThatACL();
|
|
253
|
+
}).catch(err => {
|
|
254
|
+
console.log('FAILED to copy ' + base + item.local + ' : ' + err.message);
|
|
255
|
+
complainIfBad(false, 'FAILED to copy ' + base + item.local + ' : ' + err.message);
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
};
|
|
259
|
+
fun(item);
|
|
260
|
+
}
|
|
261
|
+
agenda.push(function createNewPadDataFile() {
|
|
262
|
+
store.add(newInstance, _solidUi.ns.rdf('type'), PAD('Notepad'), newPadDoc);
|
|
263
|
+
|
|
264
|
+
// TODO @@ Remove casting of add
|
|
265
|
+
store.add(newInstance, _solidUi.ns.dc('created'), new Date(),
|
|
266
|
+
// @@ TODO Remove casting
|
|
267
|
+
newPadDoc);
|
|
268
|
+
if (me) {
|
|
269
|
+
store.add(newInstance, _solidUi.ns.dc('author'), me, newPadDoc);
|
|
270
|
+
}
|
|
271
|
+
store.add(newInstance, PAD('next'), newInstance, newPadDoc); // linked list empty
|
|
272
|
+
|
|
273
|
+
// Keep a paper trail @@ Revisit when we have non-public ones @@ Privacy
|
|
274
|
+
store.add(newInstance, _solidUi.ns.space('inspiration'), thisInstance, padDoc);
|
|
275
|
+
store.add(newInstance, _solidUi.ns.space('inspiration'), thisInstance, newPadDoc);
|
|
276
|
+
if (!updater) {
|
|
277
|
+
throw new Error('Have no updater');
|
|
278
|
+
}
|
|
279
|
+
updater.put(newPadDoc, store.statementsMatching(undefined, undefined, undefined, newPadDoc), 'text/turtle', function (_uri2, ok, message) {
|
|
280
|
+
if (ok) {
|
|
281
|
+
agenda.shift()();
|
|
282
|
+
} else {
|
|
283
|
+
complainIfBad(ok, 'FAILED to save new notepad at: ' + newPadDoc.uri + ' : ' + message);
|
|
284
|
+
console.log('FAILED to save new notepad at: ' + newPadDoc.uri + ' : ' + message);
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
agenda.push(function () {
|
|
289
|
+
setACL(newPadDoc.uri, true, function (ok, body) {
|
|
290
|
+
complainIfBad(ok, 'Failed to set Read-Write ACL on pad data file: ' + body);
|
|
291
|
+
if (ok) agenda.shift()();
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
agenda.push(function () {
|
|
295
|
+
// give the user links to the new app
|
|
296
|
+
|
|
297
|
+
const p = div.appendChild(dom.createElement('p'));
|
|
298
|
+
p.setAttribute('style', 'font-size: 140%;');
|
|
299
|
+
p.innerHTML = 'Your <a href=\'' + newIndexDoc.uri + '\'><b>new notepad</b></a> is ready. ' + '<br/><br/><a href=\'' + newIndexDoc.uri + '\'>Go to new pad</a>';
|
|
300
|
+
});
|
|
301
|
+
agenda.shift()();
|
|
302
|
+
// Created new data files.
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
// Update on incoming changes
|
|
306
|
+
const showResults = function (exists) {
|
|
307
|
+
console.log('showResults()');
|
|
308
|
+
me = _solidLogic.authn.currentUser();
|
|
309
|
+
_solidLogic.authn.checkUser().then(webId => {
|
|
310
|
+
me = webId;
|
|
311
|
+
});
|
|
312
|
+
const title = store.any(subject, _solidUi.ns.dc('title')) || store.any(subject, _solidUi.ns.vcard('fn'));
|
|
313
|
+
if (paneOptions.solo && typeof window !== 'undefined' && title) {
|
|
314
|
+
window.document.title = title.value;
|
|
315
|
+
}
|
|
316
|
+
options.exists = exists;
|
|
317
|
+
padEle = _solidUi.pad.notepad(dom, padDoc, subject, me, options);
|
|
318
|
+
naviMain.appendChild(padEle);
|
|
319
|
+
const partipationTarget = store.any(subject, _solidUi.ns.meeting('parentMeeting')) || subject;
|
|
320
|
+
_solidUi.pad.manageParticipation(dom, naviMiddle2, padDoc, partipationTarget, me, options);
|
|
321
|
+
if (!store.updater) {
|
|
322
|
+
throw new Error('Store has no updater');
|
|
323
|
+
}
|
|
324
|
+
store.updater.setRefreshHandler(padDoc, padEle.reloadAndSync); // initiated =
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
// Read or create empty data file
|
|
328
|
+
const loadPadData = function () {
|
|
329
|
+
if (!fetcher) {
|
|
330
|
+
throw new Error('Have no fetcher');
|
|
331
|
+
}
|
|
332
|
+
fetcher.nowOrWhenFetched(padDoc.uri, undefined, function (ok, body, response) {
|
|
333
|
+
if (!ok) {
|
|
334
|
+
if (response.status === 404) {
|
|
335
|
+
// / Check explicitly for 404 error
|
|
336
|
+
console.log('Initializing results file ' + padDoc);
|
|
337
|
+
if (!updater) {
|
|
338
|
+
throw new Error('Have no updater');
|
|
339
|
+
}
|
|
340
|
+
updater.put(padDoc, [], 'text/turtle', function (_uri2, ok, message) {
|
|
341
|
+
if (ok) {
|
|
342
|
+
clearElement(naviMain);
|
|
343
|
+
showResults(false);
|
|
344
|
+
} else {
|
|
345
|
+
complainIfBad(ok, 'FAILED to create results file at: ' + padDoc.uri + ' : ' + message);
|
|
346
|
+
console.log('FAILED to craete results file at: ' + padDoc.uri + ' : ' + message);
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
} else {
|
|
350
|
+
// Other error, not 404 -- do not try to overwite the file
|
|
351
|
+
complainIfBad(ok, 'FAILED to read results file: ' + body);
|
|
352
|
+
}
|
|
353
|
+
} else {
|
|
354
|
+
// Happy read
|
|
355
|
+
clearElement(naviMain);
|
|
356
|
+
if (store.holds(subject, _solidUi.ns.rdf('type'), _solidUi.ns.wf('TemplateInstance'))) {
|
|
357
|
+
showBootstrap(subject, naviMain, 'pad');
|
|
358
|
+
}
|
|
359
|
+
showResults(true);
|
|
360
|
+
naviMiddle3.appendChild(newInstanceButton());
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
// Body of Pane
|
|
366
|
+
const appPathSegment = 'app-pad.timbl.com'; // how to allocate this string and connect to
|
|
367
|
+
|
|
368
|
+
const fetcher = store.fetcher;
|
|
369
|
+
const updater = store.updater;
|
|
370
|
+
let me;
|
|
371
|
+
const PAD = (0, _rdflib.Namespace)('http://www.w3.org/ns/pim/pad#');
|
|
372
|
+
const thisInstance = subject;
|
|
373
|
+
const padDoc = subject.doc();
|
|
374
|
+
let padEle;
|
|
375
|
+
const div = dom.createElement('div');
|
|
376
|
+
|
|
377
|
+
// Build the DOM
|
|
378
|
+
const structure = div.appendChild(dom.createElement('table')); // @@ make responsive style
|
|
379
|
+
structure.setAttribute('style', 'background-color: white; min-width: 94%; margin-right:3% margin-left: 3%; min-height: 13em;');
|
|
380
|
+
const naviLoginoutTR = structure.appendChild(dom.createElement('tr'));
|
|
381
|
+
naviLoginoutTR.appendChild(dom.createElement('td')); // naviLoginout1
|
|
382
|
+
naviLoginoutTR.appendChild(dom.createElement('td'));
|
|
383
|
+
naviLoginoutTR.appendChild(dom.createElement('td'));
|
|
384
|
+
const naviTop = structure.appendChild(dom.createElement('tr')); // stuff
|
|
385
|
+
const naviMain = naviTop.appendChild(dom.createElement('td'));
|
|
386
|
+
naviMain.setAttribute('colspan', '3');
|
|
387
|
+
const naviMiddle = structure.appendChild(dom.createElement('tr')); // controls
|
|
388
|
+
const naviMiddle1 = naviMiddle.appendChild(dom.createElement('td'));
|
|
389
|
+
const naviMiddle2 = naviMiddle.appendChild(dom.createElement('td'));
|
|
390
|
+
const naviMiddle3 = naviMiddle.appendChild(dom.createElement('td'));
|
|
391
|
+
const naviStatus = structure.appendChild(dom.createElement('tr')); // status etc
|
|
392
|
+
const statusArea = naviStatus.appendChild(dom.createElement('div'));
|
|
393
|
+
const naviSpawn = structure.appendChild(dom.createElement('tr')); // create new
|
|
394
|
+
const spawnArea = naviSpawn.appendChild(dom.createElement('div'));
|
|
395
|
+
const naviMenu = structure.appendChild(dom.createElement('tr'));
|
|
396
|
+
naviMenu.setAttribute('class', 'naviMenu');
|
|
397
|
+
// naviMenu.setAttribute('style', 'margin-top: 3em;');
|
|
398
|
+
naviMenu.appendChild(dom.createElement('td')); // naviLeft
|
|
399
|
+
naviMenu.appendChild(dom.createElement('td'));
|
|
400
|
+
naviMenu.appendChild(dom.createElement('td'));
|
|
401
|
+
const options = {
|
|
402
|
+
statusArea,
|
|
403
|
+
timingArea: naviMiddle1
|
|
404
|
+
};
|
|
405
|
+
loadPadData();
|
|
406
|
+
return div;
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
// ends
|
|
410
|
+
var _default = exports.default = paneDef;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _solidUi = require("solid-ui");
|
|
8
|
+
/* Sharing Pane
|
|
9
|
+
**
|
|
10
|
+
** This outline pane allows a user to view and adjust the sharing -- access control lists
|
|
11
|
+
** for anything which has that capability.
|
|
12
|
+
**
|
|
13
|
+
** I am using in places single quotes strings like 'this'
|
|
14
|
+
** where internationalization ("i18n") is not a problem, and double quoted
|
|
15
|
+
** like "this" where the string is seen by the user and so I18n is an issue.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const sharingPane = {
|
|
19
|
+
icon: _solidUi.icons.iconBase + 'padlock-timbl.svg',
|
|
20
|
+
name: 'sharing',
|
|
21
|
+
label: (subject, context) => {
|
|
22
|
+
const store = context.session.store;
|
|
23
|
+
const t = store.findTypeURIs(subject);
|
|
24
|
+
if (t[_solidUi.ns.ldp('Resource').uri]) return 'Sharing'; // @@ be more sophisticated?
|
|
25
|
+
if (t[_solidUi.ns.ldp('Container').uri]) return 'Sharing'; // @@ be more sophisticated?
|
|
26
|
+
if (t[_solidUi.ns.ldp('BasicContainer').uri]) return 'Sharing'; // @@ be more sophisticated?
|
|
27
|
+
// check being allowed to see/change sharing?
|
|
28
|
+
return null; // No under other circumstances
|
|
29
|
+
},
|
|
30
|
+
render: (subject, context) => {
|
|
31
|
+
const dom = context.dom;
|
|
32
|
+
const store = context.session.store;
|
|
33
|
+
const noun = getNoun();
|
|
34
|
+
const div = dom.createElement('div');
|
|
35
|
+
div.classList.add('sharingPane');
|
|
36
|
+
_solidUi.aclControl.preventBrowserDropEvents(dom);
|
|
37
|
+
div.appendChild(_solidUi.aclControl.ACLControlBox5(subject, context, noun, store));
|
|
38
|
+
return div;
|
|
39
|
+
function getNoun() {
|
|
40
|
+
const t = store.findTypeURIs(subject);
|
|
41
|
+
if (t[_solidUi.ns.ldp('BasicContainer').uri] || t[_solidUi.ns.ldp('Container').uri]) {
|
|
42
|
+
return 'folder';
|
|
43
|
+
}
|
|
44
|
+
return 'file';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var _default = exports.default = sharingPane;
|