solid-ui 2.6.1-e5ad2945 → 2.6.1-e78cbe5

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.
Files changed (369) hide show
  1. package/LICENSE.md +3 -1
  2. package/README.md +85 -26
  3. package/dist/acl/access-controller.js +238 -0
  4. package/dist/acl/access-controller.js.map +1 -0
  5. package/{lib → dist}/acl/access-groups.d.ts +2 -2
  6. package/{lib → dist}/acl/access-groups.d.ts.map +1 -1
  7. package/dist/acl/access-groups.js +323 -0
  8. package/dist/acl/access-groups.js.map +1 -0
  9. package/dist/acl/acl-control.js +173 -0
  10. package/dist/acl/acl-control.js.map +1 -0
  11. package/dist/acl/acl.js +495 -0
  12. package/dist/acl/acl.js.map +1 -0
  13. package/dist/acl/add-agent-buttons.js +217 -0
  14. package/dist/acl/add-agent-buttons.js.map +1 -0
  15. package/dist/acl/index.js +32 -0
  16. package/dist/acl/index.js.map +1 -0
  17. package/dist/acl/types.js +6 -0
  18. package/dist/acl/types.js.map +1 -0
  19. package/dist/chat/keys.js +106 -0
  20. package/dist/chat/keys.js.map +1 -0
  21. package/dist/chat/signature.js +63 -0
  22. package/dist/chat/signature.js.map +1 -0
  23. package/dist/create/create.js +249 -0
  24. package/dist/create/create.js.map +1 -0
  25. package/dist/create/index.js +5 -0
  26. package/dist/create/index.js.map +1 -0
  27. package/dist/create/types.js +2 -0
  28. package/dist/create/types.js.map +1 -0
  29. package/dist/debug.d.ts.map +1 -0
  30. package/dist/debug.js +13 -0
  31. package/dist/debug.js.map +1 -0
  32. package/dist/footer/index.js +67 -0
  33. package/dist/footer/index.js.map +1 -0
  34. package/dist/header/empty-profile.js +11 -0
  35. package/dist/header/empty-profile.js.map +1 -0
  36. package/dist/header/index.js +260 -0
  37. package/dist/header/index.js.map +1 -0
  38. package/dist/iconBase.js +37 -0
  39. package/dist/iconBase.js.map +1 -0
  40. package/dist/icons/solid_logo.js.map +1 -0
  41. package/{lib → dist}/index.d.ts +7 -9
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +102 -0
  44. package/dist/index.js.map +1 -0
  45. package/{lib → dist}/log.d.ts.map +1 -1
  46. package/dist/log.js +182 -0
  47. package/dist/log.js.map +1 -0
  48. package/dist/login/login.js +858 -0
  49. package/dist/login/login.js.map +1 -0
  50. package/dist/matrix/index.js +5 -0
  51. package/dist/matrix/index.js.map +1 -0
  52. package/dist/matrix/matrix.js +217 -0
  53. package/dist/matrix/matrix.js.map +1 -0
  54. package/dist/matrix/types.js +2 -0
  55. package/dist/matrix/types.js.map +1 -0
  56. package/dist/media/index.js +6 -0
  57. package/dist/media/index.js.map +1 -0
  58. package/dist/media/media-capture.js +161 -0
  59. package/dist/media/media-capture.js.map +1 -0
  60. package/dist/pad.js +775 -0
  61. package/dist/pad.js.map +1 -0
  62. package/{lib → dist}/participation.d.ts.map +1 -1
  63. package/dist/participation.js +184 -0
  64. package/dist/participation.js.map +1 -0
  65. package/dist/solid-ui.esm.js +25531 -0
  66. package/dist/solid-ui.esm.js.map +1 -0
  67. package/dist/solid-ui.esm.min.js +43 -0
  68. package/dist/solid-ui.esm.min.js.map +1 -0
  69. package/dist/solid-ui.js +23479 -68931
  70. package/dist/solid-ui.js.map +1 -1
  71. package/dist/solid-ui.min.js +40 -2
  72. package/dist/solid-ui.min.js.map +1 -1
  73. package/dist/tabs.js +388 -0
  74. package/dist/tabs.js.map +1 -0
  75. package/{lib → dist}/utils/headerFooterHelpers.d.ts.map +1 -1
  76. package/dist/utils/headerFooterHelpers.js +114 -0
  77. package/dist/utils/headerFooterHelpers.js.map +1 -0
  78. package/dist/utils/keyHelpers/accessData.js +64 -0
  79. package/dist/utils/keyHelpers/accessData.js.map +1 -0
  80. package/dist/utils/keyHelpers/acl.js +74 -0
  81. package/dist/utils/keyHelpers/acl.js.map +1 -0
  82. package/dist/utils/keyHelpers/otherHelpers.js +13 -0
  83. package/dist/utils/keyHelpers/otherHelpers.js.map +1 -0
  84. package/dist/utils/label.js +111 -0
  85. package/dist/utils/label.js.map +1 -0
  86. package/dist/versionInfo.js +31 -0
  87. package/dist/versionInfo.js.map +1 -0
  88. package/dist/widgets/buttons/iconLinks.js +44 -0
  89. package/dist/widgets/buttons/iconLinks.js.map +1 -0
  90. package/dist/widgets/buttons.js +1280 -0
  91. package/dist/widgets/buttons.js.map +1 -0
  92. package/dist/widgets/error.d.ts +14 -0
  93. package/dist/widgets/error.d.ts.map +1 -0
  94. package/dist/widgets/error.js +35 -0
  95. package/dist/widgets/error.js.map +1 -0
  96. package/dist/widgets/forms/autocomplete/autocompleteBar.js +123 -0
  97. package/dist/widgets/forms/autocomplete/autocompleteBar.js.map +1 -0
  98. package/dist/widgets/forms/autocomplete/autocompleteField.js +199 -0
  99. package/dist/widgets/forms/autocomplete/autocompleteField.js.map +1 -0
  100. package/dist/widgets/forms/autocomplete/autocompletePicker.js +256 -0
  101. package/dist/widgets/forms/autocomplete/autocompletePicker.js.map +1 -0
  102. package/dist/widgets/forms/autocomplete/language.js +104 -0
  103. package/dist/widgets/forms/autocomplete/language.js.map +1 -0
  104. package/dist/widgets/forms/autocomplete/publicData.js +460 -0
  105. package/dist/widgets/forms/autocomplete/publicData.js.map +1 -0
  106. package/dist/widgets/forms/basic.js +241 -0
  107. package/dist/widgets/forms/basic.js.map +1 -0
  108. package/dist/widgets/forms/comment.js +46 -0
  109. package/dist/widgets/forms/comment.js.map +1 -0
  110. package/dist/widgets/forms/fieldFunction.js +44 -0
  111. package/dist/widgets/forms/fieldFunction.js.map +1 -0
  112. package/dist/widgets/forms/fieldParams.js +89 -0
  113. package/dist/widgets/forms/fieldParams.js.map +1 -0
  114. package/{lib → dist}/widgets/forms/formStyle.d.ts.map +1 -1
  115. package/dist/widgets/forms/formStyle.js +36 -0
  116. package/dist/widgets/forms/formStyle.js.map +1 -0
  117. package/{lib → dist}/widgets/widgetHelpers.d.ts.map +1 -1
  118. package/{lib → dist}/widgets/widgetHelpers.js +14 -25
  119. package/dist/widgets/widgetHelpers.js.map +1 -0
  120. package/package.json +48 -52
  121. package/dist/789.solid-ui.min.js +0 -1
  122. package/dist/841.solid-ui.min.js +0 -3
  123. package/dist/841.solid-ui.min.js.LICENSE.txt +0 -58
  124. package/dist/841.solid-ui.min.js.map +0 -1
  125. package/dist/_2b19.solid-ui.js +0 -14
  126. package/dist/_2b19.solid-ui.js.map +0 -1
  127. package/dist/index.html +0 -1
  128. package/dist/solid-ui.min.js.LICENSE.txt +0 -57
  129. package/dist/vendors-node_modules_jsonld_lib_jsonld_js.solid-ui.js +0 -12247
  130. package/dist/vendors-node_modules_jsonld_lib_jsonld_js.solid-ui.js.map +0 -1
  131. package/lib/acl/access-controller.js +0 -391
  132. package/lib/acl/access-controller.js.map +0 -1
  133. package/lib/acl/access-groups.js +0 -507
  134. package/lib/acl/access-groups.js.map +0 -1
  135. package/lib/acl/acl-control.js +0 -237
  136. package/lib/acl/acl-control.js.map +0 -1
  137. package/lib/acl/acl.js +0 -517
  138. package/lib/acl/acl.js.map +0 -1
  139. package/lib/acl/add-agent-buttons.js +0 -434
  140. package/lib/acl/add-agent-buttons.js.map +0 -1
  141. package/lib/acl/index.js +0 -39
  142. package/lib/acl/index.js.map +0 -1
  143. package/lib/acl/types.js +0 -6
  144. package/lib/acl/types.js.map +0 -1
  145. package/lib/chat/bookmarks.js +0 -303
  146. package/lib/chat/bookmarks.js.map +0 -1
  147. package/lib/chat/chatLogic.js +0 -420
  148. package/lib/chat/chatLogic.js.map +0 -1
  149. package/lib/chat/dateFolder.js +0 -328
  150. package/lib/chat/dateFolder.js.map +0 -1
  151. package/lib/chat/infinite.js +0 -994
  152. package/lib/chat/infinite.js.map +0 -1
  153. package/lib/chat/keys.js +0 -232
  154. package/lib/chat/keys.js.map +0 -1
  155. package/lib/chat/message.js +0 -715
  156. package/lib/chat/message.js.map +0 -1
  157. package/lib/chat/messageTools.js +0 -538
  158. package/lib/chat/messageTools.js.map +0 -1
  159. package/lib/chat/signature.js +0 -109
  160. package/lib/chat/signature.js.map +0 -1
  161. package/lib/chat/thread.js +0 -535
  162. package/lib/chat/thread.js.map +0 -1
  163. package/lib/create/create.js +0 -242
  164. package/lib/create/create.js.map +0 -1
  165. package/lib/create/index.js +0 -11
  166. package/lib/create/index.js.map +0 -1
  167. package/lib/create/types.js +0 -6
  168. package/lib/create/types.js.map +0 -1
  169. package/lib/debug.d.ts.map +0 -1
  170. package/lib/debug.js +0 -30
  171. package/lib/debug.js.map +0 -1
  172. package/lib/folders.js +0 -132
  173. package/lib/folders.js.map +0 -1
  174. package/lib/footer/index.js +0 -123
  175. package/lib/footer/index.js.map +0 -1
  176. package/lib/header/empty-profile.js +0 -8
  177. package/lib/header/empty-profile.js.map +0 -1
  178. package/lib/header/index.js +0 -375
  179. package/lib/header/index.js.map +0 -1
  180. package/lib/iconBase.js +0 -44
  181. package/lib/iconBase.js.map +0 -1
  182. package/lib/icons/solid_logo.js.map +0 -1
  183. package/lib/index.d.ts.map +0 -1
  184. package/lib/index.js +0 -223
  185. package/lib/index.js.map +0 -1
  186. package/lib/log.js +0 -213
  187. package/lib/log.js.map +0 -1
  188. package/lib/login/login.js +0 -1241
  189. package/lib/login/login.js.map +0 -1
  190. package/lib/matrix/index.js +0 -11
  191. package/lib/matrix/index.js.map +0 -1
  192. package/lib/matrix/matrix.js +0 -216
  193. package/lib/matrix/matrix.js.map +0 -1
  194. package/lib/matrix/types.js +0 -6
  195. package/lib/matrix/types.js.map +0 -1
  196. package/lib/media/index.js +0 -12
  197. package/lib/media/index.js.map +0 -1
  198. package/lib/media/media-capture.js +0 -194
  199. package/lib/media/media-capture.js.map +0 -1
  200. package/lib/messageArea.js +0 -319
  201. package/lib/messageArea.js.map +0 -1
  202. package/lib/noun_Camera_1618446_000000.js +0 -8
  203. package/lib/noun_Camera_1618446_000000.js.map +0 -1
  204. package/lib/ns.js +0 -17
  205. package/lib/ns.js.map +0 -1
  206. package/lib/pad.js +0 -805
  207. package/lib/pad.js.map +0 -1
  208. package/lib/participation.js +0 -219
  209. package/lib/participation.js.map +0 -1
  210. package/lib/preferences.js +0 -215
  211. package/lib/preferences.js.map +0 -1
  212. package/lib/signup/config-default.js +0 -43
  213. package/lib/signup/config-default.js.map +0 -1
  214. package/lib/signup/signup.js +0 -74
  215. package/lib/signup/signup.js.map +0 -1
  216. package/lib/stories/decorators.js +0 -10
  217. package/lib/stories/decorators.js.map +0 -1
  218. package/lib/style.js +0 -158
  219. package/lib/style.js.map +0 -1
  220. package/lib/styleConstants.js +0 -35
  221. package/lib/styleConstants.js.map +0 -1
  222. package/lib/style_multiSelect.js +0 -62
  223. package/lib/style_multiSelect.js.map +0 -1
  224. package/lib/table.js +0 -1573
  225. package/lib/table.js.map +0 -1
  226. package/lib/tabs.js +0 -448
  227. package/lib/tabs.js.map +0 -1
  228. package/lib/typings.d.js +0 -2
  229. package/lib/typings.d.js.map +0 -1
  230. package/lib/utils/headerFooterHelpers.js +0 -165
  231. package/lib/utils/headerFooterHelpers.js.map +0 -1
  232. package/lib/utils/index.js +0 -527
  233. package/lib/utils/index.js.map +0 -1
  234. package/lib/utils/keyHelpers/accessData.js +0 -131
  235. package/lib/utils/keyHelpers/accessData.js.map +0 -1
  236. package/lib/utils/keyHelpers/acl.js +0 -90
  237. package/lib/utils/keyHelpers/acl.js.map +0 -1
  238. package/lib/utils/keyHelpers/otherHelpers.js +0 -21
  239. package/lib/utils/keyHelpers/otherHelpers.js.map +0 -1
  240. package/lib/utils/label.js +0 -103
  241. package/lib/utils/label.js.map +0 -1
  242. package/lib/versionInfo.d.ts +0 -32
  243. package/lib/versionInfo.d.ts.map +0 -1
  244. package/lib/versionInfo.js +0 -37
  245. package/lib/versionInfo.js.map +0 -1
  246. package/lib/widgets/buttons/iconLinks.js +0 -53
  247. package/lib/widgets/buttons/iconLinks.js.map +0 -1
  248. package/lib/widgets/buttons.js +0 -1306
  249. package/lib/widgets/buttons.js.map +0 -1
  250. package/lib/widgets/dragAndDrop.js +0 -194
  251. package/lib/widgets/dragAndDrop.js.map +0 -1
  252. package/lib/widgets/error.d.ts +0 -2
  253. package/lib/widgets/error.d.ts.map +0 -1
  254. package/lib/widgets/error.js +0 -46
  255. package/lib/widgets/error.js.map +0 -1
  256. package/lib/widgets/forms/autocomplete/autocompleteBar.js +0 -271
  257. package/lib/widgets/forms/autocomplete/autocompleteBar.js.map +0 -1
  258. package/lib/widgets/forms/autocomplete/autocompleteField.js +0 -258
  259. package/lib/widgets/forms/autocomplete/autocompleteField.js.map +0 -1
  260. package/lib/widgets/forms/autocomplete/autocompletePicker.js +0 -436
  261. package/lib/widgets/forms/autocomplete/autocompletePicker.js.map +0 -1
  262. package/lib/widgets/forms/autocomplete/language.js +0 -189
  263. package/lib/widgets/forms/autocomplete/language.js.map +0 -1
  264. package/lib/widgets/forms/autocomplete/publicData.js +0 -636
  265. package/lib/widgets/forms/autocomplete/publicData.js.map +0 -1
  266. package/lib/widgets/forms/basic.js +0 -254
  267. package/lib/widgets/forms/basic.js.map +0 -1
  268. package/lib/widgets/forms/comment.js +0 -54
  269. package/lib/widgets/forms/comment.js.map +0 -1
  270. package/lib/widgets/forms/fieldFunction.js +0 -52
  271. package/lib/widgets/forms/fieldFunction.js.map +0 -1
  272. package/lib/widgets/forms/fieldParams.js +0 -77
  273. package/lib/widgets/forms/fieldParams.js.map +0 -1
  274. package/lib/widgets/forms/formStyle.js +0 -44
  275. package/lib/widgets/forms/formStyle.js.map +0 -1
  276. package/lib/widgets/forms.js +0 -2045
  277. package/lib/widgets/forms.js.map +0 -1
  278. package/lib/widgets/index.js +0 -110
  279. package/lib/widgets/index.js.map +0 -1
  280. package/lib/widgets/multiSelect.js +0 -658
  281. package/lib/widgets/multiSelect.js.map +0 -1
  282. package/lib/widgets/peoplePicker.js +0 -467
  283. package/lib/widgets/peoplePicker.js.map +0 -1
  284. package/lib/widgets/widgetHelpers.js.map +0 -1
  285. /package/{lib → dist}/acl/access-controller.d.ts +0 -0
  286. /package/{lib → dist}/acl/access-controller.d.ts.map +0 -0
  287. /package/{lib → dist}/acl/acl-control.d.ts +0 -0
  288. /package/{lib → dist}/acl/acl-control.d.ts.map +0 -0
  289. /package/{lib → dist}/acl/acl.d.ts +0 -0
  290. /package/{lib → dist}/acl/acl.d.ts.map +0 -0
  291. /package/{lib → dist}/acl/add-agent-buttons.d.ts +0 -0
  292. /package/{lib → dist}/acl/add-agent-buttons.d.ts.map +0 -0
  293. /package/{lib → dist}/acl/index.d.ts +0 -0
  294. /package/{lib → dist}/acl/index.d.ts.map +0 -0
  295. /package/{lib → dist}/acl/types.d.ts +0 -0
  296. /package/{lib → dist}/acl/types.d.ts.map +0 -0
  297. /package/{lib → dist}/chat/keys.d.ts +0 -0
  298. /package/{lib → dist}/chat/keys.d.ts.map +0 -0
  299. /package/{lib → dist}/chat/signature.d.ts +0 -0
  300. /package/{lib → dist}/chat/signature.d.ts.map +0 -0
  301. /package/{lib → dist}/create/create.d.ts +0 -0
  302. /package/{lib → dist}/create/create.d.ts.map +0 -0
  303. /package/{lib → dist}/create/index.d.ts +0 -0
  304. /package/{lib → dist}/create/index.d.ts.map +0 -0
  305. /package/{lib → dist}/create/types.d.ts +0 -0
  306. /package/{lib → dist}/create/types.d.ts.map +0 -0
  307. /package/{lib → dist}/debug.d.ts +0 -0
  308. /package/{lib → dist}/footer/index.d.ts +0 -0
  309. /package/{lib → dist}/footer/index.d.ts.map +0 -0
  310. /package/{lib → dist}/header/empty-profile.d.ts +0 -0
  311. /package/{lib → dist}/header/empty-profile.d.ts.map +0 -0
  312. /package/{lib → dist}/header/index.d.ts +0 -0
  313. /package/{lib → dist}/header/index.d.ts.map +0 -0
  314. /package/{lib → dist}/iconBase.d.ts +0 -0
  315. /package/{lib → dist}/iconBase.d.ts.map +0 -0
  316. /package/{lib → dist}/icons/solid_logo.d.ts +0 -0
  317. /package/{lib → dist}/icons/solid_logo.d.ts.map +0 -0
  318. /package/{lib → dist}/icons/solid_logo.js +0 -0
  319. /package/{lib → dist}/log.d.ts +0 -0
  320. /package/{lib → dist}/login/login.d.ts +0 -0
  321. /package/{lib → dist}/login/login.d.ts.map +0 -0
  322. /package/{lib → dist}/matrix/index.d.ts +0 -0
  323. /package/{lib → dist}/matrix/index.d.ts.map +0 -0
  324. /package/{lib → dist}/matrix/matrix.d.ts +0 -0
  325. /package/{lib → dist}/matrix/matrix.d.ts.map +0 -0
  326. /package/{lib → dist}/matrix/types.d.ts +0 -0
  327. /package/{lib → dist}/matrix/types.d.ts.map +0 -0
  328. /package/{lib → dist}/media/index.d.ts +0 -0
  329. /package/{lib → dist}/media/index.d.ts.map +0 -0
  330. /package/{lib → dist}/media/media-capture.d.ts +0 -0
  331. /package/{lib → dist}/media/media-capture.d.ts.map +0 -0
  332. /package/{lib → dist}/pad.d.ts +0 -0
  333. /package/{lib → dist}/pad.d.ts.map +0 -0
  334. /package/{lib → dist}/participation.d.ts +0 -0
  335. /package/{lib → dist}/tabs.d.ts +0 -0
  336. /package/{lib → dist}/tabs.d.ts.map +0 -0
  337. /package/{lib → dist}/utils/headerFooterHelpers.d.ts +0 -0
  338. /package/{lib → dist}/utils/keyHelpers/accessData.d.ts +0 -0
  339. /package/{lib → dist}/utils/keyHelpers/accessData.d.ts.map +0 -0
  340. /package/{lib → dist}/utils/keyHelpers/acl.d.ts +0 -0
  341. /package/{lib → dist}/utils/keyHelpers/acl.d.ts.map +0 -0
  342. /package/{lib → dist}/utils/keyHelpers/otherHelpers.d.ts +0 -0
  343. /package/{lib → dist}/utils/keyHelpers/otherHelpers.d.ts.map +0 -0
  344. /package/{lib → dist}/utils/label.d.ts +0 -0
  345. /package/{lib → dist}/utils/label.d.ts.map +0 -0
  346. /package/{lib → dist}/widgets/buttons/iconLinks.d.ts +0 -0
  347. /package/{lib → dist}/widgets/buttons/iconLinks.d.ts.map +0 -0
  348. /package/{lib → dist}/widgets/buttons.d.ts +0 -0
  349. /package/{lib → dist}/widgets/buttons.d.ts.map +0 -0
  350. /package/{lib → dist}/widgets/forms/autocomplete/autocompleteBar.d.ts +0 -0
  351. /package/{lib → dist}/widgets/forms/autocomplete/autocompleteBar.d.ts.map +0 -0
  352. /package/{lib → dist}/widgets/forms/autocomplete/autocompleteField.d.ts +0 -0
  353. /package/{lib → dist}/widgets/forms/autocomplete/autocompleteField.d.ts.map +0 -0
  354. /package/{lib → dist}/widgets/forms/autocomplete/autocompletePicker.d.ts +0 -0
  355. /package/{lib → dist}/widgets/forms/autocomplete/autocompletePicker.d.ts.map +0 -0
  356. /package/{lib → dist}/widgets/forms/autocomplete/language.d.ts +0 -0
  357. /package/{lib → dist}/widgets/forms/autocomplete/language.d.ts.map +0 -0
  358. /package/{lib → dist}/widgets/forms/autocomplete/publicData.d.ts +0 -0
  359. /package/{lib → dist}/widgets/forms/autocomplete/publicData.d.ts.map +0 -0
  360. /package/{lib → dist}/widgets/forms/basic.d.ts +0 -0
  361. /package/{lib → dist}/widgets/forms/basic.d.ts.map +0 -0
  362. /package/{lib → dist}/widgets/forms/comment.d.ts +0 -0
  363. /package/{lib → dist}/widgets/forms/comment.d.ts.map +0 -0
  364. /package/{lib → dist}/widgets/forms/fieldFunction.d.ts +0 -0
  365. /package/{lib → dist}/widgets/forms/fieldFunction.d.ts.map +0 -0
  366. /package/{lib → dist}/widgets/forms/fieldParams.d.ts +0 -0
  367. /package/{lib → dist}/widgets/forms/fieldParams.d.ts.map +0 -0
  368. /package/{lib → dist}/widgets/forms/formStyle.d.ts +0 -0
  369. /package/{lib → dist}/widgets/widgetHelpers.d.ts +0 -0
