No Description

workspace.html 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. {{ define "title" }}Loop: Workspace{{ end }}
  2. {{ define "styles" }}
  3. <style>
  4. pre#editor {
  5. height: 100vh;
  6. }
  7. iframe#view {
  8. height: 100vh;
  9. borders: none;
  10. }
  11. div#welcome {
  12. height: 100vh;
  13. }
  14. div#welcome h5 {
  15. width: 100%;
  16. }
  17. div#holder {
  18. border: 2px dashed #ccc;
  19. /*width: 300px;*/
  20. min-height: 110px;
  21. margin: 20px auto;
  22. }
  23. .select-wrapper {
  24. z-index: 2;
  25. }
  26. div#holder.hover {
  27. border: 2px dashed #0c0;
  28. }
  29. div#holder p {
  30. margin: 10px;
  31. font-size: 14px;
  32. }
  33. progress {
  34. width: 100%;
  35. }
  36. progress:after {
  37. content: '%';
  38. }
  39. .fail {
  40. background: #c00;
  41. padding: 2px;
  42. color: #fff;
  43. }
  44. .hidden {
  45. display: none !important;
  46. }
  47. #editor-actions a.btn-flat {
  48. padding: 0 0.5rem;
  49. }
  50. .fixed-action-btn ul button.btn-floating {
  51. opacity: 0;
  52. }
  53. .fullscreen {
  54. width: 100%;
  55. height: 100vh;
  56. }
  57. </style>
  58. {{ end }}
  59. {{ define "content" }}
  60. <div class="row">
  61. <div id="left-pane" class="col s4 m4 l2">
  62. <div class="row">
  63. <div class="col s12">
  64. <label>Workspace</label>
  65. <select>
  66. <option value="" disabled>Select a directory</option>
  67. <option value="Personal" selected>Personal</option>
  68. </select>
  69. </div>
  70. <div class="col s12 center">
  71. <a class="waves-effect waves-light btn modal-trigger" href="#modal-new-directory">New Content</a>
  72. </div>
  73. </div>
  74. <div class="row">
  75. <div class="col s12" style="overflow-y: auto;">
  76. <ul class="collection">
  77. {{ range $d := .Directories }}
  78. <li class="collection-item avatar dismissable">
  79. <i class="mdi-file-folder circle"></i>
  80. <span class="title"><a href="/{{ $.Username }}/edit/{{ $d }}">{{ $d }}</a></span>
  81. <p><!--(3 files)--></p>
  82. <a href="#" class="secondary-content"><i class="mdi-action-grade"></i></a>
  83. </li>
  84. {{ end }}
  85. </ul>
  86. </div>
  87. </div>
  88. </div>
  89. <div id="workarea" class="col s8 m8 l10">
  90. <div class="fixed-action-btn" style="bottom: 45px; right: 24px;">
  91. <a id="create" class="btn-floating btn-large red" title="Edit">
  92. <i class="large mdi-editor-mode-edit"></i>
  93. </a>
  94. <ul>
  95. <li><a id="delete" class="btn-floating red" title="Delete"><i class="large mdi-action-delete"></i></a></li>
  96. <li><a id="save" class="btn-floating amber" title="Save"><i class="large mdi-content-save"></i></a></li>
  97. <li><a id="publish" class="btn-floating green" title="Publish"><i class="large mdi-editor-publish"></i></a></li>
  98. <li><a id="upload" class="btn-floating blue modal-trigger" href="#upload-area" title="Attach file"><i class="large mdi-editor-attach-file"></i></a></li>
  99. </ul>
  100. </div>
  101. {{ if .Title }}
  102. <div id="zoom" class="row">
  103. <div id="editor-actions" class="col s12 m12 l12">
  104. <a id="fullscreen" class="waves-effect waves-teal btn-flat right" title="Fullscreen">
  105. <i class="mdi-navigation-fullscreen left hide-on-med-and-down"></i>
  106. <i class="mdi-navigation-fullscreen hide-on-large-only"></i>
  107. <span class="hide-on-med-and-down">Focus Mode</span>
  108. </a>
  109. <a id="preview" class="waves-effect waves-teal btn-flat right" title="Toggle Mode">
  110. <i class="mdi-action-cached left hide-on-med-and-down"></i>
  111. <i class="mdi-action-cached hide-on-large-only"></i>
  112. <span class="hide-on-med-and-down">Preview</span>
  113. </a>
  114. </div>
  115. <div class="col s12 m12 l12"><h4>{{ .Title }}</h4></div>
  116. <pre id="editor" class="col s12 m12 l12">{{ .Content }}</pre>
  117. <iframe id="view" class="col s12 m12 l12" style="display: none;" frameBorder="0" seamless="seamless" src="/{{ .Username }}/edit/{{ .Title }}/preview"></iframe>
  118. </div>
  119. {{ else }}
  120. <div class="row">
  121. <div id="welcome" class="col s12 m12 l12 valign-wrapper">
  122. <h5 class="valign center">Welcome!</h5>
  123. </div>
  124. </div>
  125. {{ end }}
  126. </div>
  127. </div>
  128. <div class="row">
  129. <div class="col s12">
  130. <div id="upload-area" class="modal bottom-sheet">
  131. <div class="modal-content">
  132. <h4>Upload</h4>
  133. <div id="holder" class="valign-wrapper">
  134. <p class="valign center" style="width: 100%;">Drag &amp; drop your files here!</p>
  135. </div>
  136. <p id="upload-not-available" class="hidden">
  137. <label>
  138. Drag &amp; drop is not supported, but you can still upload via:<br />
  139. <input type="file" />
  140. </label>
  141. </p>
  142. <p id="upload-no-filereader">Field API &amp; FileReader API not supported</p>
  143. <p id="upload-no-formdata">XHR2's FormData is not supported</p>
  144. <p id="upload-no-progress">XHR2's upload progress isn't supported</p>
  145. <p>Upload progress: <progress id="upload-progress" min="0" max="100" value="0">0</progress></p>
  146. </div>
  147. </div>
  148. </div>
  149. </div>
  150. <div id="modal-new-directory" class="modal">
  151. <div class="modal-content">
  152. <h4>New Content</h4>
  153. <form id="new-directory" class="col s12" method="post" action="/{{ .Username }}/edit/">
  154. <div class="row">
  155. <div class="input-field col s12">
  156. <input id="title" name="title" type="text" class="validate">
  157. <label for="title">Document Title</label>
  158. </div>
  159. </div>
  160. </form>
  161. </div>
  162. <div class="modal-footer">
  163. <a id="new" href="#" class="modal-action modal-close waves-effect waves-green btn-flat">Create</a>
  164. <a href="#" class="modal-action modal-close waves-effect waves-red btn-flat">Cancel</a>
  165. </div>
  166. </div>
  167. {{ end }}
  168. {{ define "scripts" }}
  169. <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.8/ace.js"></script>
  170. <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.8/theme-chrome.js"></script>
  171. <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.8/mode-markdown.js"></script>
  172. <script type="text/javascript">
  173. (function () {
  174. if (document.getElementById('editor')) {
  175. var editor = ace.edit('editor');
  176. editor.setTheme('ace/theme/chrome');
  177. editor.getSession().setMode('ace/mode/markdown');
  178. }
  179. })();
  180. (function () {
  181. var holder = document.getElementById('holder');
  182. var tests = {
  183. filereader: typeof FileReader != 'undefined',
  184. dnd: 'draggable' in document.createElement('span'),
  185. formdata: !!window.FormData,
  186. progress: "upload" in new XMLHttpRequest
  187. };
  188. var support = {
  189. filereader: document.getElementById('upload-no-filereader'),
  190. formdata: document.getElementById('upload-no-formdata'),
  191. progress: document.getElementById('upload-no-progress')
  192. };
  193. var acceptedTypes = {
  194. 'image/png': true,
  195. 'image/jpeg': true,
  196. 'image/gif': true
  197. };
  198. var progress = document.getElementById('upload-progress');
  199. var fileupload = document.getElementById('upload');
  200. 'filereader formdata progress'.split(' ').forEach(function (api) {
  201. if (tests[api] === false) {
  202. support[api].className = 'fail';
  203. } else {
  204. support[api].className = 'hidden';
  205. }
  206. });
  207. function readfiles(files) {
  208. var formData = tests.formdata ? new FormData() : null;
  209. for (var i = 0; i < files.length; i++) {
  210. if (tests.formdata) {
  211. formData.append('file', files[i]);
  212. }
  213. }
  214. if (tests.formdata) {
  215. var xhr = new XMLHttpRequest();
  216. xhr.open('POST', '/');
  217. xhr.onload = function () {
  218. progress.value = progress.innerHTML = 100;
  219. };
  220. if (tests.progress) {
  221. xhr.upload.onprogress = function (event) {
  222. if (event.lengthComputable) {
  223. var complete = (event.loaded / event.total * 100 | 0);
  224. progress.value = progress.innerHTML = complete;
  225. }
  226. }
  227. }
  228. xhr.send(formData);
  229. }
  230. if (tests.dnd) {
  231. holder.ondragover = function () {
  232. this.className = 'hover';
  233. return false;
  234. };
  235. holder.ondragend = function () {
  236. this.className = '';
  237. return false;
  238. };
  239. holder.ondrop = function (e) {
  240. this.className = '';
  241. e.preventDefault();
  242. readfiles(e.dataTransfer.files);
  243. };
  244. } else {
  245. fileupload.className = 'hidden';
  246. fileupload.querySelector('input').onchange = function () {
  247. readfiles(this.files);
  248. };
  249. }
  250. }
  251. })();
  252. $(function () {
  253. function toggleFullScreen() {
  254. var zoom = document.getElementById('zoom');
  255. if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) {
  256. if (document.documentElement.requestFullscreen) {
  257. zoom.requestFullscreen();
  258. } else if (document.documentElement.msRequestFullscreen) {
  259. zoom.msRequestFullscreen();
  260. } else if (document.documentElement.mozRequestFullScreen) {
  261. zoom.mozRequestFullScreen();
  262. } else if (document.documentElement.webkitRequestFullscreen) {
  263. zoom.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
  264. }
  265. } else {
  266. if (document.exitFullscreen) {
  267. document.exitFullscreen();
  268. } else if (document.msExitFullscreen) {
  269. document.msExitFullscreen();
  270. } else if (document.mozCancelFullScreen) {
  271. document.mozCancelFullScreen();
  272. } else if (document.webkitExitFullscreen) {
  273. document.webkitExitFullscreen();
  274. }
  275. }
  276. }
  277. $('select').material_select();
  278. $('.modal-trigger').leanModal();
  279. $('#fullscreen').click(function (event) {
  280. event.preventDefault();
  281. $('#zoom').toggleClass('fullscreen');
  282. toggleFullScreen();
  283. });
  284. $('#preview').click(function (event) {
  285. event.preventDefault();
  286. var editor = ace.edit('editor');
  287. if (!$('#view').is(':visible')) {
  288. $.ajax({
  289. url: window.location.href,
  290. method: 'put',
  291. data: {
  292. 'contents': editor.getValue()
  293. }
  294. })
  295. .done(function () {
  296. $('#view').attr('src', $('#view').attr('src'));
  297. $('#editor, #view').toggle();
  298. });
  299. } else {
  300. $('#editor, #view').toggle();
  301. }
  302. });
  303. $('a#delete').click(function (event) {
  304. event.preventDefault();
  305. var title = $('input#title').val();
  306. $.ajax({
  307. url: window.location.href,
  308. method: 'delete'
  309. })
  310. .done(function () {
  311. window.location.href = '/{{ .Username }}';
  312. });
  313. });
  314. $('a#new').click(function (event) {
  315. event.preventDefault();
  316. var title = $('input#title').val();
  317. var form = $('form#new-directory');
  318. form.attr('action', form.attr('action') + title);
  319. form.submit();
  320. return false;
  321. });
  322. $('a#save').click(function (event) {
  323. event.preventDefault();
  324. var editor = ace.edit('editor');
  325. $.ajax({
  326. url: window.location.href,
  327. method: 'put',
  328. data: {
  329. 'contents': editor.getValue()
  330. }
  331. });
  332. });
  333. });
  334. </script>
  335. {{ end }}