hosting/server/htdocs/account/index.html (355 lines of code) (raw):

<!DOCTYPE html> <!-- * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. --> <div id="bodydiv" class="body"> <div id="viewform" class="viewform"> <form id="userForm"> <table style="width: 100%;"> <tr><tr><td class="label">Username:</td></tr> <tr><td><input type="text" id="userName" class="readentry" size="30" readonly="readonly" placeholder="Your username" style="width: 300px;"/></td></tr> <tr><tr><td class="label">Email:</td></tr> <tr><td><input type="text" id="userEmail" class="readentry" size="30" readonly="readonly" placeholder="Your email address" style="width: 300px;"/></td></tr> <tr><tr><td class="label">Picture:</td></tr> <tr><td><img id="userPicture" style="width: 50px; height: 50px; vertical-align: top;"/><input id="uploadPicture" type="button" class="lightbutton" value="Upload"/><input id="uploadFile" type="file" accept="image/*" style="visibility: hidden;"/><span id="refreshingPicture" class="refreshing" style="display:none;"/></td></tr> <tr><tr><td class="label">Name:</td></tr> <tr><td><input type="text" id="userFullname" class="flatentry" size="30" placeholder="Your name" style="width: 300px;"/></td></tr> <tr><tr><td class="label">Bio:</td></tr> <tr><td><textarea id="userDescription" class="flatentry" cols="40" rows="3" placeholder="About yourself, in fewer than 120 characters" style="width: 300px;"></textarea></td></tr> </table> <br/> <!-- TODO Disabled for now <table style="width: 100%;"> <tr> <th class="thl thr" style="padding-top: 4px; padding-bottom: 4px; padding-left: 2px; padding-right: 2px; ">Calendar</th> </tr> </table> <table> <tr><td style="padding-right: 2px;"><input type="text" id="sched1" class="flatentry" size="10" placeholder="Schedule" style="width: 80px;"/></td><td><input type="text" id="service1" class="flatentry" size="2048" placeholder="Service URL" style="width: 200px;"/></td></tr> <tr><td style="padding-right: 2px;"><input type="text" id="sched2" class="flatentry" size="10" placeholder="Schedule" style="width: 80px;"/></td><td><input type="text" id="service2" class="flatentry" size="2048" placeholder="Service URL" style="width: 200px;"/></td></tr> <tr><td style="padding-right: 2px;"><input type="text" id="sched3" class="flatentry" size="10" placeholder="Schedule" style="width: 80px;"/></td><td><input type="text" id="service3" class="flatentry" size="2048" placeholder="Service URL" style="width: 200px;"/></td></tr> <tr><td style="padding-right: 2px;"><input type="text" id="sched4" class="flatentry" size="10" placeholder="Schedule" style="width: 80px;"/></td><td><input type="text" id="service4" class="flatentry" size="2048" placeholder="Service URL" style="width: 200px;"/></td></tr> <tr><td style="padding-right: 2px;"><input type="text" id="sched5" class="flatentry" size="10" placeholder="Schedule" style="width: 80px;"/></td><td><input type="text" id="service5" class="flatentry" size="2048" placeholder="Service URL" style="width: 200px;"/></td></tr> </table> <br/> <table style="width: 100%;"> <tr> <th class="thl thr" style="padding-top: 4px; padding-bottom: 4px; padding-left: 2px; padding-right: 2px; ">Key chain</th> </tr> </table> <table> <tr><td style="padding-right: 2px;"><input type="text" id="name1" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value1" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr> <tr><td style="padding-right: 2px;"><input type="text" id="name2" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value2" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr> <tr><td style="padding-right: 2px;"><input type="text" id="name3" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value3" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr> <tr><td style="padding-right: 2px;"><input type="text" id="name4" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value4" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr> <tr><td style="padding-right: 2px;"><input type="text" id="name5" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value5" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr> <tr><td style="padding-right: 2px;"><input type="text" id="name6" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value6" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr> <tr><td style="padding-right: 2px;"><input type="text" id="name7" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value7" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr> <tr><td style="padding-right: 2px;"><input type="text" id="name8" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value8" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr> <tr><td style="padding-right: 2px;"><input type="text" id="name9" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value9" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr> <tr><td style="padding-right: 2px;"><input type="text" id="name10" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value10" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr> </table> </form> <br/> --> </div> <script type="text/javascript"> (function accountbody() { /** * Setup page layout. */ (function layout() { document.title = config.windowtitle() + ' - Account'; $('viewhead').innerHTML = '<span class="cmenu">' + username + '</span>' + '<input type="button" class="redbutton plusminus" style="position: absolute; top: 4px; left: 2px;" id="deleteUser" value="-" title="Delete your account" disabled="true"/>'; if (!ui.isMobile()) $('viewform').className = 'viewform flatscrollbars'; $('userName').value = username; })(); /** * Set images. */ $('userPicture').src = ui.b64png(appcache.get('/public/user.b64')); /** * Initialize service references. */ var editorComp = sca.component("Editor"); var user= sca.defun(sca.reference(editorComp, "user")); var accounts = sca.reference(editorComp, "accounts"); var pictures = sca.reference(editorComp, "pictures"); /** * The current account entry and corresponding saved XML content. */ var savedacctxml = ''; var savedpicxml = ''; /** * Get and display the user's account. */ (function getacct() { workingstatus(true); showstatus('Loading'); return accounts.get('', function(doc) { // Stop now if we didn't get an account if (doc == null) { errorstatus('Account info not available'); workingstatus(false); return false; } var acctentry = car(elementsToValues(atom.readATOMEntry(mklist(doc)))); $('userFullname').value = cadr(assoc("'title", acctentry)); var acct = cadr(assoc("'content", acctentry)); var email = assoc("'email", acct); $('userEmail').value = isNull(email) || isNull(cdr(email))? (username.indexOf('@') != -1? username : '') : cadr(email); var desc = assoc("'description", acct); $('userDescription').innerHTML = isNull(desc) || isNull(cdr(desc))? '' : cadr(desc); /* TODO disabled for now var cal = assoc("'calendar", acct); reduce(function(i, evt) { var sched = assoc("'@schedule", evt); var svc = assoc("'@service", evt); $('sched' + i).value = isNull(sched)? '' : cadr(sched); $('service' + i).value = isNull(svc)? '' : cadr(svc); return i + 1; }, 1, isNull(cal)? mklist() : cadr(cadr(cal))); var keys = assoc("'keys", acct); reduce(function(i, key) { var kn = assoc("'@name", key); var kv = assoc("'@value", key); $('name' + i).value = isNull(kn)? '' : cadr(kn); $('value' + i).value = isNull(kv)? '' : cadr(kv); return i + 1; }, 1, isNull(keys)? mklist() : cadr(cadr(keys))); */ savedacctxml = car(atom.writeATOMEntry(valuesToElements(mklist(acctentry)))); return true; }); return true; })(); /** * Get and display the user's picture. */ (function getpic() { workingstatus(true); showstatus('Loading'); return pictures.get('', function(doc) { // Stop now if we didn't get a picture if (doc == null) { errorstatus('Picture not available'); workingstatus(false); return false; } var picentry = car(elementsToValues(atom.readATOMEntry(mklist(doc)))); savedpicxml = car(atom.writeATOMEntry(valuesToElements(mklist(picentry)))); var content = assoc("'content", picentry); var picture = assoc("'picture", content); var img = assoc("'image", picture); if (!isNull(img)) $('userPicture').src = cadr(img); onlinestatus(); workingstatus(false); return true; }); return true; })(); /** * Refresh picture. */ var refreshingpic = false; function refreshpic() { if (!refreshingpic) return false; $('refreshingPicture').style.display = 'inline-block'; return pictures.get('', function(doc) { if (doc == null) { errorstatus('Picture not available'); $('refreshingPicture').style.display = 'none'; refreshingpic = false; return false; } var picentry = car(elementsToValues(atom.readATOMEntry(mklist(doc)))); var content = assoc("'content", picentry); var picture = assoc("'picture", content); var token = assoc("'token", picture); // Update picture if (isNull(token)) { var entryxml = car(atom.writeATOMEntry(valuesToElements(mklist(picentry)))); savedpicxml = entryxml; var img = assoc("'image", picture); if (!isNull(img)) $('userPicture').src = cadr(img); $('refreshingPicture').style.display = 'none'; refreshingpic = false; return true; } // Refresh in 2 secs return ui.delay(refreshpic, 2000); }, 'remote'); return true; } /** * Save the user's account. */ function saveacct(entryxml) { if (isNull(username)) return false; workingstatus(true); showstatus('Saving'); savedacctxml = entryxml; accounts.put('', savedacctxml, function(e) { if (e) { showstatus('Local copy'); workingstatus(false); return false; } showstatus('Saved'); workingstatus(false); return true; }); return true; } /** * Save the user's picture. */ function savepic(entryxml) { if (isNull(username)) return false; workingstatus(true); showstatus('Uploading'); savedpicxml = entryxml; pictures.put('', savedpicxml, function(e) { if (e) { showstatus('Local copy'); workingstatus(false); return false; } showstatus('Uploaded'); workingstatus(false); return true; }); return true; } /** * Handle a change event */ function onaccountchange() { // Validate user input var title = $('userFullname').value; if (title.length == 0) { errorstatus('Name cannot be empty'); return false; } if (title.length > 40) { errorstatus('Name cannot be longer than 40 characters'); return false; } var email = $('userEmail').value; var description = $('userDescription').value; if (description.length > 120) { errorstatus('Bio cannot be longer than 120 characters'); return false; } /* TODO disabled for now var cal = map(function(i) { var sched = $('sched' + i).value; var svc = $('service' + i).value; return mklist("'event", mklist("'@schedule", sched), mklist("'@service", svc)); }, range(1, 6)); var keys = map(function(i) { var kn = $('name' + i).value; var kv = $('value' + i).value; return mklist("'key", mklist("'@name", kn), mklist("'@value", kv)); }, range(1, 11)); var acctentry = mklist("'entry", mklist("'title", title != ''? title : username), mklist("'id", username), mklist("'content", mklist("'account", mklist("'email", email), mklist("'description", description), cons("'keys", keys), cons("'calendar", cal)))); */ var acctentry = mklist("'entry", mklist("'title", title != ''? title : username), mklist("'id", username), mklist("'content", mklist("'account", mklist("'email", email), mklist("'description", description)))); var entryxml = car(atom.writeATOMEntry(valuesToElements(mklist(acctentry)))); if (savedacctxml == entryxml) return false; showstatus('Modified'); return saveacct(entryxml); } $('userFullname').onchange = onaccountchange; $('userDescription').onchange = onaccountchange; /* TODO disabled for now map(function(i) { $('sched' + i).onchange = onaccountchange; $('service' + i).onchange = onaccountchange; return true; }, range(1, 6)); map(function(i) { $('name' + i).onchange = onaccountchange; $('value' + i).onchange = onaccountchange; return true; }, range(1, 11)); */ /** * Handle a key event. */ var lastkeyup = null; $('userFullname').onkeyup = $('userDescription').onkeyup = function() { var t = new Date().getTime(); lastkeyup = t; ui.async(function() { return t == lastkeyup? onaccountchange() : true; }, 2000); }; /** * Handle a form submit event. */ $('userForm').onsubmit = function() { onaccountchange(); return false; }; /** * Read and upload icon file. */ function readpic(files) { if (!files || files.length == 0) return false; if (!files[0].type.match('image.*')) { errorstatus('Please select an image'); return false; } workingstatus(true); showstatus('Loading'); // Read the selected file into a 50x50 image return ui.readimage(files[0], function(e) { errorstatus('Couldn\'t read the file'); workingstatus(false); }, function(p) { showstatus('Loading ' + p + '%'); }, function(url) { // Update the user picture $('userPicture').src = url; showstatus('Loaded'); // Now upload it ui.async(function() { var picentry = mklist("'entry", mklist("'title", username), mklist("'id", username), mklist("'author", username), mklist("'content", mklist("'picture", mklist("'image", url)))); var entryxml = car(atom.writeATOMEntry(valuesToElements(mklist(picentry)))); if (savedpicxml == entryxml) { onlinestatus(); workingstatus(false); return false; } return savepic(entryxml); }); }, 50, 50); } /** * Upload a picture in an email. */ function emailpicture() { // Generate and put a picture email upload token workingstatus(true); showstatus('Uploading'); var token = uuid4(); var picentry = mklist("'entry", mklist("'title", username), mklist("'id", username), mklist("'author", username), mklist("'content", mklist("'picture", mklist("'token", token)))); var entryxml = car(atom.writeATOMEntry(valuesToElements(mklist(picentry)))); pictures.put('', entryxml, function(e) { if (e) { showstatus('Local copy'); workingstatus(false); return false; } workingstatus(false); // Open the email app var mailto = safeb64encode('p/' + username + '/' + token); ui.navigate('mailto:' + mailto + '@' + topdomainname(window.location.hostname) + '?subject=Uploading picture&body=Paste picture here', '_self'); // Refresh app icon refreshingpic = true; return ui.delay(refreshpic, 500); }, 'remote'); } /** * Handle picture upload events. */ ui.onclick($('uploadPicture'), function(e) { debug('uploadPicture.onclick()'); if (ui.isMobile() && ((ui.isWebkit() && ui.browserVersion() < 6.0) || (ui.isAndroid() && ui.browserVersion() < 2.2))) return ui.delay(function() { return emailpicture(); }); return ui.delay(function() { return $('uploadFile').click(); }); }); $('uploadFile').onchange = function(e) { return readpic(e.target.files); }; $('userPicture').ondrag = function(e) { e.stopPropagation(); e.preventDefault(); e.dataTransfer.dropEffect = 'copy'; }; $('userPicture').ondrop = function(e) { e.stopPropagation(); e.preventDefault(); return readpic(e.dataTransfer.files); }; })(); </script> </div>