@@ -0,0 +1,858 @@
1
+ import { BlankNode, st } from 'rdflib';
2
+ import { authn, authSession, CrossOriginForbiddenError, FetchError, getSuggestedIssuers, NotEditableError, offlineTestID, SameOriginForbiddenError, solidLogicSingleton, UnauthorizedError, WebOperationError } from 'solid-logic';
3
+ import * as debug from '../debug';
4
+ import { style } from '../style';
5
+ import { alert } from '../log';
6
+ import ns from '../ns';
7
+ import { Signup } from '../signup/signup.js';
8
+ import * as utils from '../utils';
9
+ import * as widgets from '../widgets';
10
+ const store = solidLogicSingleton.store;
11
+ const { loadPreferences, loadProfile } = solidLogicSingleton.profile;
12
+ const { getScopedAppInstances, getRegistrations, loadAllTypeIndexes, getScopedAppsFromIndex, deleteTypeIndexRegistration } = solidLogicSingleton.typeIndex;
13
+ /**
14
+ * Resolves with the logged in user's WebID
15
+ *
16
+ * @param context
17
+ */
18
+ // used to be logIn
19
+ export function ensureLoggedIn(context) {
20
+ const me = authn.currentUser();
21
+ if (me) {
22
+ authn.saveUser(me, context);
23
+ return Promise.resolve(context);
24
+ }
25
+ return new Promise((resolve) => {
26
+ authn.checkUser().then((webId) => {
27
+ // Already logged in?
28
+ if (webId) {
29
+ debug.log(`logIn: Already logged in as ${webId}`);
30
+ return resolve(context);
31
+ }
32
+ if (!context.div || !context.dom) {
33
+ return resolve(context);
34
+ }
35
+ const box = loginStatusBox(context.dom, (webIdUri) => {
36
+ authn.saveUser(webIdUri, context);
37
+ resolve(context); // always pass growing context
38
+ });
39
+ context.div.appendChild(box);
40
+ });
41
+ });
42
+ }
43
+ /**
44
+ * Loads preference file
45
+ * Do this after having done log in and load profile
46
+ *
47
+ * @private
48
+ *
49
+ * @param context
50
+ */
51
+ // used to be logInLoadPreferences
52
+ export async function ensureLoadedPreferences(context) {
53
+ if (context.preferencesFile)
54
+ return Promise.resolve(context); // already done
55
+ // const statusArea = context.statusArea || context.div || null
56
+ let progressDisplay;
57
+ /* COMPLAIN FUNCTION NOT USED/TAKING IT OUT FOR NOW
58
+ function complain (message) {
59
+ message = `ensureLoadedPreferences: ${message}`
60
+ if (statusArea) {
61
+ // statusArea.innerHTML = ''
62
+ statusArea.appendChild(widgets.errorMessageBlock(context.dom, message))
63
+ }
64
+ debug.log(message)
65
+ // reject(new Error(message))
66
+ } */
67
+ try {
68
+ context = await ensureLoadedProfile(context);
69
+ // console.log('back in Solid UI after logInLoadProfile', context)
70
+ const preferencesFile = await loadPreferences(context.me);
71
+ if (progressDisplay) {
72
+ progressDisplay.parentNode.removeChild(progressDisplay);
73
+ }
74
+ context.preferencesFile = preferencesFile;
75
+ }
76
+ catch (err) {
77
+ let m2;
78
+ if (err instanceof UnauthorizedError) {
79
+ m2 =
80
+ 'Oops — you are not authenticated (properly logged in), so SolidOS cannot read your preferences file. Try logging out and then logging back in.';
81
+ alert(m2);
82
+ }
83
+ else if (err instanceof CrossOriginForbiddenError) {
84
+ m2 = `Unauthorized: Assuming preference file blocked for origin ${window.location.origin}`;
85
+ context.preferencesFileError = m2;
86
+ return context;
87
+ }
88
+ else if (err instanceof SameOriginForbiddenError) {
89
+ m2 =
90
+ 'You are not authorized to read your preference file. This may be because you are using an untrusted web app.';
91
+ debug.warn(m2);
92
+ return context;
93
+ }
94
+ else if (err instanceof NotEditableError) {
95
+ m2 =
96
+ 'You are not authorized to edit your preference file. This may be because you are using an untrusted web app.';
97
+ debug.warn(m2);
98
+ return context;
99
+ }
100
+ else if (err instanceof WebOperationError) {
101
+ m2 =
102
+ 'You are not authorized to edit your preference file. This may be because you are using an untrusted web app.';
103
+ debug.warn(m2);
104
+ }
105
+ else if (err instanceof FetchError) {
106
+ m2 = `Strange: Error ${err.status} trying to read your preference file.${err.message}`;
107
+ alert(m2);
108
+ }
109
+ else {
110
+ throw new Error(`(via loadPrefs) ${err}`);
111
+ }
112
+ }
113
+ return context;
114
+ }
115
+ /**
116
+ * Logs the user in and loads their WebID profile document into the store
117
+ *
118
+ * @param context
119
+ *
120
+ * @returns Resolves with the context after login / fetch
121
+ */
122
+ // used to be logInLoadProfile
123
+ export async function ensureLoadedProfile(context) {
124
+ if (context.publicProfile) {
125
+ return context;
126
+ } // already done
127
+ try {
128
+ const logInContext = await ensureLoggedIn(context);
129
+ if (!logInContext.me) {
130
+ throw new Error('Could not log in');
131
+ }
132
+ context.publicProfile = await loadProfile(logInContext.me);
133
+ }
134
+ catch (err) {
135
+ if (context.div && context.dom) {
136
+ context.div.appendChild(widgets.errorMessageBlock(context.dom, err.message));
137
+ }
138
+ throw new Error(`Can't log in: ${err}`);
139
+ }
140
+ return context;
141
+ }
142
+ /**
143
+ * Returns promise of context with arrays of symbols
144
+ *
145
+ * leaving the `isPublic` param undefined will bring in community index things, too
146
+ */
147
+ export async function findAppInstances(context, theClass, isPublic) {
148
+ let items = context.me ? await getScopedAppInstances(theClass, context.me) : [];
149
+ if (isPublic === true) { // old API - not recommended!
150
+ items = items.filter(item => item.scope.label === 'public');
151
+ }
152
+ else if (isPublic === false) {
153
+ items = items.filter(item => item.scope.label === 'private');
154
+ }
155
+ context.instances = items.map(item => item.instance);
156
+ return context;
157
+ }
158
+ export function scopeLabel(context, scope) {
159
+ const mine = context.me && context.me.sameTerm(scope.agent);
160
+ const name = mine ? '' : utils.label(scope.agent) + ' ';
161
+ return `${name}${scope.label}`;
162
+ }
163
+ /**
164
+ * UI to control registration of instance
165
+ */
166
+ export async function registrationControl(context, instance, theClass) {
167
+ function registrationStatements(index) {
168
+ const registrations = getRegistrations(instance, theClass);
169
+ const reg = registrations.length ? registrations[0] : widgets.newThing(index);
170
+ return [
171
+ st(reg, ns.solid('instance'), instance, index),
172
+ st(reg, ns.solid('forClass'), theClass, index)
173
+ ];
174
+ }
175
+ function renderScopeCheckbox(scope) {
176
+ const statements = registrationStatements(scope.index);
177
+ const name = scopeLabel(context, scope);
178
+ const label = `${name} link to this ${context.noun}`;
179
+ return widgets.buildCheckboxForm(context.dom, solidLogicSingleton.store, label, null, statements, form, scope.index);
180
+ }
181
+ /// / body of registrationControl
182
+ const dom = context.dom;
183
+ if (!dom || !context.div) {
184
+ throw new Error('registrationControl: need dom and div');
185
+ }
186
+ const box = dom.createElement('div');
187
+ context.div.appendChild(box);
188
+ context.me = authn.currentUser(); // @@
189
+ const me = context.me;
190
+ if (!me) {
191
+ box.innerHTML = '<p style="margin:2em;">(Log in to save a link to this)</p>';
192
+ return context;
193
+ }
194
+ let scopes; // @@ const
195
+ try {
196
+ scopes = await loadAllTypeIndexes(me);
197
+ }
198
+ catch (e) {
199
+ let msg;
200
+ if (context.div && context.preferencesFileError) {
201
+ msg = '(Lists of stuff not available)';
202
+ context.div.appendChild(dom.createElement('p')).textContent = msg;
203
+ }
204
+ else if (context.div) {
205
+ msg = `registrationControl: Type indexes not available: ${e}`;
206
+ context.div.appendChild(widgets.errorMessageBlock(context.dom, e));
207
+ }
208
+ debug.log(msg);
209
+ return context;
210
+ }
211
+ box.innerHTML = '<table><tbody></tbody></table>'; // tbody will be inserted anyway
212
+ box.setAttribute('style', 'font-size: 120%; text-align: right; padding: 1em; border: solid gray 0.05em;');
213
+ const tbody = box.children[0].children[0];
214
+ const form = new BlankNode(); // @@ say for now
215
+ for (const scope of scopes) {
216
+ const row = tbody.appendChild(dom.createElement('tr'));
217
+ row.appendChild(renderScopeCheckbox(scope)); // @@ index
218
+ }
219
+ return context;
220
+ }
221
+ export function renderScopeHeadingRow(context, store, scope) {
222
+ const backgroundColor = { private: '#fee', public: '#efe' };
223
+ const { dom } = context;
224
+ const name = scopeLabel(context, scope);
225
+ const row = dom.createElement('tr');
226
+ const cell = row.appendChild(dom.createElement('td'));
227
+ cell.setAttribute('colspan', '3');
228
+ cell.style.backgoundColor = backgroundColor[scope.label] || 'white';
229
+ const header = cell.appendChild(dom.createElement('h3'));
230
+ header.textContent = name + ' links';
231
+ header.style.textAlign = 'left';
232
+ return row;
233
+ }
234
+ /**
235
+ * UI to List at all registered things
236
+ */
237
+ export async function registrationList(context, options) {
238
+ const dom = context.dom;
239
+ const div = context.div;
240
+ const box = dom.createElement('div');
241
+ div.appendChild(box);
242
+ context.me = authn.currentUser(); // @@
243
+ if (!context.me) {
244
+ box.innerHTML = '<p style="margin:2em;">(Log in list your stuff)</p>';
245
+ return context;
246
+ }
247
+ const scopes = await loadAllTypeIndexes(context.me); // includes community indexes
248
+ // console.log('@@ registrationList ', scopes)
249
+ box.innerHTML = '<table><tbody></tbody></table>'; // tbody will be inserted anyway
250
+ box.setAttribute('style', 'font-size: 120%; text-align: right; padding: 1em; border: solid #eee 0.5em;');
251
+ const table = box.firstChild;
252
+ const tbody = table.firstChild;
253
+ for (const scope of scopes) { // need some predicate for listing/adding agents
254
+ const headingRow = renderScopeHeadingRow(context, store, scope);
255
+ tbody.appendChild(headingRow);
256
+ const items = await getScopedAppsFromIndex(scope, options.type || null); // any class
257
+ if (items.length === 0)
258
+ headingRow.style.display = 'none';
259
+ // console.log(`registrationList: @@ instance items for class ${options.type || 'undefined' }:`, items)
260
+ for (const item of items) {
261
+ const row = widgets.personTR(dom, ns.solid('instance'), item.instance, {
262
+ deleteFunction: async () => {
263
+ await deleteTypeIndexRegistration(item);
264
+ tbody.removeChild(row);
265
+ }
266
+ });
267
+ row.children[0].style.paddingLeft = '3em';
268
+ tbody.appendChild(row);
269
+ }
270
+ }
271
+ return context;
272
+ } // registrationList
273
+ /**
274
+ * Bootstrapping identity
275
+ * (Called by `loginStatusBox()`)
276
+ *
277
+ * @param dom
278
+ * @param setUserCallback
279
+ *
280
+ * @returns
281
+ */
282
+ function signInOrSignUpBox(dom, setUserCallback, options = {}) {
283
+ options = options || {};
284
+ const signInButtonStyle = options.buttonStyle || style.signInAndUpButtonStyle;
285
+ const box = dom.createElement('div');
286
+ const magicClassName = 'SolidSignInOrSignUpBox';
287
+ debug.log('widgets.signInOrSignUpBox');
288
+ box.setUserCallback = setUserCallback;
289
+ box.setAttribute('class', magicClassName);
290
+ box.setAttribute('style', 'display:flex;');
291
+ // Sign in button with PopUP
292
+ const signInPopUpButton = dom.createElement('input'); // multi
293
+ box.appendChild(signInPopUpButton);
294
+ signInPopUpButton.setAttribute('type', 'button');
295
+ signInPopUpButton.setAttribute('value', 'Log in');
296
+ signInPopUpButton.setAttribute('style', `${signInButtonStyle}${style.headerBannerLoginInput}` + style.signUpBackground);
297
+ authSession.events.on('login', () => {
298
+ const me = authn.currentUser();
299
+ // const sessionInfo = authSession.info
300
+ // if (sessionInfo && sessionInfo.isLoggedIn) {
301
+ if (me) {
302
+ // const webIdURI = sessionInfo.webId
303
+ const webIdURI = me.uri;
304
+ // setUserCallback(webIdURI)
305
+ const divs = dom.getElementsByClassName(magicClassName);
306
+ debug.log(`Logged in, ${divs.length} panels to be serviced`);
307
+ // At the same time, satisfy all the other login boxes
308
+ for (let i = 0; i < divs.length; i++) {
309
+ const div = divs[i];
310
+ // @@ TODO Remove the need to manipulate HTML elements
311
+ if (div.setUserCallback) {
312
+ try {
313
+ div.setUserCallback(webIdURI);
314
+ const parent = div.parentNode;
315
+ if (parent) {
316
+ parent.removeChild(div);
317
+ }
318
+ }
319
+ catch (e) {
320
+ debug.log(`## Error satisfying login box: ${e}`);
321
+ div.appendChild(widgets.errorMessageBlock(dom, e));
322
+ }
323
+ }
324
+ }
325
+ }
326
+ });
327
+ signInPopUpButton.addEventListener('click', () => {
328
+ const offline = offlineTestID();
329
+ if (offline)
330
+ return setUserCallback(offline.uri);
331
+ renderSignInPopup(dom);
332
+ }, false);
333
+ // Sign up button
334
+ const signupButton = dom.createElement('input');
335
+ box.appendChild(signupButton);
336
+ signupButton.setAttribute('type', 'button');
337
+ signupButton.setAttribute('value', 'Sign Up for Solid');
338
+ signupButton.setAttribute('style', `${signInButtonStyle}${style.headerBannerLoginInput}` + style.signInBackground);
339
+ signupButton.addEventListener('click', function (_event) {
340
+ const signupMgr = new Signup();
341
+ signupMgr.signup().then(function (uri) {
342
+ debug.log('signInOrSignUpBox signed up ' + uri);
343
+ setUserCallback(uri);
344
+ });
345
+ }, false);
346
+ return box;
347
+ }
348
+ export function renderSignInPopup(dom) {
349
+ /**
350
+ * Issuer Menu
351
+ */
352
+ const issuerPopup = dom.createElement('div');
353
+ issuerPopup.setAttribute('style', 'position: fixed; top: 0; left: 0; right: 0; bottom: 0; display: flex; justify-content: center; align-items: center;');
354
+ dom.body.appendChild(issuerPopup);
355
+ const issuerPopupBox = dom.createElement('div');
356
+ issuerPopupBox.setAttribute('style', `
357
+ background-color: white;
358
+ box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.2);
359
+ -webkit-box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.2);
360
+ -moz-box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.2);
361
+ -o-box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.2);
362
+ border-radius: 4px;
363
+ min-width: 400px;
364
+ padding: 10px;
365
+ z-index : 10;
366
+ `);
367
+ issuerPopup.appendChild(issuerPopupBox);
368
+ const issuerPopupBoxTopMenu = dom.createElement('div');
369
+ issuerPopupBoxTopMenu.setAttribute('style', `
370
+ border-bottom: 1px solid #DDD;
371
+ display: flex;
372
+ flex-direction: row;
373
+ align-items: center;
374
+ justify-content: space-between;
375
+ `);
376
+ issuerPopupBox.appendChild(issuerPopupBoxTopMenu);
377
+ const issuerPopupBoxLabel = dom.createElement('label');
378
+ issuerPopupBoxLabel.setAttribute('style', 'margin-right: 5px; font-weight: 800');
379
+ issuerPopupBoxLabel.innerText = 'Select an identity provider';
380
+ const issuerPopupBoxCloseButton = dom.createElement('button');
381
+ issuerPopupBoxCloseButton.innerHTML =
382
+ '<img src="https://solidos.github.io/solid-ui/src/icons/noun_1180156.svg" style="width: 2em; height: 2em;" title="Cancel">';
383
+ issuerPopupBoxCloseButton.setAttribute('style', 'background-color: transparent; border: none;');
384
+ issuerPopupBoxCloseButton.addEventListener('click', () => {
385
+ issuerPopup.remove();
386
+ });
387
+ issuerPopupBoxTopMenu.appendChild(issuerPopupBoxLabel);
388
+ issuerPopupBoxTopMenu.appendChild(issuerPopupBoxCloseButton);
389
+ const loginToIssuer = async (issuerUri) => {
390
+ try {
391
+ // clear authorization metadata from store
392
+ solidLogicSingleton.store.updater.flagAuthorizationMetadata();
393
+ // Save hash
394
+ const preLoginRedirectHash = new URL(window.location.href).hash;
395
+ if (preLoginRedirectHash) {
396
+ window.localStorage.setItem('preLoginRedirectHash', preLoginRedirectHash);
397
+ }
398
+ window.localStorage.setItem('loginIssuer', issuerUri);
399
+ // Login
400
+ const locationUrl = new URL(window.location.href);
401
+ locationUrl.hash = ''; // remove hash part
402
+ await authSession.login({
403
+ redirectUrl: locationUrl.href,
404
+ oidcIssuer: issuerUri
405
+ });
406
+ }
407
+ catch (err) {
408
+ alert(err.message);
409
+ }
410
+ };
411
+ /**
412
+ * Text-based idp selection
413
+ */
414
+ const issuerTextContainer = dom.createElement('div');
415
+ issuerTextContainer.setAttribute('style', `
416
+ border-bottom: 1px solid #DDD;
417
+ display: flex;
418
+ flex-direction: column;
419
+ padding-top: 10px;
420
+ `);
421
+ const issuerTextInputContainer = dom.createElement('div');
422
+ issuerTextInputContainer.setAttribute('style', `
423
+ display: flex;
424
+ flex-direction: row;
425
+ `);
426
+ const issuerTextLabel = dom.createElement('label');
427
+ issuerTextLabel.innerText = 'Enter the URL of your identity provider:';
428
+ issuerTextLabel.setAttribute('style', 'color: #888');
429
+ const issuerTextInput = dom.createElement('input');
430
+ issuerTextInput.setAttribute('type', 'text');
431
+ issuerTextInput.setAttribute('style', 'margin-left: 0 !important; flex: 1; margin-right: 5px !important');
432
+ issuerTextInput.setAttribute('placeholder', 'https://example.com');
433
+ issuerTextInput.value = localStorage.getItem('loginIssuer') || '';
434
+ const issuerTextGoButton = dom.createElement('button');
435
+ issuerTextGoButton.innerText = 'Go';
436
+ issuerTextGoButton.setAttribute('style', 'margin-top: 12px; margin-bottom: 12px;');
437
+ issuerTextGoButton.addEventListener('click', () => {
438
+ loginToIssuer(issuerTextInput.value);
439
+ });
440
+ issuerTextContainer.appendChild(issuerTextLabel);
441
+ issuerTextInputContainer.appendChild(issuerTextInput);
442
+ issuerTextInputContainer.appendChild(issuerTextGoButton);
443
+ issuerTextContainer.appendChild(issuerTextInputContainer);
444
+ issuerPopupBox.appendChild(issuerTextContainer);
445
+ /**
446
+ * Button-based idp selection
447
+ */
448
+ const issuerButtonContainer = dom.createElement('div');
449
+ issuerButtonContainer.setAttribute('style', `
450
+ display: flex;
451
+ flex-direction: column;
452
+ padding-top: 10px;
453
+ `);
454
+ const issuerBottonLabel = dom.createElement('label');
455
+ issuerBottonLabel.innerText = 'Or pick an identity provider from the list below:';
456
+ issuerBottonLabel.setAttribute('style', 'color: #888');
457
+ issuerButtonContainer.appendChild(issuerBottonLabel);
458
+ getSuggestedIssuers().forEach((issuerInfo) => {
459
+ const issuerButton = dom.createElement('button');
460
+ issuerButton.innerText = issuerInfo.name;
461
+ issuerButton.setAttribute('style', 'height: 38px; margin-top: 10px');
462
+ issuerButton.addEventListener('click', () => {
463
+ loginToIssuer(issuerInfo.uri);
464
+ });
465
+ issuerButtonContainer.appendChild(issuerButton);
466
+ });
467
+ issuerPopupBox.appendChild(issuerButtonContainer);
468
+ }
469
+ /**
470
+ * Login status box
471
+ *
472
+ * A big sign-up/sign in box or a logout box depending on the state
473
+ *
474
+ * @param dom
475
+ * @param listener
476
+ *
477
+ * @returns
478
+ */
479
+ export function loginStatusBox(dom, listener = null, options = {}) {
480
+ // 20190630
481
+ let me = offlineTestID();
482
+ // @@ TODO Remove the need to cast HTML element to any
483
+ const box = dom.createElement('div');
484
+ function setIt(newidURI) {
485
+ if (!newidURI) {
486
+ return;
487
+ }
488
+ // const uri = newidURI.uri || newidURI
489
+ // me = sym(uri)
490
+ me = authn.saveUser(newidURI);
491
+ box.refresh();
492
+ if (listener)
493
+ listener(me.uri);
494
+ }
495
+ function logoutButtonHandler(_event) {
496
+ const oldMe = me;
497
+ authSession.logout().then(function () {
498
+ const message = `Your WebID was ${oldMe}. It has been forgotten.`;
499
+ me = null;
500
+ try {
501
+ alert(message);
502
+ }
503
+ catch (_e) {
504
+ window.alert(message);
505
+ }
506
+ box.refresh();
507
+ if (listener)
508
+ listener(null);
509
+ }, (err) => {
510
+ alert('Fail to log out:' + err);
511
+ });
512
+ }
513
+ function logoutButton(me, options) {
514
+ const signInButtonStyle = options.buttonStyle || style.signInAndUpButtonStyle;
515
+ let logoutLabel = 'WebID logout';
516
+ if (me) {
517
+ const nick = solidLogicSingleton.store.any(me, ns.foaf('nick')) ||
518
+ solidLogicSingleton.store.any(me, ns.foaf('name'));
519
+ if (nick) {
520
+ logoutLabel = 'Logout ' + nick.value;
521
+ }
522
+ }
523
+ const signOutButton = dom.createElement('input');
524
+ // signOutButton.className = 'WebIDCancelButton'
525
+ signOutButton.setAttribute('type', 'button');
526
+ signOutButton.setAttribute('value', logoutLabel);
527
+ signOutButton.setAttribute('style', `${signInButtonStyle}`);
528
+ signOutButton.addEventListener('click', logoutButtonHandler, false);
529
+ return signOutButton;
530
+ }
531
+ box.refresh = function () {
532
+ const sessionInfo = authSession.info;
533
+ if (sessionInfo && sessionInfo.webId && sessionInfo.isLoggedIn) {
534
+ me = solidLogicSingleton.store.sym(sessionInfo.webId);
535
+ }
536
+ else {
537
+ me = null;
538
+ }
539
+ if ((me && box.me !== me.uri) || (!me && box.me)) {
540
+ widgets.clearElement(box);
541
+ if (me) {
542
+ box.appendChild(logoutButton(me, options));
543
+ }
544
+ else {
545
+ box.appendChild(signInOrSignUpBox(dom, setIt, options));
546
+ }
547
+ }
548
+ box.me = me ? me.uri : null;
549
+ };
550
+ box.refresh();
551
+ function trackSession() {
552
+ me = authn.currentUser();
553
+ box.refresh();
554
+ }
555
+ trackSession();
556
+ authSession.events.on('login', trackSession);
557
+ authSession.events.on('logout', trackSession);
558
+ box.me = '99999'; // Force refresh
559
+ box.refresh();
560
+ return box;
561
+ }
562
+ authSession.events.on('logout', async () => {
563
+ const issuer = window.localStorage.getItem('loginIssuer');
564
+ if (issuer) {
565
+ try {
566
+ // clear authorization metadata from store
567
+ solidLogicSingleton.store.updater.flagAuthorizationMetadata();
568
+ const wellKnownUri = new URL(issuer);
569
+ wellKnownUri.pathname = '/.well-known/openid-configuration';
570
+ const wellKnownResult = await fetch(wellKnownUri.toString());
571
+ if (wellKnownResult.status === 200) {
572
+ const openidConfiguration = await wellKnownResult.json();
573
+ if (openidConfiguration && openidConfiguration.end_session_endpoint) {
574
+ await fetch(openidConfiguration.end_session_endpoint, { credentials: 'include' });
575
+ }
576
+ }
577
+ }
578
+ catch (_err) {
579
+ // Do nothing
580
+ }
581
+ }
582
+ window.location.reload();
583
+ });
584
+ /**
585
+ * Workspace selection etc
586
+ * See https://github.com/solidos/userguide/issues/16
587
+ */
588
+ /**
589
+ * Returns a UI object which, if it selects a workspace,
590
+ * will callback(workspace, newBase).
591
+ * See https://github.com/solidos/userguide/issues/16 for more info on workspaces.
592
+ *
593
+ * If necessary, will get an account, preference file, etc. In sequence:
594
+ *
595
+ * - If not logged in, log in.
596
+ * - Load preference file
597
+ * - Prompt user for workspaces
598
+ * - Allows the user to just type in a URI by hand
599
+ *
600
+ * Calls back with the workspace and the base URI
601
+ *
602
+ * @param dom
603
+ * @param appDetails
604
+ * @param callbackWS
605
+ */
606
+ export function selectWorkspace(dom, appDetails, callbackWS) {
607
+ const noun = appDetails.noun;
608
+ const appPathSegment = appDetails.appPathSegment;
609
+ const me = offlineTestID();
610
+ const box = dom.createElement('div');
611
+ const context = { me, dom, div: box };
612
+ function say(s, background) {
613
+ box.appendChild(widgets.errorMessageBlock(dom, s, background));
614
+ }
615
+ function figureOutBase(ws) {
616
+ const newBaseNode = solidLogicSingleton.store.any(ws, ns.space('uriPrefix'));
617
+ let newBaseString;
618
+ if (!newBaseNode) {
619
+ newBaseString = ws.uri.split('#')[0];
620
+ }
621
+ else {
622
+ newBaseString = newBaseNode.value;
623
+ }
624
+ if (newBaseString.slice(-1) !== '/') {
625
+ debug.log(`${appPathSegment}: No / at end of uriPrefix ${newBaseString}`); // @@ paramater?
626
+ newBaseString = `${newBaseString}/`;
627
+ }
628
+ const now = new Date();
629
+ newBaseString += `${appPathSegment}/id${now.getTime()}/`; // unique id
630
+ return newBaseString;
631
+ }
632
+ function displayOptions(context) {
633
+ // console.log('displayOptions!', context)
634
+ async function makeNewWorkspace(_event) {
635
+ const row = table.appendChild(dom.createElement('tr'));
636
+ const cell = row.appendChild(dom.createElement('td'));
637
+ cell.setAttribute('colspan', '3');
638
+ cell.style.padding = '0.5em';
639
+ const newBase = encodeURI(await widgets.askName(dom, solidLogicSingleton.store, cell, ns.solid('URL'), ns.space('Workspace'), 'Workspace'));
640
+ const newWs = widgets.newThing(context.preferencesFile);
641
+ const newData = [
642
+ st(context.me, ns.space('workspace'), newWs, context.preferencesFile),
643
+ st(newWs, ns.space('uriPrefix'), newBase, context.preferencesFile)
644
+ ];
645
+ if (!solidLogicSingleton.store.updater) {
646
+ throw new Error('store has no updater');
647
+ }
648
+ await solidLogicSingleton.store.updater.update([], newData);
649
+ // @@ now refresh list of workspaces
650
+ }
651
+ // const status = ''
652
+ const id = context.me;
653
+ const preferencesFile = context.preferencesFile;
654
+ let newBase = null;
655
+ // A workspace specifically defined in the private preference file:
656
+ let w = solidLogicSingleton.store.each(id, ns.space('workspace'), undefined, preferencesFile); // Only trust preference file here
657
+ // A workspace in a storage in the public profile:
658
+ const storages = solidLogicSingleton.store.each(id, ns.space('storage')); // @@ No provenance requirement at the moment
659
+ if (w.length === 0 && storages) {
660
+ say(`You don't seem to have any workspaces. You have ${storages.length} storage spaces.`, 'white');
661
+ storages
662
+ .map(function (s) {
663
+ w = w.concat(solidLogicSingleton.store.each(s, ns.ldp('contains')));
664
+ return w;
665
+ })
666
+ .filter((file) => {
667
+ return file.id ? ['public', 'private'].includes(file.id().toLowerCase()) : '';
668
+ });
669
+ }
670
+ if (w.length === 1) {
671
+ say(`Workspace used: ${w[0].uri}`, 'white'); // @@ allow user to see URI
672
+ newBase = figureOutBase(w[0]);
673
+ // callbackWS(w[0], newBase)
674
+ // } else if (w.length === 0) {
675
+ }
676
+ // Prompt for ws selection or creation
677
+ // say( w.length + " workspaces for " + id + "Choose one.");
678
+ const table = dom.createElement('table');
679
+ table.setAttribute('style', 'border-collapse:separate; border-spacing: 0.5em;');
680
+ // const popup = window.open(undefined, '_blank', { height: 300, width:400 }, false)
681
+ box.appendChild(table);
682
+ // Add a field for directly adding the URI yourself
683
+ // const hr = box.appendChild(dom.createElement('hr')) // @@
684
+ box.appendChild(dom.createElement('hr')); // @@
685
+ const p = box.appendChild(dom.createElement('p'));
686
+ p.setAttribute('style', style.commentStyle);
687
+ p.textContent = `Where would you like to store the data for the ${noun}?
688
+ Give the URL of the folder where you would like the data stored.
689
+ It can be anywhere in solid world - this URI is just an idea.`;
690
+ // @@ TODO Remove the need to cast baseField to any
691
+ const baseField = box.appendChild(dom.createElement('input'));
692
+ baseField.setAttribute('type', 'text');
693
+ baseField.setAttribute('style', style.textInputStyle);
694
+ baseField.size = 80; // really a string
695
+ baseField.label = 'base URL';
696
+ baseField.autocomplete = 'on';
697
+ if (newBase) {
698
+ // set to default
699
+ baseField.value = newBase;
700
+ }
701
+ context.baseField = baseField;
702
+ box.appendChild(dom.createElement('br')); // @@
703
+ const button = box.appendChild(dom.createElement('button'));
704
+ button.setAttribute('style', style.buttonStyle);
705
+ button.textContent = `Start new ${noun} at this URI`;
706
+ button.addEventListener('click', function (_event) {
707
+ let newBase = baseField.value.replace(' ', '%20'); // do not re-encode in general, as % encodings may exist
708
+ if (newBase.slice(-1) !== '/') {
709
+ newBase += '/';
710
+ }
711
+ callbackWS(null, newBase);
712
+ });
713
+ // Now go set up the table of spaces
714
+ // const row = 0
715
+ w = w.filter(function (x) {
716
+ return !solidLogicSingleton.store.holds(x, ns.rdf('type'), // Ignore master workspaces
717
+ ns.space('MasterWorkspace'));
718
+ });
719
+ let col1, col2, col3, tr, ws, localStyle, comment;
720
+ const cellStyle = 'height: 3em; margin: 1em; padding: 1em white; border-radius: 0.3em;';
721
+ const deselectedStyle = `${cellStyle}border: 0px;`;
722
+ // const selectedStyle = cellStyle + 'border: 1px solid black;'
723
+ for (let i = 0; i < w.length; i++) {
724
+ ws = w[i];
725
+ tr = dom.createElement('tr');
726
+ if (i === 0) {
727
+ col1 = dom.createElement('td');
728
+ col1.setAttribute('rowspan', `${w.length}`);
729
+ col1.textContent = 'Choose a workspace for this:';
730
+ col1.setAttribute('style', 'vertical-align:middle;');
731
+ tr.appendChild(col1);
732
+ }
733
+ col2 = dom.createElement('td');
734
+ localStyle = solidLogicSingleton.store.anyValue(ws, ns.ui('style'));
735
+ if (!localStyle) {
736
+ // Otherwise make up arbitrary colour
737
+ const hash = function (x) {
738
+ return x.split('').reduce(function (a, b) {
739
+ a = (a << 5) - a + b.charCodeAt(0);
740
+ return a & a;
741
+ }, 0);
742
+ };
743
+ const bgcolor = `#${((hash(ws.uri) & 0xffffff) | 0xc0c0c0).toString(16)}`; // c0c0c0 forces pale
744
+ localStyle = `color: black ; background-color: ${bgcolor};`;
745
+ }
746
+ col2.setAttribute('style', deselectedStyle + localStyle);
747
+ tr.target = ws.uri;
748
+ let label = solidLogicSingleton.store.any(ws, ns.rdfs('label'));
749
+ if (!label) {
750
+ label = ws.uri.split('/').slice(-1)[0] || ws.uri.split('/').slice(-2)[0];
751
+ }
752
+ col2.textContent = label || '???';
753
+ tr.appendChild(col2);
754
+ if (i === 0) {
755
+ col3 = dom.createElement('td');
756
+ col3.setAttribute('rowspan', `${w.length}1`);
757
+ // col3.textContent = '@@@@@ remove';
758
+ col3.setAttribute('style', 'width:50%;');
759
+ tr.appendChild(col3);
760
+ }
761
+ table.appendChild(tr);
762
+ comment = solidLogicSingleton.store.any(ws, ns.rdfs('comment'));
763
+ comment = comment ? comment.value : 'Use this workspace';
764
+ col2.addEventListener('click', function (_event) {
765
+ col3.textContent = comment ? comment.value : '';
766
+ col3.setAttribute('style', deselectedStyle + localStyle);
767
+ const button = dom.createElement('button');
768
+ button.textContent = 'Continue';
769
+ // button.setAttribute('style', style);
770
+ const newBase = figureOutBase(ws);
771
+ baseField.value = newBase; // show user proposed URI
772
+ button.addEventListener('click', function (_event) {
773
+ button.disabled = true;
774
+ callbackWS(ws, newBase);
775
+ button.textContent = '---->';
776
+ }, true); // capture vs bubble
777
+ col3.appendChild(button);
778
+ }, true); // capture vs bubble
779
+ }
780
+ // last line with "Make new workspace"
781
+ const trLast = dom.createElement('tr');
782
+ col2 = dom.createElement('td');
783
+ col2.setAttribute('style', cellStyle);
784
+ col2.textContent = '+ Make a new workspace';
785
+ col2.addEventListener('click', makeNewWorkspace);
786
+ trLast.appendChild(col2);
787
+ table.appendChild(trLast);
788
+ } // displayOptions
789
+ // console.log('kicking off async operation')
790
+ ensureLoadedPreferences(context) // kick off async operation
791
+ .then(displayOptions)
792
+ .catch((err) => {
793
+ // console.log("err from async op")
794
+ box.appendChild(widgets.errorMessageBlock(context.dom, err));
795
+ });
796
+ return box; // return the box element, while login proceeds
797
+ } // selectWorkspace
798
+ /**
799
+ * Creates a new instance of an app.
800
+ *
801
+ * An instance of an app could be e.g. an issue tracker for a given project,
802
+ * or a chess game, or calendar, or a health/fitness record for a person.
803
+ *
804
+ * Note that this use of the term 'app' refers more to entries in the user's
805
+ * type index than to actual software applications that use the personal data
806
+ * to which these entries point.
807
+ *
808
+ * @param dom
809
+ * @param appDetails
810
+ * @param callback
811
+ *
812
+ * @returns A div with a button in it for making a new app instance
813
+ */
814
+ export function newAppInstance(dom, appDetails, callback) {
815
+ const gotWS = function (ws, base) {
816
+ // log.debug("newAppInstance: Selected workspace = " + (ws? ws.uri : 'none'))
817
+ callback(ws, base);
818
+ };
819
+ const div = dom.createElement('div');
820
+ const b = dom.createElement('button');
821
+ b.setAttribute('type', 'button');
822
+ div.appendChild(b);
823
+ b.innerHTML = `Make new ${appDetails.noun}`;
824
+ b.addEventListener('click', (_event) => {
825
+ div.appendChild(selectWorkspace(dom, appDetails, gotWS));
826
+ }, false);
827
+ div.appendChild(b);
828
+ return div;
829
+ }
830
+ /**
831
+ * Retrieves whether the currently logged in user is a power user
832
+ * and/or a developer
833
+ */
834
+ export async function getUserRoles() {
835
+ try {
836
+ const { me, preferencesFile, preferencesFileError } = await ensureLoadedPreferences({});
837
+ if (!preferencesFile || preferencesFileError) {
838
+ throw new Error(preferencesFileError);
839
+ }
840
+ return solidLogicSingleton.store.each(me, ns.rdf('type'), null, preferencesFile.doc());
841
+ }
842
+ catch (error) {
843
+ debug.warn('Unable to fetch your preferences - this was the error: ', error);
844
+ }
845
+ return [];
846
+ }
847
+ /**
848
+ * Filters which panes should be available, based on the result of [[getUserRoles]]
849
+ */
850
+ export async function filterAvailablePanes(panes) {
851
+ const userRoles = await getUserRoles();
852
+ return panes.filter((pane) => isMatchingAudience(pane, userRoles));
853
+ }
854
+ function isMatchingAudience(pane, userRoles) {
855
+ const audience = pane.audience || [];
856
+ return audience.reduce((isMatch, audienceRole) => isMatch && !!userRoles.find((role) => role.equals(audienceRole)), true);
857
+ }
858
+ //# sourceMappingURL=login.js.map