index.html 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta name="apple-mobile-web-app-capable" content="yes" />
  5. <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
  6. <meta charset="UTF-8">
  7. <meta name="theme-color" content="#4b75ff">
  8. <link rel="stylesheet" href="./script/lightpick/css/lightpick.css">
  9. <link rel="stylesheet" href="./script/bulma/bulma.css">
  10. <script src="../script/jquery.min.js"></script>
  11. <script src="../script/ao_module.js"></script>
  12. <script src="script/lightpick/moment.min.js"></script>
  13. <script src="script/lightpick/lightpick.js"></script>
  14. <link rel="icon" type="image/png" href="img/small_icon.png"/>
  15. <title>Memo</title>
  16. <style>
  17. body{
  18. background-color:white;
  19. }
  20. </style>
  21. </head>
  22. <body>
  23. <nav class="navbar" role="navigation" aria-label="main navigation">
  24. <div class="navbar-brand">
  25. <a class="navbar-item" href="">
  26. <img src="img/logo.png" width="112" height="28">
  27. </a>
  28. </div>
  29. </nav>
  30. <div class="box">
  31. <button class="button is-warning" onclick="openMemoBox();">New Memo</button>
  32. <button class="button is-link is-light" onclick="listAllMemo();">Refresh</button>
  33. </div>
  34. <div id="memobox" class="box" style="display:none;">
  35. <h2 class="title is-4">New Memo</h2>
  36. <h4 class="subtitle is-6">Create a new Memo and try not to forget about it</h4>
  37. <hr>
  38. <div class="field">
  39. <label class="label">Title</label>
  40. <div class="control">
  41. <input class="input" id="title" type="text" placeholder="Title">
  42. </div>
  43. </div>
  44. <div class="field">
  45. <label class="label">Message</label>
  46. <div class="control">
  47. <textarea class="textarea" id="message" placeholder="Write some notes here!"></textarea>
  48. </div>
  49. </div>
  50. <div class="field">
  51. <label class="label">Deadline (Optional)</label>
  52. <div class="control">
  53. <input class="input" id="deadline" type="text" placeholder="Deadline">
  54. </div>
  55. </div>
  56. <div class="field is-grouped">
  57. <div class="control">
  58. <button class="button is-link" onclick="createNewMemo();">Submit</button>
  59. </div>
  60. <div class="control">
  61. <button class="button is-link is-light" onclick="cancelNewMemo();">Cancel</button>
  62. </div>
  63. </div>
  64. </div>
  65. <div id="deadlineTodayBanner" class="hero is-danger">
  66. <div class="hero-body">
  67. <p class="title">
  68. Deadline Today!
  69. </p>
  70. <p class="subtitle">
  71. Deadline within 24 hours!!!
  72. </p>
  73. </div>
  74. </div>
  75. <div id="deadlineTodayList">
  76. </div>
  77. <div id="deadlineSoonBanner" class="hero is-warning">
  78. <div class="hero-body">
  79. <p class="title">
  80. Deadline Soon
  81. </p>
  82. <p class="subtitle">
  83. Deadline this week
  84. </p>
  85. </div>
  86. </div>
  87. <div id="deadlineSoonList">
  88. </div>
  89. <div class="hero is-medium is-link">
  90. <div class="hero-body">
  91. <p class="title">
  92. Other Memos
  93. </p>
  94. <p class="subtitle">
  95. Non urgent items
  96. </p>
  97. </div>
  98. </div>
  99. <div id="memolist">
  100. </div>
  101. <script>
  102. let deadline = 0;
  103. let memoBuf = {};
  104. let removeMemoAfterSubmit = false;
  105. let currentEditingMemoID = 0;
  106. function openMemoBox(){
  107. deadline = 0;
  108. removeMemoAfterSubmit = false;
  109. $("#title").val("");
  110. $("#message").val("");
  111. $("#deadline").val("");
  112. $("#memobox").slideToggle("fast");
  113. }
  114. function cancelNewMemo(){
  115. $("#memobox").slideUp("fast");
  116. }
  117. var picker = new Lightpick({
  118. field: document.getElementById('deadline'),
  119. onSelect: function(date){
  120. console.log(date.unix());
  121. deadline = date.unix();
  122. }
  123. });
  124. function timestampToDateString(key){
  125. return new Date(parseInt(key)).toLocaleString(undefined, {year: 'numeric', month: '2-digit', day: '2-digit', weekday:"long", hour: '2-digit', hour12: false, minute:'2-digit', second:'2-digit'})
  126. }
  127. function uuidv4() {
  128. return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
  129. (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
  130. );
  131. }
  132. function listAllMemo(){
  133. $(".memeobject").remove();
  134. memoBuf = {};
  135. ao_module_agirun("Memo/backend/listmemo.js", {}, function(data){
  136. let memos = [];
  137. for (var [key, value] of Object.entries(data)) {
  138. let content = JSON.parse(value);
  139. console.log(key, content);
  140. memoBuf[key] = content;
  141. memos.push([key, content]);
  142. }
  143. let deadlineTodayItemCount = 0;
  144. let deadlineSoonItemCount = 0;
  145. memos.reverse();
  146. memos.forEach(function(memo){
  147. let key = memo[0];
  148. let content = memo[1];
  149. let deadline = timestampToDateString(content.deadline * 1000);
  150. if (content.deadline == 0){
  151. deadline = "No Deadline";
  152. }
  153. let fullContent = content.message;
  154. let displayContent = ``;
  155. let thisUUID = uuidv4();
  156. if (fullContent.length > 800){
  157. let abstract = fullContent.substr(0, 600);
  158. let remaining = fullContent.substr(600);
  159. displayContent = abstract + `<span id="${thisUUID}" style="display:none;">${remaining}</span><br><a onclick="handleReadMore('${thisUUID}', this);">Read More</a>`;
  160. }else{
  161. displayContent = fullContent;
  162. }
  163. let appendTarget = $("#memolist");
  164. if (content.deadline > 0){
  165. let timeBeforeDeadline = (content.deadline - (Math.floor(Date.now() / 1000)));
  166. if (timeBeforeDeadline / 3600 < 24){
  167. //Deadline today
  168. appendTarget = $("#deadlineTodayList");
  169. deadlineTodayItemCount++;
  170. }else if (timeBeforeDeadline / 3600 < (24 * 7)){
  171. //Deadline this week
  172. appendTarget = $("#deadlineSoonList");
  173. deadlineSoonItemCount++;
  174. }else{
  175. }
  176. }
  177. appendTarget.append(`<div class="card memeobject">
  178. <br>
  179. <div class="card-content">
  180. <div class="media">
  181. <div class="media-left">
  182. <figure class="image is-48x48">
  183. <img src="img/small_icon.png">
  184. </figure>
  185. </div>
  186. <div class="media-content">
  187. <p class="title is-4">${content.title}</p>
  188. <p class="subtitle is-6">${deadline}</p>
  189. </div>
  190. </div>
  191. <div class="content">
  192. ${displayContent}
  193. <br>
  194. <time>Creation Date: ${timestampToDateString(key)}</time>
  195. </div>
  196. </div>
  197. <footer class="card-footer">
  198. <a href="#" class="card-footer-item" memo="${key}" onclick="moveToTop(this)">Move to Top</a>
  199. <a href="#" class="card-footer-item" memo="${key}" onclick="editMemo(this);">Edit</a>
  200. <a href="#" class="card-footer-item" memo="${key}" onclick="removeMemoByButton(this);">Delete</a>
  201. </footer>
  202. </div>`);
  203. });
  204. if (deadlineTodayItemCount == 0){
  205. $("#deadlineTodayBanner").hide();
  206. }else{
  207. $("#deadlineTodayBanner").show();
  208. }
  209. if (deadlineSoonItemCount == 0){
  210. $("#deadlineSoonBanner").hide();
  211. }else{
  212. $("#deadlineSoonBanner").show();
  213. }
  214. })
  215. }
  216. listAllMemo();
  217. function editMemo(btn){
  218. let memoID = $(btn).attr("memo");
  219. loadMemoContentIntoNewMemoField(memoBuf[memoID]);
  220. $("#memobox").slideDown("fast");
  221. removeMemoAfterSubmit = true;
  222. currentEditingMemoID = memoID;
  223. }
  224. function loadMemoContentIntoNewMemoField(content){
  225. $("#title").val(content.title);
  226. $("#message").val(content.message);
  227. if (content.deadline > 0){
  228. $("#deadline").val(new Date(content.deadline * 1000).toLocaleDateString('en-US', {year: 'numeric', month: '2-digit', day: '2-digit'}));
  229. }
  230. deadline = content.deadline;
  231. }
  232. function handleReadMore(targetSpanID, btn){
  233. $("#" + targetSpanID).show();
  234. $(btn).hide();
  235. }
  236. function moveToTop(btn){
  237. let memoID = $(btn).attr("memo");
  238. loadMemoContentIntoNewMemoField(memoBuf[memoID]);
  239. createNewMemo(function(){
  240. removeMemo(memoID);
  241. });
  242. }
  243. function removeMemoByButton(btn){
  244. let memoID = $(btn).attr("memo");
  245. removeMemo(memoID);
  246. }
  247. function removeMemo(memoID, callback){
  248. ao_module_agirun("Memo/backend/removeMemo.js", {
  249. "memoid": memoID
  250. }, function(data){
  251. console.log(data);
  252. listAllMemo();
  253. if (callback){
  254. callback();
  255. }
  256. });
  257. }
  258. function createNewMemo(callback=undefined){
  259. //Create AJAX request
  260. let payload = {
  261. "title": $("#title").val().replace(/<[^>]*>?/gm, ''),
  262. "message":$("#message").val().replace(/<[^>]*>?/gm, ''),
  263. "deadline": deadline
  264. }
  265. console.log(payload);
  266. ao_module_agirun("Memo/backend/addMemo.js", {
  267. "memo": JSON.stringify(payload)
  268. }, function(data){
  269. if (data.error == undefined){
  270. $("#memobox").slideUp("fast");
  271. }
  272. if (removeMemoAfterSubmit){
  273. removeMemoAfterSubmit = false;
  274. removeMemo(currentEditingMemoID, callback);
  275. currentEditingMemoID = 0;
  276. }else{
  277. if (callback){
  278. callback();
  279. }else{
  280. listAllMemo();
  281. }
  282. }
  283. })
  284. }
  285. </script>
  286. </body>
  287. </html>