| <!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> |