app.es6 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /* eslint-env browser */
  2. const marked = require('marked')
  3. const dragdrop = require('drag-drop')
  4. // Add Robodog JS. It is advisable to install Robodog from npm/yarn.
  5. // But for experimenting, you can use also Transloadit’s CDN, Edgly:
  6. // <script src="https://releases.transloadit.com/uppy/robodog/v2.1.3/robodog.min.js"></script>
  7. const robodog = require('@uppy/robodog')
  8. const TRANSLOADIT_EXAMPLE_KEY = '35c1aed03f5011e982b6afe82599b6a0'
  9. const TRANSLOADIT_EXAMPLE_TEMPLATE = '0b2ee2bc25dc43619700c2ce0a75164a'
  10. /**
  11. * A textarea for markdown text, with support for file attachments.
  12. *
  13. * ## Usage
  14. *
  15. * ```js
  16. * const element = document.querySelector('textarea')
  17. * const mdtxt = new MarkdownTextarea(element)
  18. * mdtxt.install()
  19. * ```
  20. */
  21. class MarkdownTextarea {
  22. constructor (element) {
  23. this.element = element
  24. this.controls = document.createElement('div')
  25. this.controls.classList.add('mdtxt-controls')
  26. this.uploadLine = document.createElement('button')
  27. this.uploadLine.setAttribute('type', 'button')
  28. this.uploadLine.classList.add('form-upload')
  29. this.uploadLine.appendChild(
  30. document.createTextNode('Tap here to upload an attachment'))
  31. }
  32. install () {
  33. const { element } = this
  34. const wrapper = document.createElement('div')
  35. wrapper.classList.add('mdtxt')
  36. element.parentNode.replaceChild(wrapper, element)
  37. wrapper.appendChild(this.controls)
  38. wrapper.appendChild(element)
  39. wrapper.appendChild(this.uploadLine)
  40. this.setupUploadLine()
  41. this.setupTextareaDrop()
  42. }
  43. setupTextareaDrop () {
  44. dragdrop(this.element, (files) => {
  45. this.uploadFiles(files)
  46. })
  47. }
  48. setupUploadLine () {
  49. this.uploadLine.addEventListener('click', () => {
  50. this.pickFiles()
  51. })
  52. }
  53. reportUploadError (err) {
  54. this.uploadLine.classList.add('error')
  55. const message = document.createElement('span')
  56. message.appendChild(document.createTextNode(err.message))
  57. this.uploadLine.insertChild(message, this.uploadLine.firstChild)
  58. }
  59. unreportUploadError () {
  60. this.uploadLine.classList.remove('error')
  61. const message = this.uploadLine.querySelector('message')
  62. if (message) {
  63. this.uploadLine.removeChild(message)
  64. }
  65. }
  66. insertAttachments (attachments) {
  67. attachments.forEach((attachment) => {
  68. const { file, thumb } = attachment
  69. const link = `\n[LABEL](${file.ssl_url})\n`
  70. const labelText = `View File ${file.basename}`
  71. if (thumb) {
  72. this.element.value += link.replace('LABEL', `![${labelText}](${thumb.ssl_url})`)
  73. } else {
  74. this.element.value += link.replace('LABEL', labelText)
  75. }
  76. })
  77. }
  78. matchFilesAndThumbs (results) {
  79. const filesById = {}
  80. const thumbsById = {}
  81. results.forEach((result) => {
  82. if (result.stepName === 'thumbnails') {
  83. thumbsById[result.original_id] = result
  84. } else {
  85. filesById[result.original_id] = result
  86. }
  87. })
  88. return Object.keys(filesById).map((key) => ({
  89. file : filesById[key],
  90. thumb : thumbsById[key],
  91. }))
  92. }
  93. uploadFiles (files) {
  94. robodog.upload(files, {
  95. waitForEncoding: true,
  96. params: {
  97. auth: { key: TRANSLOADIT_EXAMPLE_KEY },
  98. template_id: TRANSLOADIT_EXAMPLE_TEMPLATE,
  99. },
  100. }).then((result) => {
  101. if (result === null) return
  102. this.insertAttachments(
  103. this.matchFilesAndThumbs(result.results)
  104. )
  105. }).catch((err) => {
  106. console.error(err)
  107. this.reportUploadError(err)
  108. })
  109. }
  110. pickFiles () {
  111. robodog.pick({
  112. waitForEncoding: true,
  113. params: {
  114. auth: { key: TRANSLOADIT_EXAMPLE_KEY },
  115. template_id: TRANSLOADIT_EXAMPLE_TEMPLATE,
  116. },
  117. providers: [
  118. 'webcam',
  119. 'url',
  120. 'instagram',
  121. 'google-drive',
  122. 'dropbox',
  123. ],
  124. }).then((result) => {
  125. if (result === null) return
  126. this.insertAttachments(
  127. this.matchFilesAndThumbs(result.results)
  128. )
  129. }).catch((err) => {
  130. console.error(err)
  131. this.reportUploadError(err)
  132. })
  133. }
  134. }
  135. const textarea = new MarkdownTextarea(document.querySelector('#new textarea'))
  136. textarea.install()
  137. function renderSnippet (title, text) {
  138. const template = document.querySelector('#snippet')
  139. const newSnippet = document.importNode(template.content, true)
  140. const titleEl = newSnippet.querySelector('.snippet-title')
  141. const contentEl = newSnippet.querySelector('.snippet-content')
  142. titleEl.appendChild(document.createTextNode(title))
  143. contentEl.innerHTML = marked(text)
  144. const list = document.querySelector('#snippets')
  145. list.insertBefore(newSnippet, list.firstChild)
  146. }
  147. function saveSnippet (title, text) {
  148. const id = parseInt(localStorage.numSnippets || 0, 10)
  149. localStorage[`snippet_${id}`] = JSON.stringify({ title, text })
  150. localStorage.numSnippets = id + 1
  151. }
  152. function loadSnippets () {
  153. for (let id = 0; localStorage[`snippet_${id}`] != null; id += 1) {
  154. const { title, text } = JSON.parse(localStorage[`snippet_${id}`])
  155. renderSnippet(title, text)
  156. }
  157. }
  158. document.querySelector('#new').addEventListener('submit', (event) => {
  159. event.preventDefault()
  160. const title = event.target.querySelector('input[name="title"]').value ||
  161. 'Unnamed Snippet'
  162. const text = textarea.element.value
  163. saveSnippet(title, text)
  164. renderSnippet(title, text)
  165. event.target.querySelector('input').value = ''
  166. event.target.querySelector('textarea').value = ''
  167. })
  168. window.addEventListener('DOMContentLoaded', () => {
  169. loadSnippets()
  170. })