├── LICENSE.md ├── README.md ├── app └── app.js ├── css └── style.css └── index.html /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 - present 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Solid Pastebin Tutorial 2 | [](https://github.com/solid/solid) 3 | 4 | Example application used in the 5 | [Solid intro tutorial](https://github.com/solid/solid-tutorial-intro). 6 | 7 | # Setup 8 | 9 | **Step 1:** Have a container URL ready, where you'll be writing the 10 | pastebins. (Either create an account on a Solid server, or use the URL provided 11 | by your tutorial instructor.) This will look something like: 12 | 13 | `https://username.databox.me/Public/bins/` 14 | 15 | **Step 2:** Locate the following line, near the top of 16 | [`app/app.js`](app/app.js): 17 | 18 | ```js 19 | var defaultContainer = ''; 20 | ``` 21 | 22 | Change the empty string to the URL of the container you want to use. 23 | 24 | **Step 3:** Open `index.html` in your web browser. 25 | -------------------------------------------------------------------------------- /app/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var solid = SolidClient; 3 | var vocab = solid.vocab; 4 | 5 | var Pastebin = Pastebin || {}; 6 | Pastebin = (function () { 7 | // Default publish location 8 | // ATTENTION: this variable must be set for the app to create new bins 9 | var defaultContainer = ''; 10 | 11 | // Bin structure 12 | var bin = { 13 | url: '', 14 | title: '', 15 | body: '' 16 | } 17 | 18 | function init() { 19 | document.getElementById('edit').classList.add('hidden'); 20 | document.getElementById('view').classList.add('hidden'); 21 | 22 | if (defaultContainer.lastIndexOf('/') != defaultContainer.length - 1) { 23 | defaultContainer += '/'; 24 | } 25 | console.log(defaultContainer) 26 | 27 | if (queryVals['view'] && queryVals['view'].length > 0) { 28 | load(queryVals['view']); 29 | } else if (queryVals['edit'] && queryVals['edit'].length > 0) { 30 | load(queryVals['edit'], true); 31 | } else { 32 | console.log('new pastebin form'); 33 | document.getElementById('submit') 34 | .setAttribute('onclick', 'Pastebin.publish()'); 35 | document.getElementById('edit').classList.remove('hidden'); 36 | } 37 | } 38 | 39 | function load (url, showEditor) { 40 | solid.web.get(url).then(function(response) { 41 | var graph = response.parsedGraph(); 42 | // set url 43 | bin.url = response.url; 44 | var subject = $rdf.sym(response.url); 45 | // add title 46 | var title = graph.any(subject, vocab.dct('title')); 47 | if (title) { 48 | bin.title = title.value; 49 | } 50 | // add body 51 | var body = graph.any(subject, vocab.sioc('content')); 52 | if (body) { 53 | bin.body = body.value; 54 | } 55 | 56 | if (showEditor) { 57 | document.getElementById('edit-title').value = bin.title; 58 | document.getElementById('edit-body').innerHTML = bin.body; 59 | document.getElementById('submit').setAttribute('onclick', 60 | 'Pastebin.update()'); 61 | document.getElementById('edit').classList.remove('hidden'); 62 | } else { 63 | document.getElementById('view-title').innerHTML = bin.title; 64 | document.getElementById('view-body').innerHTML = bin.body; 65 | document.getElementById('view').classList.remove('hidden'); 66 | } 67 | }).catch(function(err) { 68 | // do something with the error 69 | console.log(err); 70 | }); 71 | } 72 | 73 | function publish () { 74 | bin.title = document.getElementById('edit-title').value; 75 | bin.body = document.getElementById('edit-body').value; 76 | 77 | var graph = $rdf.graph(); 78 | var thisResource = $rdf.sym(''); 79 | graph.add(thisResource, vocab.dct('title'), $rdf.lit(bin.title)); 80 | graph.add(thisResource, vocab.sioc('content'), $rdf.lit(bin.body)); 81 | var data = new $rdf.Serializer(graph).toN3(graph); 82 | 83 | solid.web.post(defaultContainer, data).then(function(meta) { 84 | // view 85 | var url = meta.url; 86 | if (url && url.slice(0,4) != 'http') { 87 | if (url.indexOf('/') === 0) { 88 | url = url.slice(1, url.length); 89 | } 90 | url = defaultContainer + url.slice(url.lastIndexOf('/') + 1, url.length); 91 | } 92 | window.location.search = "?view="+encodeURIComponent(url); 93 | }).catch(function(err) { 94 | // do something with the error 95 | console.log(err); 96 | }); 97 | } 98 | 99 | function update () { 100 | bin.title = document.getElementById('edit-title').value; 101 | bin.body = document.getElementById('edit-body').value; 102 | 103 | var graph = $rdf.graph(); 104 | var thisResource = $rdf.sym(''); 105 | graph.add(thisResource, vocab.dct('title'), bin.title); 106 | graph.add(thisResource, vocab.sioc('content'), bin.body); 107 | var data = new $rdf.Serializer(graph).toN3(graph); 108 | 109 | solid.web.put(bin.url, data).then(function(meta) { 110 | // view 111 | window.location.search = "?view="+encodeURIComponent(meta.url); 112 | }).catch(function(err) { 113 | // do something with the error 114 | console.log(err); 115 | }); 116 | } 117 | 118 | // Utility function to parse URL query string values 119 | var queryVals = (function(a) { 120 | if (a === "") return {}; 121 | var b = {}; 122 | for (var i = 0; i < a.length; ++i) 123 | { 124 | var p=a[i].split('=', 2); 125 | if (p.length === 1) 126 | b[p[0]] = ""; 127 | else 128 | b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " ")); 129 | } 130 | return b; 131 | })(window.location.search.substr(1).split('&')); 132 | 133 | init(); 134 | 135 | // return public functions 136 | return { 137 | publish: publish, 138 | update: update 139 | }; 140 | }(this)); 141 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | font-family: 'Roboto', sans-serif; 3 | font-weight: 200; 4 | height: 100%; 5 | } 6 | 7 | * { 8 | -moz-box-sizing: border-box; 9 | -webkit-box-sizing: border-box; 10 | box-sizing: border-box; 11 | } 12 | 13 | a { 14 | text-decoration: none; 15 | color: #3D92C9; 16 | } 17 | a:hover, 18 | a:focus { 19 | text-decoration: underline; 20 | } 21 | 22 | h1 { 23 | margin-bottom: 20px; 24 | } 25 | 26 | input { 27 | font-size: 1.3em; 28 | font-family: 'Roboto', sans-serif; 29 | width: 90%; 30 | padding: 5px; 31 | margin-bottom: 20px; 32 | } 33 | 34 | textarea { 35 | font-size: 1.1em; 36 | font-family: 'Roboto', sans-serif; 37 | width: 90%; 38 | height: 300px; 39 | margin-bottom: 20px; 40 | } 41 | 42 | button { 43 | width: 90%; 44 | background-color: #fff; 45 | color: #777; 46 | letter-spacing: 0.05em; 47 | text-transform: uppercase; 48 | font-size: 60%; 49 | padding: 1em 1.5em; 50 | text-decoration: none; 51 | border: 1px solid #777; 52 | border-radius: 2px; 53 | cursor: pointer; 54 | } 55 | 56 | .float-right { 57 | float: right; 58 | } 59 | 60 | .float-left { 61 | float: left; 62 | } 63 | 64 | .center-text { 65 | text-align: center; 66 | } 67 | 68 | .center { 69 | position: relative; 70 | top: 50%; 71 | transform: translateY(-50%); 72 | } 73 | 74 | .hidden { 75 | display: none!important; 76 | } 77 | 78 | .content { 79 | /*height: 100%;*/ 80 | } 81 | 82 | footer { 83 | margin-top: 20px; 84 | padding-bottom: 10px; 85 | } 86 | 87 | /* RESPONSIVE */ 88 | @media (min-width: 48em) { 89 | 90 | } 91 | 92 | @media (max-width: 48em) { 93 | body { 94 | zoom: 80%; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |